wifi: mac80211: allow bw change during channel switch in mesh
[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
ff5c4dc4
JB
459static const struct nla_policy
460nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] = {
461 [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 },
462 [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 },
463};
464
d15da2a2 465static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
6d4dd4ef 466 [0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD },
55682965
JB
467 [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
468 [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
079e24ed 469 .len = 20-1 },
31888487 470 [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED },
3d9d1d66 471
72bdcf34 472 [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
094d05dc 473 [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 },
2a38075c
AAL
474 [NL80211_ATTR_WIPHY_EDMG_CHANNELS] = NLA_POLICY_RANGE(NLA_U8,
475 NL80211_EDMG_CHANNELS_MIN,
476 NL80211_EDMG_CHANNELS_MAX),
477 [NL80211_ATTR_WIPHY_EDMG_BW_CONFIG] = NLA_POLICY_RANGE(NLA_U8,
478 NL80211_EDMG_BW_CONFIG_MIN,
479 NL80211_EDMG_BW_CONFIG_MAX),
480
3d9d1d66
JB
481 [NL80211_ATTR_CHANNEL_WIDTH] = { .type = NLA_U32 },
482 [NL80211_ATTR_CENTER_FREQ1] = { .type = NLA_U32 },
942ba88b 483 [NL80211_ATTR_CENTER_FREQ1_OFFSET] = NLA_POLICY_RANGE(NLA_U32, 0, 999),
3d9d1d66
JB
484 [NL80211_ATTR_CENTER_FREQ2] = { .type = NLA_U32 },
485
ab0d76f6
JB
486 [NL80211_ATTR_WIPHY_RETRY_SHORT] = NLA_POLICY_MIN(NLA_U8, 1),
487 [NL80211_ATTR_WIPHY_RETRY_LONG] = NLA_POLICY_MIN(NLA_U8, 1),
b9a5f8ca
JM
488 [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 },
489 [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 },
81077e82 490 [NL80211_ATTR_WIPHY_COVERAGE_CLASS] = { .type = NLA_U8 },
3057dbfd 491 [NL80211_ATTR_WIPHY_DYN_ACK] = { .type = NLA_FLAG },
55682965 492
ab0d76f6 493 [NL80211_ATTR_IFTYPE] = NLA_POLICY_MAX(NLA_U32, NL80211_IFTYPE_MAX),
55682965
JB
494 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
495 [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
41ade00f 496
c7721c05
JB
497 [NL80211_ATTR_MAC] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
498 [NL80211_ATTR_PREV_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
41ade00f 499
b9454e83 500 [NL80211_ATTR_KEY] = { .type = NLA_NESTED, },
41ade00f
JB
501 [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
502 .len = WLAN_MAX_KEY_LEN },
56be393f 503 [NL80211_ATTR_KEY_IDX] = NLA_POLICY_MAX(NLA_U8, 7),
41ade00f
JB
504 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
505 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
81962267 506 [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
ab0d76f6
JB
507 [NL80211_ATTR_KEY_TYPE] =
508 NLA_POLICY_MAX(NLA_U32, NUM_NL80211_KEYTYPES),
ed1b6cc7
JB
509
510 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
511 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
f88eb7c0
JB
512 [NL80211_ATTR_BEACON_HEAD] =
513 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_beacon_head,
514 IEEE80211_MAX_DATA_LEN),
3d7af878
JB
515 [NL80211_ATTR_BEACON_TAIL] =
516 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
517 IEEE80211_MAX_DATA_LEN),
ab0d76f6
JB
518 [NL80211_ATTR_STA_AID] =
519 NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
5727ef1b
JB
520 [NL80211_ATTR_STA_FLAGS] = { .type = NLA_NESTED },
521 [NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 },
522 [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
523 .len = NL80211_MAX_SUPP_RATES },
ab0d76f6
JB
524 [NL80211_ATTR_STA_PLINK_ACTION] =
525 NLA_POLICY_MAX(NLA_U8, NUM_NL80211_PLINK_ACTIONS - 1),
e96d1cd2
ARN
526 [NL80211_ATTR_STA_TX_POWER_SETTING] =
527 NLA_POLICY_RANGE(NLA_U8,
528 NL80211_TX_POWER_AUTOMATIC,
529 NL80211_TX_POWER_FIXED),
530 [NL80211_ATTR_STA_TX_POWER] = { .type = NLA_S16 },
5727ef1b 531 [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
0a9542ee 532 [NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ },
2ec600d6 533 [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
a4f606ea 534 .len = IEEE80211_MAX_MESH_ID_LEN },
1fab1b89 535 [NL80211_ATTR_MPATH_NEXT_HOP] = NLA_POLICY_ETH_ADDR_COMPAT,
9f1ba906 536
6624bb34
JB
537 /* allow 3 for NUL-termination, we used to declare this NLA_STRING */
538 [NL80211_ATTR_REG_ALPHA2] = NLA_POLICY_RANGE(NLA_BINARY, 2, 3),
b2e1b302
LR
539 [NL80211_ATTR_REG_RULES] = { .type = NLA_NESTED },
540
9f1ba906
JM
541 [NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 },
542 [NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 },
543 [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 },
90c97a04
JM
544 [NL80211_ATTR_BSS_BASIC_RATES] = { .type = NLA_BINARY,
545 .len = NL80211_MAX_SUPP_RATES },
50b12f59 546 [NL80211_ATTR_BSS_HT_OPMODE] = { .type = NLA_U16 },
36aedc90 547
24bdd9f4 548 [NL80211_ATTR_MESH_CONFIG] = { .type = NLA_NESTED },
15d5dda6 549 [NL80211_ATTR_SUPPORT_MESH_AUTH] = { .type = NLA_FLAG },
93da9cc1 550
c7721c05 551 [NL80211_ATTR_HT_CAPABILITY] = NLA_POLICY_EXACT_LEN_WARN(NL80211_HT_CAPABILITY_LEN),
9aed3cc1
JM
552
553 [NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 },
3d7af878
JB
554 [NL80211_ATTR_IE] = NLA_POLICY_VALIDATE_FN(NLA_BINARY,
555 validate_ie_attr,
556 IEEE80211_MAX_DATA_LEN),
2a519311
JB
557 [NL80211_ATTR_SCAN_FREQUENCIES] = { .type = NLA_NESTED },
558 [NL80211_ATTR_SCAN_SSIDS] = { .type = NLA_NESTED },
636a5d36
JM
559
560 [NL80211_ATTR_SSID] = { .type = NLA_BINARY,
561 .len = IEEE80211_MAX_SSID_LEN },
562 [NL80211_ATTR_AUTH_TYPE] = { .type = NLA_U32 },
563 [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 },
04a773ad 564 [NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG },
1965c853 565 [NL80211_ATTR_TIMED_OUT] = { .type = NLA_FLAG },
ab0d76f6
JB
566 [NL80211_ATTR_USE_MFP] = NLA_POLICY_RANGE(NLA_U32,
567 NL80211_MFP_NO,
568 NL80211_MFP_OPTIONAL),
ff5c4dc4
JB
569 [NL80211_ATTR_STA_FLAGS2] =
570 NLA_POLICY_EXACT_LEN_WARN(sizeof(struct nl80211_sta_flag_update)),
3f77316c 571 [NL80211_ATTR_CONTROL_PORT] = { .type = NLA_FLAG },
c0692b8f
JB
572 [NL80211_ATTR_CONTROL_PORT_ETHERTYPE] = { .type = NLA_U16 },
573 [NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT] = { .type = NLA_FLAG },
64bf3d4b 574 [NL80211_ATTR_CONTROL_PORT_OVER_NL80211] = { .type = NLA_FLAG },
b23aa676 575 [NL80211_ATTR_PRIVACY] = { .type = NLA_FLAG },
ea750801 576 [NL80211_ATTR_STATUS_CODE] = { .type = NLA_U16 },
b23aa676
SO
577 [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 },
578 [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
463d0183 579 [NL80211_ATTR_PID] = { .type = NLA_U32 },
8b787643 580 [NL80211_ATTR_4ADDR] = { .type = NLA_U8 },
c7721c05 581 [NL80211_ATTR_PMKID] = NLA_POLICY_EXACT_LEN_WARN(WLAN_PMKID_LEN),
9588bbd5
JM
582 [NL80211_ATTR_DURATION] = { .type = NLA_U32 },
583 [NL80211_ATTR_COOKIE] = { .type = NLA_U64 },
13ae75b1 584 [NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED },
026331c4
JM
585 [NL80211_ATTR_FRAME] = { .type = NLA_BINARY,
586 .len = IEEE80211_MAX_DATA_LEN },
587 [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, },
ab0d76f6
JB
588 [NL80211_ATTR_PS_STATE] = NLA_POLICY_RANGE(NLA_U32,
589 NL80211_PS_DISABLED,
590 NL80211_PS_ENABLED),
d6dc1a38 591 [NL80211_ATTR_CQM] = { .type = NLA_NESTED, },
d5cdfacb 592 [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG },
fd8aaaf3 593 [NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 },
98d2ff8b
JO
594 [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 },
595 [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 },
2e161f78 596 [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 },
afe0cbf8
BR
597 [NL80211_ATTR_WIPHY_ANTENNA_TX] = { .type = NLA_U32 },
598 [NL80211_ATTR_WIPHY_ANTENNA_RX] = { .type = NLA_U32 },
885a46d0 599 [NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 },
f7ca38df 600 [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG },
dbd2fd65 601 [NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
ff1b6e69 602 [NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED },
ab0d76f6
JB
603 [NL80211_ATTR_STA_PLINK_STATE] =
604 NLA_POLICY_MAX(NLA_U8, NUM_NL80211_PLINK_STATES - 1),
056e9375
JK
605 [NL80211_ATTR_MEASUREMENT_DURATION] = { .type = NLA_U16 },
606 [NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY] = { .type = NLA_FLAG },
ab0d76f6
JB
607 [NL80211_ATTR_MESH_PEER_AID] =
608 NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
bbe6ad6d 609 [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 },
e5497d76 610 [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED },
34850ab2 611 [NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED },
ab0d76f6
JB
612 [NL80211_ATTR_HIDDEN_SSID] =
613 NLA_POLICY_RANGE(NLA_U32,
614 NL80211_HIDDEN_SSID_NOT_IN_USE,
615 NL80211_HIDDEN_SSID_ZERO_CONTENTS),
3d7af878
JB
616 [NL80211_ATTR_IE_PROBE_RESP] =
617 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
618 IEEE80211_MAX_DATA_LEN),
619 [NL80211_ATTR_IE_ASSOC_RESP] =
620 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
621 IEEE80211_MAX_DATA_LEN),
f4b34b55 622 [NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG },
ff5c4dc4 623 [NL80211_ATTR_STA_WME] = NLA_POLICY_NESTED(nl80211_sta_wme_policy),
a1f1c21c 624 [NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED },
e9f935e3 625 [NL80211_ATTR_TX_NO_CCK_RATE] = { .type = NLA_FLAG },
109086ce
AN
626 [NL80211_ATTR_TDLS_ACTION] = { .type = NLA_U8 },
627 [NL80211_ATTR_TDLS_DIALOG_TOKEN] = { .type = NLA_U8 },
628 [NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 },
629 [NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG },
630 [NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG },
31fa97c5 631 [NL80211_ATTR_TDLS_INITIATOR] = { .type = NLA_FLAG },
e247bd90 632 [NL80211_ATTR_DONT_WAIT_FOR_ACK] = { .type = NLA_FLAG },
00f740e1
AN
633 [NL80211_ATTR_PROBE_RESP] = { .type = NLA_BINARY,
634 .len = IEEE80211_MAX_DATA_LEN },
8b60b078 635 [NL80211_ATTR_DFS_REGION] = { .type = NLA_U8 },
7e7c8926
BG
636 [NL80211_ATTR_DISABLE_HT] = { .type = NLA_FLAG },
637 [NL80211_ATTR_HT_CAPABILITY_MASK] = {
638 .len = NL80211_HT_CAPABILITY_LEN
639 },
1d9d9213 640 [NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 },
1b658f11 641 [NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 },
4486ea98 642 [NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
89a54e48 643 [NL80211_ATTR_WDEV] = { .type = NLA_U64 },
57b5ce07 644 [NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },
cb9abd48
JB
645
646 /* need to include at least Auth Transaction and Status Code */
647 [NL80211_ATTR_AUTH_DATA] = NLA_POLICY_MIN_LEN(4),
648
c7721c05 649 [NL80211_ATTR_VHT_CAPABILITY] = NLA_POLICY_EXACT_LEN_WARN(NL80211_VHT_CAPABILITY_LEN),
ed473771 650 [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
ab0d76f6
JB
651 [NL80211_ATTR_P2P_CTWINDOW] = NLA_POLICY_MAX(NLA_U8, 127),
652 [NL80211_ATTR_P2P_OPPPS] = NLA_POLICY_MAX(NLA_U8, 1),
653 [NL80211_ATTR_LOCAL_MESH_POWER_MODE] =
654 NLA_POLICY_RANGE(NLA_U32,
655 NL80211_MESH_POWER_UNKNOWN + 1,
656 NL80211_MESH_POWER_MAX),
77765eaf
VT
657 [NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 },
658 [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED },
9d62a986
JM
659 [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 },
660 [NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, },
3713b4e3 661 [NL80211_ATTR_SPLIT_WIPHY_DUMP] = { .type = NLA_FLAG, },
ee2aca34
JB
662 [NL80211_ATTR_DISABLE_VHT] = { .type = NLA_FLAG },
663 [NL80211_ATTR_VHT_CAPABILITY_MASK] = {
664 .len = NL80211_VHT_CAPABILITY_LEN,
665 },
355199e0
JM
666 [NL80211_ATTR_MDID] = { .type = NLA_U16 },
667 [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,
668 .len = IEEE80211_MAX_DATA_LEN },
0e1a1d85 669 [NL80211_ATTR_CRIT_PROT_ID] = { .type = NLA_U16 },
cb9abd48
JB
670 [NL80211_ATTR_MAX_CRIT_PROT_DURATION] =
671 NLA_POLICY_MAX(NLA_U16, NL80211_CRIT_PROTO_MAX_DURATION),
ab0d76f6
JB
672 [NL80211_ATTR_PEER_AID] =
673 NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
16ef1fe2
SW
674 [NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 },
675 [NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG },
676 [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED },
00c207ed
JC
677 [NL80211_ATTR_CNTDWN_OFFS_BEACON] = { .type = NLA_BINARY },
678 [NL80211_ATTR_CNTDWN_OFFS_PRESP] = { .type = NLA_BINARY },
cb9abd48 679 [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = NLA_POLICY_MIN_LEN(2),
c8b82802
JB
680 /*
681 * The value of the Length field of the Supported Operating
682 * Classes element is between 2 and 253.
683 */
684 [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] =
685 NLA_POLICY_RANGE(NLA_BINARY, 2, 253),
5336fa88 686 [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG },
60f4a7b1 687 [NL80211_ATTR_OPMODE_NOTIF] = { .type = NLA_U8 },
ad7e718c
JB
688 [NL80211_ATTR_VENDOR_ID] = { .type = NLA_U32 },
689 [NL80211_ATTR_VENDOR_SUBCMD] = { .type = NLA_U32 },
690 [NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY },
c8b82802
JB
691 [NL80211_ATTR_QOS_MAP] = NLA_POLICY_RANGE(NLA_BINARY,
692 IEEE80211_QOS_MAP_LEN_MIN,
693 IEEE80211_QOS_MAP_LEN_MAX),
c7721c05 694 [NL80211_ATTR_MAC_HINT] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
1df4a510 695 [NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 },
df942e7b 696 [NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 },
18e5ca65 697 [NL80211_ATTR_SOCKET_OWNER] = { .type = NLA_FLAG },
34d22ce2 698 [NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY },
bab5ab7d 699 [NL80211_ATTR_USE_RRM] = { .type = NLA_FLAG },
ab0d76f6
JB
700 [NL80211_ATTR_TSID] = NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_TIDS - 1),
701 [NL80211_ATTR_USER_PRIO] =
702 NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_UPS - 1),
960d01ac 703 [NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 },
18998c38 704 [NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 },
5cde05c6 705 [NL80211_ATTR_OPER_CLASS] = { .type = NLA_U8 },
c7721c05 706 [NL80211_ATTR_MAC_MASK] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
1bdd716c 707 [NL80211_ATTR_WIPHY_SELF_MANAGED_REG] = { .type = NLA_FLAG },
4b681c82 708 [NL80211_ATTR_NETNS_FD] = { .type = NLA_U32 },
9c748934 709 [NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 },
05050753 710 [NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG },
34d50519 711 [NL80211_ATTR_PBSS] = { .type = NLA_FLAG },
38de03d2 712 [NL80211_ATTR_BSS_SELECT] = { .type = NLA_NESTED },
ab0d76f6
JB
713 [NL80211_ATTR_STA_SUPPORT_P2P_PS] =
714 NLA_POLICY_MAX(NLA_U8, NUM_NL80211_P2P_PS_STATUS - 1),
c6e6a0c8
AE
715 [NL80211_ATTR_MU_MIMO_GROUP_DATA] = {
716 .len = VHT_MUMIMO_GROUPS_DATA_LEN
717 },
c7721c05 718 [NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
ab0d76f6 719 [NL80211_ATTR_NAN_MASTER_PREF] = NLA_POLICY_MIN(NLA_U8, 1),
8585989d 720 [NL80211_ATTR_BANDS] = { .type = NLA_U32 },
a442b761 721 [NL80211_ATTR_NAN_FUNC] = { .type = NLA_NESTED },
348bd456
JM
722 [NL80211_ATTR_FILS_KEK] = { .type = NLA_BINARY,
723 .len = FILS_MAX_KEK_LEN },
c7721c05 724 [NL80211_ATTR_FILS_NONCES] = NLA_POLICY_EXACT_LEN_WARN(2 * FILS_NONCE_LEN),
ce0ce13a 725 [NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED] = { .type = NLA_FLAG, },
c7721c05 726 [NL80211_ATTR_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
bf95ecdb 727 [NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] = { .type = NLA_S8 },
728 [NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST] = {
729 .len = sizeof(struct nl80211_bss_select_rssi_adjust)
730 },
3093ebbe 731 [NL80211_ATTR_TIMEOUT_REASON] = { .type = NLA_U32 },
a3caf744
VK
732 [NL80211_ATTR_FILS_ERP_USERNAME] = { .type = NLA_BINARY,
733 .len = FILS_ERP_MAX_USERNAME_LEN },
734 [NL80211_ATTR_FILS_ERP_REALM] = { .type = NLA_BINARY,
735 .len = FILS_ERP_MAX_REALM_LEN },
736 [NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] = { .type = NLA_U16 },
737 [NL80211_ATTR_FILS_ERP_RRK] = { .type = NLA_BINARY,
738 .len = FILS_ERP_MAX_RRK_LEN },
c7721c05 739 [NL80211_ATTR_FILS_CACHE_ID] = NLA_POLICY_EXACT_LEN_WARN(2),
a3caf744 740 [NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN },
cb9abd48 741 [NL80211_ATTR_PMKR0_NAME] = NLA_POLICY_EXACT_LEN(WLAN_PMK_NAME_LEN),
ca986ad9 742 [NL80211_ATTR_SCHED_SCAN_MULTI] = { .type = NLA_FLAG },
40cbfa90 743 [NL80211_ATTR_EXTERNAL_AUTH_SUPPORT] = { .type = NLA_FLAG },
52539ca8
THJ
744
745 [NL80211_ATTR_TXQ_LIMIT] = { .type = NLA_U32 },
746 [NL80211_ATTR_TXQ_MEMORY_LIMIT] = { .type = NLA_U32 },
747 [NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 },
c8b82802 748 [NL80211_ATTR_HE_CAPABILITY] =
a3a20feb
JB
749 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_he_capa,
750 NL80211_HE_MAX_CAPABILITY_LEN),
0e012b4e
JB
751 [NL80211_ATTR_FTM_RESPONDER] =
752 NLA_POLICY_NESTED(nl80211_ftm_responder_policy),
9bb7e0f2
JB
753 [NL80211_ATTR_TIMEOUT] = NLA_POLICY_MIN(NLA_U32, 1),
754 [NL80211_ATTR_PEER_MEASUREMENTS] =
23323289 755 NLA_POLICY_NESTED(nl80211_pmsr_attr_policy),
36647055 756 [NL80211_ATTR_AIRTIME_WEIGHT] = NLA_POLICY_MIN(NLA_U16, 1),
26f7044e
CHH
757 [NL80211_ATTR_SAE_PASSWORD] = { .type = NLA_BINARY,
758 .len = SAE_PASSWORD_MAX_LEN },
a0de1ca3 759 [NL80211_ATTR_TWT_RESPONDER] = { .type = NLA_FLAG },
796e90f4 760 [NL80211_ATTR_HE_OBSS_PD] = NLA_POLICY_NESTED(he_obss_pd_policy),
14f34e36 761 [NL80211_ATTR_VLAN_ID] = NLA_POLICY_RANGE(NLA_U16, 1, VLAN_N_VID - 2),
5c5e52d1 762 [NL80211_ATTR_HE_BSS_COLOR] = NLA_POLICY_NESTED(he_bss_color_policy),
77f576de
T
763 [NL80211_ATTR_TID_CONFIG] =
764 NLA_POLICY_NESTED_ARRAY(nl80211_tid_config_attr_policy),
5631d96a 765 [NL80211_ATTR_CONTROL_PORT_NO_PREAUTH] = { .type = NLA_FLAG },
7fc82af8
VJ
766 [NL80211_ATTR_PMK_LIFETIME] = NLA_POLICY_MIN(NLA_U32, 1),
767 [NL80211_ATTR_PMK_REAUTH_THRESHOLD] = NLA_POLICY_RANGE(NLA_U8, 1, 100),
9dba48a6 768 [NL80211_ATTR_RECEIVE_MULTICAST] = { .type = NLA_FLAG },
942ba88b 769 [NL80211_ATTR_WIPHY_FREQ_OFFSET] = NLA_POLICY_RANGE(NLA_U32, 0, 999),
2032f3b2 770 [NL80211_ATTR_SCAN_FREQ_KHZ] = { .type = NLA_NESTED },
8140860c
JB
771 [NL80211_ATTR_HE_6GHZ_CAPABILITY] =
772 NLA_POLICY_EXACT_LEN(sizeof(struct ieee80211_he_6ghz_capa)),
291c49de
AD
773 [NL80211_ATTR_FILS_DISCOVERY] =
774 NLA_POLICY_NESTED(nl80211_fils_discovery_policy),
7443dcd1
AD
775 [NL80211_ATTR_UNSOL_BCAST_PROBE_RESP] =
776 NLA_POLICY_NESTED(nl80211_unsol_bcast_probe_resp_policy),
d2b7588a
TP
777 [NL80211_ATTR_S1G_CAPABILITY] =
778 NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN),
779 [NL80211_ATTR_S1G_CAPABILITY_MASK] =
780 NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN),
9f0ffa41
RD
781 [NL80211_ATTR_SAE_PWE] =
782 NLA_POLICY_RANGE(NLA_U8, NL80211_SAE_PWE_HUNT_AND_PECK,
783 NL80211_SAE_PWE_BOTH),
3bb02143 784 [NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT },
6bdb68ce 785 [NL80211_ATTR_SAR_SPEC] = NLA_POLICY_NESTED(sar_policy),
b6db0f89 786 [NL80211_ATTR_DISABLE_HE] = { .type = NLA_FLAG },
0d2ab3ae
JC
787 [NL80211_ATTR_OBSS_COLOR_BITMAP] = { .type = NLA_U64 },
788 [NL80211_ATTR_COLOR_CHANGE_COUNT] = { .type = NLA_U8 },
789 [NL80211_ATTR_COLOR_CHANGE_COLOR] = { .type = NLA_U8 },
790 [NL80211_ATTR_COLOR_CHANGE_ELEMS] = NLA_POLICY_NESTED(nl80211_policy),
dc1e3cb8
JC
791 [NL80211_ATTR_MBSSID_CONFIG] =
792 NLA_POLICY_NESTED(nl80211_mbssid_config_policy),
793 [NL80211_ATTR_MBSSID_ELEMS] = { .type = NLA_NESTED },
a95bfb87 794 [NL80211_ATTR_RADAR_BACKGROUND] = { .type = NLA_FLAG },
47301a74 795 [NL80211_ATTR_AP_SETTINGS_FLAGS] = { .type = NLA_U32 },
ea05fd35
IP
796 [NL80211_ATTR_EHT_CAPABILITY] =
797 NLA_POLICY_RANGE(NLA_BINARY,
798 NL80211_EHT_MIN_CAPABILITY_LEN,
799 NL80211_EHT_MAX_CAPABILITY_LEN),
36f84235 800 [NL80211_ATTR_DISABLE_EHT] = { .type = NLA_FLAG },
7b0a0e3c
JB
801 [NL80211_ATTR_MLO_LINKS] =
802 NLA_POLICY_NESTED_ARRAY(nl80211_policy),
803 [NL80211_ATTR_MLO_LINK_ID] =
804 NLA_POLICY_RANGE(NLA_U8, 0, IEEE80211_MLD_MAX_NUM_LINKS),
d648c230 805 [NL80211_ATTR_MLD_ADDR] = NLA_POLICY_EXACT_LEN(ETH_ALEN),
efbabc11 806 [NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG },
ecad3b0b 807 [NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_REJECT },
55682965
JB
808};
809
e31b8213 810/* policy for the key attributes */
b54452b0 811static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = {
fffd0934 812 [NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN },
b9454e83
JB
813 [NL80211_KEY_IDX] = { .type = NLA_U8 },
814 [NL80211_KEY_CIPHER] = { .type = NLA_U32 },
81962267 815 [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
b9454e83
JB
816 [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG },
817 [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
ab0d76f6 818 [NL80211_KEY_TYPE] = NLA_POLICY_MAX(NLA_U32, NUM_NL80211_KEYTYPES - 1),
dbd2fd65 819 [NL80211_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
6cdd3979 820 [NL80211_KEY_MODE] = NLA_POLICY_RANGE(NLA_U8, 0, NL80211_KEY_SET_TX),
dbd2fd65
JB
821};
822
823/* policy for the key default flags */
824static const struct nla_policy
825nl80211_key_default_policy[NUM_NL80211_KEY_DEFAULT_TYPES] = {
826 [NL80211_KEY_DEFAULT_TYPE_UNICAST] = { .type = NLA_FLAG },
827 [NL80211_KEY_DEFAULT_TYPE_MULTICAST] = { .type = NLA_FLAG },
b9454e83
JB
828};
829
f83ace3b 830#ifdef CONFIG_PM
ff1b6e69
JB
831/* policy for WoWLAN attributes */
832static const struct nla_policy
833nl80211_wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = {
834 [NL80211_WOWLAN_TRIG_ANY] = { .type = NLA_FLAG },
835 [NL80211_WOWLAN_TRIG_DISCONNECT] = { .type = NLA_FLAG },
836 [NL80211_WOWLAN_TRIG_MAGIC_PKT] = { .type = NLA_FLAG },
837 [NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .type = NLA_NESTED },
77dbbb13
JB
838 [NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE] = { .type = NLA_FLAG },
839 [NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST] = { .type = NLA_FLAG },
840 [NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE] = { .type = NLA_FLAG },
841 [NL80211_WOWLAN_TRIG_RFKILL_RELEASE] = { .type = NLA_FLAG },
2a0e047e 842 [NL80211_WOWLAN_TRIG_TCP_CONNECTION] = { .type = NLA_NESTED },
8cd4d456 843 [NL80211_WOWLAN_TRIG_NET_DETECT] = { .type = NLA_NESTED },
2a0e047e
JB
844};
845
846static const struct nla_policy
847nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = {
848 [NL80211_WOWLAN_TCP_SRC_IPV4] = { .type = NLA_U32 },
849 [NL80211_WOWLAN_TCP_DST_IPV4] = { .type = NLA_U32 },
c7721c05 850 [NL80211_WOWLAN_TCP_DST_MAC] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
2a0e047e
JB
851 [NL80211_WOWLAN_TCP_SRC_PORT] = { .type = NLA_U16 },
852 [NL80211_WOWLAN_TCP_DST_PORT] = { .type = NLA_U16 },
bc043585 853 [NL80211_WOWLAN_TCP_DATA_PAYLOAD] = NLA_POLICY_MIN_LEN(1),
2a0e047e
JB
854 [NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ] = {
855 .len = sizeof(struct nl80211_wowlan_tcp_data_seq)
856 },
857 [NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN] = {
858 .len = sizeof(struct nl80211_wowlan_tcp_data_token)
859 },
860 [NL80211_WOWLAN_TCP_DATA_INTERVAL] = { .type = NLA_U32 },
bc043585
JB
861 [NL80211_WOWLAN_TCP_WAKE_PAYLOAD] = NLA_POLICY_MIN_LEN(1),
862 [NL80211_WOWLAN_TCP_WAKE_MASK] = NLA_POLICY_MIN_LEN(1),
ff1b6e69 863};
f83ace3b 864#endif /* CONFIG_PM */
ff1b6e69 865
be29b99a
AK
866/* policy for coalesce rule attributes */
867static const struct nla_policy
868nl80211_coalesce_policy[NUM_NL80211_ATTR_COALESCE_RULE] = {
869 [NL80211_ATTR_COALESCE_RULE_DELAY] = { .type = NLA_U32 },
ab0d76f6
JB
870 [NL80211_ATTR_COALESCE_RULE_CONDITION] =
871 NLA_POLICY_RANGE(NLA_U32,
872 NL80211_COALESCE_CONDITION_MATCH,
873 NL80211_COALESCE_CONDITION_NO_MATCH),
be29b99a
AK
874 [NL80211_ATTR_COALESCE_RULE_PKT_PATTERN] = { .type = NLA_NESTED },
875};
876
e5497d76
JB
877/* policy for GTK rekey offload attributes */
878static const struct nla_policy
879nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = {
093a48d2
NE
880 [NL80211_REKEY_DATA_KEK] = {
881 .type = NLA_BINARY,
882 .len = NL80211_KEK_EXT_LEN
883 },
884 [NL80211_REKEY_DATA_KCK] = {
885 .type = NLA_BINARY,
886 .len = NL80211_KCK_EXT_LEN
887 },
cb9abd48 888 [NL80211_REKEY_DATA_REPLAY_CTR] = NLA_POLICY_EXACT_LEN(NL80211_REPLAY_CTR_LEN),
093a48d2 889 [NL80211_REKEY_DATA_AKM] = { .type = NLA_U32 },
e5497d76
JB
890};
891
1e1b11b6 892static const struct nla_policy
893nl80211_match_band_rssi_policy[NUM_NL80211_BANDS] = {
894 [NL80211_BAND_2GHZ] = { .type = NLA_S32 },
895 [NL80211_BAND_5GHZ] = { .type = NLA_S32 },
e548a1c3 896 [NL80211_BAND_6GHZ] = { .type = NLA_S32 },
1e1b11b6 897 [NL80211_BAND_60GHZ] = { .type = NLA_S32 },
63fa0426 898 [NL80211_BAND_LC] = { .type = NLA_S32 },
1e1b11b6 899};
900
a1f1c21c
LC
901static const struct nla_policy
902nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = {
4a4ab0d7 903 [NL80211_SCHED_SCAN_MATCH_ATTR_SSID] = { .type = NLA_BINARY,
a1f1c21c 904 .len = IEEE80211_MAX_SSID_LEN },
c7721c05 905 [NL80211_SCHED_SCAN_MATCH_ATTR_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
88e920b4 906 [NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] = { .type = NLA_U32 },
1e1b11b6 907 [NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI] =
908 NLA_POLICY_NESTED(nl80211_match_band_rssi_policy),
a1f1c21c
LC
909};
910
3b06d277
AS
911static const struct nla_policy
912nl80211_plan_policy[NL80211_SCHED_SCAN_PLAN_MAX + 1] = {
913 [NL80211_SCHED_SCAN_PLAN_INTERVAL] = { .type = NLA_U32 },
914 [NL80211_SCHED_SCAN_PLAN_ITERATIONS] = { .type = NLA_U32 },
915};
916
38de03d2
AS
917static const struct nla_policy
918nl80211_bss_select_policy[NL80211_BSS_SELECT_ATTR_MAX + 1] = {
919 [NL80211_BSS_SELECT_ATTR_RSSI] = { .type = NLA_FLAG },
920 [NL80211_BSS_SELECT_ATTR_BAND_PREF] = { .type = NLA_U32 },
921 [NL80211_BSS_SELECT_ATTR_RSSI_ADJUST] = {
922 .len = sizeof(struct nl80211_bss_select_rssi_adjust)
923 },
924};
925
a442b761
AB
926/* policy for NAN function attributes */
927static const struct nla_policy
928nl80211_nan_func_policy[NL80211_NAN_FUNC_ATTR_MAX + 1] = {
cb9abd48
JB
929 [NL80211_NAN_FUNC_TYPE] =
930 NLA_POLICY_MAX(NLA_U8, NL80211_NAN_FUNC_MAX_TYPE),
0a27844c 931 [NL80211_NAN_FUNC_SERVICE_ID] = {
a442b761
AB
932 .len = NL80211_NAN_FUNC_SERVICE_ID_LEN },
933 [NL80211_NAN_FUNC_PUBLISH_TYPE] = { .type = NLA_U8 },
934 [NL80211_NAN_FUNC_PUBLISH_BCAST] = { .type = NLA_FLAG },
935 [NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE] = { .type = NLA_FLAG },
936 [NL80211_NAN_FUNC_FOLLOW_UP_ID] = { .type = NLA_U8 },
937 [NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID] = { .type = NLA_U8 },
c7721c05 938 [NL80211_NAN_FUNC_FOLLOW_UP_DEST] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
a442b761
AB
939 [NL80211_NAN_FUNC_CLOSE_RANGE] = { .type = NLA_FLAG },
940 [NL80211_NAN_FUNC_TTL] = { .type = NLA_U32 },
941 [NL80211_NAN_FUNC_SERVICE_INFO] = { .type = NLA_BINARY,
942 .len = NL80211_NAN_FUNC_SERVICE_SPEC_INFO_MAX_LEN },
943 [NL80211_NAN_FUNC_SRF] = { .type = NLA_NESTED },
944 [NL80211_NAN_FUNC_RX_MATCH_FILTER] = { .type = NLA_NESTED },
945 [NL80211_NAN_FUNC_TX_MATCH_FILTER] = { .type = NLA_NESTED },
946 [NL80211_NAN_FUNC_INSTANCE_ID] = { .type = NLA_U8 },
947 [NL80211_NAN_FUNC_TERM_REASON] = { .type = NLA_U8 },
948};
949
950/* policy for Service Response Filter attributes */
951static const struct nla_policy
952nl80211_nan_srf_policy[NL80211_NAN_SRF_ATTR_MAX + 1] = {
953 [NL80211_NAN_SRF_INCLUDE] = { .type = NLA_FLAG },
954 [NL80211_NAN_SRF_BF] = { .type = NLA_BINARY,
955 .len = NL80211_NAN_FUNC_SRF_MAX_LEN },
956 [NL80211_NAN_SRF_BF_IDX] = { .type = NLA_U8 },
957 [NL80211_NAN_SRF_MAC_ADDRS] = { .type = NLA_NESTED },
958};
959
ad670233
PX
960/* policy for packet pattern attributes */
961static const struct nla_policy
962nl80211_packet_pattern_policy[MAX_NL80211_PKTPAT + 1] = {
963 [NL80211_PKTPAT_MASK] = { .type = NLA_BINARY, },
964 [NL80211_PKTPAT_PATTERN] = { .type = NLA_BINARY, },
965 [NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 },
966};
967
ce6b6974
JB
968static int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
969 struct cfg80211_registered_device **rdev,
970 struct wireless_dev **wdev,
971 struct nlattr **attrbuf)
a043897a 972{
97990a06 973 int err;
a043897a 974
97990a06 975 if (!cb->args[0]) {
ce6b6974
JB
976 struct nlattr **attrbuf_free = NULL;
977
978 if (!attrbuf) {
979 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf),
980 GFP_KERNEL);
981 if (!attrbuf)
982 return -ENOMEM;
983 attrbuf_free = attrbuf;
984 }
50508d94 985
8cb08174
JB
986 err = nlmsg_parse_deprecated(cb->nlh,
987 GENL_HDRLEN + nl80211_fam.hdrsize,
50508d94 988 attrbuf, nl80211_fam.maxattr,
8cb08174 989 nl80211_policy, NULL);
50508d94 990 if (err) {
ce6b6974 991 kfree(attrbuf_free);
ea90e0dc 992 return err;
50508d94 993 }
67748893 994
a05829a7
JB
995 rtnl_lock();
996 *wdev = __cfg80211_wdev_from_attrs(NULL, sock_net(cb->skb->sk),
50508d94 997 attrbuf);
ce6b6974 998 kfree(attrbuf_free);
a05829a7
JB
999 if (IS_ERR(*wdev)) {
1000 rtnl_unlock();
ea90e0dc 1001 return PTR_ERR(*wdev);
a05829a7 1002 }
f26cbf40 1003 *rdev = wiphy_to_rdev((*wdev)->wiphy);
a05829a7
JB
1004 mutex_lock(&(*rdev)->wiphy.mtx);
1005 rtnl_unlock();
c319d50b
JB
1006 /* 0 is the first index - add 1 to parse only once */
1007 cb->args[0] = (*rdev)->wiphy_idx + 1;
97990a06
JB
1008 cb->args[1] = (*wdev)->identifier;
1009 } else {
c319d50b 1010 /* subtract the 1 again here */
a05829a7 1011 struct wiphy *wiphy;
97990a06 1012 struct wireless_dev *tmp;
67748893 1013
a05829a7
JB
1014 rtnl_lock();
1015 wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
1016 if (!wiphy) {
1017 rtnl_unlock();
ea90e0dc 1018 return -ENODEV;
a05829a7 1019 }
f26cbf40 1020 *rdev = wiphy_to_rdev(wiphy);
97990a06 1021 *wdev = NULL;
67748893 1022
53873f13 1023 list_for_each_entry(tmp, &(*rdev)->wiphy.wdev_list, list) {
97990a06
JB
1024 if (tmp->identifier == cb->args[1]) {
1025 *wdev = tmp;
1026 break;
1027 }
1028 }
67748893 1029
a05829a7
JB
1030 if (!*wdev) {
1031 rtnl_unlock();
ea90e0dc 1032 return -ENODEV;
a05829a7
JB
1033 }
1034 mutex_lock(&(*rdev)->wiphy.mtx);
1035 rtnl_unlock();
67748893
JB
1036 }
1037
67748893 1038 return 0;
67748893
JB
1039}
1040
55682965 1041/* message building helper */
9bb7e0f2
JB
1042void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
1043 int flags, u8 cmd)
55682965
JB
1044{
1045 /* since there is no private header just add the generic one */
15e47304 1046 return genlmsg_put(skb, portid, seq, &nl80211_fam, flags, cmd);
55682965
JB
1047}
1048
50f32718
HD
1049static int nl80211_msg_put_wmm_rules(struct sk_buff *msg,
1050 const struct ieee80211_reg_rule *rule)
1051{
1052 int j;
1053 struct nlattr *nl_wmm_rules =
ae0be8de 1054 nla_nest_start_noflag(msg, NL80211_FREQUENCY_ATTR_WMM);
50f32718
HD
1055
1056 if (!nl_wmm_rules)
1057 goto nla_put_failure;
1058
1059 for (j = 0; j < IEEE80211_NUM_ACS; j++) {
ae0be8de 1060 struct nlattr *nl_wmm_rule = nla_nest_start_noflag(msg, j);
50f32718
HD
1061
1062 if (!nl_wmm_rule)
1063 goto nla_put_failure;
1064
1065 if (nla_put_u16(msg, NL80211_WMMR_CW_MIN,
38cb87ee 1066 rule->wmm_rule.client[j].cw_min) ||
50f32718 1067 nla_put_u16(msg, NL80211_WMMR_CW_MAX,
38cb87ee 1068 rule->wmm_rule.client[j].cw_max) ||
50f32718 1069 nla_put_u8(msg, NL80211_WMMR_AIFSN,
38cb87ee 1070 rule->wmm_rule.client[j].aifsn) ||
d3c89bbc
HD
1071 nla_put_u16(msg, NL80211_WMMR_TXOP,
1072 rule->wmm_rule.client[j].cot))
50f32718
HD
1073 goto nla_put_failure;
1074
1075 nla_nest_end(msg, nl_wmm_rule);
1076 }
1077 nla_nest_end(msg, nl_wmm_rules);
1078
1079 return 0;
1080
1081nla_put_failure:
1082 return -ENOBUFS;
1083}
1084
1085static int nl80211_msg_put_channel(struct sk_buff *msg, struct wiphy *wiphy,
cdc89b97
JB
1086 struct ieee80211_channel *chan,
1087 bool large)
5dab3b8a 1088{
ea077c1c
RL
1089 /* Some channels must be completely excluded from the
1090 * list to protect old user-space tools from breaking
1091 */
1092 if (!large && chan->flags &
1093 (IEEE80211_CHAN_NO_10MHZ | IEEE80211_CHAN_NO_20MHZ))
1094 return 0;
f8d504ca
JB
1095 if (!large && chan->freq_offset)
1096 return 0;
ea077c1c 1097
9360ffd1
DM
1098 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_FREQ,
1099 chan->center_freq))
1100 goto nla_put_failure;
5dab3b8a 1101
942ba88b
TP
1102 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_OFFSET, chan->freq_offset))
1103 goto nla_put_failure;
1104
9360ffd1
DM
1105 if ((chan->flags & IEEE80211_CHAN_DISABLED) &&
1106 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_DISABLED))
1107 goto nla_put_failure;
8fe02e16
LR
1108 if (chan->flags & IEEE80211_CHAN_NO_IR) {
1109 if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IR))
1110 goto nla_put_failure;
1111 if (nla_put_flag(msg, __NL80211_FREQUENCY_ATTR_NO_IBSS))
1112 goto nla_put_failure;
1113 }
cdc89b97
JB
1114 if (chan->flags & IEEE80211_CHAN_RADAR) {
1115 if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
1116 goto nla_put_failure;
1117 if (large) {
1118 u32 time;
1119
1120 time = elapsed_jiffies_msecs(chan->dfs_state_entered);
1121
1122 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_STATE,
1123 chan->dfs_state))
1124 goto nla_put_failure;
1125 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME,
1126 time))
1127 goto nla_put_failure;
089027e5
JD
1128 if (nla_put_u32(msg,
1129 NL80211_FREQUENCY_ATTR_DFS_CAC_TIME,
1130 chan->dfs_cac_ms))
1131 goto nla_put_failure;
cdc89b97
JB
1132 }
1133 }
5dab3b8a 1134
fe1abafd
JB
1135 if (large) {
1136 if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) &&
1137 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS))
1138 goto nla_put_failure;
1139 if ((chan->flags & IEEE80211_CHAN_NO_HT40PLUS) &&
1140 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_PLUS))
1141 goto nla_put_failure;
1142 if ((chan->flags & IEEE80211_CHAN_NO_80MHZ) &&
1143 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_80MHZ))
1144 goto nla_put_failure;
1145 if ((chan->flags & IEEE80211_CHAN_NO_160MHZ) &&
1146 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_160MHZ))
1147 goto nla_put_failure;
570dbde1
DS
1148 if ((chan->flags & IEEE80211_CHAN_INDOOR_ONLY) &&
1149 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_INDOOR_ONLY))
1150 goto nla_put_failure;
06f207fc
AN
1151 if ((chan->flags & IEEE80211_CHAN_IR_CONCURRENT) &&
1152 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_IR_CONCURRENT))
570dbde1 1153 goto nla_put_failure;
ea077c1c
RL
1154 if ((chan->flags & IEEE80211_CHAN_NO_20MHZ) &&
1155 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_20MHZ))
1156 goto nla_put_failure;
1157 if ((chan->flags & IEEE80211_CHAN_NO_10MHZ) &&
1158 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_10MHZ))
1159 goto nla_put_failure;
1e61d82c
HD
1160 if ((chan->flags & IEEE80211_CHAN_NO_HE) &&
1161 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HE))
1162 goto nla_put_failure;
d65a9770
TP
1163 if ((chan->flags & IEEE80211_CHAN_1MHZ) &&
1164 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_1MHZ))
1165 goto nla_put_failure;
1166 if ((chan->flags & IEEE80211_CHAN_2MHZ) &&
1167 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_2MHZ))
1168 goto nla_put_failure;
1169 if ((chan->flags & IEEE80211_CHAN_4MHZ) &&
1170 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_4MHZ))
1171 goto nla_put_failure;
1172 if ((chan->flags & IEEE80211_CHAN_8MHZ) &&
1173 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_8MHZ))
1174 goto nla_put_failure;
1175 if ((chan->flags & IEEE80211_CHAN_16MHZ) &&
1176 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_16MHZ))
1177 goto nla_put_failure;
c2b3d769
S
1178 if ((chan->flags & IEEE80211_CHAN_NO_320MHZ) &&
1179 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_320MHZ))
1180 goto nla_put_failure;
31846b65
IP
1181 if ((chan->flags & IEEE80211_CHAN_NO_EHT) &&
1182 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_EHT))
1183 goto nla_put_failure;
fe1abafd
JB
1184 }
1185
9360ffd1
DM
1186 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
1187 DBM_TO_MBM(chan->max_power)))
1188 goto nla_put_failure;
5dab3b8a 1189
50f32718
HD
1190 if (large) {
1191 const struct ieee80211_reg_rule *rule =
b88d26d9 1192 freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq));
50f32718 1193
38cb87ee 1194 if (!IS_ERR_OR_NULL(rule) && rule->has_wmm) {
50f32718
HD
1195 if (nl80211_msg_put_wmm_rules(msg, rule))
1196 goto nla_put_failure;
1197 }
1198 }
1199
5dab3b8a
LR
1200 return 0;
1201
1202 nla_put_failure:
1203 return -ENOBUFS;
1204}
1205
52539ca8
THJ
1206static bool nl80211_put_txq_stats(struct sk_buff *msg,
1207 struct cfg80211_txq_stats *txqstats,
1208 int attrtype)
1209{
1210 struct nlattr *txqattr;
1211
1212#define PUT_TXQVAL_U32(attr, memb) do { \
1213 if (txqstats->filled & BIT(NL80211_TXQ_STATS_ ## attr) && \
1214 nla_put_u32(msg, NL80211_TXQ_STATS_ ## attr, txqstats->memb)) \
1215 return false; \
1216 } while (0)
1217
ae0be8de 1218 txqattr = nla_nest_start_noflag(msg, attrtype);
52539ca8
THJ
1219 if (!txqattr)
1220 return false;
1221
1222 PUT_TXQVAL_U32(BACKLOG_BYTES, backlog_bytes);
1223 PUT_TXQVAL_U32(BACKLOG_PACKETS, backlog_packets);
1224 PUT_TXQVAL_U32(FLOWS, flows);
1225 PUT_TXQVAL_U32(DROPS, drops);
1226 PUT_TXQVAL_U32(ECN_MARKS, ecn_marks);
1227 PUT_TXQVAL_U32(OVERLIMIT, overlimit);
1228 PUT_TXQVAL_U32(OVERMEMORY, overmemory);
1229 PUT_TXQVAL_U32(COLLISIONS, collisions);
1230 PUT_TXQVAL_U32(TX_BYTES, tx_bytes);
1231 PUT_TXQVAL_U32(TX_PACKETS, tx_packets);
1232 PUT_TXQVAL_U32(MAX_FLOWS, max_flows);
1233 nla_nest_end(msg, txqattr);
1234
1235#undef PUT_TXQVAL_U32
1236 return true;
1237}
1238
55682965
JB
1239/* netlink command implementations */
1240
7b0a0e3c
JB
1241/**
1242 * nl80211_link_id - return link ID
1243 * @attrs: attributes to look at
1244 *
1245 * Returns: the link ID or 0 if not given
1246 *
1247 * Note this function doesn't do any validation of the link
1248 * ID validity wrt. links that were actually added, so it must
1249 * be called only from ops with %NL80211_FLAG_MLO_VALID_LINK_ID
1250 * or if additional validation is done.
1251 */
1252static unsigned int nl80211_link_id(struct nlattr **attrs)
1253{
1254 struct nlattr *linkid = attrs[NL80211_ATTR_MLO_LINK_ID];
1255
1256 if (!linkid)
1257 return 0;
1258
1259 return nla_get_u8(linkid);
1260}
1261
1262static int nl80211_link_id_or_invalid(struct nlattr **attrs)
1263{
1264 struct nlattr *linkid = attrs[NL80211_ATTR_MLO_LINK_ID];
1265
1266 if (!linkid)
1267 return -1;
1268
1269 return nla_get_u8(linkid);
1270}
1271
b9454e83
JB
1272struct key_parse {
1273 struct key_params p;
1274 int idx;
e31b8213 1275 int type;
56be393f 1276 bool def, defmgmt, defbeacon;
dbd2fd65 1277 bool def_uni, def_multi;
b9454e83
JB
1278};
1279
768075eb
JB
1280static int nl80211_parse_key_new(struct genl_info *info, struct nlattr *key,
1281 struct key_parse *k)
b9454e83
JB
1282{
1283 struct nlattr *tb[NL80211_KEY_MAX + 1];
8cb08174
JB
1284 int err = nla_parse_nested_deprecated(tb, NL80211_KEY_MAX, key,
1285 nl80211_key_policy,
1286 info->extack);
b9454e83
JB
1287 if (err)
1288 return err;
1289
1290 k->def = !!tb[NL80211_KEY_DEFAULT];
1291 k->defmgmt = !!tb[NL80211_KEY_DEFAULT_MGMT];
56be393f 1292 k->defbeacon = !!tb[NL80211_KEY_DEFAULT_BEACON];
b9454e83 1293
dbd2fd65
JB
1294 if (k->def) {
1295 k->def_uni = true;
1296 k->def_multi = true;
1297 }
56be393f 1298 if (k->defmgmt || k->defbeacon)
dbd2fd65
JB
1299 k->def_multi = true;
1300
b9454e83
JB
1301 if (tb[NL80211_KEY_IDX])
1302 k->idx = nla_get_u8(tb[NL80211_KEY_IDX]);
1303
1304 if (tb[NL80211_KEY_DATA]) {
1305 k->p.key = nla_data(tb[NL80211_KEY_DATA]);
1306 k->p.key_len = nla_len(tb[NL80211_KEY_DATA]);
1307 }
1308
1309 if (tb[NL80211_KEY_SEQ]) {
1310 k->p.seq = nla_data(tb[NL80211_KEY_SEQ]);
1311 k->p.seq_len = nla_len(tb[NL80211_KEY_SEQ]);
1312 }
1313
1314 if (tb[NL80211_KEY_CIPHER])
1315 k->p.cipher = nla_get_u32(tb[NL80211_KEY_CIPHER]);
1316
ab0d76f6 1317 if (tb[NL80211_KEY_TYPE])
e31b8213 1318 k->type = nla_get_u32(tb[NL80211_KEY_TYPE]);
e31b8213 1319
dbd2fd65
JB
1320 if (tb[NL80211_KEY_DEFAULT_TYPES]) {
1321 struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
7a087e74 1322
8cb08174
JB
1323 err = nla_parse_nested_deprecated(kdt,
1324 NUM_NL80211_KEY_DEFAULT_TYPES - 1,
1325 tb[NL80211_KEY_DEFAULT_TYPES],
1326 nl80211_key_default_policy,
1327 info->extack);
dbd2fd65
JB
1328 if (err)
1329 return err;
1330
1331 k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST];
1332 k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
1333 }
1334
6cdd3979
AW
1335 if (tb[NL80211_KEY_MODE])
1336 k->p.mode = nla_get_u8(tb[NL80211_KEY_MODE]);
1337
b9454e83
JB
1338 return 0;
1339}
1340
1341static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k)
1342{
1343 if (info->attrs[NL80211_ATTR_KEY_DATA]) {
1344 k->p.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]);
1345 k->p.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
1346 }
1347
1348 if (info->attrs[NL80211_ATTR_KEY_SEQ]) {
1349 k->p.seq = nla_data(info->attrs[NL80211_ATTR_KEY_SEQ]);
1350 k->p.seq_len = nla_len(info->attrs[NL80211_ATTR_KEY_SEQ]);
1351 }
1352
1353 if (info->attrs[NL80211_ATTR_KEY_IDX])
1354 k->idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
1355
1356 if (info->attrs[NL80211_ATTR_KEY_CIPHER])
1357 k->p.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);
1358
1359 k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT];
1360 k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT];
1361
dbd2fd65
JB
1362 if (k->def) {
1363 k->def_uni = true;
1364 k->def_multi = true;
1365 }
1366 if (k->defmgmt)
1367 k->def_multi = true;
1368
ab0d76f6 1369 if (info->attrs[NL80211_ATTR_KEY_TYPE])
e31b8213 1370 k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
e31b8213 1371
dbd2fd65
JB
1372 if (info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES]) {
1373 struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
8cb08174
JB
1374 int err = nla_parse_nested_deprecated(kdt,
1375 NUM_NL80211_KEY_DEFAULT_TYPES - 1,
1376 info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES],
1377 nl80211_key_default_policy,
1378 info->extack);
dbd2fd65
JB
1379 if (err)
1380 return err;
1381
1382 k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST];
1383 k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
1384 }
1385
b9454e83
JB
1386 return 0;
1387}
1388
1389static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)
1390{
1391 int err;
1392
1393 memset(k, 0, sizeof(*k));
1394 k->idx = -1;
e31b8213 1395 k->type = -1;
b9454e83
JB
1396
1397 if (info->attrs[NL80211_ATTR_KEY])
768075eb 1398 err = nl80211_parse_key_new(info, info->attrs[NL80211_ATTR_KEY], k);
b9454e83
JB
1399 else
1400 err = nl80211_parse_key_old(info, k);
1401
1402 if (err)
1403 return err;
1404
56be393f
JM
1405 if ((k->def ? 1 : 0) + (k->defmgmt ? 1 : 0) +
1406 (k->defbeacon ? 1 : 0) > 1) {
1407 GENL_SET_ERR_MSG(info,
1408 "key with multiple default flags is invalid");
b9454e83 1409 return -EINVAL;
768075eb 1410 }
b9454e83 1411
56be393f 1412 if (k->defmgmt || k->defbeacon) {
768075eb 1413 if (k->def_uni || !k->def_multi) {
56be393f
JM
1414 GENL_SET_ERR_MSG(info,
1415 "defmgmt/defbeacon key must be mcast");
dbd2fd65 1416 return -EINVAL;
768075eb 1417 }
dbd2fd65
JB
1418 }
1419
b9454e83
JB
1420 if (k->idx != -1) {
1421 if (k->defmgmt) {
768075eb
JB
1422 if (k->idx < 4 || k->idx > 5) {
1423 GENL_SET_ERR_MSG(info,
1424 "defmgmt key idx not 4 or 5");
b9454e83 1425 return -EINVAL;
768075eb 1426 }
56be393f
JM
1427 } else if (k->defbeacon) {
1428 if (k->idx < 6 || k->idx > 7) {
1429 GENL_SET_ERR_MSG(info,
1430 "defbeacon key idx not 6 or 7");
1431 return -EINVAL;
1432 }
b9454e83 1433 } else if (k->def) {
768075eb
JB
1434 if (k->idx < 0 || k->idx > 3) {
1435 GENL_SET_ERR_MSG(info, "def key idx not 0-3");
b9454e83 1436 return -EINVAL;
768075eb 1437 }
b9454e83 1438 } else {
56be393f
JM
1439 if (k->idx < 0 || k->idx > 7) {
1440 GENL_SET_ERR_MSG(info, "key idx not 0-7");
b9454e83 1441 return -EINVAL;
768075eb 1442 }
b9454e83
JB
1443 }
1444 }
1445
1446 return 0;
1447}
1448
fffd0934
JB
1449static struct cfg80211_cached_keys *
1450nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
768075eb 1451 struct genl_info *info, bool *no_ht)
fffd0934 1452{
768075eb 1453 struct nlattr *keys = info->attrs[NL80211_ATTR_KEYS];
fffd0934
JB
1454 struct key_parse parse;
1455 struct nlattr *key;
1456 struct cfg80211_cached_keys *result;
1457 int rem, err, def = 0;
f1c1f17a
JB
1458 bool have_key = false;
1459
1460 nla_for_each_nested(key, keys, rem) {
1461 have_key = true;
1462 break;
1463 }
1464
1465 if (!have_key)
1466 return NULL;
fffd0934
JB
1467
1468 result = kzalloc(sizeof(*result), GFP_KERNEL);
1469 if (!result)
1470 return ERR_PTR(-ENOMEM);
1471
1472 result->def = -1;
fffd0934
JB
1473
1474 nla_for_each_nested(key, keys, rem) {
1475 memset(&parse, 0, sizeof(parse));
1476 parse.idx = -1;
1477
768075eb 1478 err = nl80211_parse_key_new(info, key, &parse);
fffd0934
JB
1479 if (err)
1480 goto error;
1481 err = -EINVAL;
1482 if (!parse.p.key)
1483 goto error;
768075eb
JB
1484 if (parse.idx < 0 || parse.idx > 3) {
1485 GENL_SET_ERR_MSG(info, "key index out of range [0-3]");
fffd0934 1486 goto error;
768075eb 1487 }
fffd0934 1488 if (parse.def) {
768075eb
JB
1489 if (def) {
1490 GENL_SET_ERR_MSG(info,
1491 "only one key can be default");
fffd0934 1492 goto error;
768075eb 1493 }
fffd0934
JB
1494 def = 1;
1495 result->def = parse.idx;
dbd2fd65
JB
1496 if (!parse.def_uni || !parse.def_multi)
1497 goto error;
fffd0934
JB
1498 } else if (parse.defmgmt)
1499 goto error;
1500 err = cfg80211_validate_key_settings(rdev, &parse.p,
e31b8213 1501 parse.idx, false, NULL);
fffd0934
JB
1502 if (err)
1503 goto error;
386b1f27
JB
1504 if (parse.p.cipher != WLAN_CIPHER_SUITE_WEP40 &&
1505 parse.p.cipher != WLAN_CIPHER_SUITE_WEP104) {
768075eb 1506 GENL_SET_ERR_MSG(info, "connect key must be WEP");
386b1f27
JB
1507 err = -EINVAL;
1508 goto error;
1509 }
fffd0934
JB
1510 result->params[parse.idx].cipher = parse.p.cipher;
1511 result->params[parse.idx].key_len = parse.p.key_len;
1512 result->params[parse.idx].key = result->data[parse.idx];
1513 memcpy(result->data[parse.idx], parse.p.key, parse.p.key_len);
de7044ee 1514
386b1f27
JB
1515 /* must be WEP key if we got here */
1516 if (no_ht)
1517 *no_ht = true;
fffd0934
JB
1518 }
1519
f1c1f17a
JB
1520 if (result->def < 0) {
1521 err = -EINVAL;
768075eb 1522 GENL_SET_ERR_MSG(info, "need a default/TX key");
f1c1f17a
JB
1523 goto error;
1524 }
1525
fffd0934
JB
1526 return result;
1527 error:
1528 kfree(result);
1529 return ERR_PTR(err);
1530}
1531
1532static int nl80211_key_allowed(struct wireless_dev *wdev)
1533{
1534 ASSERT_WDEV_LOCK(wdev);
1535
fffd0934
JB
1536 switch (wdev->iftype) {
1537 case NL80211_IFTYPE_AP:
1538 case NL80211_IFTYPE_AP_VLAN:
074ac8df 1539 case NL80211_IFTYPE_P2P_GO:
ff973af7 1540 case NL80211_IFTYPE_MESH_POINT:
fffd0934
JB
1541 break;
1542 case NL80211_IFTYPE_ADHOC:
7b0a0e3c
JB
1543 if (wdev->u.ibss.current_bss)
1544 return 0;
1545 return -ENOLINK;
fffd0934 1546 case NL80211_IFTYPE_STATION:
074ac8df 1547 case NL80211_IFTYPE_P2P_CLIENT:
7b0a0e3c
JB
1548 if (wdev->connected)
1549 return 0;
1550 return -ENOLINK;
de4fcbad 1551 case NL80211_IFTYPE_UNSPECIFIED:
6e0bd6c3 1552 case NL80211_IFTYPE_OCB:
de4fcbad 1553 case NL80211_IFTYPE_MONITOR:
cb3b7d87 1554 case NL80211_IFTYPE_NAN:
de4fcbad
JB
1555 case NL80211_IFTYPE_P2P_DEVICE:
1556 case NL80211_IFTYPE_WDS:
1557 case NUM_NL80211_IFTYPES:
fffd0934
JB
1558 return -EINVAL;
1559 }
1560
1561 return 0;
1562}
1563
664834de 1564static struct ieee80211_channel *nl80211_get_valid_chan(struct wiphy *wiphy,
942ba88b 1565 u32 freq)
664834de
JM
1566{
1567 struct ieee80211_channel *chan;
1568
942ba88b 1569 chan = ieee80211_get_channel_khz(wiphy, freq);
664834de
JM
1570 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
1571 return NULL;
1572 return chan;
1573}
1574
7527a782
JB
1575static int nl80211_put_iftypes(struct sk_buff *msg, u32 attr, u16 ifmodes)
1576{
ae0be8de 1577 struct nlattr *nl_modes = nla_nest_start_noflag(msg, attr);
7527a782
JB
1578 int i;
1579
1580 if (!nl_modes)
1581 goto nla_put_failure;
1582
1583 i = 0;
1584 while (ifmodes) {
9360ffd1
DM
1585 if ((ifmodes & 1) && nla_put_flag(msg, i))
1586 goto nla_put_failure;
7527a782
JB
1587 ifmodes >>= 1;
1588 i++;
1589 }
1590
1591 nla_nest_end(msg, nl_modes);
1592 return 0;
1593
1594nla_put_failure:
1595 return -ENOBUFS;
1596}
1597
1598static int nl80211_put_iface_combinations(struct wiphy *wiphy,
cdc89b97
JB
1599 struct sk_buff *msg,
1600 bool large)
7527a782
JB
1601{
1602 struct nlattr *nl_combis;
1603 int i, j;
1604
ae0be8de
MK
1605 nl_combis = nla_nest_start_noflag(msg,
1606 NL80211_ATTR_INTERFACE_COMBINATIONS);
7527a782
JB
1607 if (!nl_combis)
1608 goto nla_put_failure;
1609
1610 for (i = 0; i < wiphy->n_iface_combinations; i++) {
1611 const struct ieee80211_iface_combination *c;
1612 struct nlattr *nl_combi, *nl_limits;
1613
1614 c = &wiphy->iface_combinations[i];
1615
ae0be8de 1616 nl_combi = nla_nest_start_noflag(msg, i + 1);
7527a782
JB
1617 if (!nl_combi)
1618 goto nla_put_failure;
1619
ae0be8de
MK
1620 nl_limits = nla_nest_start_noflag(msg,
1621 NL80211_IFACE_COMB_LIMITS);
7527a782
JB
1622 if (!nl_limits)
1623 goto nla_put_failure;
1624
1625 for (j = 0; j < c->n_limits; j++) {
1626 struct nlattr *nl_limit;
1627
ae0be8de 1628 nl_limit = nla_nest_start_noflag(msg, j + 1);
7527a782
JB
1629 if (!nl_limit)
1630 goto nla_put_failure;
9360ffd1
DM
1631 if (nla_put_u32(msg, NL80211_IFACE_LIMIT_MAX,
1632 c->limits[j].max))
1633 goto nla_put_failure;
7527a782
JB
1634 if (nl80211_put_iftypes(msg, NL80211_IFACE_LIMIT_TYPES,
1635 c->limits[j].types))
1636 goto nla_put_failure;
1637 nla_nest_end(msg, nl_limit);
1638 }
1639
1640 nla_nest_end(msg, nl_limits);
1641
9360ffd1
DM
1642 if (c->beacon_int_infra_match &&
1643 nla_put_flag(msg, NL80211_IFACE_COMB_STA_AP_BI_MATCH))
1644 goto nla_put_failure;
1645 if (nla_put_u32(msg, NL80211_IFACE_COMB_NUM_CHANNELS,
1646 c->num_different_channels) ||
1647 nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM,
1648 c->max_interfaces))
1649 goto nla_put_failure;
cdc89b97 1650 if (large &&
8c48b50a
FF
1651 (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
1652 c->radar_detect_widths) ||
1653 nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
1654 c->radar_detect_regions)))
cdc89b97 1655 goto nla_put_failure;
0c317a02
PK
1656 if (c->beacon_int_min_gcd &&
1657 nla_put_u32(msg, NL80211_IFACE_COMB_BI_MIN_GCD,
1658 c->beacon_int_min_gcd))
1659 goto nla_put_failure;
7527a782
JB
1660
1661 nla_nest_end(msg, nl_combi);
1662 }
1663
1664 nla_nest_end(msg, nl_combis);
1665
1666 return 0;
1667nla_put_failure:
1668 return -ENOBUFS;
1669}
1670
3713b4e3 1671#ifdef CONFIG_PM
b56cf720
JB
1672static int nl80211_send_wowlan_tcp_caps(struct cfg80211_registered_device *rdev,
1673 struct sk_buff *msg)
1674{
964dc9e2 1675 const struct wiphy_wowlan_tcp_support *tcp = rdev->wiphy.wowlan->tcp;
b56cf720
JB
1676 struct nlattr *nl_tcp;
1677
1678 if (!tcp)
1679 return 0;
1680
ae0be8de
MK
1681 nl_tcp = nla_nest_start_noflag(msg,
1682 NL80211_WOWLAN_TRIG_TCP_CONNECTION);
b56cf720
JB
1683 if (!nl_tcp)
1684 return -ENOBUFS;
1685
1686 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
1687 tcp->data_payload_max))
1688 return -ENOBUFS;
1689
1690 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
1691 tcp->data_payload_max))
1692 return -ENOBUFS;
1693
1694 if (tcp->seq && nla_put_flag(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ))
1695 return -ENOBUFS;
1696
1697 if (tcp->tok && nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
1698 sizeof(*tcp->tok), tcp->tok))
1699 return -ENOBUFS;
1700
1701 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
1702 tcp->data_interval_max))
1703 return -ENOBUFS;
1704
1705 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
1706 tcp->wake_payload_max))
1707 return -ENOBUFS;
1708
1709 nla_nest_end(msg, nl_tcp);
1710 return 0;
1711}
1712
3713b4e3 1713static int nl80211_send_wowlan(struct sk_buff *msg,
1b8ec87a 1714 struct cfg80211_registered_device *rdev,
b56cf720 1715 bool large)
55682965 1716{
3713b4e3 1717 struct nlattr *nl_wowlan;
55682965 1718
1b8ec87a 1719 if (!rdev->wiphy.wowlan)
3713b4e3 1720 return 0;
55682965 1721
ae0be8de
MK
1722 nl_wowlan = nla_nest_start_noflag(msg,
1723 NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED);
3713b4e3
JB
1724 if (!nl_wowlan)
1725 return -ENOBUFS;
9360ffd1 1726
1b8ec87a 1727 if (((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_ANY) &&
3713b4e3 1728 nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
1b8ec87a 1729 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_DISCONNECT) &&
3713b4e3 1730 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
1b8ec87a 1731 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT) &&
3713b4e3 1732 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
1b8ec87a 1733 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) &&
3713b4e3 1734 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED)) ||
1b8ec87a 1735 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
3713b4e3 1736 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
1b8ec87a 1737 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) &&
3713b4e3 1738 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
1b8ec87a 1739 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) &&
3713b4e3 1740 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
1b8ec87a 1741 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE) &&
3713b4e3
JB
1742 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
1743 return -ENOBUFS;
9360ffd1 1744
1b8ec87a 1745 if (rdev->wiphy.wowlan->n_patterns) {
50ac6607 1746 struct nl80211_pattern_support pat = {
1b8ec87a
ZG
1747 .max_patterns = rdev->wiphy.wowlan->n_patterns,
1748 .min_pattern_len = rdev->wiphy.wowlan->pattern_min_len,
1749 .max_pattern_len = rdev->wiphy.wowlan->pattern_max_len,
1750 .max_pkt_offset = rdev->wiphy.wowlan->max_pkt_offset,
3713b4e3 1751 };
9360ffd1 1752
3713b4e3
JB
1753 if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
1754 sizeof(pat), &pat))
1755 return -ENOBUFS;
1756 }
9360ffd1 1757
75453ccb
LC
1758 if ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_NET_DETECT) &&
1759 nla_put_u32(msg, NL80211_WOWLAN_TRIG_NET_DETECT,
1760 rdev->wiphy.wowlan->max_nd_match_sets))
1761 return -ENOBUFS;
1762
1b8ec87a 1763 if (large && nl80211_send_wowlan_tcp_caps(rdev, msg))
b56cf720
JB
1764 return -ENOBUFS;
1765
3713b4e3 1766 nla_nest_end(msg, nl_wowlan);
9360ffd1 1767
3713b4e3
JB
1768 return 0;
1769}
1770#endif
9360ffd1 1771
be29b99a 1772static int nl80211_send_coalesce(struct sk_buff *msg,
1b8ec87a 1773 struct cfg80211_registered_device *rdev)
be29b99a
AK
1774{
1775 struct nl80211_coalesce_rule_support rule;
1776
1b8ec87a 1777 if (!rdev->wiphy.coalesce)
be29b99a
AK
1778 return 0;
1779
1b8ec87a
ZG
1780 rule.max_rules = rdev->wiphy.coalesce->n_rules;
1781 rule.max_delay = rdev->wiphy.coalesce->max_delay;
1782 rule.pat.max_patterns = rdev->wiphy.coalesce->n_patterns;
1783 rule.pat.min_pattern_len = rdev->wiphy.coalesce->pattern_min_len;
1784 rule.pat.max_pattern_len = rdev->wiphy.coalesce->pattern_max_len;
1785 rule.pat.max_pkt_offset = rdev->wiphy.coalesce->max_pkt_offset;
be29b99a
AK
1786
1787 if (nla_put(msg, NL80211_ATTR_COALESCE_RULE, sizeof(rule), &rule))
1788 return -ENOBUFS;
1789
1790 return 0;
1791}
1792
c4cbaf79
LC
1793static int
1794nl80211_send_iftype_data(struct sk_buff *msg,
22395217 1795 const struct ieee80211_supported_band *sband,
c4cbaf79
LC
1796 const struct ieee80211_sband_iftype_data *iftdata)
1797{
1798 const struct ieee80211_sta_he_cap *he_cap = &iftdata->he_cap;
5cd5a8a3 1799 const struct ieee80211_sta_eht_cap *eht_cap = &iftdata->eht_cap;
c4cbaf79
LC
1800
1801 if (nl80211_put_iftypes(msg, NL80211_BAND_IFTYPE_ATTR_IFTYPES,
1802 iftdata->types_mask))
1803 return -ENOBUFS;
1804
1805 if (he_cap->has_he) {
1806 if (nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC,
1807 sizeof(he_cap->he_cap_elem.mac_cap_info),
1808 he_cap->he_cap_elem.mac_cap_info) ||
1809 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY,
1810 sizeof(he_cap->he_cap_elem.phy_cap_info),
1811 he_cap->he_cap_elem.phy_cap_info) ||
1812 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET,
1813 sizeof(he_cap->he_mcs_nss_supp),
1814 &he_cap->he_mcs_nss_supp) ||
1815 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE,
1816 sizeof(he_cap->ppe_thres), he_cap->ppe_thres))
1817 return -ENOBUFS;
1818 }
1819
5cd5a8a3
IP
1820 if (eht_cap->has_eht && he_cap->has_he) {
1821 u8 mcs_nss_size, ppe_thresh_size;
1822 u16 ppe_thres_hdr;
ea5cba26
JB
1823 bool is_ap;
1824
1825 is_ap = iftdata->types_mask & BIT(NL80211_IFTYPE_AP) ||
1826 iftdata->types_mask & BIT(NL80211_IFTYPE_P2P_GO);
5cd5a8a3
IP
1827
1828 mcs_nss_size =
1829 ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem,
ea5cba26
JB
1830 &eht_cap->eht_cap_elem,
1831 is_ap);
5cd5a8a3
IP
1832
1833 ppe_thres_hdr = get_unaligned_le16(&eht_cap->eht_ppe_thres[0]);
1834 ppe_thresh_size =
1835 ieee80211_eht_ppe_size(ppe_thres_hdr,
1836 eht_cap->eht_cap_elem.phy_cap_info);
1837
1838 if (nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC,
1839 sizeof(eht_cap->eht_cap_elem.mac_cap_info),
1840 eht_cap->eht_cap_elem.mac_cap_info) ||
1841 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY,
1842 sizeof(eht_cap->eht_cap_elem.phy_cap_info),
1843 eht_cap->eht_cap_elem.phy_cap_info) ||
1844 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET,
1845 mcs_nss_size, &eht_cap->eht_mcs_nss_supp) ||
1846 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE,
1847 ppe_thresh_size, eht_cap->eht_ppe_thres))
1848 return -ENOBUFS;
1849 }
1850
22395217
JB
1851 if (sband->band == NL80211_BAND_6GHZ &&
1852 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA,
1853 sizeof(iftdata->he_6ghz_capa),
1854 &iftdata->he_6ghz_capa))
1855 return -ENOBUFS;
1856
f4f86505
JB
1857 if (iftdata->vendor_elems.data && iftdata->vendor_elems.len &&
1858 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS,
1859 iftdata->vendor_elems.len, iftdata->vendor_elems.data))
1860 return -ENOBUFS;
1861
c4cbaf79
LC
1862 return 0;
1863}
1864
3713b4e3 1865static int nl80211_send_band_rateinfo(struct sk_buff *msg,
f8d504ca
JB
1866 struct ieee80211_supported_band *sband,
1867 bool large)
3713b4e3
JB
1868{
1869 struct nlattr *nl_rates, *nl_rate;
1870 struct ieee80211_rate *rate;
1871 int i;
87bbbe22 1872
3713b4e3
JB
1873 /* add HT info */
1874 if (sband->ht_cap.ht_supported &&
1875 (nla_put(msg, NL80211_BAND_ATTR_HT_MCS_SET,
1876 sizeof(sband->ht_cap.mcs),
1877 &sband->ht_cap.mcs) ||
1878 nla_put_u16(msg, NL80211_BAND_ATTR_HT_CAPA,
1879 sband->ht_cap.cap) ||
1880 nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR,
1881 sband->ht_cap.ampdu_factor) ||
1882 nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
1883 sband->ht_cap.ampdu_density)))
1884 return -ENOBUFS;
afe0cbf8 1885
3713b4e3
JB
1886 /* add VHT info */
1887 if (sband->vht_cap.vht_supported &&
1888 (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET,
1889 sizeof(sband->vht_cap.vht_mcs),
1890 &sband->vht_cap.vht_mcs) ||
1891 nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA,
1892 sband->vht_cap.cap)))
1893 return -ENOBUFS;
f59ac048 1894
f8d504ca 1895 if (large && sband->n_iftype_data) {
c4cbaf79 1896 struct nlattr *nl_iftype_data =
ae0be8de
MK
1897 nla_nest_start_noflag(msg,
1898 NL80211_BAND_ATTR_IFTYPE_DATA);
c4cbaf79
LC
1899 int err;
1900
1901 if (!nl_iftype_data)
1902 return -ENOBUFS;
1903
1904 for (i = 0; i < sband->n_iftype_data; i++) {
1905 struct nlattr *iftdata;
1906
ae0be8de 1907 iftdata = nla_nest_start_noflag(msg, i + 1);
c4cbaf79
LC
1908 if (!iftdata)
1909 return -ENOBUFS;
1910
22395217 1911 err = nl80211_send_iftype_data(msg, sband,
c4cbaf79
LC
1912 &sband->iftype_data[i]);
1913 if (err)
1914 return err;
1915
1916 nla_nest_end(msg, iftdata);
1917 }
1918
1919 nla_nest_end(msg, nl_iftype_data);
1920 }
1921
2a38075c 1922 /* add EDMG info */
f8d504ca 1923 if (large && sband->edmg_cap.channels &&
2a38075c
AAL
1924 (nla_put_u8(msg, NL80211_BAND_ATTR_EDMG_CHANNELS,
1925 sband->edmg_cap.channels) ||
1926 nla_put_u8(msg, NL80211_BAND_ATTR_EDMG_BW_CONFIG,
1927 sband->edmg_cap.bw_config)))
1928
1929 return -ENOBUFS;
1930
3713b4e3 1931 /* add bitrates */
ae0be8de 1932 nl_rates = nla_nest_start_noflag(msg, NL80211_BAND_ATTR_RATES);
3713b4e3
JB
1933 if (!nl_rates)
1934 return -ENOBUFS;
ee688b00 1935
3713b4e3 1936 for (i = 0; i < sband->n_bitrates; i++) {
ae0be8de 1937 nl_rate = nla_nest_start_noflag(msg, i);
3713b4e3
JB
1938 if (!nl_rate)
1939 return -ENOBUFS;
ee688b00 1940
3713b4e3
JB
1941 rate = &sband->bitrates[i];
1942 if (nla_put_u32(msg, NL80211_BITRATE_ATTR_RATE,
1943 rate->bitrate))
1944 return -ENOBUFS;
1945 if ((rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) &&
1946 nla_put_flag(msg,
1947 NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE))
1948 return -ENOBUFS;
ee688b00 1949
3713b4e3
JB
1950 nla_nest_end(msg, nl_rate);
1951 }
d51626df 1952
3713b4e3 1953 nla_nest_end(msg, nl_rates);
bf0c111e 1954
3713b4e3
JB
1955 return 0;
1956}
ee688b00 1957
3713b4e3
JB
1958static int
1959nl80211_send_mgmt_stypes(struct sk_buff *msg,
1960 const struct ieee80211_txrx_stypes *mgmt_stypes)
1961{
1962 u16 stypes;
1963 struct nlattr *nl_ftypes, *nl_ifs;
1964 enum nl80211_iftype ift;
1965 int i;
ee688b00 1966
3713b4e3
JB
1967 if (!mgmt_stypes)
1968 return 0;
5dab3b8a 1969
ae0be8de 1970 nl_ifs = nla_nest_start_noflag(msg, NL80211_ATTR_TX_FRAME_TYPES);
3713b4e3
JB
1971 if (!nl_ifs)
1972 return -ENOBUFS;
e2f367f2 1973
3713b4e3 1974 for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
ae0be8de 1975 nl_ftypes = nla_nest_start_noflag(msg, ift);
3713b4e3
JB
1976 if (!nl_ftypes)
1977 return -ENOBUFS;
1978 i = 0;
1979 stypes = mgmt_stypes[ift].tx;
1980 while (stypes) {
1981 if ((stypes & 1) &&
1982 nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
1983 (i << 4) | IEEE80211_FTYPE_MGMT))
1984 return -ENOBUFS;
1985 stypes >>= 1;
1986 i++;
ee688b00 1987 }
3713b4e3
JB
1988 nla_nest_end(msg, nl_ftypes);
1989 }
ee688b00 1990
3713b4e3 1991 nla_nest_end(msg, nl_ifs);
ee688b00 1992
ae0be8de 1993 nl_ifs = nla_nest_start_noflag(msg, NL80211_ATTR_RX_FRAME_TYPES);
3713b4e3
JB
1994 if (!nl_ifs)
1995 return -ENOBUFS;
ee688b00 1996
3713b4e3 1997 for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
ae0be8de 1998 nl_ftypes = nla_nest_start_noflag(msg, ift);
3713b4e3
JB
1999 if (!nl_ftypes)
2000 return -ENOBUFS;
2001 i = 0;
2002 stypes = mgmt_stypes[ift].rx;
2003 while (stypes) {
2004 if ((stypes & 1) &&
2005 nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
2006 (i << 4) | IEEE80211_FTYPE_MGMT))
2007 return -ENOBUFS;
2008 stypes >>= 1;
2009 i++;
2010 }
2011 nla_nest_end(msg, nl_ftypes);
2012 }
2013 nla_nest_end(msg, nl_ifs);
ee688b00 2014
3713b4e3
JB
2015 return 0;
2016}
ee688b00 2017
1794899e
JB
2018#define CMD(op, n) \
2019 do { \
2020 if (rdev->ops->op) { \
2021 i++; \
2022 if (nla_put_u32(msg, i, NL80211_CMD_ ## n)) \
2023 goto nla_put_failure; \
2024 } \
2025 } while (0)
2026
2027static int nl80211_add_commands_unsplit(struct cfg80211_registered_device *rdev,
2028 struct sk_buff *msg)
2029{
2030 int i = 0;
2031
2032 /*
2033 * do *NOT* add anything into this function, new things need to be
2034 * advertised only to new versions of userspace that can deal with
2035 * the split (and they can't possibly care about new features...
2036 */
2037 CMD(add_virtual_intf, NEW_INTERFACE);
2038 CMD(change_virtual_intf, SET_INTERFACE);
2039 CMD(add_key, NEW_KEY);
2040 CMD(start_ap, START_AP);
2041 CMD(add_station, NEW_STATION);
2042 CMD(add_mpath, NEW_MPATH);
2043 CMD(update_mesh_config, SET_MESH_CONFIG);
2044 CMD(change_bss, SET_BSS);
2045 CMD(auth, AUTHENTICATE);
2046 CMD(assoc, ASSOCIATE);
2047 CMD(deauth, DEAUTHENTICATE);
2048 CMD(disassoc, DISASSOCIATE);
2049 CMD(join_ibss, JOIN_IBSS);
2050 CMD(join_mesh, JOIN_MESH);
2051 CMD(set_pmksa, SET_PMKSA);
2052 CMD(del_pmksa, DEL_PMKSA);
2053 CMD(flush_pmksa, FLUSH_PMKSA);
2054 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)
2055 CMD(remain_on_channel, REMAIN_ON_CHANNEL);
2056 CMD(set_bitrate_mask, SET_TX_BITRATE_MASK);
2057 CMD(mgmt_tx, FRAME);
2058 CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL);
2059 if (rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
2060 i++;
2061 if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS))
2062 goto nla_put_failure;
2063 }
2064 if (rdev->ops->set_monitor_channel || rdev->ops->start_ap ||
2065 rdev->ops->join_mesh) {
2066 i++;
2067 if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL))
2068 goto nla_put_failure;
2069 }
1794899e
JB
2070 if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) {
2071 CMD(tdls_mgmt, TDLS_MGMT);
2072 CMD(tdls_oper, TDLS_OPER);
2073 }
ca986ad9 2074 if (rdev->wiphy.max_sched_scan_reqs)
1794899e
JB
2075 CMD(sched_scan_start, START_SCHED_SCAN);
2076 CMD(probe_client, PROBE_CLIENT);
2077 CMD(set_noack_map, SET_NOACK_MAP);
2078 if (rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) {
2079 i++;
2080 if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS))
2081 goto nla_put_failure;
2082 }
2083 CMD(start_p2p_device, START_P2P_DEVICE);
2084 CMD(set_mcast_rate, SET_MCAST_RATE);
2085#ifdef CONFIG_NL80211_TESTMODE
2086 CMD(testmode_cmd, TESTMODE);
2087#endif
2088
2089 if (rdev->ops->connect || rdev->ops->auth) {
2090 i++;
2091 if (nla_put_u32(msg, i, NL80211_CMD_CONNECT))
2092 goto nla_put_failure;
2093 }
2094
2095 if (rdev->ops->disconnect || rdev->ops->deauth) {
2096 i++;
2097 if (nla_put_u32(msg, i, NL80211_CMD_DISCONNECT))
2098 goto nla_put_failure;
2099 }
2100
2101 return i;
2102 nla_put_failure:
2103 return -ENOBUFS;
2104}
2105
9bb7e0f2
JB
2106static int
2107nl80211_send_pmsr_ftm_capa(const struct cfg80211_pmsr_capabilities *cap,
2108 struct sk_buff *msg)
2109{
2110 struct nlattr *ftm;
2111
2112 if (!cap->ftm.supported)
2113 return 0;
2114
ae0be8de 2115 ftm = nla_nest_start_noflag(msg, NL80211_PMSR_TYPE_FTM);
9bb7e0f2
JB
2116 if (!ftm)
2117 return -ENOBUFS;
2118
2119 if (cap->ftm.asap && nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_ASAP))
2120 return -ENOBUFS;
2121 if (cap->ftm.non_asap &&
2122 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_NON_ASAP))
2123 return -ENOBUFS;
2124 if (cap->ftm.request_lci &&
2125 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_REQ_LCI))
2126 return -ENOBUFS;
2127 if (cap->ftm.request_civicloc &&
2128 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_REQ_CIVICLOC))
2129 return -ENOBUFS;
2130 if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES,
2131 cap->ftm.preambles))
2132 return -ENOBUFS;
2133 if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS,
2134 cap->ftm.bandwidths))
2135 return -ENOBUFS;
2136 if (cap->ftm.max_bursts_exponent >= 0 &&
2137 nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT,
2138 cap->ftm.max_bursts_exponent))
2139 return -ENOBUFS;
2140 if (cap->ftm.max_ftms_per_burst &&
2141 nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST,
2142 cap->ftm.max_ftms_per_burst))
2143 return -ENOBUFS;
efb5520d
AS
2144 if (cap->ftm.trigger_based &&
2145 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED))
2146 return -ENOBUFS;
2147 if (cap->ftm.non_trigger_based &&
2148 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED))
2149 return -ENOBUFS;
9bb7e0f2
JB
2150
2151 nla_nest_end(msg, ftm);
2152 return 0;
2153}
2154
2155static int nl80211_send_pmsr_capa(struct cfg80211_registered_device *rdev,
2156 struct sk_buff *msg)
2157{
2158 const struct cfg80211_pmsr_capabilities *cap = rdev->wiphy.pmsr_capa;
2159 struct nlattr *pmsr, *caps;
2160
2161 if (!cap)
2162 return 0;
2163
2164 /*
2165 * we don't need to clean up anything here since the caller
2166 * will genlmsg_cancel() if we fail
2167 */
2168
ae0be8de 2169 pmsr = nla_nest_start_noflag(msg, NL80211_ATTR_PEER_MEASUREMENTS);
9bb7e0f2
JB
2170 if (!pmsr)
2171 return -ENOBUFS;
2172
2173 if (nla_put_u32(msg, NL80211_PMSR_ATTR_MAX_PEERS, cap->max_peers))
2174 return -ENOBUFS;
2175
2176 if (cap->report_ap_tsf &&
2177 nla_put_flag(msg, NL80211_PMSR_ATTR_REPORT_AP_TSF))
2178 return -ENOBUFS;
2179
2180 if (cap->randomize_mac_addr &&
2181 nla_put_flag(msg, NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR))
2182 return -ENOBUFS;
2183
ae0be8de 2184 caps = nla_nest_start_noflag(msg, NL80211_PMSR_ATTR_TYPE_CAPA);
9bb7e0f2
JB
2185 if (!caps)
2186 return -ENOBUFS;
2187
2188 if (nl80211_send_pmsr_ftm_capa(cap, msg))
2189 return -ENOBUFS;
2190
2191 nla_nest_end(msg, caps);
2192 nla_nest_end(msg, pmsr);
2193
2194 return 0;
2195}
2196
d6039a34
VJ
2197static int
2198nl80211_put_iftype_akm_suites(struct cfg80211_registered_device *rdev,
2199 struct sk_buff *msg)
2200{
2201 int i;
2202 struct nlattr *nested, *nested_akms;
2203 const struct wiphy_iftype_akm_suites *iftype_akms;
2204
2205 if (!rdev->wiphy.num_iftype_akm_suites ||
2206 !rdev->wiphy.iftype_akm_suites)
2207 return 0;
2208
2209 nested = nla_nest_start(msg, NL80211_ATTR_IFTYPE_AKM_SUITES);
2210 if (!nested)
2211 return -ENOBUFS;
2212
2213 for (i = 0; i < rdev->wiphy.num_iftype_akm_suites; i++) {
2214 nested_akms = nla_nest_start(msg, i + 1);
2215 if (!nested_akms)
2216 return -ENOBUFS;
2217
2218 iftype_akms = &rdev->wiphy.iftype_akm_suites[i];
2219
2220 if (nl80211_put_iftypes(msg, NL80211_IFTYPE_AKM_ATTR_IFTYPES,
2221 iftype_akms->iftypes_mask))
2222 return -ENOBUFS;
2223
2224 if (nla_put(msg, NL80211_IFTYPE_AKM_ATTR_SUITES,
2225 sizeof(u32) * iftype_akms->n_akm_suites,
2226 iftype_akms->akm_suites)) {
2227 return -ENOBUFS;
2228 }
2229 nla_nest_end(msg, nested_akms);
2230 }
2231
2232 nla_nest_end(msg, nested);
2233
2234 return 0;
2235}
2236
3710a8a6
JB
2237static int
2238nl80211_put_tid_config_support(struct cfg80211_registered_device *rdev,
2239 struct sk_buff *msg)
2240{
2241 struct nlattr *supp;
2242
2243 if (!rdev->wiphy.tid_config_support.vif &&
2244 !rdev->wiphy.tid_config_support.peer)
2245 return 0;
2246
2247 supp = nla_nest_start(msg, NL80211_ATTR_TID_CONFIG);
2248 if (!supp)
2249 return -ENOSPC;
2250
2251 if (rdev->wiphy.tid_config_support.vif &&
2252 nla_put_u64_64bit(msg, NL80211_TID_CONFIG_ATTR_VIF_SUPP,
2253 rdev->wiphy.tid_config_support.vif,
2254 NL80211_TID_CONFIG_ATTR_PAD))
2255 goto fail;
2256
2257 if (rdev->wiphy.tid_config_support.peer &&
2258 nla_put_u64_64bit(msg, NL80211_TID_CONFIG_ATTR_PEER_SUPP,
2259 rdev->wiphy.tid_config_support.peer,
2260 NL80211_TID_CONFIG_ATTR_PAD))
2261 goto fail;
2262
6a21d16c
T
2263 /* for now we just use the same value ... makes more sense */
2264 if (nla_put_u8(msg, NL80211_TID_CONFIG_ATTR_RETRY_SHORT,
2265 rdev->wiphy.tid_config_support.max_retry))
2266 goto fail;
2267 if (nla_put_u8(msg, NL80211_TID_CONFIG_ATTR_RETRY_LONG,
2268 rdev->wiphy.tid_config_support.max_retry))
2269 goto fail;
2270
3710a8a6
JB
2271 nla_nest_end(msg, supp);
2272
2273 return 0;
2274fail:
2275 nla_nest_cancel(msg, supp);
2276 return -ENOBUFS;
2277}
2278
6bdb68ce
CH
2279static int
2280nl80211_put_sar_specs(struct cfg80211_registered_device *rdev,
2281 struct sk_buff *msg)
2282{
2283 struct nlattr *sar_capa, *specs, *sub_freq_range;
2284 u8 num_freq_ranges;
2285 int i;
2286
2287 if (!rdev->wiphy.sar_capa)
2288 return 0;
2289
2290 num_freq_ranges = rdev->wiphy.sar_capa->num_freq_ranges;
2291
2292 sar_capa = nla_nest_start(msg, NL80211_ATTR_SAR_SPEC);
2293 if (!sar_capa)
2294 return -ENOSPC;
2295
2296 if (nla_put_u32(msg, NL80211_SAR_ATTR_TYPE, rdev->wiphy.sar_capa->type))
2297 goto fail;
2298
2299 specs = nla_nest_start(msg, NL80211_SAR_ATTR_SPECS);
2300 if (!specs)
2301 goto fail;
2302
2303 /* report supported freq_ranges */
2304 for (i = 0; i < num_freq_ranges; i++) {
2305 sub_freq_range = nla_nest_start(msg, i + 1);
2306 if (!sub_freq_range)
2307 goto fail;
2308
2309 if (nla_put_u32(msg, NL80211_SAR_ATTR_SPECS_START_FREQ,
2310 rdev->wiphy.sar_capa->freq_ranges[i].start_freq))
2311 goto fail;
2312
2313 if (nla_put_u32(msg, NL80211_SAR_ATTR_SPECS_END_FREQ,
2314 rdev->wiphy.sar_capa->freq_ranges[i].end_freq))
2315 goto fail;
2316
2317 nla_nest_end(msg, sub_freq_range);
2318 }
2319
2320 nla_nest_end(msg, specs);
2321 nla_nest_end(msg, sar_capa);
2322
2323 return 0;
2324fail:
2325 nla_nest_cancel(msg, sar_capa);
2326 return -ENOBUFS;
2327}
2328
dc1e3cb8
JC
2329static int nl80211_put_mbssid_support(struct wiphy *wiphy, struct sk_buff *msg)
2330{
2331 struct nlattr *config;
2332
2333 if (!wiphy->mbssid_max_interfaces)
2334 return 0;
2335
2336 config = nla_nest_start(msg, NL80211_ATTR_MBSSID_CONFIG);
2337 if (!config)
2338 return -ENOBUFS;
2339
2340 if (nla_put_u8(msg, NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES,
2341 wiphy->mbssid_max_interfaces))
2342 goto fail;
2343
2344 if (wiphy->ema_max_profile_periodicity &&
2345 nla_put_u8(msg,
2346 NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY,
2347 wiphy->ema_max_profile_periodicity))
2348 goto fail;
2349
2350 nla_nest_end(msg, config);
2351 return 0;
2352
2353fail:
2354 nla_nest_cancel(msg, config);
2355 return -ENOBUFS;
2356}
2357
86e8cf98
JB
2358struct nl80211_dump_wiphy_state {
2359 s64 filter_wiphy;
2360 long start;
019ae3a9 2361 long split_start, band_start, chan_start, capa_start;
86e8cf98
JB
2362 bool split;
2363};
2364
1b8ec87a 2365static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
3bb20556 2366 enum nl80211_commands cmd,
3713b4e3 2367 struct sk_buff *msg, u32 portid, u32 seq,
86e8cf98 2368 int flags, struct nl80211_dump_wiphy_state *state)
3713b4e3
JB
2369{
2370 void *hdr;
2371 struct nlattr *nl_bands, *nl_band;
2372 struct nlattr *nl_freqs, *nl_freq;
2373 struct nlattr *nl_cmds;
57fbcce3 2374 enum nl80211_band band;
3713b4e3
JB
2375 struct ieee80211_channel *chan;
2376 int i;
2377 const struct ieee80211_txrx_stypes *mgmt_stypes =
1b8ec87a 2378 rdev->wiphy.mgmt_stypes;
fe1abafd 2379 u32 features;
ee688b00 2380
3bb20556 2381 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
3713b4e3
JB
2382 if (!hdr)
2383 return -ENOBUFS;
ee688b00 2384
86e8cf98
JB
2385 if (WARN_ON(!state))
2386 return -EINVAL;
ee688b00 2387
1b8ec87a 2388 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
3713b4e3 2389 nla_put_string(msg, NL80211_ATTR_WIPHY_NAME,
1b8ec87a 2390 wiphy_name(&rdev->wiphy)) ||
3713b4e3
JB
2391 nla_put_u32(msg, NL80211_ATTR_GENERATION,
2392 cfg80211_rdev_list_generation))
8fdc621d
JB
2393 goto nla_put_failure;
2394
3bb20556
JB
2395 if (cmd != NL80211_CMD_NEW_WIPHY)
2396 goto finish;
2397
86e8cf98 2398 switch (state->split_start) {
3713b4e3
JB
2399 case 0:
2400 if (nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT,
1b8ec87a 2401 rdev->wiphy.retry_short) ||
3713b4e3 2402 nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_LONG,
1b8ec87a 2403 rdev->wiphy.retry_long) ||
3713b4e3 2404 nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
1b8ec87a 2405 rdev->wiphy.frag_threshold) ||
3713b4e3 2406 nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD,
1b8ec87a 2407 rdev->wiphy.rts_threshold) ||
3713b4e3 2408 nla_put_u8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS,
1b8ec87a 2409 rdev->wiphy.coverage_class) ||
3713b4e3 2410 nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
1b8ec87a 2411 rdev->wiphy.max_scan_ssids) ||
3713b4e3 2412 nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
1b8ec87a 2413 rdev->wiphy.max_sched_scan_ssids) ||
3713b4e3 2414 nla_put_u16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
1b8ec87a 2415 rdev->wiphy.max_scan_ie_len) ||
3713b4e3 2416 nla_put_u16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN,
1b8ec87a 2417 rdev->wiphy.max_sched_scan_ie_len) ||
3713b4e3 2418 nla_put_u8(msg, NL80211_ATTR_MAX_MATCH_SETS,
f8d504ca 2419 rdev->wiphy.max_match_sets))
9360ffd1 2420 goto nla_put_failure;
3713b4e3 2421
1b8ec87a 2422 if ((rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) &&
3713b4e3 2423 nla_put_flag(msg, NL80211_ATTR_SUPPORT_IBSS_RSN))
aa430da4 2424 goto nla_put_failure;
1b8ec87a 2425 if ((rdev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) &&
3713b4e3
JB
2426 nla_put_flag(msg, NL80211_ATTR_SUPPORT_MESH_AUTH))
2427 goto nla_put_failure;
1b8ec87a 2428 if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) &&
3713b4e3
JB
2429 nla_put_flag(msg, NL80211_ATTR_SUPPORT_AP_UAPSD))
2430 goto nla_put_failure;
1b8ec87a 2431 if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) &&
3713b4e3
JB
2432 nla_put_flag(msg, NL80211_ATTR_ROAM_SUPPORT))
2433 goto nla_put_failure;
1b8ec87a 2434 if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
3713b4e3
JB
2435 nla_put_flag(msg, NL80211_ATTR_TDLS_SUPPORT))
2436 goto nla_put_failure;
1b8ec87a 2437 if ((rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) &&
3713b4e3 2438 nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP))
9360ffd1 2439 goto nla_put_failure;
86e8cf98
JB
2440 state->split_start++;
2441 if (state->split)
3713b4e3 2442 break;
7b506ff6 2443 fallthrough;
3713b4e3
JB
2444 case 1:
2445 if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES,
1b8ec87a
ZG
2446 sizeof(u32) * rdev->wiphy.n_cipher_suites,
2447 rdev->wiphy.cipher_suites))
3713b4e3 2448 goto nla_put_failure;
4745fc09 2449
3713b4e3 2450 if (nla_put_u8(msg, NL80211_ATTR_MAX_NUM_PMKIDS,
1b8ec87a 2451 rdev->wiphy.max_num_pmkids))
3713b4e3 2452 goto nla_put_failure;
b23aa676 2453
1b8ec87a 2454 if ((rdev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) &&
3713b4e3 2455 nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE))
9360ffd1 2456 goto nla_put_failure;
b23aa676 2457
3713b4e3 2458 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX,
1b8ec87a 2459 rdev->wiphy.available_antennas_tx) ||
3713b4e3 2460 nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX,
1b8ec87a 2461 rdev->wiphy.available_antennas_rx))
9360ffd1 2462 goto nla_put_failure;
b23aa676 2463
1b8ec87a 2464 if ((rdev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) &&
3713b4e3 2465 nla_put_u32(msg, NL80211_ATTR_PROBE_RESP_OFFLOAD,
1b8ec87a 2466 rdev->wiphy.probe_resp_offload))
3713b4e3 2467 goto nla_put_failure;
8fdc621d 2468
1b8ec87a
ZG
2469 if ((rdev->wiphy.available_antennas_tx ||
2470 rdev->wiphy.available_antennas_rx) &&
2471 rdev->ops->get_antenna) {
3713b4e3
JB
2472 u32 tx_ant = 0, rx_ant = 0;
2473 int res;
7a087e74 2474
1b8ec87a 2475 res = rdev_get_antenna(rdev, &tx_ant, &rx_ant);
3713b4e3
JB
2476 if (!res) {
2477 if (nla_put_u32(msg,
2478 NL80211_ATTR_WIPHY_ANTENNA_TX,
2479 tx_ant) ||
2480 nla_put_u32(msg,
2481 NL80211_ATTR_WIPHY_ANTENNA_RX,
2482 rx_ant))
2483 goto nla_put_failure;
2484 }
2485 }
a293911d 2486
86e8cf98
JB
2487 state->split_start++;
2488 if (state->split)
3713b4e3 2489 break;
7b506ff6 2490 fallthrough;
3713b4e3
JB
2491 case 2:
2492 if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES,
1b8ec87a 2493 rdev->wiphy.interface_modes))
3713b4e3 2494 goto nla_put_failure;
86e8cf98
JB
2495 state->split_start++;
2496 if (state->split)
3713b4e3 2497 break;
7b506ff6 2498 fallthrough;
3713b4e3 2499 case 3:
ae0be8de
MK
2500 nl_bands = nla_nest_start_noflag(msg,
2501 NL80211_ATTR_WIPHY_BANDS);
3713b4e3
JB
2502 if (!nl_bands)
2503 goto nla_put_failure;
f7ca38df 2504
86e8cf98 2505 for (band = state->band_start;
0d059964
JB
2506 band < (state->split ?
2507 NUM_NL80211_BANDS :
2508 NL80211_BAND_60GHZ + 1);
2509 band++) {
3713b4e3 2510 struct ieee80211_supported_band *sband;
2e161f78 2511
f8d504ca
JB
2512 /* omit higher bands for ancient software */
2513 if (band > NL80211_BAND_5GHZ && !state->split)
2514 break;
2515
1b8ec87a 2516 sband = rdev->wiphy.bands[band];
2e161f78 2517
3713b4e3
JB
2518 if (!sband)
2519 continue;
2520
ae0be8de 2521 nl_band = nla_nest_start_noflag(msg, band);
3713b4e3 2522 if (!nl_band)
2e161f78 2523 goto nla_put_failure;
3713b4e3 2524
86e8cf98 2525 switch (state->chan_start) {
3713b4e3 2526 case 0:
f8d504ca
JB
2527 if (nl80211_send_band_rateinfo(msg, sband,
2528 state->split))
9360ffd1 2529 goto nla_put_failure;
86e8cf98
JB
2530 state->chan_start++;
2531 if (state->split)
3713b4e3 2532 break;
7b506ff6 2533 fallthrough;
3713b4e3
JB
2534 default:
2535 /* add frequencies */
ae0be8de
MK
2536 nl_freqs = nla_nest_start_noflag(msg,
2537 NL80211_BAND_ATTR_FREQS);
3713b4e3
JB
2538 if (!nl_freqs)
2539 goto nla_put_failure;
2540
86e8cf98 2541 for (i = state->chan_start - 1;
3713b4e3
JB
2542 i < sband->n_channels;
2543 i++) {
ae0be8de
MK
2544 nl_freq = nla_nest_start_noflag(msg,
2545 i);
3713b4e3
JB
2546 if (!nl_freq)
2547 goto nla_put_failure;
2548
2549 chan = &sband->channels[i];
2550
86e8cf98 2551 if (nl80211_msg_put_channel(
50f32718 2552 msg, &rdev->wiphy, chan,
86e8cf98 2553 state->split))
3713b4e3
JB
2554 goto nla_put_failure;
2555
2556 nla_nest_end(msg, nl_freq);
86e8cf98 2557 if (state->split)
3713b4e3
JB
2558 break;
2559 }
2560 if (i < sband->n_channels)
86e8cf98 2561 state->chan_start = i + 2;
3713b4e3 2562 else
86e8cf98 2563 state->chan_start = 0;
3713b4e3
JB
2564 nla_nest_end(msg, nl_freqs);
2565 }
2566
2567 nla_nest_end(msg, nl_band);
2568
86e8cf98 2569 if (state->split) {
3713b4e3 2570 /* start again here */
86e8cf98 2571 if (state->chan_start)
3713b4e3
JB
2572 band--;
2573 break;
2e161f78 2574 }
2e161f78 2575 }
3713b4e3 2576 nla_nest_end(msg, nl_bands);
2e161f78 2577
57fbcce3 2578 if (band < NUM_NL80211_BANDS)
86e8cf98 2579 state->band_start = band + 1;
3713b4e3 2580 else
86e8cf98 2581 state->band_start = 0;
74b70a4e 2582
3713b4e3 2583 /* if bands & channels are done, continue outside */
86e8cf98
JB
2584 if (state->band_start == 0 && state->chan_start == 0)
2585 state->split_start++;
2586 if (state->split)
3713b4e3 2587 break;
7b506ff6 2588 fallthrough;
3713b4e3 2589 case 4:
ae0be8de
MK
2590 nl_cmds = nla_nest_start_noflag(msg,
2591 NL80211_ATTR_SUPPORTED_COMMANDS);
3713b4e3 2592 if (!nl_cmds)
2e161f78
JB
2593 goto nla_put_failure;
2594
1794899e
JB
2595 i = nl80211_add_commands_unsplit(rdev, msg);
2596 if (i < 0)
2597 goto nla_put_failure;
86e8cf98 2598 if (state->split) {
5de17984
AS
2599 CMD(crit_proto_start, CRIT_PROTOCOL_START);
2600 CMD(crit_proto_stop, CRIT_PROTOCOL_STOP);
1b8ec87a 2601 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)
16ef1fe2 2602 CMD(channel_switch, CHANNEL_SWITCH);
02df00eb 2603 CMD(set_qos_map, SET_QOS_MAP);
723e73ac
JB
2604 if (rdev->wiphy.features &
2605 NL80211_FEATURE_SUPPORTS_WMM_ADMISSION)
960d01ac 2606 CMD(add_tx_ts, ADD_TX_TS);
ce0ce13a 2607 CMD(set_multicast_to_unicast, SET_MULTICAST_TO_UNICAST);
088e8df8 2608 CMD(update_connect_params, UPDATE_CONNECT_PARAMS);
7010998c 2609 CMD(update_ft_ies, UPDATE_FT_IES);
6bdb68ce
CH
2610 if (rdev->wiphy.sar_capa)
2611 CMD(set_sar_specs, SET_SAR_SPECS);
5de17984 2612 }
3713b4e3 2613#undef CMD
ff1b6e69 2614
3713b4e3 2615 nla_nest_end(msg, nl_cmds);
86e8cf98
JB
2616 state->split_start++;
2617 if (state->split)
3713b4e3 2618 break;
7b506ff6 2619 fallthrough;
3713b4e3 2620 case 5:
1b8ec87a
ZG
2621 if (rdev->ops->remain_on_channel &&
2622 (rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) &&
3713b4e3
JB
2623 nla_put_u32(msg,
2624 NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION,
1b8ec87a 2625 rdev->wiphy.max_remain_on_channel_duration))
3713b4e3
JB
2626 goto nla_put_failure;
2627
1b8ec87a 2628 if ((rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX) &&
3713b4e3
JB
2629 nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK))
2630 goto nla_put_failure;
2631
86e8cf98
JB
2632 state->split_start++;
2633 if (state->split)
3713b4e3 2634 break;
7b506ff6 2635 fallthrough;
3713b4e3
JB
2636 case 6:
2637#ifdef CONFIG_PM
1b8ec87a 2638 if (nl80211_send_wowlan(msg, rdev, state->split))
3713b4e3 2639 goto nla_put_failure;
86e8cf98
JB
2640 state->split_start++;
2641 if (state->split)
3713b4e3
JB
2642 break;
2643#else
86e8cf98 2644 state->split_start++;
dfb89c56 2645#endif
7b506ff6 2646 fallthrough;
3713b4e3
JB
2647 case 7:
2648 if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES,
1b8ec87a 2649 rdev->wiphy.software_iftypes))
3713b4e3 2650 goto nla_put_failure;
ff1b6e69 2651
1b8ec87a 2652 if (nl80211_put_iface_combinations(&rdev->wiphy, msg,
86e8cf98 2653 state->split))
3713b4e3 2654 goto nla_put_failure;
7527a782 2655
86e8cf98
JB
2656 state->split_start++;
2657 if (state->split)
3713b4e3 2658 break;
7b506ff6 2659 fallthrough;
3713b4e3 2660 case 8:
1b8ec87a 2661 if ((rdev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) &&
3713b4e3 2662 nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME,
1b8ec87a 2663 rdev->wiphy.ap_sme_capa))
3713b4e3 2664 goto nla_put_failure;
7527a782 2665
1b8ec87a 2666 features = rdev->wiphy.features;
fe1abafd
JB
2667 /*
2668 * We can only add the per-channel limit information if the
2669 * dump is split, otherwise it makes it too big. Therefore
2670 * only advertise it in that case.
2671 */
86e8cf98 2672 if (state->split)
fe1abafd
JB
2673 features |= NL80211_FEATURE_ADVERTISE_CHAN_LIMITS;
2674 if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, features))
3713b4e3 2675 goto nla_put_failure;
562a7480 2676
1b8ec87a 2677 if (rdev->wiphy.ht_capa_mod_mask &&
3713b4e3 2678 nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK,
1b8ec87a
ZG
2679 sizeof(*rdev->wiphy.ht_capa_mod_mask),
2680 rdev->wiphy.ht_capa_mod_mask))
3713b4e3 2681 goto nla_put_failure;
1f074bd8 2682
1b8ec87a
ZG
2683 if (rdev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME &&
2684 rdev->wiphy.max_acl_mac_addrs &&
3713b4e3 2685 nla_put_u32(msg, NL80211_ATTR_MAC_ACL_MAX,
1b8ec87a 2686 rdev->wiphy.max_acl_mac_addrs))
3713b4e3 2687 goto nla_put_failure;
7e7c8926 2688
3713b4e3
JB
2689 /*
2690 * Any information below this point is only available to
2691 * applications that can deal with it being split. This
2692 * helps ensure that newly added capabilities don't break
2693 * older tools by overrunning their buffers.
2694 *
2695 * We still increment split_start so that in the split
2696 * case we'll continue with more data in the next round,
2697 * but break unconditionally so unsplit data stops here.
2698 */
ab10c22b
JB
2699 if (state->split)
2700 state->split_start++;
2701 else
2702 state->split_start = 0;
3713b4e3
JB
2703 break;
2704 case 9:
f8d504ca
JB
2705 if (nl80211_send_mgmt_stypes(msg, mgmt_stypes))
2706 goto nla_put_failure;
2707
2708 if (nla_put_u32(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS,
2709 rdev->wiphy.max_sched_scan_plans) ||
2710 nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL,
2711 rdev->wiphy.max_sched_scan_plan_interval) ||
2712 nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS,
2713 rdev->wiphy.max_sched_scan_plan_iterations))
2714 goto nla_put_failure;
2715
1b8ec87a 2716 if (rdev->wiphy.extended_capabilities &&
fe1abafd 2717 (nla_put(msg, NL80211_ATTR_EXT_CAPA,
1b8ec87a
ZG
2718 rdev->wiphy.extended_capabilities_len,
2719 rdev->wiphy.extended_capabilities) ||
fe1abafd 2720 nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK,
1b8ec87a
ZG
2721 rdev->wiphy.extended_capabilities_len,
2722 rdev->wiphy.extended_capabilities_mask)))
fe1abafd 2723 goto nla_put_failure;
a50df0c4 2724
1b8ec87a 2725 if (rdev->wiphy.vht_capa_mod_mask &&
ee2aca34 2726 nla_put(msg, NL80211_ATTR_VHT_CAPABILITY_MASK,
1b8ec87a
ZG
2727 sizeof(*rdev->wiphy.vht_capa_mod_mask),
2728 rdev->wiphy.vht_capa_mod_mask))
ee2aca34
JB
2729 goto nla_put_failure;
2730
ae6fa4d5
DK
2731 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
2732 rdev->wiphy.perm_addr))
2733 goto nla_put_failure;
2734
2735 if (!is_zero_ether_addr(rdev->wiphy.addr_mask) &&
2736 nla_put(msg, NL80211_ATTR_MAC_MASK, ETH_ALEN,
2737 rdev->wiphy.addr_mask))
2738 goto nla_put_failure;
2739
2740 if (rdev->wiphy.n_addresses > 1) {
2741 void *attr;
2742
2743 attr = nla_nest_start(msg, NL80211_ATTR_MAC_ADDRS);
2744 if (!attr)
2745 goto nla_put_failure;
2746
2747 for (i = 0; i < rdev->wiphy.n_addresses; i++)
2748 if (nla_put(msg, i + 1, ETH_ALEN,
2749 rdev->wiphy.addresses[i].addr))
2750 goto nla_put_failure;
2751
2752 nla_nest_end(msg, attr);
2753 }
2754
be29b99a
AK
2755 state->split_start++;
2756 break;
2757 case 10:
1b8ec87a 2758 if (nl80211_send_coalesce(msg, rdev))
be29b99a
AK
2759 goto nla_put_failure;
2760
1b8ec87a 2761 if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) &&
01e0daa4
FF
2762 (nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) ||
2763 nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ)))
2764 goto nla_put_failure;
b43504cf 2765
1b8ec87a 2766 if (rdev->wiphy.max_ap_assoc_sta &&
b43504cf 2767 nla_put_u32(msg, NL80211_ATTR_MAX_AP_ASSOC_STA,
1b8ec87a 2768 rdev->wiphy.max_ap_assoc_sta))
b43504cf
JM
2769 goto nla_put_failure;
2770
ad7e718c
JB
2771 state->split_start++;
2772 break;
2773 case 11:
1b8ec87a 2774 if (rdev->wiphy.n_vendor_commands) {
567ffc35
JB
2775 const struct nl80211_vendor_cmd_info *info;
2776 struct nlattr *nested;
2777
ae0be8de
MK
2778 nested = nla_nest_start_noflag(msg,
2779 NL80211_ATTR_VENDOR_DATA);
567ffc35
JB
2780 if (!nested)
2781 goto nla_put_failure;
2782
1b8ec87a
ZG
2783 for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) {
2784 info = &rdev->wiphy.vendor_commands[i].info;
567ffc35
JB
2785 if (nla_put(msg, i + 1, sizeof(*info), info))
2786 goto nla_put_failure;
2787 }
2788 nla_nest_end(msg, nested);
2789 }
2790
1b8ec87a 2791 if (rdev->wiphy.n_vendor_events) {
567ffc35
JB
2792 const struct nl80211_vendor_cmd_info *info;
2793 struct nlattr *nested;
ad7e718c 2794
ae0be8de
MK
2795 nested = nla_nest_start_noflag(msg,
2796 NL80211_ATTR_VENDOR_EVENTS);
567ffc35 2797 if (!nested)
ad7e718c 2798 goto nla_put_failure;
567ffc35 2799
1b8ec87a
ZG
2800 for (i = 0; i < rdev->wiphy.n_vendor_events; i++) {
2801 info = &rdev->wiphy.vendor_events[i];
567ffc35
JB
2802 if (nla_put(msg, i + 1, sizeof(*info), info))
2803 goto nla_put_failure;
2804 }
2805 nla_nest_end(msg, nested);
2806 }
9a774c78
AO
2807 state->split_start++;
2808 break;
2809 case 12:
2810 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH &&
2811 nla_put_u8(msg, NL80211_ATTR_MAX_CSA_COUNTERS,
2812 rdev->wiphy.max_num_csa_counters))
2813 goto nla_put_failure;
01e0daa4 2814
1bdd716c
AN
2815 if (rdev->wiphy.regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
2816 nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
2817 goto nla_put_failure;
2818
ca986ad9
AVS
2819 if (rdev->wiphy.max_sched_scan_reqs &&
2820 nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_MAX_REQS,
2821 rdev->wiphy.max_sched_scan_reqs))
2822 goto nla_put_failure;
2823
d75bb06b
GKS
2824 if (nla_put(msg, NL80211_ATTR_EXT_FEATURES,
2825 sizeof(rdev->wiphy.ext_features),
2826 rdev->wiphy.ext_features))
2827 goto nla_put_failure;
2828
38de03d2
AS
2829 if (rdev->wiphy.bss_select_support) {
2830 struct nlattr *nested;
2831 u32 bss_select_support = rdev->wiphy.bss_select_support;
2832
ae0be8de
MK
2833 nested = nla_nest_start_noflag(msg,
2834 NL80211_ATTR_BSS_SELECT);
38de03d2
AS
2835 if (!nested)
2836 goto nla_put_failure;
2837
2838 i = 0;
2839 while (bss_select_support) {
2840 if ((bss_select_support & 1) &&
2841 nla_put_flag(msg, i))
2842 goto nla_put_failure;
2843 i++;
2844 bss_select_support >>= 1;
2845 }
2846 nla_nest_end(msg, nested);
2847 }
2848
019ae3a9
KV
2849 state->split_start++;
2850 break;
2851 case 13:
2852 if (rdev->wiphy.num_iftype_ext_capab &&
2853 rdev->wiphy.iftype_ext_capab) {
2854 struct nlattr *nested_ext_capab, *nested;
2855
ae0be8de
MK
2856 nested = nla_nest_start_noflag(msg,
2857 NL80211_ATTR_IFTYPE_EXT_CAPA);
019ae3a9
KV
2858 if (!nested)
2859 goto nla_put_failure;
2860
2861 for (i = state->capa_start;
2862 i < rdev->wiphy.num_iftype_ext_capab; i++) {
2863 const struct wiphy_iftype_ext_capab *capab;
2864
2865 capab = &rdev->wiphy.iftype_ext_capab[i];
2866
ae0be8de
MK
2867 nested_ext_capab = nla_nest_start_noflag(msg,
2868 i);
019ae3a9
KV
2869 if (!nested_ext_capab ||
2870 nla_put_u32(msg, NL80211_ATTR_IFTYPE,
2871 capab->iftype) ||
2872 nla_put(msg, NL80211_ATTR_EXT_CAPA,
2873 capab->extended_capabilities_len,
2874 capab->extended_capabilities) ||
2875 nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK,
2876 capab->extended_capabilities_len,
2877 capab->extended_capabilities_mask))
2878 goto nla_put_failure;
2879
4e9c3af3
JB
2880 if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_MLO &&
2881 (nla_put_u16(msg,
2882 NL80211_ATTR_EML_CAPABILITY,
2883 capab->eml_capabilities) ||
2884 nla_put_u16(msg,
2885 NL80211_ATTR_MLD_CAPA_AND_OPS,
2886 capab->mld_capa_and_ops)))
2887 goto nla_put_failure;
2888
019ae3a9
KV
2889 nla_nest_end(msg, nested_ext_capab);
2890 if (state->split)
2891 break;
2892 }
2893 nla_nest_end(msg, nested);
2894 if (i < rdev->wiphy.num_iftype_ext_capab) {
2895 state->capa_start = i + 1;
2896 break;
2897 }
2898 }
2899
8585989d
LC
2900 if (nla_put_u32(msg, NL80211_ATTR_BANDS,
2901 rdev->wiphy.nan_supported_bands))
2902 goto nla_put_failure;
2903
52539ca8
THJ
2904 if (wiphy_ext_feature_isset(&rdev->wiphy,
2905 NL80211_EXT_FEATURE_TXQS)) {
2906 struct cfg80211_txq_stats txqstats = {};
2907 int res;
2908
2909 res = rdev_get_txq_stats(rdev, NULL, &txqstats);
2910 if (!res &&
2911 !nl80211_put_txq_stats(msg, &txqstats,
2912 NL80211_ATTR_TXQ_STATS))
2913 goto nla_put_failure;
2914
2915 if (nla_put_u32(msg, NL80211_ATTR_TXQ_LIMIT,
2916 rdev->wiphy.txq_limit))
2917 goto nla_put_failure;
2918 if (nla_put_u32(msg, NL80211_ATTR_TXQ_MEMORY_LIMIT,
2919 rdev->wiphy.txq_memory_limit))
2920 goto nla_put_failure;
2921 if (nla_put_u32(msg, NL80211_ATTR_TXQ_QUANTUM,
2922 rdev->wiphy.txq_quantum))
2923 goto nla_put_failure;
2924 }
2925
9bb7e0f2
JB
2926 state->split_start++;
2927 break;
2928 case 14:
2929 if (nl80211_send_pmsr_capa(rdev, msg))
2930 goto nla_put_failure;
2931
ab4dfa20
VJ
2932 state->split_start++;
2933 break;
2934 case 15:
2935 if (rdev->wiphy.akm_suites &&
2936 nla_put(msg, NL80211_ATTR_AKM_SUITES,
2937 sizeof(u32) * rdev->wiphy.n_akm_suites,
2938 rdev->wiphy.akm_suites))
2939 goto nla_put_failure;
2940
d6039a34
VJ
2941 if (nl80211_put_iftype_akm_suites(rdev, msg))
2942 goto nla_put_failure;
2943
3710a8a6
JB
2944 if (nl80211_put_tid_config_support(rdev, msg))
2945 goto nla_put_failure;
6bdb68ce
CH
2946 state->split_start++;
2947 break;
2948 case 16:
2949 if (nl80211_put_sar_specs(rdev, msg))
2950 goto nla_put_failure;
3710a8a6 2951
dc1e3cb8
JC
2952 if (nl80211_put_mbssid_support(&rdev->wiphy, msg))
2953 goto nla_put_failure;
2954
ecad3b0b
VJ
2955 if (nla_put_u16(msg, NL80211_ATTR_MAX_NUM_AKM_SUITES,
2956 rdev->wiphy.max_num_akm_suites))
2957 goto nla_put_failure;
2958
fa2ca639
JB
2959 if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_MLO)
2960 nla_put_flag(msg, NL80211_ATTR_MLO_SUPPORT);
2961
3713b4e3 2962 /* done */
86e8cf98 2963 state->split_start = 0;
3713b4e3
JB
2964 break;
2965 }
3bb20556 2966 finish:
053c095a
JB
2967 genlmsg_end(msg, hdr);
2968 return 0;
55682965
JB
2969
2970 nla_put_failure:
bc3ed28c
TG
2971 genlmsg_cancel(msg, hdr);
2972 return -EMSGSIZE;
55682965
JB
2973}
2974
86e8cf98
JB
2975static int nl80211_dump_wiphy_parse(struct sk_buff *skb,
2976 struct netlink_callback *cb,
2977 struct nl80211_dump_wiphy_state *state)
2978{
50508d94
JB
2979 struct nlattr **tb = kcalloc(NUM_NL80211_ATTR, sizeof(*tb), GFP_KERNEL);
2980 int ret;
2981
2982 if (!tb)
2983 return -ENOMEM;
2984
2985 ret = nlmsg_parse_deprecated(cb->nlh,
2986 GENL_HDRLEN + nl80211_fam.hdrsize,
2987 tb, nl80211_fam.maxattr,
2988 nl80211_policy, NULL);
86e8cf98 2989 /* ignore parse errors for backward compatibility */
50508d94
JB
2990 if (ret) {
2991 ret = 0;
2992 goto out;
2993 }
86e8cf98
JB
2994
2995 state->split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP];
2996 if (tb[NL80211_ATTR_WIPHY])
2997 state->filter_wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
2998 if (tb[NL80211_ATTR_WDEV])
2999 state->filter_wiphy = nla_get_u64(tb[NL80211_ATTR_WDEV]) >> 32;
3000 if (tb[NL80211_ATTR_IFINDEX]) {
3001 struct net_device *netdev;
3002 struct cfg80211_registered_device *rdev;
3003 int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
3004
7f2b8562 3005 netdev = __dev_get_by_index(sock_net(skb->sk), ifidx);
50508d94
JB
3006 if (!netdev) {
3007 ret = -ENODEV;
3008 goto out;
3009 }
86e8cf98 3010 if (netdev->ieee80211_ptr) {
f26cbf40 3011 rdev = wiphy_to_rdev(
86e8cf98
JB
3012 netdev->ieee80211_ptr->wiphy);
3013 state->filter_wiphy = rdev->wiphy_idx;
3014 }
86e8cf98
JB
3015 }
3016
50508d94
JB
3017 ret = 0;
3018out:
3019 kfree(tb);
3020 return ret;
86e8cf98
JB
3021}
3022
55682965
JB
3023static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
3024{
645e77de 3025 int idx = 0, ret;
86e8cf98 3026 struct nl80211_dump_wiphy_state *state = (void *)cb->args[0];
1b8ec87a 3027 struct cfg80211_registered_device *rdev;
3a5a423b 3028
5fe231e8 3029 rtnl_lock();
86e8cf98
JB
3030 if (!state) {
3031 state = kzalloc(sizeof(*state), GFP_KERNEL);
57ed5cd6
JL
3032 if (!state) {
3033 rtnl_unlock();
86e8cf98 3034 return -ENOMEM;
3713b4e3 3035 }
86e8cf98
JB
3036 state->filter_wiphy = -1;
3037 ret = nl80211_dump_wiphy_parse(skb, cb, state);
3038 if (ret) {
3039 kfree(state);
3040 rtnl_unlock();
3041 return ret;
3713b4e3 3042 }
86e8cf98 3043 cb->args[0] = (long)state;
3713b4e3
JB
3044 }
3045
1b8ec87a
ZG
3046 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
3047 if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
463d0183 3048 continue;
86e8cf98 3049 if (++idx <= state->start)
55682965 3050 continue;
86e8cf98 3051 if (state->filter_wiphy != -1 &&
1b8ec87a 3052 state->filter_wiphy != rdev->wiphy_idx)
3713b4e3
JB
3053 continue;
3054 /* attempt to fit multiple wiphy data chunks into the skb */
3055 do {
3bb20556
JB
3056 ret = nl80211_send_wiphy(rdev, NL80211_CMD_NEW_WIPHY,
3057 skb,
3713b4e3
JB
3058 NETLINK_CB(cb->skb).portid,
3059 cb->nlh->nlmsg_seq,
86e8cf98 3060 NLM_F_MULTI, state);
3713b4e3
JB
3061 if (ret < 0) {
3062 /*
3063 * If sending the wiphy data didn't fit (ENOBUFS
3064 * or EMSGSIZE returned), this SKB is still
3065 * empty (so it's not too big because another
3066 * wiphy dataset is already in the skb) and
3067 * we've not tried to adjust the dump allocation
3068 * yet ... then adjust the alloc size to be
3069 * bigger, and return 1 but with the empty skb.
3070 * This results in an empty message being RX'ed
3071 * in userspace, but that is ignored.
3072 *
3073 * We can then retry with the larger buffer.
3074 */
3075 if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
f12cb289 3076 !skb->len && !state->split &&
3713b4e3
JB
3077 cb->min_dump_alloc < 4096) {
3078 cb->min_dump_alloc = 4096;
f12cb289 3079 state->split_start = 0;
d98cae64 3080 rtnl_unlock();
3713b4e3
JB
3081 return 1;
3082 }
3083 idx--;
3084 break;
645e77de 3085 }
86e8cf98 3086 } while (state->split_start > 0);
3713b4e3 3087 break;
55682965 3088 }
5fe231e8 3089 rtnl_unlock();
55682965 3090
86e8cf98 3091 state->start = idx;
55682965
JB
3092
3093 return skb->len;
3094}
3095
86e8cf98
JB
3096static int nl80211_dump_wiphy_done(struct netlink_callback *cb)
3097{
3098 kfree((void *)cb->args[0]);
3099 return 0;
3100}
3101
55682965
JB
3102static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
3103{
3104 struct sk_buff *msg;
1b8ec87a 3105 struct cfg80211_registered_device *rdev = info->user_ptr[0];
86e8cf98 3106 struct nl80211_dump_wiphy_state state = {};
55682965 3107
645e77de 3108 msg = nlmsg_new(4096, GFP_KERNEL);
55682965 3109 if (!msg)
4c476991 3110 return -ENOMEM;
55682965 3111
3bb20556
JB
3112 if (nl80211_send_wiphy(rdev, NL80211_CMD_NEW_WIPHY, msg,
3113 info->snd_portid, info->snd_seq, 0,
86e8cf98 3114 &state) < 0) {
4c476991
JB
3115 nlmsg_free(msg);
3116 return -ENOBUFS;
3117 }
55682965 3118
134e6375 3119 return genlmsg_reply(msg, info);
55682965
JB
3120}
3121
31888487
JM
3122static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = {
3123 [NL80211_TXQ_ATTR_QUEUE] = { .type = NLA_U8 },
3124 [NL80211_TXQ_ATTR_TXOP] = { .type = NLA_U16 },
3125 [NL80211_TXQ_ATTR_CWMIN] = { .type = NLA_U16 },
3126 [NL80211_TXQ_ATTR_CWMAX] = { .type = NLA_U16 },
3127 [NL80211_TXQ_ATTR_AIFS] = { .type = NLA_U8 },
3128};
3129
3130static int parse_txq_params(struct nlattr *tb[],
3131 struct ieee80211_txq_params *txq_params)
3132{
259d8c1e
DW
3133 u8 ac;
3134
a3304b0a 3135 if (!tb[NL80211_TXQ_ATTR_AC] || !tb[NL80211_TXQ_ATTR_TXOP] ||
31888487
JM
3136 !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] ||
3137 !tb[NL80211_TXQ_ATTR_AIFS])
3138 return -EINVAL;
3139
259d8c1e 3140 ac = nla_get_u8(tb[NL80211_TXQ_ATTR_AC]);
31888487
JM
3141 txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]);
3142 txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]);
3143 txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]);
3144 txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]);
3145
259d8c1e 3146 if (ac >= NL80211_NUM_ACS)
a3304b0a 3147 return -EINVAL;
259d8c1e 3148 txq_params->ac = array_index_nospec(ac, NL80211_NUM_ACS);
31888487
JM
3149 return 0;
3150}
3151
f444de05
JB
3152static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev)
3153{
3154 /*
e7e0517c
JB
3155 * You can only set the channel explicitly for some interfaces,
3156 * most have their channel managed via their respective
cc1d2806
JB
3157 * "establish a connection" command (connect, join, ...)
3158 *
3159 * For AP/GO and mesh mode, the channel can be set with the
3160 * channel userspace API, but is only stored and passed to the
3161 * low-level driver when the AP starts or the mesh is joined.
3162 * This is for backward compatibility, userspace can also give
3163 * the channel in the start-ap or join-mesh commands instead.
f444de05
JB
3164 *
3165 * Monitors are special as they are normally slaved to
e8c9bd5b
JB
3166 * whatever else is going on, so they have their own special
3167 * operation to set the monitor channel if possible.
f444de05
JB
3168 */
3169 return !wdev ||
3170 wdev->iftype == NL80211_IFTYPE_AP ||
f444de05 3171 wdev->iftype == NL80211_IFTYPE_MESH_POINT ||
074ac8df
JB
3172 wdev->iftype == NL80211_IFTYPE_MONITOR ||
3173 wdev->iftype == NL80211_IFTYPE_P2P_GO;
f444de05
JB
3174}
3175
9bb7e0f2
JB
3176int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
3177 struct genl_info *info,
3178 struct cfg80211_chan_def *chandef)
683b6d3b 3179{
49f9cf0e
JB
3180 struct netlink_ext_ack *extack = info->extack;
3181 struct nlattr **attrs = info->attrs;
dbeca2ea 3182 u32 control_freq;
683b6d3b 3183
49f9cf0e 3184 if (!attrs[NL80211_ATTR_WIPHY_FREQ])
683b6d3b
JB
3185 return -EINVAL;
3186
942ba88b
TP
3187 control_freq = MHZ_TO_KHZ(
3188 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
3189 if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
3190 control_freq +=
3191 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
683b6d3b 3192
f43e5210 3193 memset(chandef, 0, sizeof(*chandef));
942ba88b 3194 chandef->chan = ieee80211_get_channel_khz(&rdev->wiphy, control_freq);
3d9d1d66 3195 chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
942ba88b
TP
3196 chandef->center_freq1 = KHZ_TO_MHZ(control_freq);
3197 chandef->freq1_offset = control_freq % 1000;
3d9d1d66 3198 chandef->center_freq2 = 0;
683b6d3b
JB
3199
3200 /* Primary channel not allowed */
49f9cf0e
JB
3201 if (!chandef->chan || chandef->chan->flags & IEEE80211_CHAN_DISABLED) {
3202 NL_SET_ERR_MSG_ATTR(extack, attrs[NL80211_ATTR_WIPHY_FREQ],
3203 "Channel is disabled");
683b6d3b 3204 return -EINVAL;
49f9cf0e 3205 }
683b6d3b 3206
49f9cf0e 3207 if (attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
3d9d1d66
JB
3208 enum nl80211_channel_type chantype;
3209
49f9cf0e 3210 chantype = nla_get_u32(attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
3d9d1d66
JB
3211
3212 switch (chantype) {
3213 case NL80211_CHAN_NO_HT:
3214 case NL80211_CHAN_HT20:
3215 case NL80211_CHAN_HT40PLUS:
3216 case NL80211_CHAN_HT40MINUS:
3217 cfg80211_chandef_create(chandef, chandef->chan,
3218 chantype);
ffa4629e 3219 /* user input for center_freq is incorrect */
49f9cf0e
JB
3220 if (attrs[NL80211_ATTR_CENTER_FREQ1] &&
3221 chandef->center_freq1 != nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1])) {
3222 NL_SET_ERR_MSG_ATTR(extack,
3223 attrs[NL80211_ATTR_CENTER_FREQ1],
3224 "bad center frequency 1");
ffa4629e 3225 return -EINVAL;
49f9cf0e 3226 }
ffa4629e 3227 /* center_freq2 must be zero */
49f9cf0e
JB
3228 if (attrs[NL80211_ATTR_CENTER_FREQ2] &&
3229 nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2])) {
3230 NL_SET_ERR_MSG_ATTR(extack,
3231 attrs[NL80211_ATTR_CENTER_FREQ2],
3232 "center frequency 2 can't be used");
ffa4629e 3233 return -EINVAL;
49f9cf0e 3234 }
3d9d1d66
JB
3235 break;
3236 default:
49f9cf0e
JB
3237 NL_SET_ERR_MSG_ATTR(extack,
3238 attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
3239 "invalid channel type");
3d9d1d66
JB
3240 return -EINVAL;
3241 }
49f9cf0e 3242 } else if (attrs[NL80211_ATTR_CHANNEL_WIDTH]) {
3d9d1d66 3243 chandef->width =
49f9cf0e 3244 nla_get_u32(attrs[NL80211_ATTR_CHANNEL_WIDTH]);
5d087aa7
KF
3245 if (chandef->chan->band == NL80211_BAND_S1GHZ) {
3246 /* User input error for channel width doesn't match channel */
3247 if (chandef->width != ieee80211_s1g_channel_width(chandef->chan)) {
3248 NL_SET_ERR_MSG_ATTR(extack,
3249 attrs[NL80211_ATTR_CHANNEL_WIDTH],
3250 "bad channel width");
3251 return -EINVAL;
3252 }
3253 }
942ba88b 3254 if (attrs[NL80211_ATTR_CENTER_FREQ1]) {
3d9d1d66 3255 chandef->center_freq1 =
49f9cf0e 3256 nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1]);
942ba88b
TP
3257 if (attrs[NL80211_ATTR_CENTER_FREQ1_OFFSET])
3258 chandef->freq1_offset = nla_get_u32(
3259 attrs[NL80211_ATTR_CENTER_FREQ1_OFFSET]);
3260 else
3261 chandef->freq1_offset = 0;
3262 }
49f9cf0e 3263 if (attrs[NL80211_ATTR_CENTER_FREQ2])
3d9d1d66 3264 chandef->center_freq2 =
49f9cf0e 3265 nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2]);
3d9d1d66
JB
3266 }
3267
2a38075c
AAL
3268 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]) {
3269 chandef->edmg.channels =
3270 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]);
3271
3272 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG])
3273 chandef->edmg.bw_config =
3274 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]);
3275 } else {
3276 chandef->edmg.bw_config = 0;
3277 chandef->edmg.channels = 0;
3278 }
3279
49f9cf0e
JB
3280 if (!cfg80211_chandef_valid(chandef)) {
3281 NL_SET_ERR_MSG(extack, "invalid channel definition");
3d9d1d66 3282 return -EINVAL;
49f9cf0e 3283 }
3d9d1d66 3284
9f5e8f6e 3285 if (!cfg80211_chandef_usable(&rdev->wiphy, chandef,
49f9cf0e
JB
3286 IEEE80211_CHAN_DISABLED)) {
3287 NL_SET_ERR_MSG(extack, "(extension) channel is disabled");
3d9d1d66 3288 return -EINVAL;
49f9cf0e 3289 }
3d9d1d66 3290
2f301ab2
SW
3291 if ((chandef->width == NL80211_CHAN_WIDTH_5 ||
3292 chandef->width == NL80211_CHAN_WIDTH_10) &&
49f9cf0e
JB
3293 !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ)) {
3294 NL_SET_ERR_MSG(extack, "5/10 MHz not supported");
2f301ab2 3295 return -EINVAL;
49f9cf0e 3296 }
2f301ab2 3297
683b6d3b
JB
3298 return 0;
3299}
3300
f444de05 3301static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
e16821bc 3302 struct net_device *dev,
7b0a0e3c
JB
3303 struct genl_info *info,
3304 int _link_id)
f444de05 3305{
683b6d3b 3306 struct cfg80211_chan_def chandef;
f444de05 3307 int result;
e8c9bd5b 3308 enum nl80211_iftype iftype = NL80211_IFTYPE_MONITOR;
e16821bc 3309 struct wireless_dev *wdev = NULL;
7b0a0e3c 3310 int link_id = _link_id;
e8c9bd5b 3311
e16821bc
JM
3312 if (dev)
3313 wdev = dev->ieee80211_ptr;
f444de05
JB
3314 if (!nl80211_can_set_dev_channel(wdev))
3315 return -EOPNOTSUPP;
e16821bc
JM
3316 if (wdev)
3317 iftype = wdev->iftype;
f444de05 3318
7b0a0e3c
JB
3319 if (link_id < 0) {
3320 if (wdev && wdev->valid_links)
3321 return -EINVAL;
3322 link_id = 0;
3323 }
3324
683b6d3b
JB
3325 result = nl80211_parse_chandef(rdev, info, &chandef);
3326 if (result)
3327 return result;
f444de05 3328
e8c9bd5b 3329 switch (iftype) {
aa430da4
JB
3330 case NL80211_IFTYPE_AP:
3331 case NL80211_IFTYPE_P2P_GO:
923b352f 3332 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
7b0a0e3c
JB
3333 iftype))
3334 return -EINVAL;
3335 if (wdev->links[link_id].ap.beacon_interval) {
3336 struct ieee80211_channel *cur_chan;
3337
e16821bc
JM
3338 if (!dev || !rdev->ops->set_ap_chanwidth ||
3339 !(rdev->wiphy.features &
7b0a0e3c
JB
3340 NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE))
3341 return -EBUSY;
e16821bc
JM
3342
3343 /* Only allow dynamic channel width changes */
7b0a0e3c
JB
3344 cur_chan = wdev->links[link_id].ap.chandef.chan;
3345 if (chandef.chan != cur_chan)
3346 return -EBUSY;
3347
3348 result = rdev_set_ap_chanwidth(rdev, dev, link_id,
3349 &chandef);
e16821bc 3350 if (result)
7b0a0e3c
JB
3351 return result;
3352 wdev->links[link_id].ap.chandef = chandef;
3353 } else {
3354 wdev->u.ap.preset_chandef = chandef;
e16821bc 3355 }
7b0a0e3c 3356 return 0;
cc1d2806 3357 case NL80211_IFTYPE_MESH_POINT:
7b0a0e3c 3358 return cfg80211_set_mesh_channel(rdev, wdev, &chandef);
e8c9bd5b 3359 case NL80211_IFTYPE_MONITOR:
7b0a0e3c 3360 return cfg80211_set_monitor_channel(rdev, &chandef);
aa430da4 3361 default:
7b0a0e3c 3362 break;
f444de05 3363 }
f444de05 3364
7b0a0e3c 3365 return -EINVAL;
f444de05
JB
3366}
3367
3368static int nl80211_set_channel(struct sk_buff *skb, struct genl_info *info)
3369{
4c476991 3370 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c 3371 int link_id = nl80211_link_id_or_invalid(info->attrs);
4c476991 3372 struct net_device *netdev = info->user_ptr[1];
4e2f3d67
JB
3373 int ret;
3374
3375 wdev_lock(netdev->ieee80211_ptr);
3376 ret = __nl80211_set_channel(rdev, netdev, info, link_id);
3377 wdev_unlock(netdev->ieee80211_ptr);
f444de05 3378
4e2f3d67 3379 return ret;
f444de05
JB
3380}
3381
55682965
JB
3382static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
3383{
a05829a7 3384 struct cfg80211_registered_device *rdev = NULL;
f444de05
JB
3385 struct net_device *netdev = NULL;
3386 struct wireless_dev *wdev;
a1e567c8 3387 int result = 0, rem_txq_params = 0;
31888487 3388 struct nlattr *nl_txq_params;
b9a5f8ca
JM
3389 u32 changed;
3390 u8 retry_short = 0, retry_long = 0;
3391 u32 frag_threshold = 0, rts_threshold = 0;
81077e82 3392 u8 coverage_class = 0;
52539ca8 3393 u32 txq_limit = 0, txq_memory_limit = 0, txq_quantum = 0;
55682965 3394
a05829a7 3395 rtnl_lock();
f444de05
JB
3396 /*
3397 * Try to find the wiphy and netdev. Normally this
3398 * function shouldn't need the netdev, but this is
3399 * done for backward compatibility -- previously
3400 * setting the channel was done per wiphy, but now
3401 * it is per netdev. Previous userland like hostapd
3402 * also passed a netdev to set_wiphy, so that it is
3403 * possible to let that go to the right netdev!
3404 */
4bbf4d56 3405
f444de05
JB
3406 if (info->attrs[NL80211_ATTR_IFINDEX]) {
3407 int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
3408
7f2b8562 3409 netdev = __dev_get_by_index(genl_info_net(info), ifindex);
5fe231e8 3410 if (netdev && netdev->ieee80211_ptr)
f26cbf40 3411 rdev = wiphy_to_rdev(netdev->ieee80211_ptr->wiphy);
5fe231e8 3412 else
f444de05 3413 netdev = NULL;
4bbf4d56
JB
3414 }
3415
f444de05 3416 if (!netdev) {
878d9ec7
JB
3417 rdev = __cfg80211_rdev_from_attrs(genl_info_net(info),
3418 info->attrs);
a05829a7
JB
3419 if (IS_ERR(rdev)) {
3420 rtnl_unlock();
4c476991 3421 return PTR_ERR(rdev);
a05829a7 3422 }
f444de05
JB
3423 wdev = NULL;
3424 netdev = NULL;
3425 result = 0;
71fe96bf 3426 } else
f444de05 3427 wdev = netdev->ieee80211_ptr;
f444de05 3428
a05829a7 3429 wiphy_lock(&rdev->wiphy);
a05829a7 3430
f444de05
JB
3431 /*
3432 * end workaround code, by now the rdev is available
3433 * and locked, and wdev may or may not be NULL.
3434 */
4bbf4d56
JB
3435
3436 if (info->attrs[NL80211_ATTR_WIPHY_NAME])
31888487
JM
3437 result = cfg80211_dev_rename(
3438 rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
0391a45c 3439 rtnl_unlock();
4bbf4d56 3440
4bbf4d56 3441 if (result)
a05829a7 3442 goto out;
31888487
JM
3443
3444 if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) {
3445 struct ieee80211_txq_params txq_params;
3446 struct nlattr *tb[NL80211_TXQ_ATTR_MAX + 1];
3447
a05829a7
JB
3448 if (!rdev->ops->set_txq_params) {
3449 result = -EOPNOTSUPP;
3450 goto out;
3451 }
31888487 3452
a05829a7
JB
3453 if (!netdev) {
3454 result = -EINVAL;
3455 goto out;
3456 }
f70f01c2 3457
133a3ff2 3458 if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
a05829a7
JB
3459 netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
3460 result = -EINVAL;
3461 goto out;
3462 }
133a3ff2 3463
a05829a7
JB
3464 if (!netif_running(netdev)) {
3465 result = -ENETDOWN;
3466 goto out;
3467 }
2b5f8b0b 3468
31888487
JM
3469 nla_for_each_nested(nl_txq_params,
3470 info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
3471 rem_txq_params) {
8cb08174
JB
3472 result = nla_parse_nested_deprecated(tb,
3473 NL80211_TXQ_ATTR_MAX,
3474 nl_txq_params,
3475 txq_params_policy,
3476 info->extack);
ae811e21 3477 if (result)
a05829a7 3478 goto out;
31888487
JM
3479 result = parse_txq_params(tb, &txq_params);
3480 if (result)
a05829a7 3481 goto out;
31888487 3482
9d2bb84d
ST
3483 txq_params.link_id =
3484 nl80211_link_id_or_invalid(info->attrs);
3485
3486 wdev_lock(netdev->ieee80211_ptr);
3487 if (txq_params.link_id >= 0 &&
3488 !(netdev->ieee80211_ptr->valid_links &
3489 BIT(txq_params.link_id)))
3490 result = -ENOLINK;
3491 else if (txq_params.link_id >= 0 &&
3492 !netdev->ieee80211_ptr->valid_links)
3493 result = -EINVAL;
3494 else
3495 result = rdev_set_txq_params(rdev, netdev,
3496 &txq_params);
3497 wdev_unlock(netdev->ieee80211_ptr);
31888487 3498 if (result)
a05829a7 3499 goto out;
31888487
JM
3500 }
3501 }
55682965 3502
72bdcf34 3503 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
69c3f2d3
IP
3504 int link_id = nl80211_link_id_or_invalid(info->attrs);
3505
4e2f3d67
JB
3506 if (wdev) {
3507 wdev_lock(wdev);
3508 result = __nl80211_set_channel(
3509 rdev,
3510 nl80211_can_set_dev_channel(wdev) ? netdev : NULL,
69c3f2d3 3511 info, link_id);
4e2f3d67
JB
3512 wdev_unlock(wdev);
3513 } else {
69c3f2d3 3514 result = __nl80211_set_channel(rdev, netdev, info, link_id);
4e2f3d67 3515 }
69c3f2d3 3516
72bdcf34 3517 if (result)
a05829a7 3518 goto out;
72bdcf34
JM
3519 }
3520
98d2ff8b 3521 if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) {
c8442118 3522 struct wireless_dev *txp_wdev = wdev;
98d2ff8b
JO
3523 enum nl80211_tx_power_setting type;
3524 int idx, mbm = 0;
3525
c8442118
JB
3526 if (!(rdev->wiphy.features & NL80211_FEATURE_VIF_TXPOWER))
3527 txp_wdev = NULL;
3528
a05829a7
JB
3529 if (!rdev->ops->set_tx_power) {
3530 result = -EOPNOTSUPP;
3531 goto out;
3532 }
98d2ff8b
JO
3533
3534 idx = NL80211_ATTR_WIPHY_TX_POWER_SETTING;
3535 type = nla_get_u32(info->attrs[idx]);
3536
3537 if (!info->attrs[NL80211_ATTR_WIPHY_TX_POWER_LEVEL] &&
a05829a7
JB
3538 (type != NL80211_TX_POWER_AUTOMATIC)) {
3539 result = -EINVAL;
3540 goto out;
3541 }
98d2ff8b
JO
3542
3543 if (type != NL80211_TX_POWER_AUTOMATIC) {
3544 idx = NL80211_ATTR_WIPHY_TX_POWER_LEVEL;
3545 mbm = nla_get_u32(info->attrs[idx]);
3546 }
3547
c8442118 3548 result = rdev_set_tx_power(rdev, txp_wdev, type, mbm);
98d2ff8b 3549 if (result)
a05829a7 3550 goto out;
98d2ff8b
JO
3551 }
3552
afe0cbf8
BR
3553 if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
3554 info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {
3555 u32 tx_ant, rx_ant;
7a087e74 3556
7f531e03
BR
3557 if ((!rdev->wiphy.available_antennas_tx &&
3558 !rdev->wiphy.available_antennas_rx) ||
a05829a7
JB
3559 !rdev->ops->set_antenna) {
3560 result = -EOPNOTSUPP;
3561 goto out;
3562 }
afe0cbf8
BR
3563
3564 tx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]);
3565 rx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]);
3566
a7ffac95 3567 /* reject antenna configurations which don't match the
7f531e03
BR
3568 * available antenna masks, except for the "all" mask */
3569 if ((~tx_ant && (tx_ant & ~rdev->wiphy.available_antennas_tx)) ||
a05829a7
JB
3570 (~rx_ant && (rx_ant & ~rdev->wiphy.available_antennas_rx))) {
3571 result = -EINVAL;
3572 goto out;
3573 }
a7ffac95 3574
7f531e03
BR
3575 tx_ant = tx_ant & rdev->wiphy.available_antennas_tx;
3576 rx_ant = rx_ant & rdev->wiphy.available_antennas_rx;
a7ffac95 3577
e35e4d28 3578 result = rdev_set_antenna(rdev, tx_ant, rx_ant);
afe0cbf8 3579 if (result)
a05829a7 3580 goto out;
afe0cbf8
BR
3581 }
3582
b9a5f8ca
JM
3583 changed = 0;
3584
3585 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {
3586 retry_short = nla_get_u8(
3587 info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]);
7f2b8562 3588
b9a5f8ca
JM
3589 changed |= WIPHY_PARAM_RETRY_SHORT;
3590 }
3591
3592 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]) {
3593 retry_long = nla_get_u8(
3594 info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]);
7f2b8562 3595
b9a5f8ca
JM
3596 changed |= WIPHY_PARAM_RETRY_LONG;
3597 }
3598
3599 if (info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) {
3600 frag_threshold = nla_get_u32(
3601 info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]);
a05829a7
JB
3602 if (frag_threshold < 256) {
3603 result = -EINVAL;
3604 goto out;
3605 }
7f2b8562 3606
b9a5f8ca
JM
3607 if (frag_threshold != (u32) -1) {
3608 /*
3609 * Fragments (apart from the last one) are required to
3610 * have even length. Make the fragmentation code
3611 * simpler by stripping LSB should someone try to use
3612 * odd threshold value.
3613 */
3614 frag_threshold &= ~0x1;
3615 }
3616 changed |= WIPHY_PARAM_FRAG_THRESHOLD;
3617 }
3618
3619 if (info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]) {
3620 rts_threshold = nla_get_u32(
3621 info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]);
3622 changed |= WIPHY_PARAM_RTS_THRESHOLD;
3623 }
3624
81077e82 3625 if (info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) {
a05829a7
JB
3626 if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) {
3627 result = -EINVAL;
3628 goto out;
3629 }
3057dbfd 3630
81077e82
LT
3631 coverage_class = nla_get_u8(
3632 info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]);
3633 changed |= WIPHY_PARAM_COVERAGE_CLASS;
3634 }
3635
3057dbfd 3636 if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) {
a05829a7
JB
3637 if (!(rdev->wiphy.features & NL80211_FEATURE_ACKTO_ESTIMATION)) {
3638 result = -EOPNOTSUPP;
3639 goto out;
3640 }
3057dbfd
LB
3641
3642 changed |= WIPHY_PARAM_DYN_ACK;
81077e82
LT
3643 }
3644
52539ca8
THJ
3645 if (info->attrs[NL80211_ATTR_TXQ_LIMIT]) {
3646 if (!wiphy_ext_feature_isset(&rdev->wiphy,
a05829a7
JB
3647 NL80211_EXT_FEATURE_TXQS)) {
3648 result = -EOPNOTSUPP;
3649 goto out;
3650 }
52539ca8
THJ
3651 txq_limit = nla_get_u32(
3652 info->attrs[NL80211_ATTR_TXQ_LIMIT]);
3653 changed |= WIPHY_PARAM_TXQ_LIMIT;
3654 }
3655
3656 if (info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]) {
3657 if (!wiphy_ext_feature_isset(&rdev->wiphy,
a05829a7
JB
3658 NL80211_EXT_FEATURE_TXQS)) {
3659 result = -EOPNOTSUPP;
3660 goto out;
3661 }
52539ca8
THJ
3662 txq_memory_limit = nla_get_u32(
3663 info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]);
3664 changed |= WIPHY_PARAM_TXQ_MEMORY_LIMIT;
3665 }
3666
3667 if (info->attrs[NL80211_ATTR_TXQ_QUANTUM]) {
3668 if (!wiphy_ext_feature_isset(&rdev->wiphy,
a05829a7
JB
3669 NL80211_EXT_FEATURE_TXQS)) {
3670 result = -EOPNOTSUPP;
3671 goto out;
3672 }
52539ca8
THJ
3673 txq_quantum = nla_get_u32(
3674 info->attrs[NL80211_ATTR_TXQ_QUANTUM]);
3675 changed |= WIPHY_PARAM_TXQ_QUANTUM;
3676 }
3677
b9a5f8ca
JM
3678 if (changed) {
3679 u8 old_retry_short, old_retry_long;
3680 u32 old_frag_threshold, old_rts_threshold;
81077e82 3681 u8 old_coverage_class;
52539ca8 3682 u32 old_txq_limit, old_txq_memory_limit, old_txq_quantum;
b9a5f8ca 3683
a05829a7
JB
3684 if (!rdev->ops->set_wiphy_params) {
3685 result = -EOPNOTSUPP;
3686 goto out;
3687 }
b9a5f8ca
JM
3688
3689 old_retry_short = rdev->wiphy.retry_short;
3690 old_retry_long = rdev->wiphy.retry_long;
3691 old_frag_threshold = rdev->wiphy.frag_threshold;
3692 old_rts_threshold = rdev->wiphy.rts_threshold;
81077e82 3693 old_coverage_class = rdev->wiphy.coverage_class;
52539ca8
THJ
3694 old_txq_limit = rdev->wiphy.txq_limit;
3695 old_txq_memory_limit = rdev->wiphy.txq_memory_limit;
3696 old_txq_quantum = rdev->wiphy.txq_quantum;
b9a5f8ca
JM
3697
3698 if (changed & WIPHY_PARAM_RETRY_SHORT)
3699 rdev->wiphy.retry_short = retry_short;
3700 if (changed & WIPHY_PARAM_RETRY_LONG)
3701 rdev->wiphy.retry_long = retry_long;
3702 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
3703 rdev->wiphy.frag_threshold = frag_threshold;
3704 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
3705 rdev->wiphy.rts_threshold = rts_threshold;
81077e82
LT
3706 if (changed & WIPHY_PARAM_COVERAGE_CLASS)
3707 rdev->wiphy.coverage_class = coverage_class;
52539ca8
THJ
3708 if (changed & WIPHY_PARAM_TXQ_LIMIT)
3709 rdev->wiphy.txq_limit = txq_limit;
3710 if (changed & WIPHY_PARAM_TXQ_MEMORY_LIMIT)
3711 rdev->wiphy.txq_memory_limit = txq_memory_limit;
3712 if (changed & WIPHY_PARAM_TXQ_QUANTUM)
3713 rdev->wiphy.txq_quantum = txq_quantum;
b9a5f8ca 3714
e35e4d28 3715 result = rdev_set_wiphy_params(rdev, changed);
b9a5f8ca
JM
3716 if (result) {
3717 rdev->wiphy.retry_short = old_retry_short;
3718 rdev->wiphy.retry_long = old_retry_long;
3719 rdev->wiphy.frag_threshold = old_frag_threshold;
3720 rdev->wiphy.rts_threshold = old_rts_threshold;
81077e82 3721 rdev->wiphy.coverage_class = old_coverage_class;
52539ca8
THJ
3722 rdev->wiphy.txq_limit = old_txq_limit;
3723 rdev->wiphy.txq_memory_limit = old_txq_memory_limit;
3724 rdev->wiphy.txq_quantum = old_txq_quantum;
a05829a7 3725 goto out;
b9a5f8ca
JM
3726 }
3727 }
a05829a7
JB
3728
3729 result = 0;
3730
3731out:
3732 wiphy_unlock(&rdev->wiphy);
3733 return result;
55682965
JB
3734}
3735
683b6d3b 3736static int nl80211_send_chandef(struct sk_buff *msg,
d2859df5 3737 const struct cfg80211_chan_def *chandef)
683b6d3b 3738{
601555cd
JB
3739 if (WARN_ON(!cfg80211_chandef_valid(chandef)))
3740 return -EINVAL;
3d9d1d66 3741
683b6d3b
JB
3742 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
3743 chandef->chan->center_freq))
3744 return -ENOBUFS;
942ba88b
TP
3745 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
3746 chandef->chan->freq_offset))
3747 return -ENOBUFS;
3d9d1d66
JB
3748 switch (chandef->width) {
3749 case NL80211_CHAN_WIDTH_20_NOHT:
3750 case NL80211_CHAN_WIDTH_20:
3751 case NL80211_CHAN_WIDTH_40:
3752 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
3753 cfg80211_get_chandef_type(chandef)))
3754 return -ENOBUFS;
3755 break;
3756 default:
3757 break;
3758 }
3759 if (nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, chandef->width))
3760 return -ENOBUFS;
3761 if (nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ1, chandef->center_freq1))
3762 return -ENOBUFS;
3763 if (chandef->center_freq2 &&
3764 nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2, chandef->center_freq2))
683b6d3b
JB
3765 return -ENOBUFS;
3766 return 0;
3767}
3768
15e47304 3769static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags,
d726405a 3770 struct cfg80211_registered_device *rdev,
3d1a5bbf
AZ
3771 struct wireless_dev *wdev,
3772 enum nl80211_commands cmd)
55682965 3773{
72fb2abc 3774 struct net_device *dev = wdev->netdev;
55682965
JB
3775 void *hdr;
3776
3d1a5bbf
AZ
3777 WARN_ON(cmd != NL80211_CMD_NEW_INTERFACE &&
3778 cmd != NL80211_CMD_DEL_INTERFACE &&
3779 cmd != NL80211_CMD_SET_INTERFACE);
8f894be2
TB
3780
3781 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
55682965
JB
3782 if (!hdr)
3783 return -1;
3784
72fb2abc
JB
3785 if (dev &&
3786 (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
98104fde 3787 nla_put_string(msg, NL80211_ATTR_IFNAME, dev->name)))
72fb2abc
JB
3788 goto nla_put_failure;
3789
3790 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
3791 nla_put_u32(msg, NL80211_ATTR_IFTYPE, wdev->iftype) ||
2dad624e
ND
3792 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
3793 NL80211_ATTR_PAD) ||
98104fde 3794 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, wdev_address(wdev)) ||
9360ffd1
DM
3795 nla_put_u32(msg, NL80211_ATTR_GENERATION,
3796 rdev->devlist_generation ^
446faa15
AQ
3797 (cfg80211_rdev_list_generation << 2)) ||
3798 nla_put_u8(msg, NL80211_ATTR_4ADDR, wdev->use_4addr))
9360ffd1 3799 goto nla_put_failure;
f5ea9120 3800
7b0a0e3c 3801 if (rdev->ops->get_channel && !wdev->valid_links) {
f43e5210 3802 struct cfg80211_chan_def chandef = {};
7b0a0e3c 3803 int ret;
683b6d3b 3804
7b0a0e3c
JB
3805 ret = rdev_get_channel(rdev, wdev, 0, &chandef);
3806 if (ret == 0 && nl80211_send_chandef(msg, &chandef))
3807 goto nla_put_failure;
d91df0e3
PF
3808 }
3809
d55d0d59
RM
3810 if (rdev->ops->get_tx_power) {
3811 int dbm, ret;
3812
3813 ret = rdev_get_tx_power(rdev, wdev, &dbm);
3814 if (ret == 0 &&
3815 nla_put_u32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL,
3816 DBM_TO_MBM(dbm)))
3817 goto nla_put_failure;
3818 }
3819
44905265
JB
3820 wdev_lock(wdev);
3821 switch (wdev->iftype) {
3822 case NL80211_IFTYPE_AP:
a75971bc 3823 case NL80211_IFTYPE_P2P_GO:
7b0a0e3c
JB
3824 if (wdev->u.ap.ssid_len &&
3825 nla_put(msg, NL80211_ATTR_SSID, wdev->u.ap.ssid_len,
3826 wdev->u.ap.ssid))
4564b187 3827 goto nla_put_failure_locked;
44905265
JB
3828 break;
3829 case NL80211_IFTYPE_STATION:
3830 case NL80211_IFTYPE_P2P_CLIENT:
7b0a0e3c
JB
3831 if (wdev->u.client.ssid_len &&
3832 nla_put(msg, NL80211_ATTR_SSID, wdev->u.client.ssid_len,
3833 wdev->u.client.ssid))
3834 goto nla_put_failure_locked;
3835 break;
3836 case NL80211_IFTYPE_ADHOC:
3837 if (wdev->u.ibss.ssid_len &&
3838 nla_put(msg, NL80211_ATTR_SSID, wdev->u.ibss.ssid_len,
3839 wdev->u.ibss.ssid))
3840 goto nla_put_failure_locked;
44905265 3841 break;
44905265
JB
3842 default:
3843 /* nothing */
3844 break;
b84e7a05 3845 }
44905265 3846 wdev_unlock(wdev);
b84e7a05 3847
52539ca8
THJ
3848 if (rdev->ops->get_txq_stats) {
3849 struct cfg80211_txq_stats txqstats = {};
3850 int ret = rdev_get_txq_stats(rdev, wdev, &txqstats);
3851
3852 if (ret == 0 &&
3853 !nl80211_put_txq_stats(msg, &txqstats,
3854 NL80211_ATTR_TXQ_STATS))
3855 goto nla_put_failure;
3856 }
3857
ce08cd34
JB
3858 if (wdev->valid_links) {
3859 unsigned int link_id;
3860 struct nlattr *links = nla_nest_start(msg,
3861 NL80211_ATTR_MLO_LINKS);
3862
3863 if (!links)
3864 goto nla_put_failure;
3865
3866 for_each_valid_link(wdev, link_id) {
3867 struct nlattr *link = nla_nest_start(msg, link_id + 1);
3868
3869 if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id))
3870 goto nla_put_failure;
3871 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
3872 wdev->links[link_id].addr))
3873 goto nla_put_failure;
3874 nla_nest_end(msg, link);
3875 }
3876
3877 nla_nest_end(msg, links);
3878 }
3879
053c095a
JB
3880 genlmsg_end(msg, hdr);
3881 return 0;
55682965 3882
4564b187
JB
3883 nla_put_failure_locked:
3884 wdev_unlock(wdev);
55682965 3885 nla_put_failure:
bc3ed28c
TG
3886 genlmsg_cancel(msg, hdr);
3887 return -EMSGSIZE;
55682965
JB
3888}
3889
3890static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
3891{
3892 int wp_idx = 0;
3893 int if_idx = 0;
3894 int wp_start = cb->args[0];
3895 int if_start = cb->args[1];
b7fb44da 3896 int filter_wiphy = -1;
f5ea9120 3897 struct cfg80211_registered_device *rdev;
55682965 3898 struct wireless_dev *wdev;
ea90e0dc 3899 int ret;
55682965 3900
5fe231e8 3901 rtnl_lock();
b7fb44da
DK
3902 if (!cb->args[2]) {
3903 struct nl80211_dump_wiphy_state state = {
3904 .filter_wiphy = -1,
3905 };
b7fb44da
DK
3906
3907 ret = nl80211_dump_wiphy_parse(skb, cb, &state);
3908 if (ret)
ea90e0dc 3909 goto out_unlock;
b7fb44da
DK
3910
3911 filter_wiphy = state.filter_wiphy;
3912
3913 /*
3914 * if filtering, set cb->args[2] to +1 since 0 is the default
3915 * value needed to determine that parsing is necessary.
3916 */
3917 if (filter_wiphy >= 0)
3918 cb->args[2] = filter_wiphy + 1;
3919 else
3920 cb->args[2] = -1;
3921 } else if (cb->args[2] > 0) {
3922 filter_wiphy = cb->args[2] - 1;
3923 }
3924
f5ea9120
JB
3925 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
3926 if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
463d0183 3927 continue;
bba95fef
JB
3928 if (wp_idx < wp_start) {
3929 wp_idx++;
55682965 3930 continue;
bba95fef 3931 }
b7fb44da
DK
3932
3933 if (filter_wiphy >= 0 && filter_wiphy != rdev->wiphy_idx)
3934 continue;
3935
55682965
JB
3936 if_idx = 0;
3937
53873f13 3938 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
bba95fef
JB
3939 if (if_idx < if_start) {
3940 if_idx++;
55682965 3941 continue;
bba95fef 3942 }
15e47304 3943 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid,
55682965 3944 cb->nlh->nlmsg_seq, NLM_F_MULTI,
3d1a5bbf
AZ
3945 rdev, wdev,
3946 NL80211_CMD_NEW_INTERFACE) < 0) {
bba95fef
JB
3947 goto out;
3948 }
3949 if_idx++;
55682965 3950 }
bba95fef
JB
3951
3952 wp_idx++;
55682965 3953 }
bba95fef 3954 out:
55682965
JB
3955 cb->args[0] = wp_idx;
3956 cb->args[1] = if_idx;
3957
ea90e0dc
JB
3958 ret = skb->len;
3959 out_unlock:
3960 rtnl_unlock();
3961
3962 return ret;
55682965
JB
3963}
3964
3965static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
3966{
3967 struct sk_buff *msg;
1b8ec87a 3968 struct cfg80211_registered_device *rdev = info->user_ptr[0];
72fb2abc 3969 struct wireless_dev *wdev = info->user_ptr[1];
55682965 3970
fd2120ca 3971 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
55682965 3972 if (!msg)
4c476991 3973 return -ENOMEM;
55682965 3974
15e47304 3975 if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0,
3d1a5bbf 3976 rdev, wdev, NL80211_CMD_NEW_INTERFACE) < 0) {
4c476991
JB
3977 nlmsg_free(msg);
3978 return -ENOBUFS;
3979 }
55682965 3980
134e6375 3981 return genlmsg_reply(msg, info);
55682965
JB
3982}
3983
66f7ac50
MW
3984static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = {
3985 [NL80211_MNTR_FLAG_FCSFAIL] = { .type = NLA_FLAG },
3986 [NL80211_MNTR_FLAG_PLCPFAIL] = { .type = NLA_FLAG },
3987 [NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG },
3988 [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG },
3989 [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG },
e057d3c3 3990 [NL80211_MNTR_FLAG_ACTIVE] = { .type = NLA_FLAG },
66f7ac50
MW
3991};
3992
3993static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
3994{
3995 struct nlattr *flags[NL80211_MNTR_FLAG_MAX + 1];
3996 int flag;
3997
3998 *mntrflags = 0;
3999
4000 if (!nla)
4001 return -EINVAL;
4002
8cb08174 4003 if (nla_parse_nested_deprecated(flags, NL80211_MNTR_FLAG_MAX, nla, mntr_flags_policy, NULL))
66f7ac50
MW
4004 return -EINVAL;
4005
4006 for (flag = 1; flag <= NL80211_MNTR_FLAG_MAX; flag++)
4007 if (flags[flag])
4008 *mntrflags |= (1<<flag);
4009
818a986e
JB
4010 *mntrflags |= MONITOR_FLAG_CHANGED;
4011
66f7ac50
MW
4012 return 0;
4013}
4014
1db77596
JB
4015static int nl80211_parse_mon_options(struct cfg80211_registered_device *rdev,
4016 enum nl80211_iftype type,
4017 struct genl_info *info,
4018 struct vif_params *params)
4019{
4020 bool change = false;
4021 int err;
4022
4023 if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
4024 if (type != NL80211_IFTYPE_MONITOR)
4025 return -EINVAL;
4026
4027 err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS],
4028 &params->flags);
4029 if (err)
4030 return err;
4031
4032 change = true;
4033 }
4034
4035 if (params->flags & MONITOR_FLAG_ACTIVE &&
4036 !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR))
4037 return -EOPNOTSUPP;
4038
4039 if (info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]) {
4040 const u8 *mumimo_groups;
4041 u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
4042
4043 if (type != NL80211_IFTYPE_MONITOR)
4044 return -EINVAL;
4045
4046 if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
4047 return -EOPNOTSUPP;
4048
4049 mumimo_groups =
4050 nla_data(info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]);
4051
4052 /* bits 0 and 63 are reserved and must be zero */
4954601f
JB
4053 if ((mumimo_groups[0] & BIT(0)) ||
4054 (mumimo_groups[VHT_MUMIMO_GROUPS_DATA_LEN - 1] & BIT(7)))
1db77596
JB
4055 return -EINVAL;
4056
4057 params->vht_mumimo_groups = mumimo_groups;
4058 change = true;
4059 }
4060
4061 if (info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]) {
4062 u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
4063
4064 if (type != NL80211_IFTYPE_MONITOR)
4065 return -EINVAL;
4066
4067 if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
4068 return -EOPNOTSUPP;
4069
4070 params->vht_mumimo_follow_addr =
4071 nla_data(info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]);
4072 change = true;
4073 }
4074
4075 return change ? 1 : 0;
4076}
4077
9bc383de 4078static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev,
ad4bb6f8
JB
4079 struct net_device *netdev, u8 use_4addr,
4080 enum nl80211_iftype iftype)
9bc383de 4081{
ad4bb6f8 4082 if (!use_4addr) {
2e92a2d0 4083 if (netdev && netif_is_bridge_port(netdev))
ad4bb6f8 4084 return -EBUSY;
9bc383de 4085 return 0;
ad4bb6f8 4086 }
9bc383de
JB
4087
4088 switch (iftype) {
4089 case NL80211_IFTYPE_AP_VLAN:
4090 if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP)
4091 return 0;
4092 break;
4093 case NL80211_IFTYPE_STATION:
4094 if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_STATION)
4095 return 0;
4096 break;
4097 default:
4098 break;
4099 }
4100
4101 return -EOPNOTSUPP;
4102}
4103
55682965
JB
4104static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
4105{
4c476991 4106 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2ec600d6 4107 struct vif_params params;
e36d56b6 4108 int err;
04a773ad 4109 enum nl80211_iftype otype, ntype;
4c476991 4110 struct net_device *dev = info->user_ptr[1];
ac7f9cfa 4111 bool change = false;
55682965 4112
2ec600d6
LCC
4113 memset(&params, 0, sizeof(params));
4114
04a773ad 4115 otype = ntype = dev->ieee80211_ptr->iftype;
55682965 4116
723b038d 4117 if (info->attrs[NL80211_ATTR_IFTYPE]) {
ac7f9cfa 4118 ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
04a773ad 4119 if (otype != ntype)
ac7f9cfa 4120 change = true;
723b038d
JB
4121 }
4122
92ffe055 4123 if (info->attrs[NL80211_ATTR_MESH_ID]) {
29cbe68c
JB
4124 struct wireless_dev *wdev = dev->ieee80211_ptr;
4125
4c476991
JB
4126 if (ntype != NL80211_IFTYPE_MESH_POINT)
4127 return -EINVAL;
29cbe68c
JB
4128 if (netif_running(dev))
4129 return -EBUSY;
4130
4131 wdev_lock(wdev);
4132 BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN !=
4133 IEEE80211_MAX_MESH_ID_LEN);
7b0a0e3c 4134 wdev->u.mesh.id_up_len =
29cbe68c 4135 nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
7b0a0e3c
JB
4136 memcpy(wdev->u.mesh.id,
4137 nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
4138 wdev->u.mesh.id_up_len);
29cbe68c 4139 wdev_unlock(wdev);
2ec600d6
LCC
4140 }
4141
8b787643
FF
4142 if (info->attrs[NL80211_ATTR_4ADDR]) {
4143 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
4144 change = true;
ad4bb6f8 4145 err = nl80211_valid_4addr(rdev, dev, params.use_4addr, ntype);
9bc383de 4146 if (err)
4c476991 4147 return err;
8b787643
FF
4148 } else {
4149 params.use_4addr = -1;
4150 }
4151
1db77596
JB
4152 err = nl80211_parse_mon_options(rdev, ntype, info, &params);
4153 if (err < 0)
4154 return err;
4155 if (err > 0)
c6e6a0c8 4156 change = true;
e057d3c3 4157
ac7f9cfa 4158 if (change)
818a986e 4159 err = cfg80211_change_iface(rdev, dev, ntype, &params);
ac7f9cfa
JB
4160 else
4161 err = 0;
60719ffd 4162
9bc383de
JB
4163 if (!err && params.use_4addr != -1)
4164 dev->ieee80211_ptr->use_4addr = params.use_4addr;
4165
3d1a5bbf
AZ
4166 if (change && !err) {
4167 struct wireless_dev *wdev = dev->ieee80211_ptr;
4168
4169 nl80211_notify_iface(rdev, wdev, NL80211_CMD_SET_INTERFACE);
4170 }
4171
55682965
JB
4172 return err;
4173}
4174
ea6b2098 4175static int _nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
55682965 4176{
4c476991 4177 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2ec600d6 4178 struct vif_params params;
84efbb84 4179 struct wireless_dev *wdev;
896ff063 4180 struct sk_buff *msg;
55682965
JB
4181 int err;
4182 enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
4183
2ec600d6
LCC
4184 memset(&params, 0, sizeof(params));
4185
55682965
JB
4186 if (!info->attrs[NL80211_ATTR_IFNAME])
4187 return -EINVAL;
4188
ab0d76f6 4189 if (info->attrs[NL80211_ATTR_IFTYPE])
55682965 4190 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
55682965 4191
33d915d9 4192 if (!rdev->ops->add_virtual_intf)
4c476991 4193 return -EOPNOTSUPP;
55682965 4194
cb3b7d87 4195 if ((type == NL80211_IFTYPE_P2P_DEVICE || type == NL80211_IFTYPE_NAN ||
e8f479b1
BG
4196 rdev->wiphy.features & NL80211_FEATURE_MAC_ON_CREATE) &&
4197 info->attrs[NL80211_ATTR_MAC]) {
1c18f145
AS
4198 nla_memcpy(params.macaddr, info->attrs[NL80211_ATTR_MAC],
4199 ETH_ALEN);
4200 if (!is_valid_ether_addr(params.macaddr))
4201 return -EADDRNOTAVAIL;
4202 }
4203
9bc383de 4204 if (info->attrs[NL80211_ATTR_4ADDR]) {
8b787643 4205 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
ad4bb6f8 4206 err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type);
9bc383de 4207 if (err)
4c476991 4208 return err;
9bc383de 4209 }
8b787643 4210
e6f40511 4211 if (!cfg80211_iftype_allowed(&rdev->wiphy, type, params.use_4addr, 0))
33d915d9
MP
4212 return -EOPNOTSUPP;
4213
1db77596
JB
4214 err = nl80211_parse_mon_options(rdev, type, info, &params);
4215 if (err < 0)
4216 return err;
e057d3c3 4217
a18c7192
JB
4218 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4219 if (!msg)
4220 return -ENOMEM;
4221
e35e4d28
HG
4222 wdev = rdev_add_virtual_intf(rdev,
4223 nla_data(info->attrs[NL80211_ATTR_IFNAME]),
818a986e 4224 NET_NAME_USER, type, &params);
d687cbb7
RM
4225 if (WARN_ON(!wdev)) {
4226 nlmsg_free(msg);
4227 return -EPROTO;
4228 } else if (IS_ERR(wdev)) {
1c90f9d4 4229 nlmsg_free(msg);
84efbb84 4230 return PTR_ERR(wdev);
1c90f9d4 4231 }
2ec600d6 4232
18e5ca65 4233 if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
78f22b6a
JB
4234 wdev->owner_nlportid = info->snd_portid;
4235
98104fde
JB
4236 switch (type) {
4237 case NL80211_IFTYPE_MESH_POINT:
4238 if (!info->attrs[NL80211_ATTR_MESH_ID])
4239 break;
29cbe68c
JB
4240 wdev_lock(wdev);
4241 BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN !=
4242 IEEE80211_MAX_MESH_ID_LEN);
7b0a0e3c 4243 wdev->u.mesh.id_up_len =
29cbe68c 4244 nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
7b0a0e3c
JB
4245 memcpy(wdev->u.mesh.id,
4246 nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
4247 wdev->u.mesh.id_up_len);
29cbe68c 4248 wdev_unlock(wdev);
98104fde 4249 break;
cb3b7d87 4250 case NL80211_IFTYPE_NAN:
98104fde
JB
4251 case NL80211_IFTYPE_P2P_DEVICE:
4252 /*
cb3b7d87 4253 * P2P Device and NAN do not have a netdev, so don't go
98104fde
JB
4254 * through the netdev notifier and must be added here
4255 */
9bdaf3b9
JB
4256 cfg80211_init_wdev(wdev);
4257 cfg80211_register_wdev(rdev, wdev);
98104fde
JB
4258 break;
4259 default:
4260 break;
29cbe68c
JB
4261 }
4262
15e47304 4263 if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0,
3d1a5bbf 4264 rdev, wdev, NL80211_CMD_NEW_INTERFACE) < 0) {
1c90f9d4
JB
4265 nlmsg_free(msg);
4266 return -ENOBUFS;
4267 }
4268
4269 return genlmsg_reply(msg, info);
55682965
JB
4270}
4271
ea6b2098
JB
4272static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
4273{
4274 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4275 int ret;
4276
4277 /* to avoid failing a new interface creation due to pending removal */
4278 cfg80211_destroy_ifaces(rdev);
4279
4280 wiphy_lock(&rdev->wiphy);
4281 ret = _nl80211_new_interface(skb, info);
4282 wiphy_unlock(&rdev->wiphy);
4283
4284 return ret;
4285}
4286
55682965
JB
4287static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
4288{
4c476991 4289 struct cfg80211_registered_device *rdev = info->user_ptr[0];
84efbb84 4290 struct wireless_dev *wdev = info->user_ptr[1];
55682965 4291
4c476991
JB
4292 if (!rdev->ops->del_virtual_intf)
4293 return -EOPNOTSUPP;
55682965 4294
a05829a7
JB
4295 /*
4296 * We hold RTNL, so this is safe, without RTNL opencount cannot
4297 * reach 0, and thus the rdev cannot be deleted.
4298 *
4299 * We need to do it for the dev_close(), since that will call
4300 * the netdev notifiers, and we need to acquire the mutex there
4301 * but don't know if we get there from here or from some other
4302 * place (e.g. "ip link set ... down").
4303 */
4304 mutex_unlock(&rdev->wiphy.mtx);
4305
84efbb84
JB
4306 /*
4307 * If we remove a wireless device without a netdev then clear
4308 * user_ptr[1] so that nl80211_post_doit won't dereference it
4309 * to check if it needs to do dev_put(). Otherwise it crashes
4310 * since the wdev has been freed, unlike with a netdev where
4311 * we need the dev_put() for the netdev to really be freed.
4312 */
4313 if (!wdev->netdev)
4314 info->user_ptr[1] = NULL;
a05829a7
JB
4315 else
4316 dev_close(wdev->netdev);
4317
4318 mutex_lock(&rdev->wiphy.mtx);
84efbb84 4319
cdf0a0a8 4320 return cfg80211_remove_virtual_intf(rdev, wdev);
55682965
JB
4321}
4322
1d9d9213
SW
4323static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info)
4324{
4325 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4326 struct net_device *dev = info->user_ptr[1];
4327 u16 noack_map;
4328
4329 if (!info->attrs[NL80211_ATTR_NOACK_MAP])
4330 return -EINVAL;
4331
4332 if (!rdev->ops->set_noack_map)
4333 return -EOPNOTSUPP;
4334
4335 noack_map = nla_get_u16(info->attrs[NL80211_ATTR_NOACK_MAP]);
4336
e35e4d28 4337 return rdev_set_noack_map(rdev, dev, noack_map);
1d9d9213
SW
4338}
4339
e7a7b84e
VJ
4340static int nl80211_validate_key_link_id(struct genl_info *info,
4341 struct wireless_dev *wdev,
4342 int link_id, bool pairwise)
4343{
4344 if (pairwise) {
4345 if (link_id != -1) {
4346 GENL_SET_ERR_MSG(info,
4347 "link ID not allowed for pairwise key");
4348 return -EINVAL;
4349 }
4350
4351 return 0;
4352 }
4353
4354 if (wdev->valid_links) {
4355 if (link_id == -1) {
4356 GENL_SET_ERR_MSG(info,
4357 "link ID must for MLO group key");
4358 return -EINVAL;
4359 }
4360 if (!(wdev->valid_links & BIT(link_id))) {
4361 GENL_SET_ERR_MSG(info, "invalid link ID for MLO group key");
4362 return -EINVAL;
4363 }
4364 } else if (link_id != -1) {
4365 GENL_SET_ERR_MSG(info, "link ID not allowed for non-MLO group key");
4366 return -EINVAL;
4367 }
4368
4369 return 0;
4370}
4371
41ade00f
JB
4372struct get_key_cookie {
4373 struct sk_buff *msg;
4374 int error;
b9454e83 4375 int idx;
41ade00f
JB
4376};
4377
4378static void get_key_callback(void *c, struct key_params *params)
4379{
b9454e83 4380 struct nlattr *key;
41ade00f
JB
4381 struct get_key_cookie *cookie = c;
4382
9360ffd1
DM
4383 if ((params->key &&
4384 nla_put(cookie->msg, NL80211_ATTR_KEY_DATA,
4385 params->key_len, params->key)) ||
4386 (params->seq &&
4387 nla_put(cookie->msg, NL80211_ATTR_KEY_SEQ,
4388 params->seq_len, params->seq)) ||
4389 (params->cipher &&
4390 nla_put_u32(cookie->msg, NL80211_ATTR_KEY_CIPHER,
4391 params->cipher)))
4392 goto nla_put_failure;
41ade00f 4393
ae0be8de 4394 key = nla_nest_start_noflag(cookie->msg, NL80211_ATTR_KEY);
b9454e83
JB
4395 if (!key)
4396 goto nla_put_failure;
4397
9360ffd1
DM
4398 if ((params->key &&
4399 nla_put(cookie->msg, NL80211_KEY_DATA,
4400 params->key_len, params->key)) ||
4401 (params->seq &&
4402 nla_put(cookie->msg, NL80211_KEY_SEQ,
4403 params->seq_len, params->seq)) ||
4404 (params->cipher &&
4405 nla_put_u32(cookie->msg, NL80211_KEY_CIPHER,
4406 params->cipher)))
4407 goto nla_put_failure;
b9454e83 4408
efdfce72 4409 if (nla_put_u8(cookie->msg, NL80211_KEY_IDX, cookie->idx))
9360ffd1 4410 goto nla_put_failure;
b9454e83
JB
4411
4412 nla_nest_end(cookie->msg, key);
4413
41ade00f
JB
4414 return;
4415 nla_put_failure:
4416 cookie->error = 1;
4417}
4418
4419static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
4420{
4c476991 4421 struct cfg80211_registered_device *rdev = info->user_ptr[0];
41ade00f 4422 int err;
4c476991 4423 struct net_device *dev = info->user_ptr[1];
41ade00f 4424 u8 key_idx = 0;
e31b8213
JB
4425 const u8 *mac_addr = NULL;
4426 bool pairwise;
41ade00f
JB
4427 struct get_key_cookie cookie = {
4428 .error = 0,
4429 };
4430 void *hdr;
4431 struct sk_buff *msg;
155d7c73 4432 bool bigtk_support = false;
e7a7b84e
VJ
4433 int link_id = nl80211_link_id_or_invalid(info->attrs);
4434 struct wireless_dev *wdev = dev->ieee80211_ptr;
155d7c73
JB
4435
4436 if (wiphy_ext_feature_isset(&rdev->wiphy,
4437 NL80211_EXT_FEATURE_BEACON_PROTECTION))
4438 bigtk_support = true;
4439
e7a7b84e
VJ
4440 if ((wdev->iftype == NL80211_IFTYPE_STATION ||
4441 wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
155d7c73
JB
4442 wiphy_ext_feature_isset(&rdev->wiphy,
4443 NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT))
4444 bigtk_support = true;
41ade00f 4445
56be393f 4446 if (info->attrs[NL80211_ATTR_KEY_IDX]) {
41ade00f 4447 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
155d7c73
JB
4448
4449 if (key_idx >= 6 && key_idx <= 7 && !bigtk_support) {
4450 GENL_SET_ERR_MSG(info, "BIGTK not supported");
56be393f 4451 return -EINVAL;
155d7c73 4452 }
56be393f 4453 }
41ade00f 4454
41ade00f
JB
4455 if (info->attrs[NL80211_ATTR_MAC])
4456 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4457
e31b8213
JB
4458 pairwise = !!mac_addr;
4459 if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
4460 u32 kt = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
7a087e74 4461
e31b8213
JB
4462 if (kt != NL80211_KEYTYPE_GROUP &&
4463 kt != NL80211_KEYTYPE_PAIRWISE)
4464 return -EINVAL;
4465 pairwise = kt == NL80211_KEYTYPE_PAIRWISE;
4466 }
4467
4c476991
JB
4468 if (!rdev->ops->get_key)
4469 return -EOPNOTSUPP;
41ade00f 4470
0fa7b391
JB
4471 if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
4472 return -ENOENT;
4473
fd2120ca 4474 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
4475 if (!msg)
4476 return -ENOMEM;
41ade00f 4477
15e47304 4478 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
41ade00f 4479 NL80211_CMD_NEW_KEY);
cb35fba3 4480 if (!hdr)
9fe271af 4481 goto nla_put_failure;
41ade00f
JB
4482
4483 cookie.msg = msg;
b9454e83 4484 cookie.idx = key_idx;
41ade00f 4485
9360ffd1
DM
4486 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
4487 nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx))
4488 goto nla_put_failure;
4489 if (mac_addr &&
4490 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr))
4491 goto nla_put_failure;
41ade00f 4492
e7a7b84e
VJ
4493 err = nl80211_validate_key_link_id(info, wdev, link_id, pairwise);
4494 if (err)
4495 goto free_msg;
4496
4497 err = rdev_get_key(rdev, dev, link_id, key_idx, pairwise, mac_addr,
4498 &cookie, get_key_callback);
41ade00f
JB
4499
4500 if (err)
6c95e2a2 4501 goto free_msg;
41ade00f
JB
4502
4503 if (cookie.error)
4504 goto nla_put_failure;
4505
4506 genlmsg_end(msg, hdr);
4c476991 4507 return genlmsg_reply(msg, info);
41ade00f
JB
4508
4509 nla_put_failure:
4510 err = -ENOBUFS;
6c95e2a2 4511 free_msg:
41ade00f 4512 nlmsg_free(msg);
41ade00f
JB
4513 return err;
4514}
4515
4516static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
4517{
4c476991 4518 struct cfg80211_registered_device *rdev = info->user_ptr[0];
b9454e83 4519 struct key_parse key;
41ade00f 4520 int err;
4c476991 4521 struct net_device *dev = info->user_ptr[1];
e7a7b84e
VJ
4522 int link_id = nl80211_link_id_or_invalid(info->attrs);
4523 struct wireless_dev *wdev = dev->ieee80211_ptr;
41ade00f 4524
b9454e83
JB
4525 err = nl80211_parse_key(info, &key);
4526 if (err)
4527 return err;
41ade00f 4528
b9454e83 4529 if (key.idx < 0)
41ade00f
JB
4530 return -EINVAL;
4531
6cdd3979
AW
4532 /* Only support setting default key and
4533 * Extended Key ID action NL80211_KEY_SET_TX.
4534 */
56be393f 4535 if (!key.def && !key.defmgmt && !key.defbeacon &&
6cdd3979 4536 !(key.p.mode == NL80211_KEY_SET_TX))
41ade00f
JB
4537 return -EINVAL;
4538
e7a7b84e 4539 wdev_lock(wdev);
3cfcf6ac 4540
dbd2fd65
JB
4541 if (key.def) {
4542 if (!rdev->ops->set_default_key) {
4543 err = -EOPNOTSUPP;
4544 goto out;
4545 }
41ade00f 4546
e7a7b84e
VJ
4547 err = nl80211_key_allowed(wdev);
4548 if (err)
4549 goto out;
4550
4551 err = nl80211_validate_key_link_id(info, wdev, link_id, false);
dbd2fd65
JB
4552 if (err)
4553 goto out;
4554
e7a7b84e
VJ
4555 err = rdev_set_default_key(rdev, dev, link_id, key.idx,
4556 key.def_uni, key.def_multi);
dbd2fd65
JB
4557
4558 if (err)
4559 goto out;
fffd0934 4560
3d23e349 4561#ifdef CONFIG_CFG80211_WEXT
e7a7b84e 4562 wdev->wext.default_key = key.idx;
dbd2fd65 4563#endif
6cdd3979 4564 } else if (key.defmgmt) {
dbd2fd65
JB
4565 if (key.def_uni || !key.def_multi) {
4566 err = -EINVAL;
4567 goto out;
4568 }
4569
4570 if (!rdev->ops->set_default_mgmt_key) {
4571 err = -EOPNOTSUPP;
4572 goto out;
4573 }
4574
e7a7b84e
VJ
4575 err = nl80211_key_allowed(wdev);
4576 if (err)
4577 goto out;
4578
4579 err = nl80211_validate_key_link_id(info, wdev, link_id, false);
dbd2fd65
JB
4580 if (err)
4581 goto out;
4582
e7a7b84e 4583 err = rdev_set_default_mgmt_key(rdev, dev, link_id, key.idx);
dbd2fd65
JB
4584 if (err)
4585 goto out;
4586
4587#ifdef CONFIG_CFG80211_WEXT
e7a7b84e 4588 wdev->wext.default_mgmt_key = key.idx;
08645126 4589#endif
56be393f
JM
4590 } else if (key.defbeacon) {
4591 if (key.def_uni || !key.def_multi) {
4592 err = -EINVAL;
4593 goto out;
4594 }
4595
4596 if (!rdev->ops->set_default_beacon_key) {
4597 err = -EOPNOTSUPP;
4598 goto out;
4599 }
4600
e7a7b84e 4601 err = nl80211_key_allowed(wdev);
56be393f
JM
4602 if (err)
4603 goto out;
4604
e7a7b84e
VJ
4605 err = nl80211_validate_key_link_id(info, wdev, link_id, false);
4606 if (err)
4607 goto out;
4608
4609 err = rdev_set_default_beacon_key(rdev, dev, link_id, key.idx);
56be393f
JM
4610 if (err)
4611 goto out;
6cdd3979
AW
4612 } else if (key.p.mode == NL80211_KEY_SET_TX &&
4613 wiphy_ext_feature_isset(&rdev->wiphy,
4614 NL80211_EXT_FEATURE_EXT_KEY_ID)) {
4615 u8 *mac_addr = NULL;
4616
4617 if (info->attrs[NL80211_ATTR_MAC])
4618 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4619
4620 if (!mac_addr || key.idx < 0 || key.idx > 1) {
4621 err = -EINVAL;
4622 goto out;
4623 }
dbd2fd65 4624
e7a7b84e
VJ
4625 err = nl80211_validate_key_link_id(info, wdev, link_id, true);
4626 if (err)
4627 goto out;
4628
4629 err = rdev_add_key(rdev, dev, link_id, key.idx,
6cdd3979
AW
4630 NL80211_KEYTYPE_PAIRWISE,
4631 mac_addr, &key.p);
4632 } else {
4633 err = -EINVAL;
4634 }
dbd2fd65 4635 out:
e7a7b84e 4636 wdev_unlock(wdev);
41ade00f 4637
41ade00f
JB
4638 return err;
4639}
4640
4641static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
4642{
4c476991 4643 struct cfg80211_registered_device *rdev = info->user_ptr[0];
fffd0934 4644 int err;
4c476991 4645 struct net_device *dev = info->user_ptr[1];
b9454e83 4646 struct key_parse key;
e31b8213 4647 const u8 *mac_addr = NULL;
e7a7b84e
VJ
4648 int link_id = nl80211_link_id_or_invalid(info->attrs);
4649 struct wireless_dev *wdev = dev->ieee80211_ptr;
41ade00f 4650
b9454e83
JB
4651 err = nl80211_parse_key(info, &key);
4652 if (err)
4653 return err;
41ade00f 4654
f8af764b
JM
4655 if (!key.p.key) {
4656 GENL_SET_ERR_MSG(info, "no key");
41ade00f 4657 return -EINVAL;
f8af764b 4658 }
41ade00f 4659
41ade00f
JB
4660 if (info->attrs[NL80211_ATTR_MAC])
4661 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4662
e31b8213
JB
4663 if (key.type == -1) {
4664 if (mac_addr)
4665 key.type = NL80211_KEYTYPE_PAIRWISE;
4666 else
4667 key.type = NL80211_KEYTYPE_GROUP;
4668 }
4669
4670 /* for now */
4671 if (key.type != NL80211_KEYTYPE_PAIRWISE &&
f8af764b
JM
4672 key.type != NL80211_KEYTYPE_GROUP) {
4673 GENL_SET_ERR_MSG(info, "key type not pairwise or group");
e31b8213 4674 return -EINVAL;
f8af764b 4675 }
e31b8213 4676
14f34e36
GG
4677 if (key.type == NL80211_KEYTYPE_GROUP &&
4678 info->attrs[NL80211_ATTR_VLAN_ID])
4679 key.p.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
4680
4c476991
JB
4681 if (!rdev->ops->add_key)
4682 return -EOPNOTSUPP;
25e47c18 4683
e31b8213
JB
4684 if (cfg80211_validate_key_settings(rdev, &key.p, key.idx,
4685 key.type == NL80211_KEYTYPE_PAIRWISE,
f8af764b
JM
4686 mac_addr)) {
4687 GENL_SET_ERR_MSG(info, "key setting validation failed");
4c476991 4688 return -EINVAL;
f8af764b 4689 }
41ade00f 4690
e7a7b84e
VJ
4691 wdev_lock(wdev);
4692 err = nl80211_key_allowed(wdev);
f8af764b
JM
4693 if (err)
4694 GENL_SET_ERR_MSG(info, "key not allowed");
e7a7b84e
VJ
4695
4696 if (!err)
4697 err = nl80211_validate_key_link_id(info, wdev, link_id,
4698 key.type == NL80211_KEYTYPE_PAIRWISE);
4699
f8af764b 4700 if (!err) {
e7a7b84e 4701 err = rdev_add_key(rdev, dev, link_id, key.idx,
e35e4d28
HG
4702 key.type == NL80211_KEYTYPE_PAIRWISE,
4703 mac_addr, &key.p);
f8af764b
JM
4704 if (err)
4705 GENL_SET_ERR_MSG(info, "key addition failed");
4706 }
e7a7b84e 4707 wdev_unlock(wdev);
41ade00f 4708
41ade00f
JB
4709 return err;
4710}
4711
4712static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
4713{
4c476991 4714 struct cfg80211_registered_device *rdev = info->user_ptr[0];
41ade00f 4715 int err;
4c476991 4716 struct net_device *dev = info->user_ptr[1];
41ade00f 4717 u8 *mac_addr = NULL;
b9454e83 4718 struct key_parse key;
e7a7b84e
VJ
4719 int link_id = nl80211_link_id_or_invalid(info->attrs);
4720 struct wireless_dev *wdev = dev->ieee80211_ptr;
41ade00f 4721
b9454e83
JB
4722 err = nl80211_parse_key(info, &key);
4723 if (err)
4724 return err;
41ade00f
JB
4725
4726 if (info->attrs[NL80211_ATTR_MAC])
4727 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4728
e31b8213
JB
4729 if (key.type == -1) {
4730 if (mac_addr)
4731 key.type = NL80211_KEYTYPE_PAIRWISE;
4732 else
4733 key.type = NL80211_KEYTYPE_GROUP;
4734 }
4735
4736 /* for now */
4737 if (key.type != NL80211_KEYTYPE_PAIRWISE &&
4738 key.type != NL80211_KEYTYPE_GROUP)
4739 return -EINVAL;
4740
2d946308
AT
4741 if (!cfg80211_valid_key_idx(rdev, key.idx,
4742 key.type == NL80211_KEYTYPE_PAIRWISE))
4743 return -EINVAL;
4744
4c476991
JB
4745 if (!rdev->ops->del_key)
4746 return -EOPNOTSUPP;
41ade00f 4747
e7a7b84e
VJ
4748 wdev_lock(wdev);
4749 err = nl80211_key_allowed(wdev);
e31b8213 4750
0fa7b391 4751 if (key.type == NL80211_KEYTYPE_GROUP && mac_addr &&
e31b8213
JB
4752 !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
4753 err = -ENOENT;
4754
fffd0934 4755 if (!err)
e7a7b84e
VJ
4756 err = nl80211_validate_key_link_id(info, wdev, link_id,
4757 key.type == NL80211_KEYTYPE_PAIRWISE);
4758
4759 if (!err)
4760 err = rdev_del_key(rdev, dev, link_id, key.idx,
e35e4d28
HG
4761 key.type == NL80211_KEYTYPE_PAIRWISE,
4762 mac_addr);
41ade00f 4763
3d23e349 4764#ifdef CONFIG_CFG80211_WEXT
08645126 4765 if (!err) {
e7a7b84e
VJ
4766 if (key.idx == wdev->wext.default_key)
4767 wdev->wext.default_key = -1;
4768 else if (key.idx == wdev->wext.default_mgmt_key)
4769 wdev->wext.default_mgmt_key = -1;
08645126
JB
4770 }
4771#endif
e7a7b84e 4772 wdev_unlock(wdev);
08645126 4773
41ade00f
JB
4774 return err;
4775}
4776
77765eaf
VT
4777/* This function returns an error or the number of nested attributes */
4778static int validate_acl_mac_addrs(struct nlattr *nl_attr)
4779{
4780 struct nlattr *attr;
4781 int n_entries = 0, tmp;
4782
4783 nla_for_each_nested(attr, nl_attr, tmp) {
4784 if (nla_len(attr) != ETH_ALEN)
4785 return -EINVAL;
4786
4787 n_entries++;
4788 }
4789
4790 return n_entries;
4791}
4792
4793/*
4794 * This function parses ACL information and allocates memory for ACL data.
4795 * On successful return, the calling function is responsible to free the
4796 * ACL buffer returned by this function.
4797 */
4798static struct cfg80211_acl_data *parse_acl_data(struct wiphy *wiphy,
4799 struct genl_info *info)
4800{
4801 enum nl80211_acl_policy acl_policy;
4802 struct nlattr *attr;
4803 struct cfg80211_acl_data *acl;
4804 int i = 0, n_entries, tmp;
4805
4806 if (!wiphy->max_acl_mac_addrs)
4807 return ERR_PTR(-EOPNOTSUPP);
4808
4809 if (!info->attrs[NL80211_ATTR_ACL_POLICY])
4810 return ERR_PTR(-EINVAL);
4811
4812 acl_policy = nla_get_u32(info->attrs[NL80211_ATTR_ACL_POLICY]);
4813 if (acl_policy != NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED &&
4814 acl_policy != NL80211_ACL_POLICY_DENY_UNLESS_LISTED)
4815 return ERR_PTR(-EINVAL);
4816
4817 if (!info->attrs[NL80211_ATTR_MAC_ADDRS])
4818 return ERR_PTR(-EINVAL);
4819
4820 n_entries = validate_acl_mac_addrs(info->attrs[NL80211_ATTR_MAC_ADDRS]);
4821 if (n_entries < 0)
4822 return ERR_PTR(n_entries);
4823
4824 if (n_entries > wiphy->max_acl_mac_addrs)
4825 return ERR_PTR(-ENOTSUPP);
4826
391d132c 4827 acl = kzalloc(struct_size(acl, mac_addrs, n_entries), GFP_KERNEL);
77765eaf
VT
4828 if (!acl)
4829 return ERR_PTR(-ENOMEM);
4830
4831 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_MAC_ADDRS], tmp) {
4832 memcpy(acl->mac_addrs[i].addr, nla_data(attr), ETH_ALEN);
4833 i++;
4834 }
4835
4836 acl->n_acl_entries = n_entries;
4837 acl->acl_policy = acl_policy;
4838
4839 return acl;
4840}
4841
4842static int nl80211_set_mac_acl(struct sk_buff *skb, struct genl_info *info)
4843{
4844 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4845 struct net_device *dev = info->user_ptr[1];
4846 struct cfg80211_acl_data *acl;
4847 int err;
4848
4849 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
4850 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
4851 return -EOPNOTSUPP;
4852
7b0a0e3c 4853 if (!dev->ieee80211_ptr->links[0].ap.beacon_interval)
77765eaf
VT
4854 return -EINVAL;
4855
4856 acl = parse_acl_data(&rdev->wiphy, info);
4857 if (IS_ERR(acl))
4858 return PTR_ERR(acl);
4859
4860 err = rdev_set_mac_acl(rdev, dev, acl);
4861
4862 kfree(acl);
4863
4864 return err;
4865}
4866
a7c7fbff
PK
4867static u32 rateset_to_mask(struct ieee80211_supported_band *sband,
4868 u8 *rates, u8 rates_len)
4869{
4870 u8 i;
4871 u32 mask = 0;
4872
4873 for (i = 0; i < rates_len; i++) {
4874 int rate = (rates[i] & 0x7f) * 5;
4875 int ridx;
4876
4877 for (ridx = 0; ridx < sband->n_bitrates; ridx++) {
4878 struct ieee80211_rate *srate =
4879 &sband->bitrates[ridx];
4880 if (rate == srate->bitrate) {
4881 mask |= 1 << ridx;
4882 break;
4883 }
4884 }
4885 if (ridx == sband->n_bitrates)
4886 return 0; /* rate not found */
4887 }
4888
4889 return mask;
4890}
4891
4892static bool ht_rateset_to_mask(struct ieee80211_supported_band *sband,
4893 u8 *rates, u8 rates_len,
4894 u8 mcs[IEEE80211_HT_MCS_MASK_LEN])
4895{
4896 u8 i;
4897
4898 memset(mcs, 0, IEEE80211_HT_MCS_MASK_LEN);
4899
4900 for (i = 0; i < rates_len; i++) {
4901 int ridx, rbit;
4902
4903 ridx = rates[i] / 8;
4904 rbit = BIT(rates[i] % 8);
4905
4906 /* check validity */
4907 if ((ridx < 0) || (ridx >= IEEE80211_HT_MCS_MASK_LEN))
4908 return false;
4909
4910 /* check availability */
30fe6d50 4911 ridx = array_index_nospec(ridx, IEEE80211_HT_MCS_MASK_LEN);
a7c7fbff
PK
4912 if (sband->ht_cap.mcs.rx_mask[ridx] & rbit)
4913 mcs[ridx] |= rbit;
4914 else
4915 return false;
4916 }
4917
4918 return true;
4919}
4920
4921static u16 vht_mcs_map_to_mcs_mask(u8 vht_mcs_map)
4922{
4923 u16 mcs_mask = 0;
4924
4925 switch (vht_mcs_map) {
4926 case IEEE80211_VHT_MCS_NOT_SUPPORTED:
4927 break;
4928 case IEEE80211_VHT_MCS_SUPPORT_0_7:
4929 mcs_mask = 0x00FF;
4930 break;
4931 case IEEE80211_VHT_MCS_SUPPORT_0_8:
4932 mcs_mask = 0x01FF;
4933 break;
4934 case IEEE80211_VHT_MCS_SUPPORT_0_9:
4935 mcs_mask = 0x03FF;
4936 break;
4937 default:
4938 break;
4939 }
4940
4941 return mcs_mask;
4942}
4943
4944static void vht_build_mcs_mask(u16 vht_mcs_map,
4945 u16 vht_mcs_mask[NL80211_VHT_NSS_MAX])
4946{
4947 u8 nss;
4948
4949 for (nss = 0; nss < NL80211_VHT_NSS_MAX; nss++) {
4950 vht_mcs_mask[nss] = vht_mcs_map_to_mcs_mask(vht_mcs_map & 0x03);
4951 vht_mcs_map >>= 2;
4952 }
4953}
4954
4955static bool vht_set_mcs_mask(struct ieee80211_supported_band *sband,
4956 struct nl80211_txrate_vht *txrate,
4957 u16 mcs[NL80211_VHT_NSS_MAX])
4958{
4959 u16 tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
4960 u16 tx_mcs_mask[NL80211_VHT_NSS_MAX] = {};
4961 u8 i;
4962
4963 if (!sband->vht_cap.vht_supported)
4964 return false;
4965
4966 memset(mcs, 0, sizeof(u16) * NL80211_VHT_NSS_MAX);
4967
4968 /* Build vht_mcs_mask from VHT capabilities */
4969 vht_build_mcs_mask(tx_mcs_map, tx_mcs_mask);
4970
4971 for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
4972 if ((tx_mcs_mask[i] & txrate->mcs[i]) == txrate->mcs[i])
4973 mcs[i] = txrate->mcs[i];
4974 else
4975 return false;
4976 }
4977
4978 return true;
4979}
4980
eb89a6a6
MH
4981static u16 he_mcs_map_to_mcs_mask(u8 he_mcs_map)
4982{
4983 switch (he_mcs_map) {
4984 case IEEE80211_HE_MCS_NOT_SUPPORTED:
4985 return 0;
4986 case IEEE80211_HE_MCS_SUPPORT_0_7:
4987 return 0x00FF;
4988 case IEEE80211_HE_MCS_SUPPORT_0_9:
4989 return 0x03FF;
4990 case IEEE80211_HE_MCS_SUPPORT_0_11:
4991 return 0xFFF;
4992 default:
4993 break;
4994 }
4995 return 0;
4996}
4997
4998static void he_build_mcs_mask(u16 he_mcs_map,
4999 u16 he_mcs_mask[NL80211_HE_NSS_MAX])
5000{
5001 u8 nss;
5002
5003 for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++) {
5004 he_mcs_mask[nss] = he_mcs_map_to_mcs_mask(he_mcs_map & 0x03);
5005 he_mcs_map >>= 2;
5006 }
5007}
5008
7b0a0e3c 5009static u16 he_get_txmcsmap(struct genl_info *info, unsigned int link_id,
eb89a6a6
MH
5010 const struct ieee80211_sta_he_cap *he_cap)
5011{
5012 struct net_device *dev = info->user_ptr[1];
5013 struct wireless_dev *wdev = dev->ieee80211_ptr;
7b0a0e3c
JB
5014 struct cfg80211_chan_def *chandef;
5015 __le16 tx_mcs;
eb89a6a6 5016
7b0a0e3c
JB
5017 chandef = wdev_chandef(wdev, link_id);
5018 if (!chandef) {
5019 /*
5020 * This is probably broken, but we never maintained
5021 * a chandef in these cases, so it always was.
5022 */
5023 return le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80);
5024 }
5025
5026 switch (chandef->width) {
eb89a6a6
MH
5027 case NL80211_CHAN_WIDTH_80P80:
5028 tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_80p80;
5029 break;
5030 case NL80211_CHAN_WIDTH_160:
5031 tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_160;
5032 break;
5033 default:
5034 tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_80;
5035 break;
5036 }
7b0a0e3c 5037
eb89a6a6
MH
5038 return le16_to_cpu(tx_mcs);
5039}
5040
5041static bool he_set_mcs_mask(struct genl_info *info,
5042 struct wireless_dev *wdev,
5043 struct ieee80211_supported_band *sband,
5044 struct nl80211_txrate_he *txrate,
7b0a0e3c
JB
5045 u16 mcs[NL80211_HE_NSS_MAX],
5046 unsigned int link_id)
eb89a6a6
MH
5047{
5048 const struct ieee80211_sta_he_cap *he_cap;
5049 u16 tx_mcs_mask[NL80211_HE_NSS_MAX] = {};
5050 u16 tx_mcs_map = 0;
5051 u8 i;
5052
5053 he_cap = ieee80211_get_he_iftype_cap(sband, wdev->iftype);
5054 if (!he_cap)
5055 return false;
5056
5057 memset(mcs, 0, sizeof(u16) * NL80211_HE_NSS_MAX);
5058
7b0a0e3c 5059 tx_mcs_map = he_get_txmcsmap(info, link_id, he_cap);
eb89a6a6
MH
5060
5061 /* Build he_mcs_mask from HE capabilities */
5062 he_build_mcs_mask(tx_mcs_map, tx_mcs_mask);
5063
5064 for (i = 0; i < NL80211_HE_NSS_MAX; i++) {
5065 if ((tx_mcs_mask[i] & txrate->mcs[i]) == txrate->mcs[i])
5066 mcs[i] = txrate->mcs[i];
5067 else
5068 return false;
5069 }
5070
5071 return true;
5072}
5073
a7c7fbff 5074static int nl80211_parse_tx_bitrate_mask(struct genl_info *info,
9a5f6488
TC
5075 struct nlattr *attrs[],
5076 enum nl80211_attrs attr,
eb89a6a6 5077 struct cfg80211_bitrate_mask *mask,
857b34c4 5078 struct net_device *dev,
7b0a0e3c
JB
5079 bool default_all_enabled,
5080 unsigned int link_id)
a7c7fbff
PK
5081{
5082 struct nlattr *tb[NL80211_TXRATE_MAX + 1];
5083 struct cfg80211_registered_device *rdev = info->user_ptr[0];
eb89a6a6 5084 struct wireless_dev *wdev = dev->ieee80211_ptr;
a7c7fbff
PK
5085 int rem, i;
5086 struct nlattr *tx_rates;
5087 struct ieee80211_supported_band *sband;
eb89a6a6 5088 u16 vht_tx_mcs_map, he_tx_mcs_map;
a7c7fbff
PK
5089
5090 memset(mask, 0, sizeof(*mask));
5091 /* Default to all rates enabled */
5092 for (i = 0; i < NUM_NL80211_BANDS; i++) {
eb89a6a6
MH
5093 const struct ieee80211_sta_he_cap *he_cap;
5094
857b34c4
RM
5095 if (!default_all_enabled)
5096 break;
5097
a7c7fbff
PK
5098 sband = rdev->wiphy.bands[i];
5099
5100 if (!sband)
5101 continue;
5102
5103 mask->control[i].legacy = (1 << sband->n_bitrates) - 1;
5104 memcpy(mask->control[i].ht_mcs,
5105 sband->ht_cap.mcs.rx_mask,
5106 sizeof(mask->control[i].ht_mcs));
5107
9df66d5b
PKS
5108 if (sband->vht_cap.vht_supported) {
5109 vht_tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
5110 vht_build_mcs_mask(vht_tx_mcs_map, mask->control[i].vht_mcs);
5111 }
eb89a6a6
MH
5112
5113 he_cap = ieee80211_get_he_iftype_cap(sband, wdev->iftype);
5114 if (!he_cap)
5115 continue;
5116
7b0a0e3c 5117 he_tx_mcs_map = he_get_txmcsmap(info, link_id, he_cap);
eb89a6a6
MH
5118 he_build_mcs_mask(he_tx_mcs_map, mask->control[i].he_mcs);
5119
5120 mask->control[i].he_gi = 0xFF;
5121 mask->control[i].he_ltf = 0xFF;
a7c7fbff
PK
5122 }
5123
5124 /* if no rates are given set it back to the defaults */
9a5f6488 5125 if (!attrs[attr])
a7c7fbff
PK
5126 goto out;
5127
5128 /* The nested attribute uses enum nl80211_band as the index. This maps
5129 * directly to the enum nl80211_band values used in cfg80211.
5130 */
5131 BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8);
9a5f6488 5132 nla_for_each_nested(tx_rates, attrs[attr], rem) {
a7c7fbff
PK
5133 enum nl80211_band band = nla_type(tx_rates);
5134 int err;
5135
5136 if (band < 0 || band >= NUM_NL80211_BANDS)
5137 return -EINVAL;
5138 sband = rdev->wiphy.bands[band];
5139 if (sband == NULL)
5140 return -EINVAL;
8cb08174
JB
5141 err = nla_parse_nested_deprecated(tb, NL80211_TXRATE_MAX,
5142 tx_rates,
5143 nl80211_txattr_policy,
5144 info->extack);
a7c7fbff
PK
5145 if (err)
5146 return err;
5147 if (tb[NL80211_TXRATE_LEGACY]) {
5148 mask->control[band].legacy = rateset_to_mask(
5149 sband,
5150 nla_data(tb[NL80211_TXRATE_LEGACY]),
5151 nla_len(tb[NL80211_TXRATE_LEGACY]));
5152 if ((mask->control[band].legacy == 0) &&
5153 nla_len(tb[NL80211_TXRATE_LEGACY]))
5154 return -EINVAL;
5155 }
5156 if (tb[NL80211_TXRATE_HT]) {
5157 if (!ht_rateset_to_mask(
5158 sband,
5159 nla_data(tb[NL80211_TXRATE_HT]),
5160 nla_len(tb[NL80211_TXRATE_HT]),
5161 mask->control[band].ht_mcs))
5162 return -EINVAL;
5163 }
c4a30446 5164
a7c7fbff
PK
5165 if (tb[NL80211_TXRATE_VHT]) {
5166 if (!vht_set_mcs_mask(
5167 sband,
5168 nla_data(tb[NL80211_TXRATE_VHT]),
5169 mask->control[band].vht_mcs))
5170 return -EINVAL;
5171 }
c4a30446 5172
a7c7fbff
PK
5173 if (tb[NL80211_TXRATE_GI]) {
5174 mask->control[band].gi =
5175 nla_get_u8(tb[NL80211_TXRATE_GI]);
5176 if (mask->control[band].gi > NL80211_TXRATE_FORCE_LGI)
5177 return -EINVAL;
5178 }
eb89a6a6
MH
5179 if (tb[NL80211_TXRATE_HE] &&
5180 !he_set_mcs_mask(info, wdev, sband,
5181 nla_data(tb[NL80211_TXRATE_HE]),
7b0a0e3c
JB
5182 mask->control[band].he_mcs,
5183 link_id))
eb89a6a6 5184 return -EINVAL;
c4a30446 5185
eb89a6a6
MH
5186 if (tb[NL80211_TXRATE_HE_GI])
5187 mask->control[band].he_gi =
5188 nla_get_u8(tb[NL80211_TXRATE_HE_GI]);
5189 if (tb[NL80211_TXRATE_HE_LTF])
5190 mask->control[band].he_ltf =
5191 nla_get_u8(tb[NL80211_TXRATE_HE_LTF]);
a7c7fbff
PK
5192
5193 if (mask->control[band].legacy == 0) {
eb89a6a6 5194 /* don't allow empty legacy rates if HT, VHT or HE
a7c7fbff
PK
5195 * are not even supported.
5196 */
5197 if (!(rdev->wiphy.bands[band]->ht_cap.ht_supported ||
eb89a6a6
MH
5198 rdev->wiphy.bands[band]->vht_cap.vht_supported ||
5199 ieee80211_get_he_iftype_cap(sband, wdev->iftype)))
a7c7fbff
PK
5200 return -EINVAL;
5201
5202 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
5203 if (mask->control[band].ht_mcs[i])
5204 goto out;
5205
5206 for (i = 0; i < NL80211_VHT_NSS_MAX; i++)
5207 if (mask->control[band].vht_mcs[i])
5208 goto out;
5209
eb89a6a6
MH
5210 for (i = 0; i < NL80211_HE_NSS_MAX; i++)
5211 if (mask->control[band].he_mcs[i])
5212 goto out;
5213
a7c7fbff
PK
5214 /* legacy and mcs rates may not be both empty */
5215 return -EINVAL;
5216 }
5217 }
5218
5219out:
5220 return 0;
5221}
5222
8564e382
JB
5223static int validate_beacon_tx_rate(struct cfg80211_registered_device *rdev,
5224 enum nl80211_band band,
5225 struct cfg80211_bitrate_mask *beacon_rate)
a7c7fbff 5226{
c4a30446 5227 u32 count_ht, count_vht, count_he, i;
8564e382 5228 u32 rate = beacon_rate->control[band].legacy;
a7c7fbff
PK
5229
5230 /* Allow only one rate */
5231 if (hweight32(rate) > 1)
5232 return -EINVAL;
5233
5234 count_ht = 0;
5235 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
8564e382 5236 if (hweight8(beacon_rate->control[band].ht_mcs[i]) > 1) {
a7c7fbff 5237 return -EINVAL;
8564e382 5238 } else if (beacon_rate->control[band].ht_mcs[i]) {
a7c7fbff
PK
5239 count_ht++;
5240 if (count_ht > 1)
5241 return -EINVAL;
5242 }
5243 if (count_ht && rate)
5244 return -EINVAL;
5245 }
5246
5247 count_vht = 0;
5248 for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
8564e382 5249 if (hweight16(beacon_rate->control[band].vht_mcs[i]) > 1) {
a7c7fbff 5250 return -EINVAL;
8564e382 5251 } else if (beacon_rate->control[band].vht_mcs[i]) {
a7c7fbff
PK
5252 count_vht++;
5253 if (count_vht > 1)
5254 return -EINVAL;
5255 }
5256 if (count_vht && rate)
5257 return -EINVAL;
5258 }
5259
c4a30446
RM
5260 count_he = 0;
5261 for (i = 0; i < NL80211_HE_NSS_MAX; i++) {
5262 if (hweight16(beacon_rate->control[band].he_mcs[i]) > 1) {
5263 return -EINVAL;
5264 } else if (beacon_rate->control[band].he_mcs[i]) {
5265 count_he++;
5266 if (count_he > 1)
5267 return -EINVAL;
5268 }
5269 if (count_he && rate)
5270 return -EINVAL;
5271 }
5272
5273 if ((count_ht && count_vht && count_he) ||
5274 (!rate && !count_ht && !count_vht && !count_he))
a7c7fbff
PK
5275 return -EINVAL;
5276
8564e382
JB
5277 if (rate &&
5278 !wiphy_ext_feature_isset(&rdev->wiphy,
5279 NL80211_EXT_FEATURE_BEACON_RATE_LEGACY))
5280 return -EINVAL;
5281 if (count_ht &&
5282 !wiphy_ext_feature_isset(&rdev->wiphy,
5283 NL80211_EXT_FEATURE_BEACON_RATE_HT))
5284 return -EINVAL;
5285 if (count_vht &&
5286 !wiphy_ext_feature_isset(&rdev->wiphy,
5287 NL80211_EXT_FEATURE_BEACON_RATE_VHT))
5288 return -EINVAL;
c4a30446
RM
5289 if (count_he &&
5290 !wiphy_ext_feature_isset(&rdev->wiphy,
5291 NL80211_EXT_FEATURE_BEACON_RATE_HE))
5292 return -EINVAL;
8564e382 5293
a7c7fbff
PK
5294 return 0;
5295}
5296
dc1e3cb8
JC
5297static int nl80211_parse_mbssid_config(struct wiphy *wiphy,
5298 struct net_device *dev,
5299 struct nlattr *attrs,
5300 struct cfg80211_mbssid_config *config,
5301 u8 num_elems)
5302{
5303 struct nlattr *tb[NL80211_MBSSID_CONFIG_ATTR_MAX + 1];
5304
5305 if (!wiphy->mbssid_max_interfaces)
5306 return -EOPNOTSUPP;
5307
5308 if (nla_parse_nested(tb, NL80211_MBSSID_CONFIG_ATTR_MAX, attrs, NULL,
5309 NULL) ||
5310 !tb[NL80211_MBSSID_CONFIG_ATTR_INDEX])
5311 return -EINVAL;
5312
5313 config->ema = nla_get_flag(tb[NL80211_MBSSID_CONFIG_ATTR_EMA]);
5314 if (config->ema) {
5315 if (!wiphy->ema_max_profile_periodicity)
5316 return -EOPNOTSUPP;
5317
5318 if (num_elems > wiphy->ema_max_profile_periodicity)
5319 return -EINVAL;
5320 }
5321
5322 config->index = nla_get_u8(tb[NL80211_MBSSID_CONFIG_ATTR_INDEX]);
5323 if (config->index >= wiphy->mbssid_max_interfaces ||
5324 (!config->index && !num_elems))
5325 return -EINVAL;
5326
5327 if (tb[NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX]) {
5328 u32 tx_ifindex =
5329 nla_get_u32(tb[NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX]);
5330
5331 if ((!config->index && tx_ifindex != dev->ifindex) ||
5332 (config->index && tx_ifindex == dev->ifindex))
5333 return -EINVAL;
5334
5335 if (tx_ifindex != dev->ifindex) {
5336 struct net_device *tx_netdev =
5337 dev_get_by_index(wiphy_net(wiphy), tx_ifindex);
5338
5339 if (!tx_netdev || !tx_netdev->ieee80211_ptr ||
5340 tx_netdev->ieee80211_ptr->wiphy != wiphy ||
5341 tx_netdev->ieee80211_ptr->iftype !=
5342 NL80211_IFTYPE_AP) {
5343 dev_put(tx_netdev);
5344 return -EINVAL;
5345 }
5346
5347 config->tx_wdev = tx_netdev->ieee80211_ptr;
5348 } else {
5349 config->tx_wdev = dev->ieee80211_ptr;
5350 }
5351 } else if (!config->index) {
5352 config->tx_wdev = dev->ieee80211_ptr;
5353 } else {
5354 return -EINVAL;
5355 }
5356
5357 return 0;
5358}
5359
5360static struct cfg80211_mbssid_elems *
5361nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs)
5362{
5363 struct nlattr *nl_elems;
5364 struct cfg80211_mbssid_elems *elems;
5365 int rem_elems;
5366 u8 i = 0, num_elems = 0;
5367
5368 if (!wiphy->mbssid_max_interfaces)
5369 return ERR_PTR(-EINVAL);
5370
5371 nla_for_each_nested(nl_elems, attrs, rem_elems)
5372 num_elems++;
5373
5374 elems = kzalloc(struct_size(elems, elem, num_elems), GFP_KERNEL);
5375 if (!elems)
5376 return ERR_PTR(-ENOMEM);
5377
5378 nla_for_each_nested(nl_elems, attrs, rem_elems) {
5379 elems->elem[i].data = nla_data(nl_elems);
5380 elems->elem[i].len = nla_len(nl_elems);
5381 i++;
5382 }
5383 elems->cnt = num_elems;
5384 return elems;
5385}
5386
3d48cb74
RS
5387static int nl80211_parse_he_bss_color(struct nlattr *attrs,
5388 struct cfg80211_he_bss_color *he_bss_color)
5389{
5390 struct nlattr *tb[NL80211_HE_BSS_COLOR_ATTR_MAX + 1];
5391 int err;
5392
5393 err = nla_parse_nested(tb, NL80211_HE_BSS_COLOR_ATTR_MAX, attrs,
5394 he_bss_color_policy, NULL);
5395 if (err)
5396 return err;
5397
5398 if (!tb[NL80211_HE_BSS_COLOR_ATTR_COLOR])
5399 return -EINVAL;
5400
5401 he_bss_color->color =
5402 nla_get_u8(tb[NL80211_HE_BSS_COLOR_ATTR_COLOR]);
5403 he_bss_color->enabled =
5404 !nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_DISABLED]);
5405 he_bss_color->partial =
5406 nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_PARTIAL]);
5407
5408 return 0;
5409}
5410
81e54d08
PKC
5411static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
5412 struct nlattr *attrs[],
8860020e 5413 struct cfg80211_beacon_data *bcn)
ed1b6cc7 5414{
8860020e 5415 bool haveinfo = false;
81e54d08 5416 int err;
ed1b6cc7 5417
8860020e 5418 memset(bcn, 0, sizeof(*bcn));
ed1b6cc7 5419
7b0a0e3c
JB
5420 bcn->link_id = nl80211_link_id(attrs);
5421
a1193be8
SW
5422 if (attrs[NL80211_ATTR_BEACON_HEAD]) {
5423 bcn->head = nla_data(attrs[NL80211_ATTR_BEACON_HEAD]);
5424 bcn->head_len = nla_len(attrs[NL80211_ATTR_BEACON_HEAD]);
8860020e
JB
5425 if (!bcn->head_len)
5426 return -EINVAL;
5427 haveinfo = true;
ed1b6cc7
JB
5428 }
5429
a1193be8
SW
5430 if (attrs[NL80211_ATTR_BEACON_TAIL]) {
5431 bcn->tail = nla_data(attrs[NL80211_ATTR_BEACON_TAIL]);
5432 bcn->tail_len = nla_len(attrs[NL80211_ATTR_BEACON_TAIL]);
8860020e 5433 haveinfo = true;
ed1b6cc7
JB
5434 }
5435
4c476991
JB
5436 if (!haveinfo)
5437 return -EINVAL;
3b85875a 5438
a1193be8
SW
5439 if (attrs[NL80211_ATTR_IE]) {
5440 bcn->beacon_ies = nla_data(attrs[NL80211_ATTR_IE]);
5441 bcn->beacon_ies_len = nla_len(attrs[NL80211_ATTR_IE]);
9946ecfb
JM
5442 }
5443
a1193be8 5444 if (attrs[NL80211_ATTR_IE_PROBE_RESP]) {
8860020e 5445 bcn->proberesp_ies =
a1193be8 5446 nla_data(attrs[NL80211_ATTR_IE_PROBE_RESP]);
8860020e 5447 bcn->proberesp_ies_len =
a1193be8 5448 nla_len(attrs[NL80211_ATTR_IE_PROBE_RESP]);
9946ecfb
JM
5449 }
5450
a1193be8 5451 if (attrs[NL80211_ATTR_IE_ASSOC_RESP]) {
8860020e 5452 bcn->assocresp_ies =
a1193be8 5453 nla_data(attrs[NL80211_ATTR_IE_ASSOC_RESP]);
8860020e 5454 bcn->assocresp_ies_len =
a1193be8 5455 nla_len(attrs[NL80211_ATTR_IE_ASSOC_RESP]);
9946ecfb
JM
5456 }
5457
a1193be8
SW
5458 if (attrs[NL80211_ATTR_PROBE_RESP]) {
5459 bcn->probe_resp = nla_data(attrs[NL80211_ATTR_PROBE_RESP]);
5460 bcn->probe_resp_len = nla_len(attrs[NL80211_ATTR_PROBE_RESP]);
00f740e1
AN
5461 }
5462
81e54d08
PKC
5463 if (attrs[NL80211_ATTR_FTM_RESPONDER]) {
5464 struct nlattr *tb[NL80211_FTM_RESP_ATTR_MAX + 1];
5465
8cb08174
JB
5466 err = nla_parse_nested_deprecated(tb,
5467 NL80211_FTM_RESP_ATTR_MAX,
5468 attrs[NL80211_ATTR_FTM_RESPONDER],
5469 NULL, NULL);
81e54d08
PKC
5470 if (err)
5471 return err;
5472
5473 if (tb[NL80211_FTM_RESP_ATTR_ENABLED] &&
5474 wiphy_ext_feature_isset(&rdev->wiphy,
5475 NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER))
5476 bcn->ftm_responder = 1;
5477 else
5478 return -EOPNOTSUPP;
5479
5480 if (tb[NL80211_FTM_RESP_ATTR_LCI]) {
5481 bcn->lci = nla_data(tb[NL80211_FTM_RESP_ATTR_LCI]);
5482 bcn->lci_len = nla_len(tb[NL80211_FTM_RESP_ATTR_LCI]);
5483 }
5484
5485 if (tb[NL80211_FTM_RESP_ATTR_CIVICLOC]) {
5486 bcn->civicloc = nla_data(tb[NL80211_FTM_RESP_ATTR_CIVICLOC]);
5487 bcn->civicloc_len = nla_len(tb[NL80211_FTM_RESP_ATTR_CIVICLOC]);
5488 }
5489 } else {
5490 bcn->ftm_responder = -1;
5491 }
5492
3d48cb74
RS
5493 if (attrs[NL80211_ATTR_HE_BSS_COLOR]) {
5494 err = nl80211_parse_he_bss_color(attrs[NL80211_ATTR_HE_BSS_COLOR],
5495 &bcn->he_bss_color);
5496 if (err)
5497 return err;
5498 bcn->he_bss_color_valid = true;
5499 }
5500
dc1e3cb8
JC
5501 if (attrs[NL80211_ATTR_MBSSID_ELEMS]) {
5502 struct cfg80211_mbssid_elems *mbssid =
5503 nl80211_parse_mbssid_elems(&rdev->wiphy,
5504 attrs[NL80211_ATTR_MBSSID_ELEMS]);
5505
5506 if (IS_ERR(mbssid))
5507 return PTR_ERR(mbssid);
5508
5509 bcn->mbssid_ies = mbssid;
5510 }
5511
8860020e
JB
5512 return 0;
5513}
5514
796e90f4
JC
5515static int nl80211_parse_he_obss_pd(struct nlattr *attrs,
5516 struct ieee80211_he_obss_pd *he_obss_pd)
5517{
5518 struct nlattr *tb[NL80211_HE_OBSS_PD_ATTR_MAX + 1];
5519 int err;
5520
5521 err = nla_parse_nested(tb, NL80211_HE_OBSS_PD_ATTR_MAX, attrs,
5522 he_obss_pd_policy, NULL);
5523 if (err)
5524 return err;
5525
f5bec330
RM
5526 if (!tb[NL80211_HE_OBSS_PD_ATTR_SR_CTRL])
5527 return -EINVAL;
5528
5529 he_obss_pd->sr_ctrl = nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_SR_CTRL]);
5530
6c8b6e4a
RM
5531 if (tb[NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET])
5532 he_obss_pd->min_offset =
5533 nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET]);
5534 if (tb[NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET])
5535 he_obss_pd->max_offset =
5536 nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET]);
f5bec330
RM
5537 if (tb[NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET])
5538 he_obss_pd->non_srg_max_offset =
5539 nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET]);
6c8b6e4a
RM
5540
5541 if (he_obss_pd->min_offset > he_obss_pd->max_offset)
796e90f4
JC
5542 return -EINVAL;
5543
f5bec330
RM
5544 if (tb[NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP])
5545 memcpy(he_obss_pd->bss_color_bitmap,
5546 nla_data(tb[NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP]),
5547 sizeof(he_obss_pd->bss_color_bitmap));
5548
5549 if (tb[NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP])
5550 memcpy(he_obss_pd->partial_bssid_bitmap,
5551 nla_data(tb[NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP]),
5552 sizeof(he_obss_pd->partial_bssid_bitmap));
5553
796e90f4
JC
5554 he_obss_pd->enable = true;
5555
5556 return 0;
5557}
5558
291c49de
AD
5559static int nl80211_parse_fils_discovery(struct cfg80211_registered_device *rdev,
5560 struct nlattr *attrs,
5561 struct cfg80211_ap_settings *params)
5562{
5563 struct nlattr *tb[NL80211_FILS_DISCOVERY_ATTR_MAX + 1];
5564 int ret;
5565 struct cfg80211_fils_discovery *fd = &params->fils_discovery;
5566
5567 if (!wiphy_ext_feature_isset(&rdev->wiphy,
5568 NL80211_EXT_FEATURE_FILS_DISCOVERY))
5569 return -EINVAL;
5570
5571 ret = nla_parse_nested(tb, NL80211_FILS_DISCOVERY_ATTR_MAX, attrs,
5572 NULL, NULL);
5573 if (ret)
5574 return ret;
5575
5576 if (!tb[NL80211_FILS_DISCOVERY_ATTR_INT_MIN] ||
5577 !tb[NL80211_FILS_DISCOVERY_ATTR_INT_MAX] ||
5578 !tb[NL80211_FILS_DISCOVERY_ATTR_TMPL])
5579 return -EINVAL;
5580
5581 fd->tmpl_len = nla_len(tb[NL80211_FILS_DISCOVERY_ATTR_TMPL]);
5582 fd->tmpl = nla_data(tb[NL80211_FILS_DISCOVERY_ATTR_TMPL]);
5583 fd->min_interval = nla_get_u32(tb[NL80211_FILS_DISCOVERY_ATTR_INT_MIN]);
5584 fd->max_interval = nla_get_u32(tb[NL80211_FILS_DISCOVERY_ATTR_INT_MAX]);
5585
5586 return 0;
5587}
5588
7443dcd1
AD
5589static int
5590nl80211_parse_unsol_bcast_probe_resp(struct cfg80211_registered_device *rdev,
5591 struct nlattr *attrs,
5592 struct cfg80211_ap_settings *params)
5593{
5594 struct nlattr *tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX + 1];
5595 int ret;
5596 struct cfg80211_unsol_bcast_probe_resp *presp =
5597 &params->unsol_bcast_probe_resp;
5598
5599 if (!wiphy_ext_feature_isset(&rdev->wiphy,
5600 NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP))
5601 return -EINVAL;
5602
5603 ret = nla_parse_nested(tb, NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX,
5604 attrs, NULL, NULL);
5605 if (ret)
5606 return ret;
5607
5608 if (!tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT] ||
5609 !tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL])
5610 return -EINVAL;
5611
5612 presp->tmpl = nla_data(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL]);
5613 presp->tmpl_len = nla_len(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL]);
5614 presp->interval = nla_get_u32(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT]);
5615 return 0;
5616}
5617
66cd794e 5618static void nl80211_check_ap_rate_selectors(struct cfg80211_ap_settings *params,
153e2a11 5619 const struct element *rates)
66cd794e
JB
5620{
5621 int i;
5622
5623 if (!rates)
5624 return;
5625
153e2a11
JB
5626 for (i = 0; i < rates->datalen; i++) {
5627 if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_HT_PHY)
66cd794e 5628 params->ht_required = true;
153e2a11 5629 if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_VHT_PHY)
66cd794e 5630 params->vht_required = true;
153e2a11 5631 if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_HE_PHY)
2a392596 5632 params->he_required = true;
153e2a11 5633 if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_SAE_H2E)
d6587602 5634 params->sae_h2e_required = true;
66cd794e
JB
5635 }
5636}
5637
5638/*
5639 * Since the nl80211 API didn't include, from the beginning, attributes about
5640 * HT/VHT requirements/capabilities, we parse them out of the IEs for the
5641 * benefit of drivers that rebuild IEs in the firmware.
5642 */
8bc65d38 5643static int nl80211_calculate_ap_params(struct cfg80211_ap_settings *params)
66cd794e
JB
5644{
5645 const struct cfg80211_beacon_data *bcn = &params->beacon;
ba83bfb1
IM
5646 size_t ies_len = bcn->tail_len;
5647 const u8 *ies = bcn->tail;
153e2a11
JB
5648 const struct element *rates;
5649 const struct element *cap;
66cd794e 5650
153e2a11 5651 rates = cfg80211_find_elem(WLAN_EID_SUPP_RATES, ies, ies_len);
66cd794e
JB
5652 nl80211_check_ap_rate_selectors(params, rates);
5653
153e2a11 5654 rates = cfg80211_find_elem(WLAN_EID_EXT_SUPP_RATES, ies, ies_len);
66cd794e
JB
5655 nl80211_check_ap_rate_selectors(params, rates);
5656
153e2a11
JB
5657 cap = cfg80211_find_elem(WLAN_EID_HT_CAPABILITY, ies, ies_len);
5658 if (cap && cap->datalen >= sizeof(*params->ht_cap))
5659 params->ht_cap = (void *)cap->data;
5660 cap = cfg80211_find_elem(WLAN_EID_VHT_CAPABILITY, ies, ies_len);
5661 if (cap && cap->datalen >= sizeof(*params->vht_cap))
5662 params->vht_cap = (void *)cap->data;
5663 cap = cfg80211_find_ext_elem(WLAN_EID_EXT_HE_CAPABILITY, ies, ies_len);
5664 if (cap && cap->datalen >= sizeof(*params->he_cap) + 1)
5665 params->he_cap = (void *)(cap->data + 1);
5666 cap = cfg80211_find_ext_elem(WLAN_EID_EXT_HE_OPERATION, ies, ies_len);
5667 if (cap && cap->datalen >= sizeof(*params->he_oper) + 1)
5668 params->he_oper = (void *)(cap->data + 1);
8bc65d38
AD
5669 cap = cfg80211_find_ext_elem(WLAN_EID_EXT_EHT_CAPABILITY, ies, ies_len);
5670 if (cap) {
5671 if (!cap->datalen)
5672 return -EINVAL;
5673 params->eht_cap = (void *)(cap->data + 1);
5674 if (!ieee80211_eht_capa_size_ok((const u8 *)params->he_cap,
5675 (const u8 *)params->eht_cap,
ea5cba26 5676 cap->datalen - 1, true))
8bc65d38
AD
5677 return -EINVAL;
5678 }
5679 cap = cfg80211_find_ext_elem(WLAN_EID_EXT_EHT_OPERATION, ies, ies_len);
5680 if (cap) {
5681 if (!cap->datalen)
5682 return -EINVAL;
5683 params->eht_oper = (void *)(cap->data + 1);
5684 if (!ieee80211_eht_oper_size_ok((const u8 *)params->eht_oper,
5685 cap->datalen - 1))
5686 return -EINVAL;
5687 }
5688 return 0;
66cd794e
JB
5689}
5690
46c1dd0c
FF
5691static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
5692 struct cfg80211_ap_settings *params)
5693{
5694 struct wireless_dev *wdev;
46c1dd0c 5695
53873f13 5696 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
46c1dd0c
FF
5697 if (wdev->iftype != NL80211_IFTYPE_AP &&
5698 wdev->iftype != NL80211_IFTYPE_P2P_GO)
5699 continue;
5700
7b0a0e3c 5701 if (!wdev->u.ap.preset_chandef.chan)
46c1dd0c
FF
5702 continue;
5703
7b0a0e3c
JB
5704 params->chandef = wdev->u.ap.preset_chandef;
5705 return true;
46c1dd0c
FF
5706 }
5707
7b0a0e3c 5708 return false;
46c1dd0c
FF
5709}
5710
e39e5b5e
JM
5711static bool nl80211_valid_auth_type(struct cfg80211_registered_device *rdev,
5712 enum nl80211_auth_type auth_type,
5713 enum nl80211_commands cmd)
5714{
5715 if (auth_type > NL80211_AUTHTYPE_MAX)
5716 return false;
5717
5718 switch (cmd) {
5719 case NL80211_CMD_AUTHENTICATE:
5720 if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) &&
5721 auth_type == NL80211_AUTHTYPE_SAE)
5722 return false;
63181060
JM
5723 if (!wiphy_ext_feature_isset(&rdev->wiphy,
5724 NL80211_EXT_FEATURE_FILS_STA) &&
5725 (auth_type == NL80211_AUTHTYPE_FILS_SK ||
5726 auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
5727 auth_type == NL80211_AUTHTYPE_FILS_PK))
5728 return false;
e39e5b5e
JM
5729 return true;
5730 case NL80211_CMD_CONNECT:
10773a7c 5731 if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) &&
26f7044e
CHH
5732 !wiphy_ext_feature_isset(&rdev->wiphy,
5733 NL80211_EXT_FEATURE_SAE_OFFLOAD) &&
10773a7c 5734 auth_type == NL80211_AUTHTYPE_SAE)
a3caf744 5735 return false;
10773a7c 5736
a3caf744
VK
5737 /* FILS with SK PFS or PK not supported yet */
5738 if (auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
5739 auth_type == NL80211_AUTHTYPE_FILS_PK)
5740 return false;
5741 if (!wiphy_ext_feature_isset(
5742 &rdev->wiphy,
5743 NL80211_EXT_FEATURE_FILS_SK_OFFLOAD) &&
5744 auth_type == NL80211_AUTHTYPE_FILS_SK)
5745 return false;
5746 return true;
e39e5b5e 5747 case NL80211_CMD_START_AP:
2831a631
CHH
5748 if (!wiphy_ext_feature_isset(&rdev->wiphy,
5749 NL80211_EXT_FEATURE_SAE_OFFLOAD_AP) &&
5750 auth_type == NL80211_AUTHTYPE_SAE)
e39e5b5e 5751 return false;
63181060
JM
5752 /* FILS not supported yet */
5753 if (auth_type == NL80211_AUTHTYPE_FILS_SK ||
5754 auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
5755 auth_type == NL80211_AUTHTYPE_FILS_PK)
5756 return false;
e39e5b5e
JM
5757 return true;
5758 default:
5759 return false;
5760 }
5761}
5762
8860020e
JB
5763static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
5764{
5765 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c 5766 unsigned int link_id = nl80211_link_id(info->attrs);
8860020e
JB
5767 struct net_device *dev = info->user_ptr[1];
5768 struct wireless_dev *wdev = dev->ieee80211_ptr;
9e263e19 5769 struct cfg80211_ap_settings *params;
8860020e
JB
5770 int err;
5771
5772 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
5773 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
5774 return -EOPNOTSUPP;
5775
5776 if (!rdev->ops->start_ap)
5777 return -EOPNOTSUPP;
5778
7b0a0e3c 5779 if (wdev->links[link_id].ap.beacon_interval)
8860020e
JB
5780 return -EALREADY;
5781
8860020e
JB
5782 /* these are required for START_AP */
5783 if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
5784 !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
5785 !info->attrs[NL80211_ATTR_BEACON_HEAD])
5786 return -EINVAL;
5787
9e263e19
JB
5788 params = kzalloc(sizeof(*params), GFP_KERNEL);
5789 if (!params)
5790 return -ENOMEM;
5791
5792 err = nl80211_parse_beacon(rdev, info->attrs, &params->beacon);
8860020e 5793 if (err)
9e263e19 5794 goto out;
8860020e 5795
9e263e19 5796 params->beacon_interval =
8860020e 5797 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
9e263e19 5798 params->dtim_period =
8860020e
JB
5799 nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
5800
0c317a02 5801 err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype,
9e263e19 5802 params->beacon_interval);
8860020e 5803 if (err)
9e263e19 5804 goto out;
8860020e
JB
5805
5806 /*
5807 * In theory, some of these attributes should be required here
5808 * but since they were not used when the command was originally
5809 * added, keep them optional for old user space programs to let
5810 * them continue to work with drivers that do not need the
5811 * additional information -- drivers must check!
5812 */
5813 if (info->attrs[NL80211_ATTR_SSID]) {
9e263e19
JB
5814 params->ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
5815 params->ssid_len =
8860020e 5816 nla_len(info->attrs[NL80211_ATTR_SSID]);
9e263e19
JB
5817 if (params->ssid_len == 0) {
5818 err = -EINVAL;
5819 goto out;
5820 }
7b0a0e3c
JB
5821
5822 if (wdev->u.ap.ssid_len &&
5823 (wdev->u.ap.ssid_len != params->ssid_len ||
5824 memcmp(wdev->u.ap.ssid, params->ssid, params->ssid_len))) {
5825 /* require identical SSID for MLO */
5826 err = -EINVAL;
5827 goto out;
5828 }
5829 } else if (wdev->valid_links) {
5830 /* require SSID for MLO */
5831 err = -EINVAL;
5832 goto out;
8860020e
JB
5833 }
5834
ab0d76f6 5835 if (info->attrs[NL80211_ATTR_HIDDEN_SSID])
9e263e19 5836 params->hidden_ssid = nla_get_u32(
8860020e 5837 info->attrs[NL80211_ATTR_HIDDEN_SSID]);
8860020e 5838
9e263e19 5839 params->privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
8860020e
JB
5840
5841 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
9e263e19 5842 params->auth_type = nla_get_u32(
8860020e 5843 info->attrs[NL80211_ATTR_AUTH_TYPE]);
9e263e19
JB
5844 if (!nl80211_valid_auth_type(rdev, params->auth_type,
5845 NL80211_CMD_START_AP)) {
5846 err = -EINVAL;
5847 goto out;
5848 }
8860020e 5849 } else
9e263e19 5850 params->auth_type = NL80211_AUTHTYPE_AUTOMATIC;
8860020e 5851
9e263e19 5852 err = nl80211_crypto_settings(rdev, info, &params->crypto,
8860020e
JB
5853 NL80211_MAX_NR_CIPHER_SUITES);
5854 if (err)
9e263e19 5855 goto out;
8860020e 5856
1b658f11 5857 if (info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]) {
9e263e19
JB
5858 if (!(rdev->wiphy.features & NL80211_FEATURE_INACTIVITY_TIMER)) {
5859 err = -EOPNOTSUPP;
5860 goto out;
5861 }
5862 params->inactivity_timeout = nla_get_u16(
1b658f11
VT
5863 info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
5864 }
5865
53cabad7 5866 if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
9e263e19
JB
5867 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
5868 err = -EINVAL;
5869 goto out;
5870 }
5871 params->p2p_ctwindow =
53cabad7 5872 nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
9e263e19
JB
5873 if (params->p2p_ctwindow != 0 &&
5874 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN)) {
5875 err = -EINVAL;
5876 goto out;
5877 }
53cabad7
JB
5878 }
5879
5880 if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
5881 u8 tmp;
5882
9e263e19
JB
5883 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
5884 err = -EINVAL;
5885 goto out;
5886 }
53cabad7 5887 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
9e263e19
JB
5888 params->p2p_opp_ps = tmp;
5889 if (params->p2p_opp_ps != 0 &&
5890 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS)) {
5891 err = -EINVAL;
5892 goto out;
5893 }
53cabad7
JB
5894 }
5895
aa430da4 5896 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
9e263e19 5897 err = nl80211_parse_chandef(rdev, info, &params->chandef);
683b6d3b 5898 if (err)
9e263e19 5899 goto out;
7b0a0e3c
JB
5900 } else if (wdev->valid_links) {
5901 /* with MLD need to specify the channel configuration */
5902 err = -EINVAL;
5903 goto out;
5904 } else if (wdev->u.ap.preset_chandef.chan) {
5905 params->chandef = wdev->u.ap.preset_chandef;
9e263e19
JB
5906 } else if (!nl80211_get_ap_channel(rdev, params)) {
5907 err = -EINVAL;
5908 goto out;
5909 }
aa430da4 5910
9e263e19
JB
5911 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params->chandef,
5912 wdev->iftype)) {
5913 err = -EINVAL;
5914 goto out;
5915 }
aa430da4 5916
c2653990
JB
5917 wdev_lock(wdev);
5918
a7c7fbff 5919 if (info->attrs[NL80211_ATTR_TX_RATES]) {
9a5f6488
TC
5920 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
5921 NL80211_ATTR_TX_RATES,
9e263e19 5922 &params->beacon_rate,
7b0a0e3c 5923 dev, false, link_id);
a7c7fbff 5924 if (err)
c2653990 5925 goto out_unlock;
a7c7fbff 5926
9e263e19
JB
5927 err = validate_beacon_tx_rate(rdev, params->chandef.chan->band,
5928 &params->beacon_rate);
a7c7fbff 5929 if (err)
c2653990 5930 goto out_unlock;
a7c7fbff
PK
5931 }
5932
18998c38 5933 if (info->attrs[NL80211_ATTR_SMPS_MODE]) {
9e263e19 5934 params->smps_mode =
18998c38 5935 nla_get_u8(info->attrs[NL80211_ATTR_SMPS_MODE]);
9e263e19 5936 switch (params->smps_mode) {
18998c38
EP
5937 case NL80211_SMPS_OFF:
5938 break;
5939 case NL80211_SMPS_STATIC:
5940 if (!(rdev->wiphy.features &
9e263e19
JB
5941 NL80211_FEATURE_STATIC_SMPS)) {
5942 err = -EINVAL;
c2653990 5943 goto out_unlock;
9e263e19 5944 }
18998c38
EP
5945 break;
5946 case NL80211_SMPS_DYNAMIC:
5947 if (!(rdev->wiphy.features &
9e263e19
JB
5948 NL80211_FEATURE_DYNAMIC_SMPS)) {
5949 err = -EINVAL;
c2653990 5950 goto out_unlock;
9e263e19 5951 }
18998c38
EP
5952 break;
5953 default:
9e263e19 5954 err = -EINVAL;
c2653990 5955 goto out_unlock;
18998c38
EP
5956 }
5957 } else {
9e263e19 5958 params->smps_mode = NL80211_SMPS_OFF;
18998c38
EP
5959 }
5960
9e263e19
JB
5961 params->pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
5962 if (params->pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) {
5963 err = -EOPNOTSUPP;
c2653990 5964 goto out_unlock;
9e263e19 5965 }
6e8ef842 5966
4baf6bea 5967 if (info->attrs[NL80211_ATTR_ACL_POLICY]) {
9e263e19
JB
5968 params->acl = parse_acl_data(&rdev->wiphy, info);
5969 if (IS_ERR(params->acl)) {
5970 err = PTR_ERR(params->acl);
05075fe7 5971 params->acl = NULL;
c2653990 5972 goto out_unlock;
9e263e19 5973 }
4baf6bea
OO
5974 }
5975
9e263e19 5976 params->twt_responder =
a0de1ca3
JC
5977 nla_get_flag(info->attrs[NL80211_ATTR_TWT_RESPONDER]);
5978
796e90f4
JC
5979 if (info->attrs[NL80211_ATTR_HE_OBSS_PD]) {
5980 err = nl80211_parse_he_obss_pd(
5981 info->attrs[NL80211_ATTR_HE_OBSS_PD],
9e263e19 5982 &params->he_obss_pd);
bc7a39b4 5983 if (err)
c2653990 5984 goto out_unlock;
796e90f4
JC
5985 }
5986
291c49de
AD
5987 if (info->attrs[NL80211_ATTR_FILS_DISCOVERY]) {
5988 err = nl80211_parse_fils_discovery(rdev,
5989 info->attrs[NL80211_ATTR_FILS_DISCOVERY],
9e263e19 5990 params);
291c49de 5991 if (err)
c2653990 5992 goto out_unlock;
291c49de
AD
5993 }
5994
7443dcd1
AD
5995 if (info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP]) {
5996 err = nl80211_parse_unsol_bcast_probe_resp(
5997 rdev, info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP],
9e263e19 5998 params);
7443dcd1 5999 if (err)
c2653990 6000 goto out_unlock;
7443dcd1
AD
6001 }
6002
dc1e3cb8
JC
6003 if (info->attrs[NL80211_ATTR_MBSSID_CONFIG]) {
6004 err = nl80211_parse_mbssid_config(&rdev->wiphy, dev,
6005 info->attrs[NL80211_ATTR_MBSSID_CONFIG],
6006 &params->mbssid_config,
6007 params->beacon.mbssid_ies ?
6008 params->beacon.mbssid_ies->cnt :
6009 0);
6010 if (err)
c2653990 6011 goto out_unlock;
dc1e3cb8
JC
6012 }
6013
8bc65d38
AD
6014 err = nl80211_calculate_ap_params(params);
6015 if (err)
6016 goto out_unlock;
66cd794e 6017
47301a74
VJ
6018 if (info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS])
6019 params->flags = nla_get_u32(
6020 info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS]);
6021 else if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
6022 params->flags |= NL80211_AP_SETTINGS_EXTERNAL_AUTH_SUPPORT;
fe494370 6023
7b0a0e3c
JB
6024 if (wdev->conn_owner_nlportid &&
6025 info->attrs[NL80211_ATTR_SOCKET_OWNER] &&
6026 wdev->conn_owner_nlportid != info->snd_portid) {
6027 err = -EINVAL;
6028 goto out_unlock;
6029 }
6030
6031 /* FIXME: validate MLO/link-id against driver capabilities */
6032
9e263e19 6033 err = rdev_start_ap(rdev, dev, params);
46c1dd0c 6034 if (!err) {
7b0a0e3c
JB
6035 wdev->links[link_id].ap.beacon_interval = params->beacon_interval;
6036 wdev->links[link_id].ap.chandef = params->chandef;
6037 wdev->u.ap.ssid_len = params->ssid_len;
6038 memcpy(wdev->u.ap.ssid, params->ssid,
6039 params->ssid_len);
466a3061
DK
6040
6041 if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
6042 wdev->conn_owner_nlportid = info->snd_portid;
46c1dd0c 6043 }
7b0a0e3c 6044out_unlock:
c56589ed 6045 wdev_unlock(wdev);
9951ebfc 6046out:
9e263e19 6047 kfree(params->acl);
dc1e3cb8
JC
6048 kfree(params->beacon.mbssid_ies);
6049 if (params->mbssid_config.tx_wdev &&
6050 params->mbssid_config.tx_wdev->netdev &&
6051 params->mbssid_config.tx_wdev->netdev != dev)
6052 dev_put(params->mbssid_config.tx_wdev->netdev);
9e263e19 6053 kfree(params);
77765eaf 6054
56d1893d 6055 return err;
ed1b6cc7
JB
6056}
6057
8860020e
JB
6058static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info)
6059{
6060 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c 6061 unsigned int link_id = nl80211_link_id(info->attrs);
8860020e
JB
6062 struct net_device *dev = info->user_ptr[1];
6063 struct wireless_dev *wdev = dev->ieee80211_ptr;
6064 struct cfg80211_beacon_data params;
6065 int err;
6066
6067 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
6068 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
6069 return -EOPNOTSUPP;
6070
6071 if (!rdev->ops->change_beacon)
6072 return -EOPNOTSUPP;
6073
7b0a0e3c 6074 if (!wdev->links[link_id].ap.beacon_interval)
8860020e
JB
6075 return -EINVAL;
6076
81e54d08 6077 err = nl80211_parse_beacon(rdev, info->attrs, &params);
8860020e 6078 if (err)
dc1e3cb8 6079 goto out;
8860020e 6080
c56589ed
SW
6081 wdev_lock(wdev);
6082 err = rdev_change_beacon(rdev, dev, &params);
6083 wdev_unlock(wdev);
6084
dc1e3cb8
JC
6085out:
6086 kfree(params.mbssid_ies);
c56589ed 6087 return err;
8860020e
JB
6088}
6089
6090static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info)
ed1b6cc7 6091{
4c476991 6092 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c 6093 unsigned int link_id = nl80211_link_id(info->attrs);
4c476991 6094 struct net_device *dev = info->user_ptr[1];
ed1b6cc7 6095
7b0a0e3c 6096 return cfg80211_stop_ap(rdev, dev, link_id, false);
ed1b6cc7
JB
6097}
6098
5727ef1b
JB
6099static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
6100 [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG },
6101 [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG },
6102 [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG },
0e46724a 6103 [NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG },
b39c48fa 6104 [NL80211_STA_FLAG_AUTHENTICATED] = { .type = NLA_FLAG },
d83023da 6105 [NL80211_STA_FLAG_TDLS_PEER] = { .type = NLA_FLAG },
5727ef1b
JB
6106};
6107
eccb8e8f 6108static int parse_station_flags(struct genl_info *info,
bdd3ae3d 6109 enum nl80211_iftype iftype,
eccb8e8f 6110 struct station_parameters *params)
5727ef1b
JB
6111{
6112 struct nlattr *flags[NL80211_STA_FLAG_MAX + 1];
eccb8e8f 6113 struct nlattr *nla;
5727ef1b
JB
6114 int flag;
6115
eccb8e8f
JB
6116 /*
6117 * Try parsing the new attribute first so userspace
6118 * can specify both for older kernels.
6119 */
6120 nla = info->attrs[NL80211_ATTR_STA_FLAGS2];
6121 if (nla) {
6122 struct nl80211_sta_flag_update *sta_flags;
6123
6124 sta_flags = nla_data(nla);
6125 params->sta_flags_mask = sta_flags->mask;
6126 params->sta_flags_set = sta_flags->set;
77ee7c89 6127 params->sta_flags_set &= params->sta_flags_mask;
eccb8e8f
JB
6128 if ((params->sta_flags_mask |
6129 params->sta_flags_set) & BIT(__NL80211_STA_FLAG_INVALID))
6130 return -EINVAL;
6131 return 0;
6132 }
6133
6134 /* if present, parse the old attribute */
5727ef1b 6135
eccb8e8f 6136 nla = info->attrs[NL80211_ATTR_STA_FLAGS];
5727ef1b
JB
6137 if (!nla)
6138 return 0;
6139
8cb08174 6140 if (nla_parse_nested_deprecated(flags, NL80211_STA_FLAG_MAX, nla, sta_flags_policy, info->extack))
5727ef1b
JB
6141 return -EINVAL;
6142
bdd3ae3d
JB
6143 /*
6144 * Only allow certain flags for interface types so that
6145 * other attributes are silently ignored. Remember that
6146 * this is backward compatibility code with old userspace
6147 * and shouldn't be hit in other cases anyway.
6148 */
6149 switch (iftype) {
6150 case NL80211_IFTYPE_AP:
6151 case NL80211_IFTYPE_AP_VLAN:
6152 case NL80211_IFTYPE_P2P_GO:
6153 params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
6154 BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
6155 BIT(NL80211_STA_FLAG_WME) |
6156 BIT(NL80211_STA_FLAG_MFP);
6157 break;
6158 case NL80211_IFTYPE_P2P_CLIENT:
6159 case NL80211_IFTYPE_STATION:
6160 params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
6161 BIT(NL80211_STA_FLAG_TDLS_PEER);
6162 break;
6163 case NL80211_IFTYPE_MESH_POINT:
6164 params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHENTICATED) |
6165 BIT(NL80211_STA_FLAG_MFP) |
6166 BIT(NL80211_STA_FLAG_AUTHORIZED);
5cf3006c 6167 break;
bdd3ae3d
JB
6168 default:
6169 return -EINVAL;
6170 }
5727ef1b 6171
3383b5a6
JB
6172 for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++) {
6173 if (flags[flag]) {
eccb8e8f 6174 params->sta_flags_set |= (1<<flag);
5727ef1b 6175
3383b5a6
JB
6176 /* no longer support new API additions in old API */
6177 if (flag > NL80211_STA_FLAG_MAX_OLD_API)
6178 return -EINVAL;
6179 }
6180 }
6181
5727ef1b
JB
6182 return 0;
6183}
6184
9bb7e0f2 6185bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr)
c8dcfd8a
FF
6186{
6187 struct nlattr *rate;
8eb41c8d
VK
6188 u32 bitrate;
6189 u16 bitrate_compat;
bbf67e45 6190 enum nl80211_rate_info rate_flg;
c8dcfd8a 6191
ae0be8de 6192 rate = nla_nest_start_noflag(msg, attr);
c8dcfd8a 6193 if (!rate)
db9c64cf 6194 return false;
c8dcfd8a
FF
6195
6196 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
6197 bitrate = cfg80211_calculate_bitrate(info);
8eb41c8d
VK
6198 /* report 16-bit bitrate only if we can */
6199 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
db9c64cf
JB
6200 if (bitrate > 0 &&
6201 nla_put_u32(msg, NL80211_RATE_INFO_BITRATE32, bitrate))
6202 return false;
6203 if (bitrate_compat > 0 &&
6204 nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat))
6205 return false;
6206
b51f3bee
JB
6207 switch (info->bw) {
6208 case RATE_INFO_BW_5:
6209 rate_flg = NL80211_RATE_INFO_5_MHZ_WIDTH;
6210 break;
6211 case RATE_INFO_BW_10:
6212 rate_flg = NL80211_RATE_INFO_10_MHZ_WIDTH;
6213 break;
6214 default:
6215 WARN_ON(1);
7b506ff6 6216 fallthrough;
b51f3bee
JB
6217 case RATE_INFO_BW_20:
6218 rate_flg = 0;
6219 break;
6220 case RATE_INFO_BW_40:
6221 rate_flg = NL80211_RATE_INFO_40_MHZ_WIDTH;
6222 break;
6223 case RATE_INFO_BW_80:
6224 rate_flg = NL80211_RATE_INFO_80_MHZ_WIDTH;
6225 break;
6226 case RATE_INFO_BW_160:
6227 rate_flg = NL80211_RATE_INFO_160_MHZ_WIDTH;
6228 break;
c4cbaf79
LC
6229 case RATE_INFO_BW_HE_RU:
6230 rate_flg = 0;
6231 WARN_ON(!(info->flags & RATE_INFO_FLAGS_HE_MCS));
cfb14110
VJ
6232 break;
6233 case RATE_INFO_BW_320:
6234 rate_flg = NL80211_RATE_INFO_320_MHZ_WIDTH;
6235 break;
6236 case RATE_INFO_BW_EHT_RU:
6237 rate_flg = 0;
6238 WARN_ON(!(info->flags & RATE_INFO_FLAGS_EHT_MCS));
6239 break;
b51f3bee
JB
6240 }
6241
6242 if (rate_flg && nla_put_flag(msg, rate_flg))
6243 return false;
6244
db9c64cf
JB
6245 if (info->flags & RATE_INFO_FLAGS_MCS) {
6246 if (nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs))
6247 return false;
db9c64cf
JB
6248 if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
6249 nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
6250 return false;
6251 } else if (info->flags & RATE_INFO_FLAGS_VHT_MCS) {
6252 if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_MCS, info->mcs))
6253 return false;
6254 if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_NSS, info->nss))
6255 return false;
db9c64cf
JB
6256 if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
6257 nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
6258 return false;
c4cbaf79
LC
6259 } else if (info->flags & RATE_INFO_FLAGS_HE_MCS) {
6260 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_MCS, info->mcs))
6261 return false;
6262 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_NSS, info->nss))
6263 return false;
6264 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_GI, info->he_gi))
6265 return false;
6266 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_DCM, info->he_dcm))
6267 return false;
6268 if (info->bw == RATE_INFO_BW_HE_RU &&
6269 nla_put_u8(msg, NL80211_RATE_INFO_HE_RU_ALLOC,
6270 info->he_ru_alloc))
6271 return false;
cfb14110
VJ
6272 } else if (info->flags & RATE_INFO_FLAGS_EHT_MCS) {
6273 if (nla_put_u8(msg, NL80211_RATE_INFO_EHT_MCS, info->mcs))
6274 return false;
6275 if (nla_put_u8(msg, NL80211_RATE_INFO_EHT_NSS, info->nss))
6276 return false;
6277 if (nla_put_u8(msg, NL80211_RATE_INFO_EHT_GI, info->eht_gi))
6278 return false;
6279 if (info->bw == RATE_INFO_BW_EHT_RU &&
6280 nla_put_u8(msg, NL80211_RATE_INFO_EHT_RU_ALLOC,
6281 info->eht_ru_alloc))
6282 return false;
db9c64cf 6283 }
c8dcfd8a
FF
6284
6285 nla_nest_end(msg, rate);
6286 return true;
c8dcfd8a
FF
6287}
6288
119363c7
FF
6289static bool nl80211_put_signal(struct sk_buff *msg, u8 mask, s8 *signal,
6290 int id)
6291{
6292 void *attr;
6293 int i = 0;
6294
6295 if (!mask)
6296 return true;
6297
ae0be8de 6298 attr = nla_nest_start_noflag(msg, id);
119363c7
FF
6299 if (!attr)
6300 return false;
6301
6302 for (i = 0; i < IEEE80211_MAX_CHAINS; i++) {
6303 if (!(mask & BIT(i)))
6304 continue;
6305
6306 if (nla_put_u8(msg, i, signal[i]))
6307 return false;
6308 }
6309
6310 nla_nest_end(msg, attr);
6311
6312 return true;
6313}
6314
cf5ead82
JB
6315static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
6316 u32 seq, int flags,
66266b3a
JL
6317 struct cfg80211_registered_device *rdev,
6318 struct net_device *dev,
98b62183 6319 const u8 *mac_addr, struct station_info *sinfo)
fd5b74dc
JB
6320{
6321 void *hdr;
f4263c98 6322 struct nlattr *sinfoattr, *bss_param;
fd5b74dc 6323
cf5ead82 6324 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
f77bf486
AS
6325 if (!hdr) {
6326 cfg80211_sinfo_release_content(sinfo);
fd5b74dc 6327 return -1;
f77bf486 6328 }
fd5b74dc 6329
9360ffd1
DM
6330 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
6331 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) ||
6332 nla_put_u32(msg, NL80211_ATTR_GENERATION, sinfo->generation))
6333 goto nla_put_failure;
f5ea9120 6334
ae0be8de 6335 sinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_STA_INFO);
2ec600d6 6336 if (!sinfoattr)
fd5b74dc 6337 goto nla_put_failure;
319090bf
JB
6338
6339#define PUT_SINFO(attr, memb, type) do { \
d686b920 6340 BUILD_BUG_ON(sizeof(type) == sizeof(u64)); \
397c657a 6341 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
319090bf
JB
6342 nla_put_ ## type(msg, NL80211_STA_INFO_ ## attr, \
6343 sinfo->memb)) \
6344 goto nla_put_failure; \
6345 } while (0)
d686b920 6346#define PUT_SINFO_U64(attr, memb) do { \
397c657a 6347 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
d686b920
JB
6348 nla_put_u64_64bit(msg, NL80211_STA_INFO_ ## attr, \
6349 sinfo->memb, NL80211_STA_INFO_PAD)) \
6350 goto nla_put_failure; \
6351 } while (0)
319090bf
JB
6352
6353 PUT_SINFO(CONNECTED_TIME, connected_time, u32);
6354 PUT_SINFO(INACTIVE_TIME, inactive_time, u32);
6c7a0033 6355 PUT_SINFO_U64(ASSOC_AT_BOOTTIME, assoc_at);
319090bf 6356
397c657a
OE
6357 if (sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES) |
6358 BIT_ULL(NL80211_STA_INFO_RX_BYTES64)) &&
9360ffd1 6359 nla_put_u32(msg, NL80211_STA_INFO_RX_BYTES,
42745e03 6360 (u32)sinfo->rx_bytes))
9360ffd1 6361 goto nla_put_failure;
319090bf 6362
397c657a
OE
6363 if (sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES) |
6364 BIT_ULL(NL80211_STA_INFO_TX_BYTES64)) &&
9360ffd1 6365 nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES,
42745e03
VK
6366 (u32)sinfo->tx_bytes))
6367 goto nla_put_failure;
319090bf 6368
d686b920
JB
6369 PUT_SINFO_U64(RX_BYTES64, rx_bytes);
6370 PUT_SINFO_U64(TX_BYTES64, tx_bytes);
319090bf
JB
6371 PUT_SINFO(LLID, llid, u16);
6372 PUT_SINFO(PLID, plid, u16);
6373 PUT_SINFO(PLINK_STATE, plink_state, u8);
d686b920 6374 PUT_SINFO_U64(RX_DURATION, rx_duration);
36647055
THJ
6375 PUT_SINFO_U64(TX_DURATION, tx_duration);
6376
6377 if (wiphy_ext_feature_isset(&rdev->wiphy,
6378 NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
6379 PUT_SINFO(AIRTIME_WEIGHT, airtime_weight, u16);
319090bf 6380
66266b3a
JL
6381 switch (rdev->wiphy.signal_type) {
6382 case CFG80211_SIGNAL_TYPE_MBM:
319090bf
JB
6383 PUT_SINFO(SIGNAL, signal, u8);
6384 PUT_SINFO(SIGNAL_AVG, signal_avg, u8);
66266b3a
JL
6385 break;
6386 default:
6387 break;
6388 }
397c657a 6389 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) {
119363c7
FF
6390 if (!nl80211_put_signal(msg, sinfo->chains,
6391 sinfo->chain_signal,
6392 NL80211_STA_INFO_CHAIN_SIGNAL))
6393 goto nla_put_failure;
6394 }
397c657a 6395 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) {
119363c7
FF
6396 if (!nl80211_put_signal(msg, sinfo->chains,
6397 sinfo->chain_signal_avg,
6398 NL80211_STA_INFO_CHAIN_SIGNAL_AVG))
6399 goto nla_put_failure;
6400 }
397c657a 6401 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) {
c8dcfd8a
FF
6402 if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
6403 NL80211_STA_INFO_TX_BITRATE))
6404 goto nla_put_failure;
6405 }
397c657a 6406 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) {
c8dcfd8a
FF
6407 if (!nl80211_put_sta_rate(msg, &sinfo->rxrate,
6408 NL80211_STA_INFO_RX_BITRATE))
420e7fab 6409 goto nla_put_failure;
420e7fab 6410 }
319090bf
JB
6411
6412 PUT_SINFO(RX_PACKETS, rx_packets, u32);
6413 PUT_SINFO(TX_PACKETS, tx_packets, u32);
6414 PUT_SINFO(TX_RETRIES, tx_retries, u32);
6415 PUT_SINFO(TX_FAILED, tx_failed, u32);
6416 PUT_SINFO(EXPECTED_THROUGHPUT, expected_throughput, u32);
ab60633c 6417 PUT_SINFO(AIRTIME_LINK_METRIC, airtime_link_metric, u32);
319090bf
JB
6418 PUT_SINFO(BEACON_LOSS, beacon_loss_count, u32);
6419 PUT_SINFO(LOCAL_PM, local_pm, u32);
6420 PUT_SINFO(PEER_PM, peer_pm, u32);
6421 PUT_SINFO(NONPEER_PM, nonpeer_pm, u32);
dbdaee7a 6422 PUT_SINFO(CONNECTED_TO_GATE, connected_to_gate, u8);
1303a51c 6423 PUT_SINFO(CONNECTED_TO_AS, connected_to_as, u8);
319090bf 6424
397c657a 6425 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_BSS_PARAM)) {
ae0be8de
MK
6426 bss_param = nla_nest_start_noflag(msg,
6427 NL80211_STA_INFO_BSS_PARAM);
f4263c98
PS
6428 if (!bss_param)
6429 goto nla_put_failure;
6430
9360ffd1
DM
6431 if (((sinfo->bss_param.flags & BSS_PARAM_FLAGS_CTS_PROT) &&
6432 nla_put_flag(msg, NL80211_STA_BSS_PARAM_CTS_PROT)) ||
6433 ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_PREAMBLE) &&
6434 nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_PREAMBLE)) ||
6435 ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_SLOT_TIME) &&
6436 nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME)) ||
6437 nla_put_u8(msg, NL80211_STA_BSS_PARAM_DTIM_PERIOD,
6438 sinfo->bss_param.dtim_period) ||
6439 nla_put_u16(msg, NL80211_STA_BSS_PARAM_BEACON_INTERVAL,
6440 sinfo->bss_param.beacon_interval))
6441 goto nla_put_failure;
f4263c98
PS
6442
6443 nla_nest_end(msg, bss_param);
6444 }
397c657a 6445 if ((sinfo->filled & BIT_ULL(NL80211_STA_INFO_STA_FLAGS)) &&
9360ffd1
DM
6446 nla_put(msg, NL80211_STA_INFO_STA_FLAGS,
6447 sizeof(struct nl80211_sta_flag_update),
6448 &sinfo->sta_flags))
6449 goto nla_put_failure;
319090bf 6450
d686b920
JB
6451 PUT_SINFO_U64(T_OFFSET, t_offset);
6452 PUT_SINFO_U64(RX_DROP_MISC, rx_dropped_misc);
6453 PUT_SINFO_U64(BEACON_RX, rx_beacon);
a76b1942 6454 PUT_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8);
0d4e14a3
AB
6455 PUT_SINFO(RX_MPDUS, rx_mpdu_count, u32);
6456 PUT_SINFO(FCS_ERROR_COUNT, fcs_err_count, u32);
81d5439d 6457 if (wiphy_ext_feature_isset(&rdev->wiphy,
9c06602b
BP
6458 NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT)) {
6459 PUT_SINFO(ACK_SIGNAL, ack_signal, u8);
6460 PUT_SINFO(ACK_SIGNAL_AVG, avg_ack_signal, s8);
6461 }
319090bf
JB
6462
6463#undef PUT_SINFO
d686b920 6464#undef PUT_SINFO_U64
6de39808 6465
8689c051 6466 if (sinfo->pertid) {
6de39808
JB
6467 struct nlattr *tidsattr;
6468 int tid;
6469
ae0be8de
MK
6470 tidsattr = nla_nest_start_noflag(msg,
6471 NL80211_STA_INFO_TID_STATS);
6de39808
JB
6472 if (!tidsattr)
6473 goto nla_put_failure;
6474
6475 for (tid = 0; tid < IEEE80211_NUM_TIDS + 1; tid++) {
6476 struct cfg80211_tid_stats *tidstats;
6477 struct nlattr *tidattr;
6478
6479 tidstats = &sinfo->pertid[tid];
6480
6481 if (!tidstats->filled)
6482 continue;
6483
ae0be8de 6484 tidattr = nla_nest_start_noflag(msg, tid + 1);
6de39808
JB
6485 if (!tidattr)
6486 goto nla_put_failure;
6487
d686b920 6488#define PUT_TIDVAL_U64(attr, memb) do { \
6de39808 6489 if (tidstats->filled & BIT(NL80211_TID_STATS_ ## attr) && \
d686b920
JB
6490 nla_put_u64_64bit(msg, NL80211_TID_STATS_ ## attr, \
6491 tidstats->memb, NL80211_TID_STATS_PAD)) \
6de39808
JB
6492 goto nla_put_failure; \
6493 } while (0)
6494
d686b920
JB
6495 PUT_TIDVAL_U64(RX_MSDU, rx_msdu);
6496 PUT_TIDVAL_U64(TX_MSDU, tx_msdu);
6497 PUT_TIDVAL_U64(TX_MSDU_RETRIES, tx_msdu_retries);
6498 PUT_TIDVAL_U64(TX_MSDU_FAILED, tx_msdu_failed);
6de39808 6499
d686b920 6500#undef PUT_TIDVAL_U64
52539ca8
THJ
6501 if ((tidstats->filled &
6502 BIT(NL80211_TID_STATS_TXQ_STATS)) &&
6503 !nl80211_put_txq_stats(msg, &tidstats->txq_stats,
6504 NL80211_TID_STATS_TXQ_STATS))
6505 goto nla_put_failure;
6506
6de39808
JB
6507 nla_nest_end(msg, tidattr);
6508 }
6509
6510 nla_nest_end(msg, tidsattr);
6511 }
6512
2ec600d6 6513 nla_nest_end(msg, sinfoattr);
fd5b74dc 6514
319090bf 6515 if (sinfo->assoc_req_ies_len &&
9360ffd1
DM
6516 nla_put(msg, NL80211_ATTR_IE, sinfo->assoc_req_ies_len,
6517 sinfo->assoc_req_ies))
6518 goto nla_put_failure;
50d3dfb7 6519
7ea3e110 6520 cfg80211_sinfo_release_content(sinfo);
053c095a
JB
6521 genlmsg_end(msg, hdr);
6522 return 0;
fd5b74dc
JB
6523
6524 nla_put_failure:
7ea3e110 6525 cfg80211_sinfo_release_content(sinfo);
bc3ed28c
TG
6526 genlmsg_cancel(msg, hdr);
6527 return -EMSGSIZE;
fd5b74dc
JB
6528}
6529
2ec600d6 6530static int nl80211_dump_station(struct sk_buff *skb,
bba95fef 6531 struct netlink_callback *cb)
2ec600d6 6532{
73887fd9 6533 struct station_info sinfo;
1b8ec87a 6534 struct cfg80211_registered_device *rdev;
97990a06 6535 struct wireless_dev *wdev;
2ec600d6 6536 u8 mac_addr[ETH_ALEN];
97990a06 6537 int sta_idx = cb->args[2];
2ec600d6 6538 int err;
2ec600d6 6539
ce6b6974 6540 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL);
67748893 6541 if (err)
a05829a7
JB
6542 return err;
6543 /* nl80211_prepare_wdev_dump acquired it in the successful case */
6544 __acquire(&rdev->wiphy.mtx);
bba95fef 6545
97990a06
JB
6546 if (!wdev->netdev) {
6547 err = -EINVAL;
6548 goto out_err;
6549 }
6550
1b8ec87a 6551 if (!rdev->ops->dump_station) {
eec60b03 6552 err = -EOPNOTSUPP;
bba95fef
JB
6553 goto out_err;
6554 }
6555
bba95fef 6556 while (1) {
73887fd9 6557 memset(&sinfo, 0, sizeof(sinfo));
1b8ec87a 6558 err = rdev_dump_station(rdev, wdev->netdev, sta_idx,
73887fd9 6559 mac_addr, &sinfo);
bba95fef
JB
6560 if (err == -ENOENT)
6561 break;
6562 if (err)
3b85875a 6563 goto out_err;
bba95fef 6564
cf5ead82 6565 if (nl80211_send_station(skb, NL80211_CMD_NEW_STATION,
15e47304 6566 NETLINK_CB(cb->skb).portid,
bba95fef 6567 cb->nlh->nlmsg_seq, NLM_F_MULTI,
1b8ec87a 6568 rdev, wdev->netdev, mac_addr,
73887fd9 6569 &sinfo) < 0)
bba95fef
JB
6570 goto out;
6571
6572 sta_idx++;
6573 }
6574
bba95fef 6575 out:
97990a06 6576 cb->args[2] = sta_idx;
bba95fef 6577 err = skb->len;
bba95fef 6578 out_err:
a05829a7 6579 wiphy_unlock(&rdev->wiphy);
bba95fef
JB
6580
6581 return err;
2ec600d6 6582}
fd5b74dc 6583
5727ef1b
JB
6584static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
6585{
4c476991
JB
6586 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6587 struct net_device *dev = info->user_ptr[1];
73887fd9 6588 struct station_info sinfo;
fd5b74dc
JB
6589 struct sk_buff *msg;
6590 u8 *mac_addr = NULL;
4c476991 6591 int err;
fd5b74dc 6592
73887fd9 6593 memset(&sinfo, 0, sizeof(sinfo));
fd5b74dc 6594
73887fd9
JB
6595 if (!info->attrs[NL80211_ATTR_MAC])
6596 return -EINVAL;
fd5b74dc
JB
6597
6598 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
6599
73887fd9
JB
6600 if (!rdev->ops->get_station)
6601 return -EOPNOTSUPP;
3b85875a 6602
73887fd9 6603 err = rdev_get_station(rdev, dev, mac_addr, &sinfo);
fd5b74dc 6604 if (err)
73887fd9 6605 return err;
2ec600d6 6606
fd2120ca 6607 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7ea3e110 6608 if (!msg) {
ba8f566a 6609 cfg80211_sinfo_release_content(&sinfo);
73887fd9 6610 return -ENOMEM;
7ea3e110 6611 }
fd5b74dc 6612
cf5ead82
JB
6613 if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION,
6614 info->snd_portid, info->snd_seq, 0,
73887fd9 6615 rdev, dev, mac_addr, &sinfo) < 0) {
4c476991 6616 nlmsg_free(msg);
73887fd9 6617 return -ENOBUFS;
4c476991 6618 }
3b85875a 6619
73887fd9 6620 return genlmsg_reply(msg, info);
5727ef1b
JB
6621}
6622
77ee7c89
JB
6623int cfg80211_check_station_change(struct wiphy *wiphy,
6624 struct station_parameters *params,
6625 enum cfg80211_station_type statype)
6626{
e4208427
AB
6627 if (params->listen_interval != -1 &&
6628 statype != CFG80211_STA_AP_CLIENT_UNASSOC)
77ee7c89 6629 return -EINVAL;
e4208427 6630
17b94247
AB
6631 if (params->support_p2p_ps != -1 &&
6632 statype != CFG80211_STA_AP_CLIENT_UNASSOC)
6633 return -EINVAL;
6634
c72e1140 6635 if (params->aid &&
e4208427
AB
6636 !(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
6637 statype != CFG80211_STA_AP_CLIENT_UNASSOC)
77ee7c89
JB
6638 return -EINVAL;
6639
6640 /* When you run into this, adjust the code below for the new flag */
6641 BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7);
6642
6643 switch (statype) {
eef941e6
TP
6644 case CFG80211_STA_MESH_PEER_KERNEL:
6645 case CFG80211_STA_MESH_PEER_USER:
77ee7c89
JB
6646 /*
6647 * No ignoring the TDLS flag here -- the userspace mesh
6648 * code doesn't have the bug of including TDLS in the
6649 * mask everywhere.
6650 */
6651 if (params->sta_flags_mask &
6652 ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) |
6653 BIT(NL80211_STA_FLAG_MFP) |
6654 BIT(NL80211_STA_FLAG_AUTHORIZED)))
6655 return -EINVAL;
6656 break;
6657 case CFG80211_STA_TDLS_PEER_SETUP:
6658 case CFG80211_STA_TDLS_PEER_ACTIVE:
6659 if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
6660 return -EINVAL;
6661 /* ignore since it can't change */
6662 params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
6663 break;
6664 default:
6665 /* disallow mesh-specific things */
6666 if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION)
6667 return -EINVAL;
6668 if (params->local_pm)
6669 return -EINVAL;
6670 if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)
6671 return -EINVAL;
6672 }
6673
6674 if (statype != CFG80211_STA_TDLS_PEER_SETUP &&
6675 statype != CFG80211_STA_TDLS_PEER_ACTIVE) {
6676 /* TDLS can't be set, ... */
6677 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
6678 return -EINVAL;
6679 /*
6680 * ... but don't bother the driver with it. This works around
6681 * a hostapd/wpa_supplicant issue -- it always includes the
6682 * TLDS_PEER flag in the mask even for AP mode.
6683 */
6684 params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
6685 }
6686
47edb11b
AB
6687 if (statype != CFG80211_STA_TDLS_PEER_SETUP &&
6688 statype != CFG80211_STA_AP_CLIENT_UNASSOC) {
77ee7c89
JB
6689 /* reject other things that can't change */
6690 if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD)
6691 return -EINVAL;
6692 if (params->sta_modify_mask & STATION_PARAM_APPLY_CAPABILITY)
6693 return -EINVAL;
b95eb7f0 6694 if (params->link_sta_params.supported_rates)
77ee7c89 6695 return -EINVAL;
b95eb7f0
ST
6696 if (params->ext_capab || params->link_sta_params.ht_capa ||
6697 params->link_sta_params.vht_capa ||
6698 params->link_sta_params.he_capa ||
6699 params->link_sta_params.eht_capa)
77ee7c89
JB
6700 return -EINVAL;
6701 }
6702
47edb11b
AB
6703 if (statype != CFG80211_STA_AP_CLIENT &&
6704 statype != CFG80211_STA_AP_CLIENT_UNASSOC) {
77ee7c89
JB
6705 if (params->vlan)
6706 return -EINVAL;
6707 }
6708
6709 switch (statype) {
6710 case CFG80211_STA_AP_MLME_CLIENT:
6711 /* Use this only for authorizing/unauthorizing a station */
6712 if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))
6713 return -EOPNOTSUPP;
6714 break;
6715 case CFG80211_STA_AP_CLIENT:
47edb11b 6716 case CFG80211_STA_AP_CLIENT_UNASSOC:
77ee7c89
JB
6717 /* accept only the listed bits */
6718 if (params->sta_flags_mask &
6719 ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
6720 BIT(NL80211_STA_FLAG_AUTHENTICATED) |
6721 BIT(NL80211_STA_FLAG_ASSOCIATED) |
6722 BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
6723 BIT(NL80211_STA_FLAG_WME) |
6724 BIT(NL80211_STA_FLAG_MFP)))
6725 return -EINVAL;
6726
6727 /* but authenticated/associated only if driver handles it */
6728 if (!(wiphy->features & NL80211_FEATURE_FULL_AP_CLIENT_STATE) &&
6729 params->sta_flags_mask &
6730 (BIT(NL80211_STA_FLAG_AUTHENTICATED) |
6731 BIT(NL80211_STA_FLAG_ASSOCIATED)))
6732 return -EINVAL;
6733 break;
6734 case CFG80211_STA_IBSS:
6735 case CFG80211_STA_AP_STA:
6736 /* reject any changes other than AUTHORIZED */
6737 if (params->sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED))
6738 return -EINVAL;
6739 break;
6740 case CFG80211_STA_TDLS_PEER_SETUP:
6741 /* reject any changes other than AUTHORIZED or WME */
6742 if (params->sta_flags_mask & ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
6743 BIT(NL80211_STA_FLAG_WME)))
6744 return -EINVAL;
6745 /* force (at least) rates when authorizing */
6746 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED) &&
b95eb7f0 6747 !params->link_sta_params.supported_rates)
77ee7c89
JB
6748 return -EINVAL;
6749 break;
6750 case CFG80211_STA_TDLS_PEER_ACTIVE:
6751 /* reject any changes */
6752 return -EINVAL;
eef941e6 6753 case CFG80211_STA_MESH_PEER_KERNEL:
77ee7c89
JB
6754 if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)
6755 return -EINVAL;
6756 break;
eef941e6 6757 case CFG80211_STA_MESH_PEER_USER:
42925040
CYY
6758 if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION &&
6759 params->plink_action != NL80211_PLINK_ACTION_BLOCK)
77ee7c89
JB
6760 return -EINVAL;
6761 break;
6762 }
6763
06f7c88c
BL
6764 /*
6765 * Older kernel versions ignored this attribute entirely, so don't
6766 * reject attempts to update it but mark it as unused instead so the
6767 * driver won't look at the data.
6768 */
6769 if (statype != CFG80211_STA_AP_CLIENT_UNASSOC &&
6770 statype != CFG80211_STA_TDLS_PEER_SETUP)
b95eb7f0 6771 params->link_sta_params.opmode_notif_used = false;
06f7c88c 6772
77ee7c89
JB
6773 return 0;
6774}
6775EXPORT_SYMBOL(cfg80211_check_station_change);
6776
5727ef1b 6777/*
c258d2de 6778 * Get vlan interface making sure it is running and on the right wiphy.
5727ef1b 6779 */
80b99899
JB
6780static struct net_device *get_vlan(struct genl_info *info,
6781 struct cfg80211_registered_device *rdev)
5727ef1b 6782{
463d0183 6783 struct nlattr *vlanattr = info->attrs[NL80211_ATTR_STA_VLAN];
80b99899
JB
6784 struct net_device *v;
6785 int ret;
6786
6787 if (!vlanattr)
6788 return NULL;
6789
6790 v = dev_get_by_index(genl_info_net(info), nla_get_u32(vlanattr));
6791 if (!v)
6792 return ERR_PTR(-ENODEV);
6793
6794 if (!v->ieee80211_ptr || v->ieee80211_ptr->wiphy != &rdev->wiphy) {
6795 ret = -EINVAL;
6796 goto error;
5727ef1b 6797 }
80b99899 6798
77ee7c89
JB
6799 if (v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
6800 v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
6801 v->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
6802 ret = -EINVAL;
6803 goto error;
6804 }
6805
80b99899
JB
6806 if (!netif_running(v)) {
6807 ret = -ENETDOWN;
6808 goto error;
6809 }
6810
6811 return v;
6812 error:
6813 dev_put(v);
6814 return ERR_PTR(ret);
5727ef1b
JB
6815}
6816
ff276691
JB
6817static int nl80211_parse_sta_wme(struct genl_info *info,
6818 struct station_parameters *params)
df881293 6819{
df881293
JM
6820 struct nlattr *tb[NL80211_STA_WME_MAX + 1];
6821 struct nlattr *nla;
6822 int err;
6823
df881293
JM
6824 /* parse WME attributes if present */
6825 if (!info->attrs[NL80211_ATTR_STA_WME])
6826 return 0;
6827
6828 nla = info->attrs[NL80211_ATTR_STA_WME];
8cb08174
JB
6829 err = nla_parse_nested_deprecated(tb, NL80211_STA_WME_MAX, nla,
6830 nl80211_sta_wme_policy,
6831 info->extack);
df881293
JM
6832 if (err)
6833 return err;
6834
6835 if (tb[NL80211_STA_WME_UAPSD_QUEUES])
6836 params->uapsd_queues = nla_get_u8(
6837 tb[NL80211_STA_WME_UAPSD_QUEUES]);
6838 if (params->uapsd_queues & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
6839 return -EINVAL;
6840
6841 if (tb[NL80211_STA_WME_MAX_SP])
6842 params->max_sp = nla_get_u8(tb[NL80211_STA_WME_MAX_SP]);
6843
6844 if (params->max_sp & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
6845 return -EINVAL;
6846
6847 params->sta_modify_mask |= STATION_PARAM_APPLY_UAPSD;
6848
6849 return 0;
6850}
6851
c01fc9ad
SD
6852static int nl80211_parse_sta_channel_info(struct genl_info *info,
6853 struct station_parameters *params)
6854{
6855 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]) {
6856 params->supported_channels =
6857 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
6858 params->supported_channels_len =
6859 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
6860 /*
6861 * Need to include at least one (first channel, number of
cb9abd48
JB
6862 * channels) tuple for each subband (checked in policy),
6863 * and must have proper tuples for the rest of the data as well.
c01fc9ad 6864 */
c01fc9ad
SD
6865 if (params->supported_channels_len % 2)
6866 return -EINVAL;
6867 }
6868
6869 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]) {
6870 params->supported_oper_classes =
6871 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
6872 params->supported_oper_classes_len =
6873 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
c01fc9ad
SD
6874 }
6875 return 0;
6876}
6877
ff276691
JB
6878static int nl80211_set_station_tdls(struct genl_info *info,
6879 struct station_parameters *params)
6880{
c01fc9ad 6881 int err;
ff276691 6882 /* Dummy STA entry gets updated once the peer capabilities are known */
5e4b6f56
JM
6883 if (info->attrs[NL80211_ATTR_PEER_AID])
6884 params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
ff276691 6885 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
b95eb7f0 6886 params->link_sta_params.ht_capa =
ff276691
JB
6887 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
6888 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
b95eb7f0 6889 params->link_sta_params.vht_capa =
ff276691 6890 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
c4cbaf79 6891 if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
b95eb7f0 6892 params->link_sta_params.he_capa =
c4cbaf79 6893 nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
b95eb7f0 6894 params->link_sta_params.he_capa_len =
c4cbaf79 6895 nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
ea05fd35
IP
6896
6897 if (info->attrs[NL80211_ATTR_EHT_CAPABILITY]) {
b95eb7f0 6898 params->link_sta_params.eht_capa =
ea05fd35 6899 nla_data(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
b95eb7f0 6900 params->link_sta_params.eht_capa_len =
ea05fd35
IP
6901 nla_len(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
6902
b95eb7f0
ST
6903 if (!ieee80211_eht_capa_size_ok((const u8 *)params->link_sta_params.he_capa,
6904 (const u8 *)params->link_sta_params.eht_capa,
ea5cba26
JB
6905 params->link_sta_params.eht_capa_len,
6906 false))
ea05fd35
IP
6907 return -EINVAL;
6908 }
c4cbaf79 6909 }
ff276691 6910
c01fc9ad
SD
6911 err = nl80211_parse_sta_channel_info(info, params);
6912 if (err)
6913 return err;
6914
ff276691
JB
6915 return nl80211_parse_sta_wme(info, params);
6916}
6917
e96d1cd2 6918static int nl80211_parse_sta_txpower_setting(struct genl_info *info,
577e5b8c
ST
6919 struct sta_txpwr *txpwr,
6920 bool *txpwr_set)
e96d1cd2
ARN
6921{
6922 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6923 int idx;
6924
6925 if (info->attrs[NL80211_ATTR_STA_TX_POWER_SETTING]) {
6926 if (!rdev->ops->set_tx_power ||
6927 !wiphy_ext_feature_isset(&rdev->wiphy,
6928 NL80211_EXT_FEATURE_STA_TX_PWR))
6929 return -EOPNOTSUPP;
6930
6931 idx = NL80211_ATTR_STA_TX_POWER_SETTING;
577e5b8c 6932 txpwr->type = nla_get_u8(info->attrs[idx]);
e96d1cd2 6933
577e5b8c 6934 if (txpwr->type == NL80211_TX_POWER_LIMITED) {
e96d1cd2
ARN
6935 idx = NL80211_ATTR_STA_TX_POWER;
6936
6937 if (info->attrs[idx])
577e5b8c 6938 txpwr->power = nla_get_s16(info->attrs[idx]);
e96d1cd2
ARN
6939 else
6940 return -EINVAL;
6941 }
577e5b8c
ST
6942
6943 *txpwr_set = true;
6944 } else {
6945 *txpwr_set = false;
e96d1cd2
ARN
6946 }
6947
6948 return 0;
6949}
6950
5727ef1b
JB
6951static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
6952{
4c476991 6953 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 6954 struct net_device *dev = info->user_ptr[1];
5727ef1b 6955 struct station_parameters params;
77ee7c89
JB
6956 u8 *mac_addr;
6957 int err;
5727ef1b
JB
6958
6959 memset(&params, 0, sizeof(params));
6960
77ee7c89
JB
6961 if (!rdev->ops->change_station)
6962 return -EOPNOTSUPP;
6963
e4208427
AB
6964 /*
6965 * AID and listen_interval properties can be set only for unassociated
6966 * station. Include these parameters here and will check them in
6967 * cfg80211_check_station_change().
6968 */
a9bc31e4
AB
6969 if (info->attrs[NL80211_ATTR_STA_AID])
6970 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
e4208427 6971
14f34e36
GG
6972 if (info->attrs[NL80211_ATTR_VLAN_ID])
6973 params.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
6974
e4208427
AB
6975 if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
6976 params.listen_interval =
6977 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
6978 else
6979 params.listen_interval = -1;
5727ef1b 6980
ab0d76f6
JB
6981 if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS])
6982 params.support_p2p_ps =
6983 nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
6984 else
17b94247 6985 params.support_p2p_ps = -1;
17b94247 6986
5727ef1b
JB
6987 if (!info->attrs[NL80211_ATTR_MAC])
6988 return -EINVAL;
6989
d2bc5249
AO
6990 params.link_sta_params.link_id =
6991 nl80211_link_id_or_invalid(info->attrs);
6992
6993 if (info->attrs[NL80211_ATTR_MLD_ADDR]) {
6994 /* If MLD_ADDR attribute is set then this is an MLD station
6995 * and the MLD_ADDR attribute holds the MLD address and the
6996 * MAC attribute holds for the LINK address.
6997 * In that case, the link_id is also expected to be valid.
6998 */
6999 if (params.link_sta_params.link_id < 0)
7000 return -EINVAL;
7001
7002 mac_addr = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
7003 params.link_sta_params.mld_mac = mac_addr;
7004 params.link_sta_params.link_mac =
7005 nla_data(info->attrs[NL80211_ATTR_MAC]);
7006 if (!is_valid_ether_addr(params.link_sta_params.link_mac))
7007 return -EINVAL;
7008 } else {
7009 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
7010 }
7011
5727ef1b
JB
7012
7013 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
b95eb7f0 7014 params.link_sta_params.supported_rates =
5727ef1b 7015 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
b95eb7f0 7016 params.link_sta_params.supported_rates_len =
5727ef1b
JB
7017 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
7018 }
7019
9d62a986
JM
7020 if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
7021 params.capability =
7022 nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]);
7023 params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY;
7024 }
7025
7026 if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) {
7027 params.ext_capab =
7028 nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
7029 params.ext_capab_len =
7030 nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
7031 }
7032
bdd3ae3d 7033 if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
5727ef1b
JB
7034 return -EINVAL;
7035
ab0d76f6 7036 if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
2ec600d6 7037 params.plink_action =
f8bacc21 7038 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
2ec600d6 7039
f8bacc21 7040 if (info->attrs[NL80211_ATTR_STA_PLINK_STATE]) {
9c3990aa 7041 params.plink_state =
f8bacc21 7042 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]);
ab0d76f6 7043 if (info->attrs[NL80211_ATTR_MESH_PEER_AID])
7d27a0ba
MH
7044 params.peer_aid = nla_get_u16(
7045 info->attrs[NL80211_ATTR_MESH_PEER_AID]);
f8bacc21
JB
7046 params.sta_modify_mask |= STATION_PARAM_APPLY_PLINK_STATE;
7047 }
9c3990aa 7048
ab0d76f6
JB
7049 if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE])
7050 params.local_pm = nla_get_u32(
3b1c5a53
MP
7051 info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]);
7052
06f7c88c 7053 if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
b95eb7f0
ST
7054 params.link_sta_params.opmode_notif_used = true;
7055 params.link_sta_params.opmode_notif =
06f7c88c
BL
7056 nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
7057 }
7058
43e64bf3 7059 if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
b95eb7f0 7060 params.link_sta_params.he_6ghz_capa =
fce2ff72 7061 nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
43e64bf3 7062
36647055
THJ
7063 if (info->attrs[NL80211_ATTR_AIRTIME_WEIGHT])
7064 params.airtime_weight =
7065 nla_get_u16(info->attrs[NL80211_ATTR_AIRTIME_WEIGHT]);
7066
7067 if (params.airtime_weight &&
7068 !wiphy_ext_feature_isset(&rdev->wiphy,
7069 NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
7070 return -EOPNOTSUPP;
7071
b95eb7f0
ST
7072 err = nl80211_parse_sta_txpower_setting(info,
7073 &params.link_sta_params.txpwr,
7074 &params.link_sta_params.txpwr_set);
e96d1cd2
ARN
7075 if (err)
7076 return err;
7077
77ee7c89
JB
7078 /* Include parameters for TDLS peer (will check later) */
7079 err = nl80211_set_station_tdls(info, &params);
7080 if (err)
7081 return err;
7082
7083 params.vlan = get_vlan(info, rdev);
7084 if (IS_ERR(params.vlan))
7085 return PTR_ERR(params.vlan);
7086
a97f4424
JB
7087 switch (dev->ieee80211_ptr->iftype) {
7088 case NL80211_IFTYPE_AP:
7089 case NL80211_IFTYPE_AP_VLAN:
074ac8df 7090 case NL80211_IFTYPE_P2P_GO:
074ac8df 7091 case NL80211_IFTYPE_P2P_CLIENT:
a97f4424 7092 case NL80211_IFTYPE_STATION:
267335d6 7093 case NL80211_IFTYPE_ADHOC:
a97f4424 7094 case NL80211_IFTYPE_MESH_POINT:
a97f4424
JB
7095 break;
7096 default:
77ee7c89
JB
7097 err = -EOPNOTSUPP;
7098 goto out_put_vlan;
034d655e
JB
7099 }
7100
77ee7c89 7101 /* driver will call cfg80211_check_station_change() */
3d1cc7cd 7102 wdev_lock(dev->ieee80211_ptr);
e35e4d28 7103 err = rdev_change_station(rdev, dev, mac_addr, &params);
3d1cc7cd 7104 wdev_unlock(dev->ieee80211_ptr);
5727ef1b 7105
77ee7c89 7106 out_put_vlan:
1160dfa1 7107 dev_put(params.vlan);
3b85875a 7108
5727ef1b
JB
7109 return err;
7110}
7111
7112static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
7113{
4c476991 7114 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5727ef1b 7115 int err;
4c476991 7116 struct net_device *dev = info->user_ptr[1];
efbfe516 7117 struct wireless_dev *wdev = dev->ieee80211_ptr;
5727ef1b
JB
7118 struct station_parameters params;
7119 u8 *mac_addr = NULL;
bda95eb1
JB
7120 u32 auth_assoc = BIT(NL80211_STA_FLAG_AUTHENTICATED) |
7121 BIT(NL80211_STA_FLAG_ASSOCIATED);
5727ef1b
JB
7122
7123 memset(&params, 0, sizeof(params));
7124
984c311b
JB
7125 if (!rdev->ops->add_station)
7126 return -EOPNOTSUPP;
7127
5727ef1b
JB
7128 if (!info->attrs[NL80211_ATTR_MAC])
7129 return -EINVAL;
7130
5727ef1b
JB
7131 if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
7132 return -EINVAL;
7133
7134 if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
7135 return -EINVAL;
7136
5e4b6f56
JM
7137 if (!info->attrs[NL80211_ATTR_STA_AID] &&
7138 !info->attrs[NL80211_ATTR_PEER_AID])
0e956c13
TLSC
7139 return -EINVAL;
7140
b95eb7f0
ST
7141 params.link_sta_params.link_id =
7142 nl80211_link_id_or_invalid(info->attrs);
7143
c0d67012 7144 if (info->attrs[NL80211_ATTR_MLD_ADDR]) {
c0d67012
ST
7145 mac_addr = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
7146 params.link_sta_params.mld_mac = mac_addr;
7147 params.link_sta_params.link_mac =
7148 nla_data(info->attrs[NL80211_ATTR_MAC]);
7149 if (!is_valid_ether_addr(params.link_sta_params.link_mac))
7150 return -EINVAL;
7151 } else {
7152 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
7153 }
7154
b95eb7f0 7155 params.link_sta_params.supported_rates =
5727ef1b 7156 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
b95eb7f0 7157 params.link_sta_params.supported_rates_len =
5727ef1b
JB
7158 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
7159 params.listen_interval =
7160 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
51b50fbe 7161
14f34e36
GG
7162 if (info->attrs[NL80211_ATTR_VLAN_ID])
7163 params.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
7164
17b94247 7165 if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) {
ab0d76f6
JB
7166 params.support_p2p_ps =
7167 nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
17b94247
AB
7168 } else {
7169 /*
7170 * if not specified, assume it's supported for P2P GO interface,
7171 * and is NOT supported for AP interface
7172 */
7173 params.support_p2p_ps =
7174 dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO;
7175 }
7176
3d124ea2 7177 if (info->attrs[NL80211_ATTR_PEER_AID])
5e4b6f56 7178 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
3d124ea2
JM
7179 else
7180 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
51b50fbe 7181
9d62a986
JM
7182 if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
7183 params.capability =
7184 nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]);
7185 params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY;
7186 }
7187
7188 if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) {
7189 params.ext_capab =
7190 nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
7191 params.ext_capab_len =
7192 nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
7193 }
7194
36aedc90 7195 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
b95eb7f0 7196 params.link_sta_params.ht_capa =
36aedc90 7197 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
5727ef1b 7198
f461be3e 7199 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
b95eb7f0 7200 params.link_sta_params.vht_capa =
f461be3e
MP
7201 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
7202
c4cbaf79 7203 if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
b95eb7f0 7204 params.link_sta_params.he_capa =
c4cbaf79 7205 nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
b95eb7f0 7206 params.link_sta_params.he_capa_len =
c4cbaf79 7207 nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
ea05fd35
IP
7208
7209 if (info->attrs[NL80211_ATTR_EHT_CAPABILITY]) {
b95eb7f0 7210 params.link_sta_params.eht_capa =
ea05fd35 7211 nla_data(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
b95eb7f0 7212 params.link_sta_params.eht_capa_len =
ea05fd35
IP
7213 nla_len(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
7214
b95eb7f0
ST
7215 if (!ieee80211_eht_capa_size_ok((const u8 *)params.link_sta_params.he_capa,
7216 (const u8 *)params.link_sta_params.eht_capa,
ea5cba26
JB
7217 params.link_sta_params.eht_capa_len,
7218 false))
ea05fd35
IP
7219 return -EINVAL;
7220 }
c4cbaf79
LC
7221 }
7222
43e64bf3 7223 if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
b95eb7f0 7224 params.link_sta_params.he_6ghz_capa =
43e64bf3
RM
7225 nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
7226
60f4a7b1 7227 if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
b95eb7f0
ST
7228 params.link_sta_params.opmode_notif_used = true;
7229 params.link_sta_params.opmode_notif =
60f4a7b1
MK
7230 nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
7231 }
7232
ab0d76f6 7233 if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
96b78dff 7234 params.plink_action =
f8bacc21 7235 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
96b78dff 7236
36647055
THJ
7237 if (info->attrs[NL80211_ATTR_AIRTIME_WEIGHT])
7238 params.airtime_weight =
7239 nla_get_u16(info->attrs[NL80211_ATTR_AIRTIME_WEIGHT]);
7240
7241 if (params.airtime_weight &&
7242 !wiphy_ext_feature_isset(&rdev->wiphy,
7243 NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
7244 return -EOPNOTSUPP;
7245
b95eb7f0
ST
7246 err = nl80211_parse_sta_txpower_setting(info,
7247 &params.link_sta_params.txpwr,
7248 &params.link_sta_params.txpwr_set);
e96d1cd2
ARN
7249 if (err)
7250 return err;
7251
c01fc9ad
SD
7252 err = nl80211_parse_sta_channel_info(info, &params);
7253 if (err)
7254 return err;
7255
ff276691
JB
7256 err = nl80211_parse_sta_wme(info, &params);
7257 if (err)
7258 return err;
bdd90d5e 7259
bdd3ae3d 7260 if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
5727ef1b
JB
7261 return -EINVAL;
7262
496fcc29
JB
7263 /* HT/VHT requires QoS, but if we don't have that just ignore HT/VHT
7264 * as userspace might just pass through the capabilities from the IEs
7265 * directly, rather than enforcing this restriction and returning an
7266 * error in this case.
7267 */
7268 if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME))) {
b95eb7f0
ST
7269 params.link_sta_params.ht_capa = NULL;
7270 params.link_sta_params.vht_capa = NULL;
c4cbaf79 7271
ea05fd35 7272 /* HE and EHT require WME */
b95eb7f0
ST
7273 if (params.link_sta_params.he_capa_len ||
7274 params.link_sta_params.he_6ghz_capa ||
7275 params.link_sta_params.eht_capa_len)
c4cbaf79 7276 return -EINVAL;
496fcc29
JB
7277 }
7278
43e64bf3 7279 /* Ensure that HT/VHT capabilities are not set for 6 GHz HE STA */
b95eb7f0
ST
7280 if (params.link_sta_params.he_6ghz_capa &&
7281 (params.link_sta_params.ht_capa || params.link_sta_params.vht_capa))
43e64bf3
RM
7282 return -EINVAL;
7283
77ee7c89
JB
7284 /* When you run into this, adjust the code below for the new flag */
7285 BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7);
7286
bdd90d5e
JB
7287 switch (dev->ieee80211_ptr->iftype) {
7288 case NL80211_IFTYPE_AP:
7289 case NL80211_IFTYPE_AP_VLAN:
7290 case NL80211_IFTYPE_P2P_GO:
984c311b
JB
7291 /* ignore WME attributes if iface/sta is not capable */
7292 if (!(rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) ||
7293 !(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)))
7294 params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
c75786c9 7295
bdd90d5e 7296 /* TDLS peers cannot be added */
3d124ea2
JM
7297 if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ||
7298 info->attrs[NL80211_ATTR_PEER_AID])
4319e193 7299 return -EINVAL;
bdd90d5e
JB
7300 /* but don't bother the driver with it */
7301 params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
3b9ce80c 7302
d582cffb
JB
7303 /* allow authenticated/associated only if driver handles it */
7304 if (!(rdev->wiphy.features &
7305 NL80211_FEATURE_FULL_AP_CLIENT_STATE) &&
bda95eb1 7306 params.sta_flags_mask & auth_assoc)
d582cffb
JB
7307 return -EINVAL;
7308
bda95eb1
JB
7309 /* Older userspace, or userspace wanting to be compatible with
7310 * !NL80211_FEATURE_FULL_AP_CLIENT_STATE, will not set the auth
7311 * and assoc flags in the mask, but assumes the station will be
7312 * added as associated anyway since this was the required driver
7313 * behaviour before NL80211_FEATURE_FULL_AP_CLIENT_STATE was
7314 * introduced.
7315 * In order to not bother drivers with this quirk in the API
7316 * set the flags in both the mask and set for new stations in
7317 * this case.
7318 */
7319 if (!(params.sta_flags_mask & auth_assoc)) {
7320 params.sta_flags_mask |= auth_assoc;
7321 params.sta_flags_set |= auth_assoc;
7322 }
7323
bdd90d5e
JB
7324 /* must be last in here for error handling */
7325 params.vlan = get_vlan(info, rdev);
7326 if (IS_ERR(params.vlan))
7327 return PTR_ERR(params.vlan);
7328 break;
7329 case NL80211_IFTYPE_MESH_POINT:
984c311b
JB
7330 /* ignore uAPSD data */
7331 params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
7332
d582cffb
JB
7333 /* associated is disallowed */
7334 if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED))
7335 return -EINVAL;
bdd90d5e 7336 /* TDLS peers cannot be added */
3d124ea2
JM
7337 if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ||
7338 info->attrs[NL80211_ATTR_PEER_AID])
bdd90d5e
JB
7339 return -EINVAL;
7340 break;
7341 case NL80211_IFTYPE_STATION:
93d08f0b 7342 case NL80211_IFTYPE_P2P_CLIENT:
984c311b
JB
7343 /* ignore uAPSD data */
7344 params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
7345
77ee7c89
JB
7346 /* these are disallowed */
7347 if (params.sta_flags_mask &
7348 (BIT(NL80211_STA_FLAG_ASSOCIATED) |
7349 BIT(NL80211_STA_FLAG_AUTHENTICATED)))
d582cffb 7350 return -EINVAL;
bdd90d5e
JB
7351 /* Only TDLS peers can be added */
7352 if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
7353 return -EINVAL;
7354 /* Can only add if TDLS ... */
7355 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS))
7356 return -EOPNOTSUPP;
7357 /* ... with external setup is supported */
7358 if (!(rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP))
7359 return -EOPNOTSUPP;
77ee7c89
JB
7360 /*
7361 * Older wpa_supplicant versions always mark the TDLS peer
7362 * as authorized, but it shouldn't yet be.
7363 */
7364 params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_AUTHORIZED);
bdd90d5e
JB
7365 break;
7366 default:
7367 return -EOPNOTSUPP;
c75786c9
EP
7368 }
7369
bdd90d5e 7370 /* be aware of params.vlan when changing code here */
5727ef1b 7371
3d1cc7cd 7372 wdev_lock(dev->ieee80211_ptr);
efbfe516
JB
7373 if (wdev->valid_links) {
7374 if (params.link_sta_params.link_id < 0) {
7375 err = -EINVAL;
7376 goto out;
7377 }
7378 if (!(wdev->valid_links & BIT(params.link_sta_params.link_id))) {
7379 err = -ENOLINK;
7380 goto out;
7381 }
7382 } else {
7383 if (params.link_sta_params.link_id >= 0) {
7384 err = -EINVAL;
7385 goto out;
7386 }
7387 }
e35e4d28 7388 err = rdev_add_station(rdev, dev, mac_addr, &params);
efbfe516 7389out:
3d1cc7cd 7390 wdev_unlock(dev->ieee80211_ptr);
1160dfa1 7391 dev_put(params.vlan);
5727ef1b
JB
7392 return err;
7393}
7394
7395static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
7396{
4c476991
JB
7397 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7398 struct net_device *dev = info->user_ptr[1];
89c771e5 7399 struct station_del_parameters params;
3d1cc7cd 7400 int ret;
89c771e5
JM
7401
7402 memset(&params, 0, sizeof(params));
5727ef1b
JB
7403
7404 if (info->attrs[NL80211_ATTR_MAC])
89c771e5 7405 params.mac = nla_data(info->attrs[NL80211_ATTR_MAC]);
5727ef1b 7406
306b79ea
JB
7407 switch (dev->ieee80211_ptr->iftype) {
7408 case NL80211_IFTYPE_AP:
7409 case NL80211_IFTYPE_AP_VLAN:
7410 case NL80211_IFTYPE_MESH_POINT:
7411 case NL80211_IFTYPE_P2P_GO:
7412 /* always accept these */
7413 break;
7414 case NL80211_IFTYPE_ADHOC:
7415 /* conditionally accept */
7416 if (wiphy_ext_feature_isset(&rdev->wiphy,
7417 NL80211_EXT_FEATURE_DEL_IBSS_STA))
7418 break;
edafcf42 7419 return -EINVAL;
306b79ea 7420 default:
4c476991 7421 return -EINVAL;
306b79ea 7422 }
5727ef1b 7423
4c476991
JB
7424 if (!rdev->ops->del_station)
7425 return -EOPNOTSUPP;
3b85875a 7426
98856866
JM
7427 if (info->attrs[NL80211_ATTR_MGMT_SUBTYPE]) {
7428 params.subtype =
7429 nla_get_u8(info->attrs[NL80211_ATTR_MGMT_SUBTYPE]);
7430 if (params.subtype != IEEE80211_STYPE_DISASSOC >> 4 &&
7431 params.subtype != IEEE80211_STYPE_DEAUTH >> 4)
7432 return -EINVAL;
7433 } else {
7434 /* Default to Deauthentication frame */
7435 params.subtype = IEEE80211_STYPE_DEAUTH >> 4;
7436 }
7437
7438 if (info->attrs[NL80211_ATTR_REASON_CODE]) {
7439 params.reason_code =
7440 nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
7441 if (params.reason_code == 0)
7442 return -EINVAL; /* 0 is reserved */
7443 } else {
7444 /* Default to reason code 2 */
7445 params.reason_code = WLAN_REASON_PREV_AUTH_NOT_VALID;
7446 }
7447
3d1cc7cd
JB
7448 wdev_lock(dev->ieee80211_ptr);
7449 ret = rdev_del_station(rdev, dev, &params);
7450 wdev_unlock(dev->ieee80211_ptr);
7451
7452 return ret;
5727ef1b
JB
7453}
7454
15e47304 7455static int nl80211_send_mpath(struct sk_buff *msg, u32 portid, u32 seq,
2ec600d6
LCC
7456 int flags, struct net_device *dev,
7457 u8 *dst, u8 *next_hop,
7458 struct mpath_info *pinfo)
7459{
7460 void *hdr;
7461 struct nlattr *pinfoattr;
7462
1ef4c850 7463 hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_MPATH);
2ec600d6
LCC
7464 if (!hdr)
7465 return -1;
7466
9360ffd1
DM
7467 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
7468 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, dst) ||
7469 nla_put(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop) ||
7470 nla_put_u32(msg, NL80211_ATTR_GENERATION, pinfo->generation))
7471 goto nla_put_failure;
f5ea9120 7472
ae0be8de 7473 pinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_MPATH_INFO);
2ec600d6
LCC
7474 if (!pinfoattr)
7475 goto nla_put_failure;
9360ffd1
DM
7476 if ((pinfo->filled & MPATH_INFO_FRAME_QLEN) &&
7477 nla_put_u32(msg, NL80211_MPATH_INFO_FRAME_QLEN,
7478 pinfo->frame_qlen))
7479 goto nla_put_failure;
7480 if (((pinfo->filled & MPATH_INFO_SN) &&
7481 nla_put_u32(msg, NL80211_MPATH_INFO_SN, pinfo->sn)) ||
7482 ((pinfo->filled & MPATH_INFO_METRIC) &&
7483 nla_put_u32(msg, NL80211_MPATH_INFO_METRIC,
7484 pinfo->metric)) ||
7485 ((pinfo->filled & MPATH_INFO_EXPTIME) &&
7486 nla_put_u32(msg, NL80211_MPATH_INFO_EXPTIME,
7487 pinfo->exptime)) ||
7488 ((pinfo->filled & MPATH_INFO_FLAGS) &&
7489 nla_put_u8(msg, NL80211_MPATH_INFO_FLAGS,
7490 pinfo->flags)) ||
7491 ((pinfo->filled & MPATH_INFO_DISCOVERY_TIMEOUT) &&
7492 nla_put_u32(msg, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT,
7493 pinfo->discovery_timeout)) ||
7494 ((pinfo->filled & MPATH_INFO_DISCOVERY_RETRIES) &&
7495 nla_put_u8(msg, NL80211_MPATH_INFO_DISCOVERY_RETRIES,
cc241636
JH
7496 pinfo->discovery_retries)) ||
7497 ((pinfo->filled & MPATH_INFO_HOP_COUNT) &&
7498 nla_put_u8(msg, NL80211_MPATH_INFO_HOP_COUNT,
540bbcb9
JH
7499 pinfo->hop_count)) ||
7500 ((pinfo->filled & MPATH_INFO_PATH_CHANGE) &&
7501 nla_put_u32(msg, NL80211_MPATH_INFO_PATH_CHANGE,
7502 pinfo->path_change_count)))
9360ffd1 7503 goto nla_put_failure;
2ec600d6
LCC
7504
7505 nla_nest_end(msg, pinfoattr);
7506
053c095a
JB
7507 genlmsg_end(msg, hdr);
7508 return 0;
2ec600d6
LCC
7509
7510 nla_put_failure:
bc3ed28c
TG
7511 genlmsg_cancel(msg, hdr);
7512 return -EMSGSIZE;
2ec600d6
LCC
7513}
7514
7515static int nl80211_dump_mpath(struct sk_buff *skb,
bba95fef 7516 struct netlink_callback *cb)
2ec600d6 7517{
2ec600d6 7518 struct mpath_info pinfo;
1b8ec87a 7519 struct cfg80211_registered_device *rdev;
97990a06 7520 struct wireless_dev *wdev;
2ec600d6
LCC
7521 u8 dst[ETH_ALEN];
7522 u8 next_hop[ETH_ALEN];
97990a06 7523 int path_idx = cb->args[2];
2ec600d6 7524 int err;
2ec600d6 7525
ce6b6974 7526 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL);
67748893 7527 if (err)
a05829a7
JB
7528 return err;
7529 /* nl80211_prepare_wdev_dump acquired it in the successful case */
7530 __acquire(&rdev->wiphy.mtx);
bba95fef 7531
1b8ec87a 7532 if (!rdev->ops->dump_mpath) {
eec60b03 7533 err = -EOPNOTSUPP;
bba95fef
JB
7534 goto out_err;
7535 }
7536
97990a06 7537 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
eec60b03 7538 err = -EOPNOTSUPP;
0448b5fc 7539 goto out_err;
eec60b03
JM
7540 }
7541
bba95fef 7542 while (1) {
1b8ec87a 7543 err = rdev_dump_mpath(rdev, wdev->netdev, path_idx, dst,
97990a06 7544 next_hop, &pinfo);
bba95fef 7545 if (err == -ENOENT)
2ec600d6 7546 break;
bba95fef 7547 if (err)
3b85875a 7548 goto out_err;
2ec600d6 7549
15e47304 7550 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid,
bba95fef 7551 cb->nlh->nlmsg_seq, NLM_F_MULTI,
97990a06 7552 wdev->netdev, dst, next_hop,
bba95fef
JB
7553 &pinfo) < 0)
7554 goto out;
2ec600d6 7555
bba95fef 7556 path_idx++;
2ec600d6 7557 }
2ec600d6 7558
bba95fef 7559 out:
97990a06 7560 cb->args[2] = path_idx;
bba95fef 7561 err = skb->len;
bba95fef 7562 out_err:
a05829a7 7563 wiphy_unlock(&rdev->wiphy);
bba95fef 7564 return err;
2ec600d6
LCC
7565}
7566
7567static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
7568{
4c476991 7569 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2ec600d6 7570 int err;
4c476991 7571 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
7572 struct mpath_info pinfo;
7573 struct sk_buff *msg;
7574 u8 *dst = NULL;
7575 u8 next_hop[ETH_ALEN];
7576
7577 memset(&pinfo, 0, sizeof(pinfo));
7578
7579 if (!info->attrs[NL80211_ATTR_MAC])
7580 return -EINVAL;
7581
7582 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
7583
4c476991
JB
7584 if (!rdev->ops->get_mpath)
7585 return -EOPNOTSUPP;
2ec600d6 7586
4c476991
JB
7587 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
7588 return -EOPNOTSUPP;
eec60b03 7589
e35e4d28 7590 err = rdev_get_mpath(rdev, dev, dst, next_hop, &pinfo);
2ec600d6 7591 if (err)
4c476991 7592 return err;
2ec600d6 7593
fd2120ca 7594 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2ec600d6 7595 if (!msg)
4c476991 7596 return -ENOMEM;
2ec600d6 7597
15e47304 7598 if (nl80211_send_mpath(msg, info->snd_portid, info->snd_seq, 0,
4c476991
JB
7599 dev, dst, next_hop, &pinfo) < 0) {
7600 nlmsg_free(msg);
7601 return -ENOBUFS;
7602 }
3b85875a 7603
4c476991 7604 return genlmsg_reply(msg, info);
2ec600d6
LCC
7605}
7606
7607static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
7608{
4c476991
JB
7609 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7610 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
7611 u8 *dst = NULL;
7612 u8 *next_hop = NULL;
7613
7614 if (!info->attrs[NL80211_ATTR_MAC])
7615 return -EINVAL;
7616
7617 if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
7618 return -EINVAL;
7619
7620 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
7621 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
7622
4c476991
JB
7623 if (!rdev->ops->change_mpath)
7624 return -EOPNOTSUPP;
35a8efe1 7625
4c476991
JB
7626 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
7627 return -EOPNOTSUPP;
2ec600d6 7628
e35e4d28 7629 return rdev_change_mpath(rdev, dev, dst, next_hop);
2ec600d6 7630}
4c476991 7631
2ec600d6
LCC
7632static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
7633{
4c476991
JB
7634 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7635 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
7636 u8 *dst = NULL;
7637 u8 *next_hop = NULL;
7638
7639 if (!info->attrs[NL80211_ATTR_MAC])
7640 return -EINVAL;
7641
7642 if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
7643 return -EINVAL;
7644
7645 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
7646 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
7647
4c476991
JB
7648 if (!rdev->ops->add_mpath)
7649 return -EOPNOTSUPP;
35a8efe1 7650
4c476991
JB
7651 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
7652 return -EOPNOTSUPP;
2ec600d6 7653
e35e4d28 7654 return rdev_add_mpath(rdev, dev, dst, next_hop);
2ec600d6
LCC
7655}
7656
7657static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
7658{
4c476991
JB
7659 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7660 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
7661 u8 *dst = NULL;
7662
7663 if (info->attrs[NL80211_ATTR_MAC])
7664 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
7665
4c476991
JB
7666 if (!rdev->ops->del_mpath)
7667 return -EOPNOTSUPP;
3b85875a 7668
b501426c
MP
7669 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
7670 return -EOPNOTSUPP;
7671
e35e4d28 7672 return rdev_del_mpath(rdev, dev, dst);
2ec600d6
LCC
7673}
7674
66be7d2b
HR
7675static int nl80211_get_mpp(struct sk_buff *skb, struct genl_info *info)
7676{
7677 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7678 int err;
7679 struct net_device *dev = info->user_ptr[1];
7680 struct mpath_info pinfo;
7681 struct sk_buff *msg;
7682 u8 *dst = NULL;
7683 u8 mpp[ETH_ALEN];
7684
7685 memset(&pinfo, 0, sizeof(pinfo));
7686
7687 if (!info->attrs[NL80211_ATTR_MAC])
7688 return -EINVAL;
7689
7690 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
7691
7692 if (!rdev->ops->get_mpp)
7693 return -EOPNOTSUPP;
7694
7695 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
7696 return -EOPNOTSUPP;
7697
7698 err = rdev_get_mpp(rdev, dev, dst, mpp, &pinfo);
7699 if (err)
7700 return err;
7701
7702 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7703 if (!msg)
7704 return -ENOMEM;
7705
7706 if (nl80211_send_mpath(msg, info->snd_portid, info->snd_seq, 0,
7707 dev, dst, mpp, &pinfo) < 0) {
7708 nlmsg_free(msg);
7709 return -ENOBUFS;
7710 }
7711
7712 return genlmsg_reply(msg, info);
7713}
7714
7715static int nl80211_dump_mpp(struct sk_buff *skb,
7716 struct netlink_callback *cb)
7717{
7718 struct mpath_info pinfo;
7719 struct cfg80211_registered_device *rdev;
7720 struct wireless_dev *wdev;
7721 u8 dst[ETH_ALEN];
7722 u8 mpp[ETH_ALEN];
7723 int path_idx = cb->args[2];
7724 int err;
7725
ce6b6974 7726 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL);
66be7d2b 7727 if (err)
a05829a7
JB
7728 return err;
7729 /* nl80211_prepare_wdev_dump acquired it in the successful case */
7730 __acquire(&rdev->wiphy.mtx);
66be7d2b
HR
7731
7732 if (!rdev->ops->dump_mpp) {
7733 err = -EOPNOTSUPP;
7734 goto out_err;
7735 }
7736
7737 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
7738 err = -EOPNOTSUPP;
7739 goto out_err;
7740 }
7741
7742 while (1) {
7743 err = rdev_dump_mpp(rdev, wdev->netdev, path_idx, dst,
7744 mpp, &pinfo);
7745 if (err == -ENOENT)
7746 break;
7747 if (err)
7748 goto out_err;
7749
7750 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid,
7751 cb->nlh->nlmsg_seq, NLM_F_MULTI,
7752 wdev->netdev, dst, mpp,
7753 &pinfo) < 0)
7754 goto out;
7755
7756 path_idx++;
7757 }
7758
7759 out:
7760 cb->args[2] = path_idx;
7761 err = skb->len;
7762 out_err:
a05829a7 7763 wiphy_unlock(&rdev->wiphy);
66be7d2b
HR
7764 return err;
7765}
7766
9f1ba906
JM
7767static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
7768{
4c476991
JB
7769 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7770 struct net_device *dev = info->user_ptr[1];
c56589ed 7771 struct wireless_dev *wdev = dev->ieee80211_ptr;
9f1ba906 7772 struct bss_parameters params;
c56589ed 7773 int err;
9f1ba906
JM
7774
7775 memset(&params, 0, sizeof(params));
7776 /* default to not changing parameters */
7777 params.use_cts_prot = -1;
7778 params.use_short_preamble = -1;
7779 params.use_short_slot_time = -1;
fd8aaaf3 7780 params.ap_isolate = -1;
50b12f59 7781 params.ht_opmode = -1;
53cabad7
JB
7782 params.p2p_ctwindow = -1;
7783 params.p2p_opp_ps = -1;
9f1ba906
JM
7784
7785 if (info->attrs[NL80211_ATTR_BSS_CTS_PROT])
7786 params.use_cts_prot =
7787 nla_get_u8(info->attrs[NL80211_ATTR_BSS_CTS_PROT]);
7788 if (info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE])
7789 params.use_short_preamble =
7790 nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]);
7791 if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME])
7792 params.use_short_slot_time =
7793 nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]);
90c97a04
JM
7794 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
7795 params.basic_rates =
7796 nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
7797 params.basic_rates_len =
7798 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
7799 }
fd8aaaf3
FF
7800 if (info->attrs[NL80211_ATTR_AP_ISOLATE])
7801 params.ap_isolate = !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]);
50b12f59
HS
7802 if (info->attrs[NL80211_ATTR_BSS_HT_OPMODE])
7803 params.ht_opmode =
7804 nla_get_u16(info->attrs[NL80211_ATTR_BSS_HT_OPMODE]);
9f1ba906 7805
53cabad7
JB
7806 if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
7807 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
7808 return -EINVAL;
7809 params.p2p_ctwindow =
ab0d76f6 7810 nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
53cabad7
JB
7811 if (params.p2p_ctwindow != 0 &&
7812 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
7813 return -EINVAL;
7814 }
7815
7816 if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
7817 u8 tmp;
7818
7819 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
7820 return -EINVAL;
7821 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
53cabad7
JB
7822 params.p2p_opp_ps = tmp;
7823 if (params.p2p_opp_ps &&
7824 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
7825 return -EINVAL;
7826 }
7827
4c476991
JB
7828 if (!rdev->ops->change_bss)
7829 return -EOPNOTSUPP;
9f1ba906 7830
074ac8df 7831 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
4c476991
JB
7832 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
7833 return -EOPNOTSUPP;
3b85875a 7834
c56589ed
SW
7835 wdev_lock(wdev);
7836 err = rdev_change_bss(rdev, dev, &params);
7837 wdev_unlock(wdev);
7838
7839 return err;
9f1ba906
JM
7840}
7841
b2e1b302
LR
7842static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
7843{
b2e1b302 7844 char *data = NULL;
05050753 7845 bool is_indoor;
57b5ce07 7846 enum nl80211_user_reg_hint_type user_reg_hint_type;
05050753
I
7847 u32 owner_nlportid;
7848
80778f18
LR
7849 /*
7850 * You should only get this when cfg80211 hasn't yet initialized
7851 * completely when built-in to the kernel right between the time
7852 * window between nl80211_init() and regulatory_init(), if that is
7853 * even possible.
7854 */
458f4f9e 7855 if (unlikely(!rcu_access_pointer(cfg80211_regdomain)))
fe33eb39 7856 return -EINPROGRESS;
80778f18 7857
57b5ce07
LR
7858 if (info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE])
7859 user_reg_hint_type =
7860 nla_get_u32(info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE]);
7861 else
7862 user_reg_hint_type = NL80211_USER_REG_HINT_USER;
7863
7864 switch (user_reg_hint_type) {
7865 case NL80211_USER_REG_HINT_USER:
7866 case NL80211_USER_REG_HINT_CELL_BASE:
52616f2b
IP
7867 if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
7868 return -EINVAL;
7869
7870 data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
7871 return regulatory_hint_user(data, user_reg_hint_type);
7872 case NL80211_USER_REG_HINT_INDOOR:
05050753
I
7873 if (info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
7874 owner_nlportid = info->snd_portid;
7875 is_indoor = !!info->attrs[NL80211_ATTR_REG_INDOOR];
7876 } else {
7877 owner_nlportid = 0;
7878 is_indoor = true;
7879 }
7880
7881 return regulatory_hint_indoor(is_indoor, owner_nlportid);
57b5ce07
LR
7882 default:
7883 return -EINVAL;
7884 }
b2e1b302
LR
7885}
7886
1ea4ff3e
JB
7887static int nl80211_reload_regdb(struct sk_buff *skb, struct genl_info *info)
7888{
7889 return reg_reload_regdb();
7890}
7891
24bdd9f4 7892static int nl80211_get_mesh_config(struct sk_buff *skb,
29cbe68c 7893 struct genl_info *info)
93da9cc1 7894{
4c476991 7895 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 7896 struct net_device *dev = info->user_ptr[1];
29cbe68c
JB
7897 struct wireless_dev *wdev = dev->ieee80211_ptr;
7898 struct mesh_config cur_params;
7899 int err = 0;
93da9cc1 7900 void *hdr;
7901 struct nlattr *pinfoattr;
7902 struct sk_buff *msg;
7903
29cbe68c
JB
7904 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
7905 return -EOPNOTSUPP;
7906
24bdd9f4 7907 if (!rdev->ops->get_mesh_config)
4c476991 7908 return -EOPNOTSUPP;
f3f92586 7909
29cbe68c
JB
7910 wdev_lock(wdev);
7911 /* If not connected, get default parameters */
7b0a0e3c 7912 if (!wdev->u.mesh.id_len)
29cbe68c
JB
7913 memcpy(&cur_params, &default_mesh_config, sizeof(cur_params));
7914 else
e35e4d28 7915 err = rdev_get_mesh_config(rdev, dev, &cur_params);
29cbe68c
JB
7916 wdev_unlock(wdev);
7917
93da9cc1 7918 if (err)
4c476991 7919 return err;
93da9cc1 7920
7921 /* Draw up a netlink message to send back */
fd2120ca 7922 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
7923 if (!msg)
7924 return -ENOMEM;
15e47304 7925 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
24bdd9f4 7926 NL80211_CMD_GET_MESH_CONFIG);
93da9cc1 7927 if (!hdr)
efe1cf0c 7928 goto out;
ae0be8de 7929 pinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_MESH_CONFIG);
93da9cc1 7930 if (!pinfoattr)
7931 goto nla_put_failure;
9360ffd1
DM
7932 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
7933 nla_put_u16(msg, NL80211_MESHCONF_RETRY_TIMEOUT,
7934 cur_params.dot11MeshRetryTimeout) ||
7935 nla_put_u16(msg, NL80211_MESHCONF_CONFIRM_TIMEOUT,
7936 cur_params.dot11MeshConfirmTimeout) ||
7937 nla_put_u16(msg, NL80211_MESHCONF_HOLDING_TIMEOUT,
7938 cur_params.dot11MeshHoldingTimeout) ||
7939 nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS,
7940 cur_params.dot11MeshMaxPeerLinks) ||
7941 nla_put_u8(msg, NL80211_MESHCONF_MAX_RETRIES,
7942 cur_params.dot11MeshMaxRetries) ||
7943 nla_put_u8(msg, NL80211_MESHCONF_TTL,
7944 cur_params.dot11MeshTTL) ||
7945 nla_put_u8(msg, NL80211_MESHCONF_ELEMENT_TTL,
7946 cur_params.element_ttl) ||
7947 nla_put_u8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
7948 cur_params.auto_open_plinks) ||
7eab0f64
JL
7949 nla_put_u32(msg, NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
7950 cur_params.dot11MeshNbrOffsetMaxNeighbor) ||
9360ffd1
DM
7951 nla_put_u8(msg, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
7952 cur_params.dot11MeshHWMPmaxPREQretries) ||
7953 nla_put_u32(msg, NL80211_MESHCONF_PATH_REFRESH_TIME,
7954 cur_params.path_refresh_time) ||
7955 nla_put_u16(msg, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
7956 cur_params.min_discovery_timeout) ||
7957 nla_put_u32(msg, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
7958 cur_params.dot11MeshHWMPactivePathTimeout) ||
7959 nla_put_u16(msg, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
7960 cur_params.dot11MeshHWMPpreqMinInterval) ||
7961 nla_put_u16(msg, NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
7962 cur_params.dot11MeshHWMPperrMinInterval) ||
7963 nla_put_u16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
7964 cur_params.dot11MeshHWMPnetDiameterTraversalTime) ||
7965 nla_put_u8(msg, NL80211_MESHCONF_HWMP_ROOTMODE,
7966 cur_params.dot11MeshHWMPRootMode) ||
7967 nla_put_u16(msg, NL80211_MESHCONF_HWMP_RANN_INTERVAL,
7968 cur_params.dot11MeshHWMPRannInterval) ||
7969 nla_put_u8(msg, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
7970 cur_params.dot11MeshGateAnnouncementProtocol) ||
7971 nla_put_u8(msg, NL80211_MESHCONF_FORWARDING,
7972 cur_params.dot11MeshForwarding) ||
335d5349 7973 nla_put_s32(msg, NL80211_MESHCONF_RSSI_THRESHOLD,
70c33eaa
AN
7974 cur_params.rssi_threshold) ||
7975 nla_put_u32(msg, NL80211_MESHCONF_HT_OPMODE,
ac1073a6
CYY
7976 cur_params.ht_opmode) ||
7977 nla_put_u32(msg, NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
7978 cur_params.dot11MeshHWMPactivePathToRootTimeout) ||
7979 nla_put_u16(msg, NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
728b19e5
CYY
7980 cur_params.dot11MeshHWMProotInterval) ||
7981 nla_put_u16(msg, NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
3b1c5a53
MP
7982 cur_params.dot11MeshHWMPconfirmationInterval) ||
7983 nla_put_u32(msg, NL80211_MESHCONF_POWER_MODE,
7984 cur_params.power_mode) ||
7985 nla_put_u16(msg, NL80211_MESHCONF_AWAKE_WINDOW,
8e7c0538
CT
7986 cur_params.dot11MeshAwakeWindowDuration) ||
7987 nla_put_u32(msg, NL80211_MESHCONF_PLINK_TIMEOUT,
01d66fbd
BC
7988 cur_params.plink_timeout) ||
7989 nla_put_u8(msg, NL80211_MESHCONF_CONNECTED_TO_GATE,
e3718a61
LL
7990 cur_params.dot11MeshConnectedToMeshGate) ||
7991 nla_put_u8(msg, NL80211_MESHCONF_NOLEARN,
184eebe6
MT
7992 cur_params.dot11MeshNolearn) ||
7993 nla_put_u8(msg, NL80211_MESHCONF_CONNECTED_TO_AS,
7994 cur_params.dot11MeshConnectedToAuthServer))
9360ffd1 7995 goto nla_put_failure;
93da9cc1 7996 nla_nest_end(msg, pinfoattr);
7997 genlmsg_end(msg, hdr);
4c476991 7998 return genlmsg_reply(msg, info);
93da9cc1 7999
3b85875a 8000 nla_put_failure:
efe1cf0c 8001 out:
d080e275 8002 nlmsg_free(msg);
4c476991 8003 return -ENOBUFS;
93da9cc1 8004}
8005
ab0d76f6
JB
8006static const struct nla_policy
8007nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] = {
8008 [NL80211_MESHCONF_RETRY_TIMEOUT] =
8009 NLA_POLICY_RANGE(NLA_U16, 1, 255),
8010 [NL80211_MESHCONF_CONFIRM_TIMEOUT] =
8011 NLA_POLICY_RANGE(NLA_U16, 1, 255),
8012 [NL80211_MESHCONF_HOLDING_TIMEOUT] =
8013 NLA_POLICY_RANGE(NLA_U16, 1, 255),
8014 [NL80211_MESHCONF_MAX_PEER_LINKS] =
8015 NLA_POLICY_RANGE(NLA_U16, 0, 255),
8016 [NL80211_MESHCONF_MAX_RETRIES] = NLA_POLICY_MAX(NLA_U8, 16),
8017 [NL80211_MESHCONF_TTL] = NLA_POLICY_MIN(NLA_U8, 1),
8018 [NL80211_MESHCONF_ELEMENT_TTL] = NLA_POLICY_MIN(NLA_U8, 1),
8019 [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = NLA_POLICY_MAX(NLA_U8, 1),
8020 [NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR] =
8021 NLA_POLICY_RANGE(NLA_U32, 1, 255),
93da9cc1 8022 [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 },
8023 [NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 },
ab0d76f6 8024 [NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = NLA_POLICY_MIN(NLA_U16, 1),
93da9cc1 8025 [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 },
ab0d76f6
JB
8026 [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] =
8027 NLA_POLICY_MIN(NLA_U16, 1),
8028 [NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL] =
8029 NLA_POLICY_MIN(NLA_U16, 1),
8030 [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] =
8031 NLA_POLICY_MIN(NLA_U16, 1),
8032 [NL80211_MESHCONF_HWMP_ROOTMODE] = NLA_POLICY_MAX(NLA_U8, 4),
8033 [NL80211_MESHCONF_HWMP_RANN_INTERVAL] =
8034 NLA_POLICY_MIN(NLA_U16, 1),
8035 [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = NLA_POLICY_MAX(NLA_U8, 1),
8036 [NL80211_MESHCONF_FORWARDING] = NLA_POLICY_MAX(NLA_U8, 1),
8037 [NL80211_MESHCONF_RSSI_THRESHOLD] =
8038 NLA_POLICY_RANGE(NLA_S32, -255, 0),
a4f606ea 8039 [NL80211_MESHCONF_HT_OPMODE] = { .type = NLA_U16 },
ac1073a6 8040 [NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT] = { .type = NLA_U32 },
ab0d76f6
JB
8041 [NL80211_MESHCONF_HWMP_ROOT_INTERVAL] =
8042 NLA_POLICY_MIN(NLA_U16, 1),
8043 [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] =
8044 NLA_POLICY_MIN(NLA_U16, 1),
8045 [NL80211_MESHCONF_POWER_MODE] =
8046 NLA_POLICY_RANGE(NLA_U32,
8047 NL80211_MESH_POWER_ACTIVE,
8048 NL80211_MESH_POWER_MAX),
3b1c5a53 8049 [NL80211_MESHCONF_AWAKE_WINDOW] = { .type = NLA_U16 },
8e7c0538 8050 [NL80211_MESHCONF_PLINK_TIMEOUT] = { .type = NLA_U32 },
01d66fbd 8051 [NL80211_MESHCONF_CONNECTED_TO_GATE] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
e3718a61 8052 [NL80211_MESHCONF_NOLEARN] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
184eebe6 8053 [NL80211_MESHCONF_CONNECTED_TO_AS] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
93da9cc1 8054};
8055
c80d545d
JC
8056static const struct nla_policy
8057 nl80211_mesh_setup_params_policy[NL80211_MESH_SETUP_ATTR_MAX+1] = {
d299a1f2 8058 [NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC] = { .type = NLA_U8 },
c80d545d
JC
8059 [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 },
8060 [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 },
15d5dda6 8061 [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG },
6e16d90b 8062 [NL80211_MESH_SETUP_AUTH_PROTOCOL] = { .type = NLA_U8 },
bb2798d4 8063 [NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG },
3d7af878
JB
8064 [NL80211_MESH_SETUP_IE] =
8065 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
8066 IEEE80211_MAX_DATA_LEN),
b130e5ce 8067 [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG },
c80d545d
JC
8068};
8069
24bdd9f4 8070static int nl80211_parse_mesh_config(struct genl_info *info,
bd90fdcc
JB
8071 struct mesh_config *cfg,
8072 u32 *mask_out)
93da9cc1 8073{
93da9cc1 8074 struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1];
bd90fdcc 8075 u32 mask = 0;
9757235f 8076 u16 ht_opmode;
93da9cc1 8077
ab0d76f6
JB
8078#define FILL_IN_MESH_PARAM_IF_SET(tb, cfg, param, mask, attr, fn) \
8079do { \
8080 if (tb[attr]) { \
8081 cfg->param = fn(tb[attr]); \
8082 mask |= BIT((attr) - 1); \
8083 } \
ea54fba2 8084} while (0)
bd90fdcc 8085
24bdd9f4 8086 if (!info->attrs[NL80211_ATTR_MESH_CONFIG])
93da9cc1 8087 return -EINVAL;
8cb08174 8088 if (nla_parse_nested_deprecated(tb, NL80211_MESHCONF_ATTR_MAX, info->attrs[NL80211_ATTR_MESH_CONFIG], nl80211_meshconf_params_policy, info->extack))
93da9cc1 8089 return -EINVAL;
8090
93da9cc1 8091 /* This makes sure that there aren't more than 32 mesh config
8092 * parameters (otherwise our bitfield scheme would not work.) */
8093 BUILD_BUG_ON(NL80211_MESHCONF_ATTR_MAX > 32);
8094
8095 /* Fill in the params struct */
ab0d76f6
JB
8096 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, mask,
8097 NL80211_MESHCONF_RETRY_TIMEOUT, nla_get_u16);
8098 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, mask,
8099 NL80211_MESHCONF_CONFIRM_TIMEOUT,
8100 nla_get_u16);
8101 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, mask,
8102 NL80211_MESHCONF_HOLDING_TIMEOUT,
8103 nla_get_u16);
8104 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, mask,
8105 NL80211_MESHCONF_MAX_PEER_LINKS,
8106 nla_get_u16);
8107 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, mask,
8108 NL80211_MESHCONF_MAX_RETRIES, nla_get_u8);
8109 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, mask,
8110 NL80211_MESHCONF_TTL, nla_get_u8);
8111 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, mask,
8112 NL80211_MESHCONF_ELEMENT_TTL, nla_get_u8);
8113 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, mask,
8114 NL80211_MESHCONF_AUTO_OPEN_PLINKS,
8115 nla_get_u8);
ea54fba2 8116 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor,
ab0d76f6 8117 mask,
a4f606ea 8118 NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
ab0d76f6
JB
8119 nla_get_u32);
8120 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, mask,
8121 NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
8122 nla_get_u8);
8123 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, mask,
8124 NL80211_MESHCONF_PATH_REFRESH_TIME,
8125 nla_get_u32);
8126 if (mask & BIT(NL80211_MESHCONF_PATH_REFRESH_TIME) &&
8127 (cfg->path_refresh_time < 1 || cfg->path_refresh_time > 65535))
8128 return -EINVAL;
8129 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, mask,
8130 NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
8131 nla_get_u16);
ea54fba2 8132 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout,
ab0d76f6 8133 mask,
a4f606ea 8134 NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
ab0d76f6
JB
8135 nla_get_u32);
8136 if (mask & BIT(NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT) &&
8137 (cfg->dot11MeshHWMPactivePathTimeout < 1 ||
8138 cfg->dot11MeshHWMPactivePathTimeout > 65535))
8139 return -EINVAL;
8140 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval, mask,
ea54fba2 8141 NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
ab0d76f6
JB
8142 nla_get_u16);
8143 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval, mask,
ea54fba2 8144 NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
ab0d76f6 8145 nla_get_u16);
93da9cc1 8146 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
ab0d76f6 8147 dot11MeshHWMPnetDiameterTraversalTime, mask,
a4f606ea 8148 NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
ab0d76f6
JB
8149 nla_get_u16);
8150 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, mask,
8151 NL80211_MESHCONF_HWMP_ROOTMODE, nla_get_u8);
8152 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, mask,
8153 NL80211_MESHCONF_HWMP_RANN_INTERVAL,
8154 nla_get_u16);
8155 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshGateAnnouncementProtocol,
ea54fba2 8156 mask, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
ab0d76f6
JB
8157 nla_get_u8);
8158 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, mask,
8159 NL80211_MESHCONF_FORWARDING, nla_get_u8);
8160 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, mask,
8161 NL80211_MESHCONF_RSSI_THRESHOLD,
8162 nla_get_s32);
01d66fbd
BC
8163 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConnectedToMeshGate, mask,
8164 NL80211_MESHCONF_CONNECTED_TO_GATE,
8165 nla_get_u8);
184eebe6
MT
8166 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConnectedToAuthServer, mask,
8167 NL80211_MESHCONF_CONNECTED_TO_AS,
8168 nla_get_u8);
9757235f
MH
8169 /*
8170 * Check HT operation mode based on
188f60ab 8171 * IEEE 802.11-2016 9.4.2.57 HT Operation element.
9757235f
MH
8172 */
8173 if (tb[NL80211_MESHCONF_HT_OPMODE]) {
8174 ht_opmode = nla_get_u16(tb[NL80211_MESHCONF_HT_OPMODE]);
8175
8176 if (ht_opmode & ~(IEEE80211_HT_OP_MODE_PROTECTION |
8177 IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT |
8178 IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT))
8179 return -EINVAL;
8180
188f60ab
BC
8181 /* NON_HT_STA bit is reserved, but some programs set it */
8182 ht_opmode &= ~IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT;
9757235f 8183
9757235f 8184 cfg->ht_opmode = ht_opmode;
fd551bac 8185 mask |= (1 << (NL80211_MESHCONF_HT_OPMODE - 1));
9757235f 8186 }
728b19e5 8187 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
ab0d76f6
JB
8188 dot11MeshHWMPactivePathToRootTimeout, mask,
8189 NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
8190 nla_get_u32);
8191 if (mask & BIT(NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT) &&
8192 (cfg->dot11MeshHWMPactivePathToRootTimeout < 1 ||
8193 cfg->dot11MeshHWMPactivePathToRootTimeout > 65535))
8194 return -EINVAL;
8195 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMProotInterval, mask,
8196 NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
8197 nla_get_u16);
8198 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPconfirmationInterval,
8199 mask,
728b19e5 8200 NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
ab0d76f6
JB
8201 nla_get_u16);
8202 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode, mask,
8203 NL80211_MESHCONF_POWER_MODE, nla_get_u32);
8204 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration, mask,
8205 NL80211_MESHCONF_AWAKE_WINDOW, nla_get_u16);
8206 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, mask,
8207 NL80211_MESHCONF_PLINK_TIMEOUT, nla_get_u32);
e3718a61
LL
8208 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNolearn, mask,
8209 NL80211_MESHCONF_NOLEARN, nla_get_u8);
bd90fdcc
JB
8210 if (mask_out)
8211 *mask_out = mask;
c80d545d 8212
bd90fdcc
JB
8213 return 0;
8214
8215#undef FILL_IN_MESH_PARAM_IF_SET
8216}
8217
c80d545d
JC
8218static int nl80211_parse_mesh_setup(struct genl_info *info,
8219 struct mesh_setup *setup)
8220{
bb2798d4 8221 struct cfg80211_registered_device *rdev = info->user_ptr[0];
c80d545d
JC
8222 struct nlattr *tb[NL80211_MESH_SETUP_ATTR_MAX + 1];
8223
8224 if (!info->attrs[NL80211_ATTR_MESH_SETUP])
8225 return -EINVAL;
8cb08174 8226 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
8227 return -EINVAL;
8228
d299a1f2
JC
8229 if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC])
8230 setup->sync_method =
8231 (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC])) ?
8232 IEEE80211_SYNC_METHOD_VENDOR :
8233 IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET;
8234
c80d545d
JC
8235 if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])
8236 setup->path_sel_proto =
8237 (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])) ?
8238 IEEE80211_PATH_PROTOCOL_VENDOR :
8239 IEEE80211_PATH_PROTOCOL_HWMP;
8240
8241 if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC])
8242 setup->path_metric =
8243 (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC])) ?
8244 IEEE80211_PATH_METRIC_VENDOR :
8245 IEEE80211_PATH_METRIC_AIRTIME;
8246
581a8b0f 8247 if (tb[NL80211_MESH_SETUP_IE]) {
c80d545d 8248 struct nlattr *ieattr =
581a8b0f 8249 tb[NL80211_MESH_SETUP_IE];
581a8b0f
JC
8250 setup->ie = nla_data(ieattr);
8251 setup->ie_len = nla_len(ieattr);
c80d545d 8252 }
bb2798d4
TP
8253 if (tb[NL80211_MESH_SETUP_USERSPACE_MPM] &&
8254 !(rdev->wiphy.features & NL80211_FEATURE_USERSPACE_MPM))
8255 return -EINVAL;
8256 setup->user_mpm = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_MPM]);
b130e5ce
JC
8257 setup->is_authenticated = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]);
8258 setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AMPE]);
bb2798d4
TP
8259 if (setup->is_secure)
8260 setup->user_mpm = true;
c80d545d 8261
6e16d90b
CT
8262 if (tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]) {
8263 if (!setup->user_mpm)
8264 return -EINVAL;
8265 setup->auth_id =
8266 nla_get_u8(tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]);
8267 }
8268
c80d545d
JC
8269 return 0;
8270}
8271
24bdd9f4 8272static int nl80211_update_mesh_config(struct sk_buff *skb,
29cbe68c 8273 struct genl_info *info)
bd90fdcc
JB
8274{
8275 struct cfg80211_registered_device *rdev = info->user_ptr[0];
8276 struct net_device *dev = info->user_ptr[1];
29cbe68c 8277 struct wireless_dev *wdev = dev->ieee80211_ptr;
bd90fdcc
JB
8278 struct mesh_config cfg;
8279 u32 mask;
8280 int err;
8281
29cbe68c
JB
8282 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
8283 return -EOPNOTSUPP;
8284
24bdd9f4 8285 if (!rdev->ops->update_mesh_config)
bd90fdcc
JB
8286 return -EOPNOTSUPP;
8287
24bdd9f4 8288 err = nl80211_parse_mesh_config(info, &cfg, &mask);
bd90fdcc
JB
8289 if (err)
8290 return err;
8291
29cbe68c 8292 wdev_lock(wdev);
7b0a0e3c 8293 if (!wdev->u.mesh.id_len)
29cbe68c
JB
8294 err = -ENOLINK;
8295
8296 if (!err)
e35e4d28 8297 err = rdev_update_mesh_config(rdev, dev, mask, &cfg);
29cbe68c
JB
8298
8299 wdev_unlock(wdev);
8300
8301 return err;
93da9cc1 8302}
8303
ad30ca2c
AN
8304static int nl80211_put_regdom(const struct ieee80211_regdomain *regdom,
8305 struct sk_buff *msg)
f130347c 8306{
f130347c
LR
8307 struct nlattr *nl_reg_rules;
8308 unsigned int i;
f130347c 8309
458f4f9e
JB
8310 if (nla_put_string(msg, NL80211_ATTR_REG_ALPHA2, regdom->alpha2) ||
8311 (regdom->dfs_region &&
8312 nla_put_u8(msg, NL80211_ATTR_DFS_REGION, regdom->dfs_region)))
ad30ca2c 8313 goto nla_put_failure;
458f4f9e 8314
ae0be8de 8315 nl_reg_rules = nla_nest_start_noflag(msg, NL80211_ATTR_REG_RULES);
f130347c 8316 if (!nl_reg_rules)
ad30ca2c 8317 goto nla_put_failure;
f130347c 8318
458f4f9e 8319 for (i = 0; i < regdom->n_reg_rules; i++) {
f130347c
LR
8320 struct nlattr *nl_reg_rule;
8321 const struct ieee80211_reg_rule *reg_rule;
8322 const struct ieee80211_freq_range *freq_range;
8323 const struct ieee80211_power_rule *power_rule;
97524820 8324 unsigned int max_bandwidth_khz;
f130347c 8325
458f4f9e 8326 reg_rule = &regdom->reg_rules[i];
f130347c
LR
8327 freq_range = &reg_rule->freq_range;
8328 power_rule = &reg_rule->power_rule;
8329
ae0be8de 8330 nl_reg_rule = nla_nest_start_noflag(msg, i);
f130347c 8331 if (!nl_reg_rule)
ad30ca2c 8332 goto nla_put_failure;
f130347c 8333
97524820
JD
8334 max_bandwidth_khz = freq_range->max_bandwidth_khz;
8335 if (!max_bandwidth_khz)
8336 max_bandwidth_khz = reg_get_max_bandwidth(regdom,
8337 reg_rule);
8338
9360ffd1
DM
8339 if (nla_put_u32(msg, NL80211_ATTR_REG_RULE_FLAGS,
8340 reg_rule->flags) ||
8341 nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_START,
8342 freq_range->start_freq_khz) ||
8343 nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_END,
8344 freq_range->end_freq_khz) ||
8345 nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW,
97524820 8346 max_bandwidth_khz) ||
9360ffd1
DM
8347 nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
8348 power_rule->max_antenna_gain) ||
8349 nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP,
089027e5
JD
8350 power_rule->max_eirp) ||
8351 nla_put_u32(msg, NL80211_ATTR_DFS_CAC_TIME,
8352 reg_rule->dfs_cac_ms))
ad30ca2c 8353 goto nla_put_failure;
f130347c
LR
8354
8355 nla_nest_end(msg, nl_reg_rule);
8356 }
8357
8358 nla_nest_end(msg, nl_reg_rules);
ad30ca2c
AN
8359 return 0;
8360
8361nla_put_failure:
8362 return -EMSGSIZE;
8363}
8364
8365static int nl80211_get_reg_do(struct sk_buff *skb, struct genl_info *info)
8366{
8367 const struct ieee80211_regdomain *regdom = NULL;
8368 struct cfg80211_registered_device *rdev;
8369 struct wiphy *wiphy = NULL;
8370 struct sk_buff *msg;
024fcf5e 8371 int err = -EMSGSIZE;
ad30ca2c
AN
8372 void *hdr;
8373
8374 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
8375 if (!msg)
8376 return -ENOBUFS;
8377
8378 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
8379 NL80211_CMD_GET_REG);
8380 if (!hdr)
8381 goto put_failure;
8382
a05829a7
JB
8383 rtnl_lock();
8384
ad30ca2c 8385 if (info->attrs[NL80211_ATTR_WIPHY]) {
1bdd716c
AN
8386 bool self_managed;
8387
ad30ca2c
AN
8388 rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
8389 if (IS_ERR(rdev)) {
024fcf5e
JB
8390 err = PTR_ERR(rdev);
8391 goto nla_put_failure;
ad30ca2c
AN
8392 }
8393
8394 wiphy = &rdev->wiphy;
1bdd716c
AN
8395 self_managed = wiphy->regulatory_flags &
8396 REGULATORY_WIPHY_SELF_MANAGED;
024fcf5e
JB
8397
8398 rcu_read_lock();
8399
ad30ca2c
AN
8400 regdom = get_wiphy_regdom(wiphy);
8401
1bdd716c
AN
8402 /* a self-managed-reg device must have a private regdom */
8403 if (WARN_ON(!regdom && self_managed)) {
024fcf5e
JB
8404 err = -EINVAL;
8405 goto nla_put_failure_rcu;
1bdd716c
AN
8406 }
8407
ad30ca2c
AN
8408 if (regdom &&
8409 nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
024fcf5e
JB
8410 goto nla_put_failure_rcu;
8411 } else {
8412 rcu_read_lock();
ad30ca2c
AN
8413 }
8414
8415 if (!wiphy && reg_last_request_cell_base() &&
8416 nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
8417 NL80211_USER_REG_HINT_CELL_BASE))
024fcf5e 8418 goto nla_put_failure_rcu;
ad30ca2c
AN
8419
8420 if (!regdom)
8421 regdom = rcu_dereference(cfg80211_regdomain);
8422
8423 if (nl80211_put_regdom(regdom, msg))
8424 goto nla_put_failure_rcu;
8425
8426 rcu_read_unlock();
f130347c
LR
8427
8428 genlmsg_end(msg, hdr);
a05829a7 8429 rtnl_unlock();
5fe231e8 8430 return genlmsg_reply(msg, info);
f130347c 8431
458f4f9e
JB
8432nla_put_failure_rcu:
8433 rcu_read_unlock();
f130347c 8434nla_put_failure:
a05829a7 8435 rtnl_unlock();
efe1cf0c 8436put_failure:
d080e275 8437 nlmsg_free(msg);
024fcf5e 8438 return err;
f130347c
LR
8439}
8440
ad30ca2c
AN
8441static int nl80211_send_regdom(struct sk_buff *msg, struct netlink_callback *cb,
8442 u32 seq, int flags, struct wiphy *wiphy,
8443 const struct ieee80211_regdomain *regdom)
8444{
8445 void *hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).portid, seq, flags,
8446 NL80211_CMD_GET_REG);
8447
8448 if (!hdr)
8449 return -1;
8450
0a833c29 8451 genl_dump_check_consistent(cb, hdr);
ad30ca2c
AN
8452
8453 if (nl80211_put_regdom(regdom, msg))
8454 goto nla_put_failure;
8455
8456 if (!wiphy && reg_last_request_cell_base() &&
8457 nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
8458 NL80211_USER_REG_HINT_CELL_BASE))
8459 goto nla_put_failure;
8460
8461 if (wiphy &&
8462 nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
8463 goto nla_put_failure;
8464
1bdd716c
AN
8465 if (wiphy && wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
8466 nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
8467 goto nla_put_failure;
8468
053c095a
JB
8469 genlmsg_end(msg, hdr);
8470 return 0;
ad30ca2c
AN
8471
8472nla_put_failure:
8473 genlmsg_cancel(msg, hdr);
8474 return -EMSGSIZE;
8475}
8476
8477static int nl80211_get_reg_dump(struct sk_buff *skb,
8478 struct netlink_callback *cb)
8479{
8480 const struct ieee80211_regdomain *regdom = NULL;
8481 struct cfg80211_registered_device *rdev;
8482 int err, reg_idx, start = cb->args[2];
8483
024fcf5e 8484 rcu_read_lock();
ad30ca2c
AN
8485
8486 if (cfg80211_regdomain && start == 0) {
8487 err = nl80211_send_regdom(skb, cb, cb->nlh->nlmsg_seq,
8488 NLM_F_MULTI, NULL,
024fcf5e 8489 rcu_dereference(cfg80211_regdomain));
ad30ca2c
AN
8490 if (err < 0)
8491 goto out_err;
8492 }
8493
8494 /* the global regdom is idx 0 */
8495 reg_idx = 1;
024fcf5e 8496 list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
ad30ca2c
AN
8497 regdom = get_wiphy_regdom(&rdev->wiphy);
8498 if (!regdom)
8499 continue;
8500
8501 if (++reg_idx <= start)
8502 continue;
8503
8504 err = nl80211_send_regdom(skb, cb, cb->nlh->nlmsg_seq,
8505 NLM_F_MULTI, &rdev->wiphy, regdom);
8506 if (err < 0) {
8507 reg_idx--;
8508 break;
8509 }
8510 }
8511
8512 cb->args[2] = reg_idx;
8513 err = skb->len;
8514out_err:
024fcf5e 8515 rcu_read_unlock();
ad30ca2c
AN
8516 return err;
8517}
8518
b6863036
JB
8519#ifdef CONFIG_CFG80211_CRDA_SUPPORT
8520static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = {
8521 [NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 },
8522 [NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 },
8523 [NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 },
8524 [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 },
8525 [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 },
8526 [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 },
8527 [NL80211_ATTR_DFS_CAC_TIME] = { .type = NLA_U32 },
8528};
8529
8530static int parse_reg_rule(struct nlattr *tb[],
8531 struct ieee80211_reg_rule *reg_rule)
8532{
8533 struct ieee80211_freq_range *freq_range = &reg_rule->freq_range;
8534 struct ieee80211_power_rule *power_rule = &reg_rule->power_rule;
8535
8536 if (!tb[NL80211_ATTR_REG_RULE_FLAGS])
8537 return -EINVAL;
8538 if (!tb[NL80211_ATTR_FREQ_RANGE_START])
8539 return -EINVAL;
8540 if (!tb[NL80211_ATTR_FREQ_RANGE_END])
8541 return -EINVAL;
8542 if (!tb[NL80211_ATTR_FREQ_RANGE_MAX_BW])
8543 return -EINVAL;
8544 if (!tb[NL80211_ATTR_POWER_RULE_MAX_EIRP])
8545 return -EINVAL;
8546
8547 reg_rule->flags = nla_get_u32(tb[NL80211_ATTR_REG_RULE_FLAGS]);
8548
8549 freq_range->start_freq_khz =
8550 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]);
8551 freq_range->end_freq_khz =
8552 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]);
8553 freq_range->max_bandwidth_khz =
8554 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]);
8555
8556 power_rule->max_eirp =
8557 nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]);
8558
8559 if (tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN])
8560 power_rule->max_antenna_gain =
8561 nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]);
8562
8563 if (tb[NL80211_ATTR_DFS_CAC_TIME])
8564 reg_rule->dfs_cac_ms =
8565 nla_get_u32(tb[NL80211_ATTR_DFS_CAC_TIME]);
8566
8567 return 0;
8568}
8569
b2e1b302
LR
8570static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
8571{
8572 struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1];
8573 struct nlattr *nl_reg_rule;
ea372c54
JB
8574 char *alpha2;
8575 int rem_reg_rules, r;
391d132c 8576 u32 num_rules = 0, rule_idx = 0;
4c7d3982 8577 enum nl80211_dfs_regions dfs_region = NL80211_DFS_UNSET;
ea372c54 8578 struct ieee80211_regdomain *rd;
b2e1b302
LR
8579
8580 if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
8581 return -EINVAL;
8582
8583 if (!info->attrs[NL80211_ATTR_REG_RULES])
8584 return -EINVAL;
8585
8586 alpha2 = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
8587
8b60b078
LR
8588 if (info->attrs[NL80211_ATTR_DFS_REGION])
8589 dfs_region = nla_get_u8(info->attrs[NL80211_ATTR_DFS_REGION]);
8590
b2e1b302 8591 nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
1a919318 8592 rem_reg_rules) {
b2e1b302
LR
8593 num_rules++;
8594 if (num_rules > NL80211_MAX_SUPP_REG_RULES)
4776c6e7 8595 return -EINVAL;
b2e1b302
LR
8596 }
8597
a05829a7
JB
8598 rtnl_lock();
8599 if (!reg_is_valid_request(alpha2)) {
8600 r = -EINVAL;
8601 goto out;
8602 }
e438768f 8603
391d132c 8604 rd = kzalloc(struct_size(rd, reg_rules, num_rules), GFP_KERNEL);
a05829a7
JB
8605 if (!rd) {
8606 r = -ENOMEM;
8607 goto out;
8608 }
b2e1b302
LR
8609
8610 rd->n_reg_rules = num_rules;
8611 rd->alpha2[0] = alpha2[0];
8612 rd->alpha2[1] = alpha2[1];
8613
8b60b078
LR
8614 /*
8615 * Disable DFS master mode if the DFS region was
8616 * not supported or known on this kernel.
8617 */
8618 if (reg_supported_dfs_region(dfs_region))
8619 rd->dfs_region = dfs_region;
8620
b2e1b302 8621 nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
1a919318 8622 rem_reg_rules) {
8cb08174
JB
8623 r = nla_parse_nested_deprecated(tb, NL80211_REG_RULE_ATTR_MAX,
8624 nl_reg_rule, reg_rule_policy,
8625 info->extack);
ae811e21
JB
8626 if (r)
8627 goto bad_reg;
b2e1b302
LR
8628 r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]);
8629 if (r)
8630 goto bad_reg;
8631
8632 rule_idx++;
8633
d0e18f83
LR
8634 if (rule_idx > NL80211_MAX_SUPP_REG_RULES) {
8635 r = -EINVAL;
b2e1b302 8636 goto bad_reg;
d0e18f83 8637 }
b2e1b302
LR
8638 }
8639
a05829a7 8640 r = set_regdom(rd, REGD_SOURCE_CRDA);
06627990 8641 /* set_regdom takes ownership of rd */
a05829a7 8642 rd = NULL;
d2372b31 8643 bad_reg:
b2e1b302 8644 kfree(rd);
a05829a7
JB
8645 out:
8646 rtnl_unlock();
d0e18f83 8647 return r;
b2e1b302 8648}
b6863036 8649#endif /* CONFIG_CFG80211_CRDA_SUPPORT */
b2e1b302 8650
83f5e2cf
JB
8651static int validate_scan_freqs(struct nlattr *freqs)
8652{
8653 struct nlattr *attr1, *attr2;
8654 int n_channels = 0, tmp1, tmp2;
8655
d7f13f74
SD
8656 nla_for_each_nested(attr1, freqs, tmp1)
8657 if (nla_len(attr1) != sizeof(u32))
8658 return 0;
8659
83f5e2cf
JB
8660 nla_for_each_nested(attr1, freqs, tmp1) {
8661 n_channels++;
8662 /*
8663 * Some hardware has a limited channel list for
8664 * scanning, and it is pretty much nonsensical
8665 * to scan for a channel twice, so disallow that
8666 * and don't require drivers to check that the
8667 * channel list they get isn't longer than what
8668 * they can scan, as long as they can scan all
8669 * the channels they registered at once.
8670 */
8671 nla_for_each_nested(attr2, freqs, tmp2)
8672 if (attr1 != attr2 &&
8673 nla_get_u32(attr1) == nla_get_u32(attr2))
8674 return 0;
8675 }
8676
8677 return n_channels;
8678}
8679
57fbcce3 8680static bool is_band_valid(struct wiphy *wiphy, enum nl80211_band b)
38de03d2 8681{
57fbcce3 8682 return b < NUM_NL80211_BANDS && wiphy->bands[b];
38de03d2
AS
8683}
8684
8685static int parse_bss_select(struct nlattr *nla, struct wiphy *wiphy,
8686 struct cfg80211_bss_selection *bss_select)
8687{
8688 struct nlattr *attr[NL80211_BSS_SELECT_ATTR_MAX + 1];
8689 struct nlattr *nest;
8690 int err;
8691 bool found = false;
8692 int i;
8693
8694 /* only process one nested attribute */
8695 nest = nla_data(nla);
8696 if (!nla_ok(nest, nla_len(nest)))
8697 return -EINVAL;
8698
8cb08174
JB
8699 err = nla_parse_nested_deprecated(attr, NL80211_BSS_SELECT_ATTR_MAX,
8700 nest, nl80211_bss_select_policy,
8701 NULL);
38de03d2
AS
8702 if (err)
8703 return err;
8704
8705 /* only one attribute may be given */
8706 for (i = 0; i <= NL80211_BSS_SELECT_ATTR_MAX; i++) {
8707 if (attr[i]) {
8708 if (found)
8709 return -EINVAL;
8710 found = true;
8711 }
8712 }
8713
8714 bss_select->behaviour = __NL80211_BSS_SELECT_ATTR_INVALID;
8715
8716 if (attr[NL80211_BSS_SELECT_ATTR_RSSI])
8717 bss_select->behaviour = NL80211_BSS_SELECT_ATTR_RSSI;
8718
8719 if (attr[NL80211_BSS_SELECT_ATTR_BAND_PREF]) {
8720 bss_select->behaviour = NL80211_BSS_SELECT_ATTR_BAND_PREF;
8721 bss_select->param.band_pref =
8722 nla_get_u32(attr[NL80211_BSS_SELECT_ATTR_BAND_PREF]);
8723 if (!is_band_valid(wiphy, bss_select->param.band_pref))
8724 return -EINVAL;
8725 }
8726
8727 if (attr[NL80211_BSS_SELECT_ATTR_RSSI_ADJUST]) {
8728 struct nl80211_bss_select_rssi_adjust *adj_param;
8729
8730 adj_param = nla_data(attr[NL80211_BSS_SELECT_ATTR_RSSI_ADJUST]);
8731 bss_select->behaviour = NL80211_BSS_SELECT_ATTR_RSSI_ADJUST;
8732 bss_select->param.adjust.band = adj_param->band;
8733 bss_select->param.adjust.delta = adj_param->delta;
8734 if (!is_band_valid(wiphy, bss_select->param.adjust.band))
8735 return -EINVAL;
8736 }
8737
8738 /* user-space did not provide behaviour attribute */
8739 if (bss_select->behaviour == __NL80211_BSS_SELECT_ATTR_INVALID)
8740 return -EINVAL;
8741
8742 if (!(wiphy->bss_select_support & BIT(bss_select->behaviour)))
8743 return -EINVAL;
8744
8745 return 0;
8746}
8747
9bb7e0f2
JB
8748int nl80211_parse_random_mac(struct nlattr **attrs,
8749 u8 *mac_addr, u8 *mac_addr_mask)
ad2b26ab
JB
8750{
8751 int i;
8752
8753 if (!attrs[NL80211_ATTR_MAC] && !attrs[NL80211_ATTR_MAC_MASK]) {
d2beae10
JP
8754 eth_zero_addr(mac_addr);
8755 eth_zero_addr(mac_addr_mask);
ad2b26ab
JB
8756 mac_addr[0] = 0x2;
8757 mac_addr_mask[0] = 0x3;
8758
8759 return 0;
8760 }
8761
8762 /* need both or none */
8763 if (!attrs[NL80211_ATTR_MAC] || !attrs[NL80211_ATTR_MAC_MASK])
8764 return -EINVAL;
8765
8766 memcpy(mac_addr, nla_data(attrs[NL80211_ATTR_MAC]), ETH_ALEN);
8767 memcpy(mac_addr_mask, nla_data(attrs[NL80211_ATTR_MAC_MASK]), ETH_ALEN);
8768
8769 /* don't allow or configure an mcast address */
8770 if (!is_multicast_ether_addr(mac_addr_mask) ||
8771 is_multicast_ether_addr(mac_addr))
8772 return -EINVAL;
8773
8774 /*
8775 * allow users to pass a MAC address that has bits set outside
8776 * of the mask, but don't bother drivers with having to deal
8777 * with such bits
8778 */
8779 for (i = 0; i < ETH_ALEN; i++)
8780 mac_addr[i] &= mac_addr_mask[i];
8781
8782 return 0;
8783}
8784
7b0a0e3c
JB
8785static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev,
8786 struct ieee80211_channel *chan)
34373d12 8787{
7b0a0e3c
JB
8788 unsigned int link_id;
8789 bool all_ok = true;
8790
34373d12
VT
8791 ASSERT_WDEV_LOCK(wdev);
8792
8793 if (!cfg80211_beaconing_iface_active(wdev))
8794 return true;
8795
7b0a0e3c
JB
8796 /*
8797 * FIXME: check if we have a free HW resource/link for chan
8798 *
8799 * This, as well as the FIXME below, requires knowing the link
8800 * capabilities of the hardware.
8801 */
8802
8803 /* we cannot leave radar channels */
8804 for_each_valid_link(wdev, link_id) {
8805 struct cfg80211_chan_def *chandef;
8806
8807 chandef = wdev_chandef(wdev, link_id);
8808 if (!chandef)
8809 continue;
8810
8811 /*
8812 * FIXME: don't require all_ok, but rather check only the
8813 * correct HW resource/link onto which 'chan' falls,
8814 * as only that link leaves the channel for doing
8815 * the off-channel operation.
8816 */
8817
8818 if (chandef->chan->flags & IEEE80211_CHAN_RADAR)
8819 all_ok = false;
8820 }
8821
8822 if (all_ok)
34373d12
VT
8823 return true;
8824
8825 return regulatory_pre_cac_allowed(wdev->wiphy);
8826}
8827
db0a4ad8
JB
8828static bool nl80211_check_scan_feat(struct wiphy *wiphy, u32 flags, u32 flag,
8829 enum nl80211_ext_feature_index feat)
8830{
8831 if (!(flags & flag))
8832 return true;
8833 if (wiphy_ext_feature_isset(wiphy, feat))
8834 return true;
8835 return false;
8836}
8837
2d23d073
RZ
8838static int
8839nl80211_check_scan_flags(struct wiphy *wiphy, struct wireless_dev *wdev,
8840 void *request, struct nlattr **attrs,
8841 bool is_sched_scan)
8842{
8843 u8 *mac_addr, *mac_addr_mask;
8844 u32 *flags;
8845 enum nl80211_feature_flags randomness_flag;
8846
8847 if (!attrs[NL80211_ATTR_SCAN_FLAGS])
8848 return 0;
8849
8850 if (is_sched_scan) {
8851 struct cfg80211_sched_scan_request *req = request;
8852
8853 randomness_flag = wdev ?
8854 NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR :
8855 NL80211_FEATURE_ND_RANDOM_MAC_ADDR;
8856 flags = &req->flags;
8857 mac_addr = req->mac_addr;
8858 mac_addr_mask = req->mac_addr_mask;
8859 } else {
8860 struct cfg80211_scan_request *req = request;
8861
8862 randomness_flag = NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
8863 flags = &req->flags;
8864 mac_addr = req->mac_addr;
8865 mac_addr_mask = req->mac_addr_mask;
8866 }
8867
8868 *flags = nla_get_u32(attrs[NL80211_ATTR_SCAN_FLAGS]);
8869
5037a009
SD
8870 if (((*flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
8871 !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) ||
db0a4ad8
JB
8872 !nl80211_check_scan_feat(wiphy, *flags,
8873 NL80211_SCAN_FLAG_LOW_SPAN,
8874 NL80211_EXT_FEATURE_LOW_SPAN_SCAN) ||
8875 !nl80211_check_scan_feat(wiphy, *flags,
8876 NL80211_SCAN_FLAG_LOW_POWER,
8877 NL80211_EXT_FEATURE_LOW_POWER_SCAN) ||
8878 !nl80211_check_scan_feat(wiphy, *flags,
8879 NL80211_SCAN_FLAG_HIGH_ACCURACY,
8880 NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN) ||
8881 !nl80211_check_scan_feat(wiphy, *flags,
8882 NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME,
8883 NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME) ||
8884 !nl80211_check_scan_feat(wiphy, *flags,
8885 NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP,
8886 NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP) ||
8887 !nl80211_check_scan_feat(wiphy, *flags,
8888 NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION,
8889 NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION) ||
8890 !nl80211_check_scan_feat(wiphy, *flags,
8891 NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE,
2e076f19
JB
8892 NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE) ||
8893 !nl80211_check_scan_feat(wiphy, *flags,
8894 NL80211_SCAN_FLAG_RANDOM_SN,
8895 NL80211_EXT_FEATURE_SCAN_RANDOM_SN) ||
8896 !nl80211_check_scan_feat(wiphy, *flags,
8897 NL80211_SCAN_FLAG_MIN_PREQ_CONTENT,
8898 NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT))
2d23d073
RZ
8899 return -EOPNOTSUPP;
8900
8901 if (*flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
8902 int err;
8903
8904 if (!(wiphy->features & randomness_flag) ||
7b0a0e3c 8905 (wdev && wdev->connected))
2d23d073
RZ
8906 return -EOPNOTSUPP;
8907
8908 err = nl80211_parse_random_mac(attrs, mac_addr, mac_addr_mask);
8909 if (err)
8910 return err;
8911 }
8912
2d23d073
RZ
8913 return 0;
8914}
8915
2a519311
JB
8916static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
8917{
4c476991 8918 struct cfg80211_registered_device *rdev = info->user_ptr[0];
fd014284 8919 struct wireless_dev *wdev = info->user_ptr[1];
2a519311 8920 struct cfg80211_scan_request *request;
2032f3b2
TP
8921 struct nlattr *scan_freqs = NULL;
8922 bool scan_freqs_khz = false;
2a519311
JB
8923 struct nlattr *attr;
8924 struct wiphy *wiphy;
83f5e2cf 8925 int err, tmp, n_ssids = 0, n_channels, i;
70692ad2 8926 size_t ie_len;
2a519311 8927
79c97e97 8928 wiphy = &rdev->wiphy;
2a519311 8929
cb3b7d87
AB
8930 if (wdev->iftype == NL80211_IFTYPE_NAN)
8931 return -EOPNOTSUPP;
8932
4c476991
JB
8933 if (!rdev->ops->scan)
8934 return -EOPNOTSUPP;
2a519311 8935
83286856
CJ
8936 if (rdev->scan_req || rdev->scan_msg)
8937 return -EBUSY;
2a519311 8938
2032f3b2
TP
8939 if (info->attrs[NL80211_ATTR_SCAN_FREQ_KHZ]) {
8940 if (!wiphy_ext_feature_isset(wiphy,
8941 NL80211_EXT_FEATURE_SCAN_FREQ_KHZ))
8942 return -EOPNOTSUPP;
8943 scan_freqs = info->attrs[NL80211_ATTR_SCAN_FREQ_KHZ];
8944 scan_freqs_khz = true;
8945 } else if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES])
8946 scan_freqs = info->attrs[NL80211_ATTR_SCAN_FREQUENCIES];
8947
8948 if (scan_freqs) {
8949 n_channels = validate_scan_freqs(scan_freqs);
83286856
CJ
8950 if (!n_channels)
8951 return -EINVAL;
2a519311 8952 } else {
bdfbec2d 8953 n_channels = ieee80211_get_num_supported_channels(wiphy);
2a519311
JB
8954 }
8955
8956 if (info->attrs[NL80211_ATTR_SCAN_SSIDS])
8957 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp)
8958 n_ssids++;
8959
83286856
CJ
8960 if (n_ssids > wiphy->max_scan_ssids)
8961 return -EINVAL;
2a519311 8962
70692ad2
JM
8963 if (info->attrs[NL80211_ATTR_IE])
8964 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
8965 else
8966 ie_len = 0;
8967
83286856
CJ
8968 if (ie_len > wiphy->max_scan_ie_len)
8969 return -EINVAL;
18a83659 8970
2a519311 8971 request = kzalloc(sizeof(*request)
a2cd43c5
LC
8972 + sizeof(*request->ssids) * n_ssids
8973 + sizeof(*request->channels) * n_channels
70692ad2 8974 + ie_len, GFP_KERNEL);
83286856
CJ
8975 if (!request)
8976 return -ENOMEM;
2a519311 8977
2a519311 8978 if (n_ssids)
5ba63533 8979 request->ssids = (void *)&request->channels[n_channels];
2a519311 8980 request->n_ssids = n_ssids;
70692ad2 8981 if (ie_len) {
13874e4b 8982 if (n_ssids)
70692ad2
JM
8983 request->ie = (void *)(request->ssids + n_ssids);
8984 else
8985 request->ie = (void *)(request->channels + n_channels);
8986 }
2a519311 8987
584991dc 8988 i = 0;
2032f3b2 8989 if (scan_freqs) {
2a519311 8990 /* user specified, bail out if channel not found */
2032f3b2 8991 nla_for_each_nested(attr, scan_freqs, tmp) {
584991dc 8992 struct ieee80211_channel *chan;
2032f3b2 8993 int freq = nla_get_u32(attr);
584991dc 8994
2032f3b2
TP
8995 if (!scan_freqs_khz)
8996 freq = MHZ_TO_KHZ(freq);
584991dc 8997
2032f3b2 8998 chan = ieee80211_get_channel_khz(wiphy, freq);
584991dc 8999 if (!chan) {
2a519311
JB
9000 err = -EINVAL;
9001 goto out_free;
9002 }
584991dc
JB
9003
9004 /* ignore disabled channels */
9005 if (chan->flags & IEEE80211_CHAN_DISABLED)
9006 continue;
9007
9008 request->channels[i] = chan;
2a519311
JB
9009 i++;
9010 }
9011 } else {
57fbcce3 9012 enum nl80211_band band;
34850ab2 9013
2a519311 9014 /* all channels */
57fbcce3 9015 for (band = 0; band < NUM_NL80211_BANDS; band++) {
2a519311 9016 int j;
7a087e74 9017
2a519311
JB
9018 if (!wiphy->bands[band])
9019 continue;
9020 for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
584991dc
JB
9021 struct ieee80211_channel *chan;
9022
9023 chan = &wiphy->bands[band]->channels[j];
9024
9025 if (chan->flags & IEEE80211_CHAN_DISABLED)
9026 continue;
9027
9028 request->channels[i] = chan;
2a519311
JB
9029 i++;
9030 }
9031 }
9032 }
9033
584991dc
JB
9034 if (!i) {
9035 err = -EINVAL;
9036 goto out_free;
9037 }
9038
9039 request->n_channels = i;
9040
34373d12 9041 wdev_lock(wdev);
7b0a0e3c
JB
9042 for (i = 0; i < request->n_channels; i++) {
9043 struct ieee80211_channel *chan = request->channels[i];
34373d12 9044
7b0a0e3c
JB
9045 /* if we can go off-channel to the target channel we're good */
9046 if (cfg80211_off_channel_oper_allowed(wdev, chan))
9047 continue;
34373d12 9048
7b0a0e3c 9049 if (!cfg80211_wdev_on_sub_chan(wdev, chan, true)) {
34373d12
VT
9050 wdev_unlock(wdev);
9051 err = -EBUSY;
9052 goto out_free;
9053 }
9054 }
9055 wdev_unlock(wdev);
9056
2a519311 9057 i = 0;
13874e4b 9058 if (n_ssids) {
2a519311 9059 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) {
57a27e1d 9060 if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) {
2a519311
JB
9061 err = -EINVAL;
9062 goto out_free;
9063 }
57a27e1d 9064 request->ssids[i].ssid_len = nla_len(attr);
2a519311 9065 memcpy(request->ssids[i].ssid, nla_data(attr), nla_len(attr));
2a519311
JB
9066 i++;
9067 }
9068 }
9069
70692ad2
JM
9070 if (info->attrs[NL80211_ATTR_IE]) {
9071 request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
de95a54b
JB
9072 memcpy((void *)request->ie,
9073 nla_data(info->attrs[NL80211_ATTR_IE]),
70692ad2
JM
9074 request->ie_len);
9075 }
9076
57fbcce3 9077 for (i = 0; i < NUM_NL80211_BANDS; i++)
a401d2bb
JB
9078 if (wiphy->bands[i])
9079 request->rates[i] =
9080 (1 << wiphy->bands[i]->n_bitrates) - 1;
34850ab2
JB
9081
9082 if (info->attrs[NL80211_ATTR_SCAN_SUPP_RATES]) {
9083 nla_for_each_nested(attr,
9084 info->attrs[NL80211_ATTR_SCAN_SUPP_RATES],
9085 tmp) {
57fbcce3 9086 enum nl80211_band band = nla_type(attr);
34850ab2 9087
57fbcce3 9088 if (band < 0 || band >= NUM_NL80211_BANDS) {
34850ab2
JB
9089 err = -EINVAL;
9090 goto out_free;
9091 }
1b09cd82
FF
9092
9093 if (!wiphy->bands[band])
9094 continue;
9095
34850ab2
JB
9096 err = ieee80211_get_ratemask(wiphy->bands[band],
9097 nla_data(attr),
9098 nla_len(attr),
9099 &request->rates[band]);
9100 if (err)
9101 goto out_free;
9102 }
9103 }
9104
1d76250b 9105 if (info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]) {
1d76250b
AS
9106 request->duration =
9107 nla_get_u16(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]);
9108 request->duration_mandatory =
9109 nla_get_flag(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY]);
9110 }
9111
2d23d073
RZ
9112 err = nl80211_check_scan_flags(wiphy, wdev, request, info->attrs,
9113 false);
9114 if (err)
9115 goto out_free;
ed473771 9116
e9f935e3
RM
9117 request->no_cck =
9118 nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
9119
2fa436b3
VK
9120 /* Initial implementation used NL80211_ATTR_MAC to set the specific
9121 * BSSID to scan for. This was problematic because that same attribute
9122 * was already used for another purpose (local random MAC address). The
9123 * NL80211_ATTR_BSSID attribute was added to fix this. For backwards
9124 * compatibility with older userspace components, also use the
9125 * NL80211_ATTR_MAC value here if it can be determined to be used for
9126 * the specific BSSID use case instead of the random MAC address
9127 * (NL80211_ATTR_SCAN_FLAGS is used to enable random MAC address use).
9128 */
9129 if (info->attrs[NL80211_ATTR_BSSID])
9130 memcpy(request->bssid,
9131 nla_data(info->attrs[NL80211_ATTR_BSSID]), ETH_ALEN);
9132 else if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) &&
9133 info->attrs[NL80211_ATTR_MAC])
818965d3
JM
9134 memcpy(request->bssid, nla_data(info->attrs[NL80211_ATTR_MAC]),
9135 ETH_ALEN);
9136 else
9137 eth_broadcast_addr(request->bssid);
9138
fd014284 9139 request->wdev = wdev;
79c97e97 9140 request->wiphy = &rdev->wiphy;
15d6030b 9141 request->scan_start = jiffies;
2a519311 9142
79c97e97 9143 rdev->scan_req = request;
c8cb5b85 9144 err = cfg80211_scan(rdev);
2a519311 9145
504776be
CJ
9146 if (err)
9147 goto out_free;
9148
9149 nl80211_send_scan_start(rdev, wdev);
1160dfa1 9150 dev_hold(wdev->netdev);
504776be
CJ
9151
9152 return 0;
9153
2a519311 9154 out_free:
504776be
CJ
9155 rdev->scan_req = NULL;
9156 kfree(request);
3b85875a 9157
2a519311
JB
9158 return err;
9159}
9160
91d3ab46
VK
9161static int nl80211_abort_scan(struct sk_buff *skb, struct genl_info *info)
9162{
9163 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9164 struct wireless_dev *wdev = info->user_ptr[1];
9165
9166 if (!rdev->ops->abort_scan)
9167 return -EOPNOTSUPP;
9168
9169 if (rdev->scan_msg)
9170 return 0;
9171
9172 if (!rdev->scan_req)
9173 return -ENOENT;
9174
9175 rdev_abort_scan(rdev, wdev);
9176 return 0;
9177}
9178
3b06d277
AS
9179static int
9180nl80211_parse_sched_scan_plans(struct wiphy *wiphy, int n_plans,
9181 struct cfg80211_sched_scan_request *request,
9182 struct nlattr **attrs)
9183{
9184 int tmp, err, i = 0;
9185 struct nlattr *attr;
9186
9187 if (!attrs[NL80211_ATTR_SCHED_SCAN_PLANS]) {
9188 u32 interval;
9189
9190 /*
9191 * If scan plans are not specified,
5a88de53 9192 * %NL80211_ATTR_SCHED_SCAN_INTERVAL will be specified. In this
3b06d277
AS
9193 * case one scan plan will be set with the specified scan
9194 * interval and infinite number of iterations.
9195 */
3b06d277
AS
9196 interval = nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]);
9197 if (!interval)
9198 return -EINVAL;
9199
9200 request->scan_plans[0].interval =
9201 DIV_ROUND_UP(interval, MSEC_PER_SEC);
9202 if (!request->scan_plans[0].interval)
9203 return -EINVAL;
9204
9205 if (request->scan_plans[0].interval >
9206 wiphy->max_sched_scan_plan_interval)
9207 request->scan_plans[0].interval =
9208 wiphy->max_sched_scan_plan_interval;
9209
9210 return 0;
9211 }
9212
9213 nla_for_each_nested(attr, attrs[NL80211_ATTR_SCHED_SCAN_PLANS], tmp) {
9214 struct nlattr *plan[NL80211_SCHED_SCAN_PLAN_MAX + 1];
9215
9216 if (WARN_ON(i >= n_plans))
9217 return -EINVAL;
9218
8cb08174
JB
9219 err = nla_parse_nested_deprecated(plan,
9220 NL80211_SCHED_SCAN_PLAN_MAX,
9221 attr, nl80211_plan_policy,
9222 NULL);
3b06d277
AS
9223 if (err)
9224 return err;
9225
9226 if (!plan[NL80211_SCHED_SCAN_PLAN_INTERVAL])
9227 return -EINVAL;
9228
9229 request->scan_plans[i].interval =
9230 nla_get_u32(plan[NL80211_SCHED_SCAN_PLAN_INTERVAL]);
9231 if (!request->scan_plans[i].interval ||
9232 request->scan_plans[i].interval >
9233 wiphy->max_sched_scan_plan_interval)
9234 return -EINVAL;
9235
9236 if (plan[NL80211_SCHED_SCAN_PLAN_ITERATIONS]) {
9237 request->scan_plans[i].iterations =
9238 nla_get_u32(plan[NL80211_SCHED_SCAN_PLAN_ITERATIONS]);
9239 if (!request->scan_plans[i].iterations ||
9240 (request->scan_plans[i].iterations >
9241 wiphy->max_sched_scan_plan_iterations))
9242 return -EINVAL;
9243 } else if (i < n_plans - 1) {
9244 /*
9245 * All scan plans but the last one must specify
9246 * a finite number of iterations
9247 */
9248 return -EINVAL;
9249 }
9250
9251 i++;
9252 }
9253
9254 /*
9255 * The last scan plan must not specify the number of
9256 * iterations, it is supposed to run infinitely
9257 */
9258 if (request->scan_plans[n_plans - 1].iterations)
9259 return -EINVAL;
9260
9261 return 0;
9262}
9263
1e1b11b6 9264static int
9265nl80211_parse_sched_scan_per_band_rssi(struct wiphy *wiphy,
9266 struct cfg80211_match_set *match_sets,
9267 struct nlattr *tb_band_rssi,
9268 s32 rssi_thold)
9269{
9270 struct nlattr *attr;
9271 int i, tmp, ret = 0;
9272
9273 if (!wiphy_ext_feature_isset(wiphy,
9274 NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD)) {
9275 if (tb_band_rssi)
9276 ret = -EOPNOTSUPP;
9277 else
9278 for (i = 0; i < NUM_NL80211_BANDS; i++)
9279 match_sets->per_band_rssi_thold[i] =
9280 NL80211_SCAN_RSSI_THOLD_OFF;
9281 return ret;
9282 }
9283
9284 for (i = 0; i < NUM_NL80211_BANDS; i++)
9285 match_sets->per_band_rssi_thold[i] = rssi_thold;
9286
9287 nla_for_each_nested(attr, tb_band_rssi, tmp) {
9288 enum nl80211_band band = nla_type(attr);
9289
9290 if (band < 0 || band >= NUM_NL80211_BANDS)
9291 return -EINVAL;
9292
9293 match_sets->per_band_rssi_thold[band] = nla_get_s32(attr);
9294 }
9295
9296 return 0;
9297}
9298
256da02d 9299static struct cfg80211_sched_scan_request *
ad2b26ab 9300nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
aad1e812 9301 struct nlattr **attrs, int max_match_sets)
807f8a8c
LC
9302{
9303 struct cfg80211_sched_scan_request *request;
807f8a8c 9304 struct nlattr *attr;
3b06d277 9305 int err, tmp, n_ssids = 0, n_match_sets = 0, n_channels, i, n_plans = 0;
57fbcce3 9306 enum nl80211_band band;
807f8a8c 9307 size_t ie_len;
a1f1c21c 9308 struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
ea73cbce 9309 s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
807f8a8c 9310
256da02d 9311 if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
807f8a8c 9312 n_channels = validate_scan_freqs(
256da02d 9313 attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
807f8a8c 9314 if (!n_channels)
256da02d 9315 return ERR_PTR(-EINVAL);
807f8a8c 9316 } else {
bdfbec2d 9317 n_channels = ieee80211_get_num_supported_channels(wiphy);
807f8a8c
LC
9318 }
9319
256da02d
LC
9320 if (attrs[NL80211_ATTR_SCAN_SSIDS])
9321 nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
807f8a8c
LC
9322 tmp)
9323 n_ssids++;
9324
93b6aa69 9325 if (n_ssids > wiphy->max_sched_scan_ssids)
256da02d 9326 return ERR_PTR(-EINVAL);
807f8a8c 9327
ea73cbce
JB
9328 /*
9329 * First, count the number of 'real' matchsets. Due to an issue with
9330 * the old implementation, matchsets containing only the RSSI attribute
9331 * (NL80211_SCHED_SCAN_MATCH_ATTR_RSSI) are considered as the 'default'
9332 * RSSI for all matchsets, rather than their own matchset for reporting
9333 * all APs with a strong RSSI. This is needed to be compatible with
9334 * older userspace that treated a matchset with only the RSSI as the
9335 * global RSSI for all other matchsets - if there are other matchsets.
9336 */
256da02d 9337 if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
a1f1c21c 9338 nla_for_each_nested(attr,
256da02d 9339 attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
ea73cbce
JB
9340 tmp) {
9341 struct nlattr *rssi;
9342
8cb08174
JB
9343 err = nla_parse_nested_deprecated(tb,
9344 NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
9345 attr,
9346 nl80211_match_policy,
9347 NULL);
ea73cbce 9348 if (err)
256da02d 9349 return ERR_PTR(err);
3007e352
AVS
9350
9351 /* SSID and BSSID are mutually exclusive */
9352 if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID] &&
9353 tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID])
9354 return ERR_PTR(-EINVAL);
9355
ea73cbce 9356 /* add other standalone attributes here */
3007e352
AVS
9357 if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID] ||
9358 tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID]) {
ea73cbce
JB
9359 n_match_sets++;
9360 continue;
9361 }
9362 rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
9363 if (rssi)
9364 default_match_rssi = nla_get_s32(rssi);
9365 }
9366 }
9367
9368 /* However, if there's no other matchset, add the RSSI one */
9369 if (!n_match_sets && default_match_rssi != NL80211_SCAN_RSSI_THOLD_OFF)
9370 n_match_sets = 1;
a1f1c21c 9371
aad1e812 9372 if (n_match_sets > max_match_sets)
256da02d 9373 return ERR_PTR(-EINVAL);
a1f1c21c 9374
256da02d
LC
9375 if (attrs[NL80211_ATTR_IE])
9376 ie_len = nla_len(attrs[NL80211_ATTR_IE]);
807f8a8c
LC
9377 else
9378 ie_len = 0;
9379
5a865bad 9380 if (ie_len > wiphy->max_sched_scan_ie_len)
256da02d 9381 return ERR_PTR(-EINVAL);
c10841ca 9382
3b06d277
AS
9383 if (attrs[NL80211_ATTR_SCHED_SCAN_PLANS]) {
9384 /*
9385 * NL80211_ATTR_SCHED_SCAN_INTERVAL must not be specified since
9386 * each scan plan already specifies its own interval
9387 */
9388 if (attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
9389 return ERR_PTR(-EINVAL);
9390
9391 nla_for_each_nested(attr,
9392 attrs[NL80211_ATTR_SCHED_SCAN_PLANS], tmp)
9393 n_plans++;
9394 } else {
9395 /*
9396 * The scan interval attribute is kept for backward
9397 * compatibility. If no scan plans are specified and sched scan
9398 * interval is specified, one scan plan will be set with this
9399 * scan interval and infinite number of iterations.
9400 */
9401 if (!attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
9402 return ERR_PTR(-EINVAL);
9403
9404 n_plans = 1;
9405 }
9406
9407 if (!n_plans || n_plans > wiphy->max_sched_scan_plans)
9408 return ERR_PTR(-EINVAL);
9409
bf95ecdb 9410 if (!wiphy_ext_feature_isset(
9411 wiphy, NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI) &&
9412 (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] ||
9413 attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]))
9414 return ERR_PTR(-EINVAL);
9415
807f8a8c 9416 request = kzalloc(sizeof(*request)
a2cd43c5 9417 + sizeof(*request->ssids) * n_ssids
a1f1c21c 9418 + sizeof(*request->match_sets) * n_match_sets
3b06d277 9419 + sizeof(*request->scan_plans) * n_plans
a2cd43c5 9420 + sizeof(*request->channels) * n_channels
807f8a8c 9421 + ie_len, GFP_KERNEL);
256da02d
LC
9422 if (!request)
9423 return ERR_PTR(-ENOMEM);
807f8a8c
LC
9424
9425 if (n_ssids)
9426 request->ssids = (void *)&request->channels[n_channels];
9427 request->n_ssids = n_ssids;
9428 if (ie_len) {
13874e4b 9429 if (n_ssids)
807f8a8c
LC
9430 request->ie = (void *)(request->ssids + n_ssids);
9431 else
9432 request->ie = (void *)(request->channels + n_channels);
9433 }
9434
a1f1c21c
LC
9435 if (n_match_sets) {
9436 if (request->ie)
9437 request->match_sets = (void *)(request->ie + ie_len);
13874e4b 9438 else if (n_ssids)
a1f1c21c
LC
9439 request->match_sets =
9440 (void *)(request->ssids + n_ssids);
9441 else
9442 request->match_sets =
9443 (void *)(request->channels + n_channels);
9444 }
9445 request->n_match_sets = n_match_sets;
9446
3b06d277
AS
9447 if (n_match_sets)
9448 request->scan_plans = (void *)(request->match_sets +
9449 n_match_sets);
9450 else if (request->ie)
9451 request->scan_plans = (void *)(request->ie + ie_len);
9452 else if (n_ssids)
9453 request->scan_plans = (void *)(request->ssids + n_ssids);
9454 else
9455 request->scan_plans = (void *)(request->channels + n_channels);
9456
9457 request->n_scan_plans = n_plans;
9458
807f8a8c 9459 i = 0;
256da02d 9460 if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
807f8a8c
LC
9461 /* user specified, bail out if channel not found */
9462 nla_for_each_nested(attr,
256da02d 9463 attrs[NL80211_ATTR_SCAN_FREQUENCIES],
807f8a8c
LC
9464 tmp) {
9465 struct ieee80211_channel *chan;
9466
9467 chan = ieee80211_get_channel(wiphy, nla_get_u32(attr));
9468
9469 if (!chan) {
9470 err = -EINVAL;
9471 goto out_free;
9472 }
9473
9474 /* ignore disabled channels */
9475 if (chan->flags & IEEE80211_CHAN_DISABLED)
9476 continue;
9477
9478 request->channels[i] = chan;
9479 i++;
9480 }
9481 } else {
9482 /* all channels */
57fbcce3 9483 for (band = 0; band < NUM_NL80211_BANDS; band++) {
807f8a8c 9484 int j;
7a087e74 9485
807f8a8c
LC
9486 if (!wiphy->bands[band])
9487 continue;
9488 for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
9489 struct ieee80211_channel *chan;
9490
9491 chan = &wiphy->bands[band]->channels[j];
9492
9493 if (chan->flags & IEEE80211_CHAN_DISABLED)
9494 continue;
9495
9496 request->channels[i] = chan;
9497 i++;
9498 }
9499 }
9500 }
9501
9502 if (!i) {
9503 err = -EINVAL;
9504 goto out_free;
9505 }
9506
9507 request->n_channels = i;
9508
9509 i = 0;
13874e4b 9510 if (n_ssids) {
256da02d 9511 nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
807f8a8c 9512 tmp) {
57a27e1d 9513 if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) {
807f8a8c
LC
9514 err = -EINVAL;
9515 goto out_free;
9516 }
57a27e1d 9517 request->ssids[i].ssid_len = nla_len(attr);
807f8a8c
LC
9518 memcpy(request->ssids[i].ssid, nla_data(attr),
9519 nla_len(attr));
807f8a8c
LC
9520 i++;
9521 }
9522 }
9523
a1f1c21c 9524 i = 0;
256da02d 9525 if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
a1f1c21c 9526 nla_for_each_nested(attr,
256da02d 9527 attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
a1f1c21c 9528 tmp) {
3007e352 9529 struct nlattr *ssid, *bssid, *rssi;
a1f1c21c 9530
8cb08174
JB
9531 err = nla_parse_nested_deprecated(tb,
9532 NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
9533 attr,
9534 nl80211_match_policy,
9535 NULL);
ae811e21
JB
9536 if (err)
9537 goto out_free;
4a4ab0d7 9538 ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID];
3007e352 9539 bssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID];
d39f3b4f
JB
9540
9541 if (!ssid && !bssid) {
9542 i++;
9543 continue;
9544 }
9545
9546 if (WARN_ON(i >= n_match_sets)) {
9547 /* this indicates a programming error,
9548 * the loop above should have verified
9549 * things properly
9550 */
9551 err = -EINVAL;
9552 goto out_free;
9553 }
9554
9555 if (ssid) {
d39f3b4f
JB
9556 memcpy(request->match_sets[i].ssid.ssid,
9557 nla_data(ssid), nla_len(ssid));
9558 request->match_sets[i].ssid.ssid_len =
9559 nla_len(ssid);
9560 }
cb9abd48 9561 if (bssid)
d39f3b4f
JB
9562 memcpy(request->match_sets[i].bssid,
9563 nla_data(bssid), ETH_ALEN);
3007e352 9564
d39f3b4f
JB
9565 /* special attribute - old implementation w/a */
9566 request->match_sets[i].rssi_thold = default_match_rssi;
9567 rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
9568 if (rssi)
ea73cbce 9569 request->match_sets[i].rssi_thold =
d39f3b4f 9570 nla_get_s32(rssi);
1e1b11b6 9571
9572 /* Parse per band RSSI attribute */
9573 err = nl80211_parse_sched_scan_per_band_rssi(wiphy,
9574 &request->match_sets[i],
9575 tb[NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI],
9576 request->match_sets[i].rssi_thold);
9577 if (err)
9578 goto out_free;
9579
a1f1c21c
LC
9580 i++;
9581 }
ea73cbce
JB
9582
9583 /* there was no other matchset, so the RSSI one is alone */
f89f46cf 9584 if (i == 0 && n_match_sets)
ea73cbce
JB
9585 request->match_sets[0].rssi_thold = default_match_rssi;
9586
9587 request->min_rssi_thold = INT_MAX;
9588 for (i = 0; i < n_match_sets; i++)
9589 request->min_rssi_thold =
9590 min(request->match_sets[i].rssi_thold,
9591 request->min_rssi_thold);
9592 } else {
9593 request->min_rssi_thold = NL80211_SCAN_RSSI_THOLD_OFF;
a1f1c21c
LC
9594 }
9595
9900e484
JB
9596 if (ie_len) {
9597 request->ie_len = ie_len;
807f8a8c 9598 memcpy((void *)request->ie,
256da02d 9599 nla_data(attrs[NL80211_ATTR_IE]),
807f8a8c
LC
9600 request->ie_len);
9601 }
9602
2d23d073
RZ
9603 err = nl80211_check_scan_flags(wiphy, wdev, request, attrs, true);
9604 if (err)
9605 goto out_free;
ed473771 9606
9c748934
LC
9607 if (attrs[NL80211_ATTR_SCHED_SCAN_DELAY])
9608 request->delay =
9609 nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_DELAY]);
9610
bf95ecdb 9611 if (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI]) {
9612 request->relative_rssi = nla_get_s8(
9613 attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI]);
9614 request->relative_rssi_set = true;
9615 }
9616
9617 if (request->relative_rssi_set &&
9618 attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]) {
9619 struct nl80211_bss_select_rssi_adjust *rssi_adjust;
9620
9621 rssi_adjust = nla_data(
9622 attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]);
9623 request->rssi_adjust.band = rssi_adjust->band;
9624 request->rssi_adjust.delta = rssi_adjust->delta;
9625 if (!is_band_valid(wiphy, request->rssi_adjust.band)) {
9626 err = -EINVAL;
9627 goto out_free;
9628 }
9629 }
9630
3b06d277
AS
9631 err = nl80211_parse_sched_scan_plans(wiphy, n_plans, request, attrs);
9632 if (err)
9633 goto out_free;
9634
15d6030b 9635 request->scan_start = jiffies;
807f8a8c 9636
256da02d 9637 return request;
807f8a8c
LC
9638
9639out_free:
9640 kfree(request);
256da02d
LC
9641 return ERR_PTR(err);
9642}
9643
9644static int nl80211_start_sched_scan(struct sk_buff *skb,
9645 struct genl_info *info)
9646{
9647 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9648 struct net_device *dev = info->user_ptr[1];
ad2b26ab 9649 struct wireless_dev *wdev = dev->ieee80211_ptr;
31a60ed1 9650 struct cfg80211_sched_scan_request *sched_scan_req;
ca986ad9 9651 bool want_multi;
256da02d
LC
9652 int err;
9653
ca986ad9 9654 if (!rdev->wiphy.max_sched_scan_reqs || !rdev->ops->sched_scan_start)
256da02d
LC
9655 return -EOPNOTSUPP;
9656
ca986ad9
AVS
9657 want_multi = info->attrs[NL80211_ATTR_SCHED_SCAN_MULTI];
9658 err = cfg80211_sched_scan_req_possible(rdev, want_multi);
9659 if (err)
9660 return err;
256da02d 9661
31a60ed1 9662 sched_scan_req = nl80211_parse_sched_scan(&rdev->wiphy, wdev,
aad1e812
AVS
9663 info->attrs,
9664 rdev->wiphy.max_match_sets);
31a60ed1
JR
9665
9666 err = PTR_ERR_OR_ZERO(sched_scan_req);
256da02d
LC
9667 if (err)
9668 goto out_err;
9669
ca986ad9
AVS
9670 /* leave request id zero for legacy request
9671 * or if driver does not support multi-scheduled scan
9672 */
2fd351a8
DK
9673 if (want_multi && rdev->wiphy.max_sched_scan_reqs > 1)
9674 sched_scan_req->reqid = cfg80211_assign_cookie(rdev);
ca986ad9 9675
31a60ed1 9676 err = rdev_sched_scan_start(rdev, dev, sched_scan_req);
256da02d
LC
9677 if (err)
9678 goto out_free;
9679
31a60ed1
JR
9680 sched_scan_req->dev = dev;
9681 sched_scan_req->wiphy = &rdev->wiphy;
9682
93a1e86c
JR
9683 if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
9684 sched_scan_req->owner_nlportid = info->snd_portid;
9685
ca986ad9 9686 cfg80211_add_sched_scan_req(rdev, sched_scan_req);
256da02d 9687
96b08fd6 9688 nl80211_send_sched_scan(sched_scan_req, NL80211_CMD_START_SCHED_SCAN);
256da02d
LC
9689 return 0;
9690
9691out_free:
31a60ed1 9692 kfree(sched_scan_req);
256da02d 9693out_err:
807f8a8c
LC
9694 return err;
9695}
9696
9697static int nl80211_stop_sched_scan(struct sk_buff *skb,
9698 struct genl_info *info)
9699{
ca986ad9 9700 struct cfg80211_sched_scan_request *req;
807f8a8c 9701 struct cfg80211_registered_device *rdev = info->user_ptr[0];
ca986ad9 9702 u64 cookie;
807f8a8c 9703
ca986ad9 9704 if (!rdev->wiphy.max_sched_scan_reqs || !rdev->ops->sched_scan_stop)
807f8a8c
LC
9705 return -EOPNOTSUPP;
9706
ca986ad9
AVS
9707 if (info->attrs[NL80211_ATTR_COOKIE]) {
9708 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
9709 return __cfg80211_stop_sched_scan(rdev, cookie, false);
9710 }
9711
9712 req = list_first_or_null_rcu(&rdev->sched_scan_req_list,
9713 struct cfg80211_sched_scan_request,
9714 list);
9715 if (!req || req->reqid ||
9716 (req->owner_nlportid &&
9717 req->owner_nlportid != info->snd_portid))
9718 return -ENOENT;
9719
9720 return cfg80211_stop_sched_scan_req(rdev, req, false);
807f8a8c
LC
9721}
9722
04f39047
SW
9723static int nl80211_start_radar_detection(struct sk_buff *skb,
9724 struct genl_info *info)
9725{
9726 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9727 struct net_device *dev = info->user_ptr[1];
9728 struct wireless_dev *wdev = dev->ieee80211_ptr;
13cf6dec 9729 struct wiphy *wiphy = wdev->wiphy;
04f39047 9730 struct cfg80211_chan_def chandef;
55f7435c 9731 enum nl80211_dfs_regions dfs_region;
31559f35 9732 unsigned int cac_time_ms;
84158164
LB
9733 int err = -EINVAL;
9734
9735 flush_delayed_work(&rdev->dfs_update_channels_wk);
9736
9737 wiphy_lock(wiphy);
04f39047 9738
13cf6dec 9739 dfs_region = reg_get_dfs_region(wiphy);
55f7435c 9740 if (dfs_region == NL80211_DFS_UNSET)
84158164 9741 goto unlock;
55f7435c 9742
04f39047
SW
9743 err = nl80211_parse_chandef(rdev, info, &chandef);
9744 if (err)
84158164 9745 goto unlock;
04f39047 9746
13cf6dec 9747 err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype);
04f39047 9748 if (err < 0)
84158164 9749 goto unlock;
04f39047 9750
84158164
LB
9751 if (err == 0) {
9752 err = -EINVAL;
9753 goto unlock;
9754 }
04f39047 9755
84158164
LB
9756 if (!cfg80211_chandef_dfs_usable(wiphy, &chandef)) {
9757 err = -EINVAL;
9758 goto unlock;
9759 }
04f39047 9760
a95bfb87
LB
9761 if (nla_get_flag(info->attrs[NL80211_ATTR_RADAR_BACKGROUND])) {
9762 err = cfg80211_start_background_radar_detection(rdev, wdev,
9763 &chandef);
84158164
LB
9764 goto unlock;
9765 }
bc2dfc02 9766
84158164
LB
9767 if (netif_carrier_ok(dev)) {
9768 err = -EBUSY;
9769 goto unlock;
9770 }
bc2dfc02 9771
84158164
LB
9772 if (wdev->cac_started) {
9773 err = -EBUSY;
9774 goto unlock;
9775 }
bc2dfc02 9776
13cf6dec 9777 /* CAC start is offloaded to HW and can't be started manually */
84158164
LB
9778 if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD)) {
9779 err = -EOPNOTSUPP;
9780 goto unlock;
9781 }
13cf6dec 9782
84158164
LB
9783 if (!rdev->ops->start_radar_detection) {
9784 err = -EOPNOTSUPP;
9785 goto unlock;
9786 }
04f39047 9787
31559f35
JD
9788 cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef);
9789 if (WARN_ON(!cac_time_ms))
9790 cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
9791
a1056b1b 9792 err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms);
04f39047 9793 if (!err) {
7b0a0e3c 9794 wdev->links[0].ap.chandef = chandef;
04f39047
SW
9795 wdev->cac_started = true;
9796 wdev->cac_start_time = jiffies;
31559f35 9797 wdev->cac_time_ms = cac_time_ms;
04f39047 9798 }
84158164
LB
9799unlock:
9800 wiphy_unlock(wiphy);
9801
04f39047
SW
9802 return err;
9803}
9804
30c63115
S
9805static int nl80211_notify_radar_detection(struct sk_buff *skb,
9806 struct genl_info *info)
9807{
9808 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9809 struct net_device *dev = info->user_ptr[1];
9810 struct wireless_dev *wdev = dev->ieee80211_ptr;
9811 struct wiphy *wiphy = wdev->wiphy;
9812 struct cfg80211_chan_def chandef;
9813 enum nl80211_dfs_regions dfs_region;
9814 int err;
9815
9816 dfs_region = reg_get_dfs_region(wiphy);
9817 if (dfs_region == NL80211_DFS_UNSET) {
9818 GENL_SET_ERR_MSG(info,
9819 "DFS Region is not set. Unexpected Radar indication");
9820 return -EINVAL;
9821 }
9822
9823 err = nl80211_parse_chandef(rdev, info, &chandef);
9824 if (err) {
9825 GENL_SET_ERR_MSG(info, "Unable to extract chandef info");
9826 return err;
9827 }
9828
9829 err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype);
9830 if (err < 0) {
9831 GENL_SET_ERR_MSG(info, "chandef is invalid");
9832 return err;
9833 }
9834
9835 if (err == 0) {
9836 GENL_SET_ERR_MSG(info,
9837 "Unexpected Radar indication for chandef/iftype");
9838 return -EINVAL;
9839 }
9840
9841 /* Do not process this notification if radar is already detected
9842 * by kernel on this channel, and return success.
9843 */
9844 if (chandef.chan->dfs_state == NL80211_DFS_UNAVAILABLE)
9845 return 0;
9846
9847 cfg80211_set_dfs_state(wiphy, &chandef, NL80211_DFS_UNAVAILABLE);
9848
9849 cfg80211_sched_dfs_chan_update(rdev);
9850
a680fe46 9851 rdev->radar_chandef = chandef;
30c63115
S
9852
9853 /* Propagate this notification to other radios as well */
9854 queue_work(cfg80211_wq, &rdev->propagate_radar_detect_wk);
9855
9856 return 0;
9857}
9858
16ef1fe2
SW
9859static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
9860{
9861 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c 9862 unsigned int link_id = nl80211_link_id(info->attrs);
16ef1fe2
SW
9863 struct net_device *dev = info->user_ptr[1];
9864 struct wireless_dev *wdev = dev->ieee80211_ptr;
9865 struct cfg80211_csa_settings params;
a05829a7 9866 struct nlattr **csa_attrs = NULL;
16ef1fe2 9867 int err;
ee4bc9e7 9868 bool need_new_beacon = false;
8d9de16f 9869 bool need_handle_dfs_flag = true;
9a774c78 9870 int len, i;
252e07ca 9871 u32 cs_count;
16ef1fe2
SW
9872
9873 if (!rdev->ops->channel_switch ||
9874 !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
9875 return -EOPNOTSUPP;
9876
ee4bc9e7
SW
9877 switch (dev->ieee80211_ptr->iftype) {
9878 case NL80211_IFTYPE_AP:
9879 case NL80211_IFTYPE_P2P_GO:
9880 need_new_beacon = true;
8d9de16f
BB
9881 /* For all modes except AP the handle_dfs flag needs to be
9882 * supplied to tell the kernel that userspace will handle radar
9883 * events when they happen. Otherwise a switch to a channel
9884 * requiring DFS will be rejected.
9885 */
9886 need_handle_dfs_flag = false;
ee4bc9e7
SW
9887
9888 /* useless if AP is not running */
7b0a0e3c 9889 if (!wdev->links[link_id].ap.beacon_interval)
1ff79dfa 9890 return -ENOTCONN;
ee4bc9e7
SW
9891 break;
9892 case NL80211_IFTYPE_ADHOC:
7b0a0e3c 9893 if (!wdev->u.ibss.ssid_len)
1ff79dfa
JB
9894 return -ENOTCONN;
9895 break;
c6da674a 9896 case NL80211_IFTYPE_MESH_POINT:
7b0a0e3c 9897 if (!wdev->u.mesh.id_len)
1ff79dfa 9898 return -ENOTCONN;
ee4bc9e7
SW
9899 break;
9900 default:
16ef1fe2 9901 return -EOPNOTSUPP;
ee4bc9e7 9902 }
16ef1fe2
SW
9903
9904 memset(&params, 0, sizeof(params));
c177db2d 9905 params.beacon_csa.ftm_responder = -1;
16ef1fe2
SW
9906
9907 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
9908 !info->attrs[NL80211_ATTR_CH_SWITCH_COUNT])
9909 return -EINVAL;
9910
9911 /* only important for AP, IBSS and mesh create IEs internally */
d0a361a5 9912 if (need_new_beacon && !info->attrs[NL80211_ATTR_CSA_IES])
16ef1fe2
SW
9913 return -EINVAL;
9914
252e07ca
LC
9915 /* Even though the attribute is u32, the specification says
9916 * u8, so let's make sure we don't overflow.
9917 */
9918 cs_count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
9919 if (cs_count > 255)
9920 return -EINVAL;
9921
9922 params.count = cs_count;
16ef1fe2 9923
ee4bc9e7
SW
9924 if (!need_new_beacon)
9925 goto skip_beacons;
9926
81e54d08 9927 err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon_after);
16ef1fe2 9928 if (err)
dc1e3cb8 9929 goto free;
16ef1fe2 9930
a05829a7
JB
9931 csa_attrs = kcalloc(NL80211_ATTR_MAX + 1, sizeof(*csa_attrs),
9932 GFP_KERNEL);
dc1e3cb8
JC
9933 if (!csa_attrs) {
9934 err = -ENOMEM;
9935 goto free;
9936 }
a05829a7 9937
8cb08174
JB
9938 err = nla_parse_nested_deprecated(csa_attrs, NL80211_ATTR_MAX,
9939 info->attrs[NL80211_ATTR_CSA_IES],
9940 nl80211_policy, info->extack);
16ef1fe2 9941 if (err)
a05829a7 9942 goto free;
16ef1fe2 9943
81e54d08 9944 err = nl80211_parse_beacon(rdev, csa_attrs, &params.beacon_csa);
16ef1fe2 9945 if (err)
a05829a7 9946 goto free;
16ef1fe2 9947
a05829a7
JB
9948 if (!csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]) {
9949 err = -EINVAL;
9950 goto free;
9951 }
16ef1fe2 9952
00c207ed 9953 len = nla_len(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
a05829a7
JB
9954 if (!len || (len % sizeof(u16))) {
9955 err = -EINVAL;
9956 goto free;
9957 }
16ef1fe2 9958
9a774c78
AO
9959 params.n_counter_offsets_beacon = len / sizeof(u16);
9960 if (rdev->wiphy.max_num_csa_counters &&
9961 (params.n_counter_offsets_beacon >
a05829a7
JB
9962 rdev->wiphy.max_num_csa_counters)) {
9963 err = -EINVAL;
9964 goto free;
9965 }
16ef1fe2 9966
9a774c78 9967 params.counter_offsets_beacon =
00c207ed 9968 nla_data(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
9a774c78
AO
9969
9970 /* sanity checks - counters should fit and be the same */
9971 for (i = 0; i < params.n_counter_offsets_beacon; i++) {
9972 u16 offset = params.counter_offsets_beacon[i];
9973
a05829a7
JB
9974 if (offset >= params.beacon_csa.tail_len) {
9975 err = -EINVAL;
9976 goto free;
9977 }
9a774c78 9978
a05829a7
JB
9979 if (params.beacon_csa.tail[offset] != params.count) {
9980 err = -EINVAL;
9981 goto free;
9982 }
9a774c78
AO
9983 }
9984
00c207ed
JC
9985 if (csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]) {
9986 len = nla_len(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
a05829a7
JB
9987 if (!len || (len % sizeof(u16))) {
9988 err = -EINVAL;
9989 goto free;
9990 }
16ef1fe2 9991
9a774c78
AO
9992 params.n_counter_offsets_presp = len / sizeof(u16);
9993 if (rdev->wiphy.max_num_csa_counters &&
ad5987b4 9994 (params.n_counter_offsets_presp >
a05829a7
JB
9995 rdev->wiphy.max_num_csa_counters)) {
9996 err = -EINVAL;
9997 goto free;
9998 }
9a774c78
AO
9999
10000 params.counter_offsets_presp =
00c207ed 10001 nla_data(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
9a774c78
AO
10002
10003 /* sanity checks - counters should fit and be the same */
10004 for (i = 0; i < params.n_counter_offsets_presp; i++) {
10005 u16 offset = params.counter_offsets_presp[i];
10006
a05829a7
JB
10007 if (offset >= params.beacon_csa.probe_resp_len) {
10008 err = -EINVAL;
10009 goto free;
10010 }
9a774c78
AO
10011
10012 if (params.beacon_csa.probe_resp[offset] !=
a05829a7
JB
10013 params.count) {
10014 err = -EINVAL;
10015 goto free;
10016 }
9a774c78 10017 }
16ef1fe2
SW
10018 }
10019
ee4bc9e7 10020skip_beacons:
16ef1fe2
SW
10021 err = nl80211_parse_chandef(rdev, info, &params.chandef);
10022 if (err)
a05829a7 10023 goto free;
16ef1fe2 10024
923b352f 10025 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params.chandef,
a05829a7
JB
10026 wdev->iftype)) {
10027 err = -EINVAL;
10028 goto free;
10029 }
16ef1fe2 10030
2beb6dab
LC
10031 err = cfg80211_chandef_dfs_required(wdev->wiphy,
10032 &params.chandef,
10033 wdev->iftype);
10034 if (err < 0)
a05829a7 10035 goto free;
2beb6dab 10036
8d9de16f 10037 if (err > 0) {
2beb6dab 10038 params.radar_required = true;
8d9de16f
BB
10039 if (need_handle_dfs_flag &&
10040 !nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS])) {
a05829a7
JB
10041 err = -EINVAL;
10042 goto free;
8d9de16f
BB
10043 }
10044 }
16ef1fe2 10045
16ef1fe2
SW
10046 if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
10047 params.block_tx = true;
10048
c56589ed
SW
10049 wdev_lock(wdev);
10050 err = rdev_channel_switch(rdev, dev, &params);
10051 wdev_unlock(wdev);
10052
a05829a7 10053free:
dc1e3cb8
JC
10054 kfree(params.beacon_after.mbssid_ies);
10055 kfree(params.beacon_csa.mbssid_ies);
a05829a7 10056 kfree(csa_attrs);
c56589ed 10057 return err;
16ef1fe2
SW
10058}
10059
9720bb3a
JB
10060static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
10061 u32 seq, int flags,
2a519311 10062 struct cfg80211_registered_device *rdev,
48ab905d
JB
10063 struct wireless_dev *wdev,
10064 struct cfg80211_internal_bss *intbss)
2a519311 10065{
48ab905d 10066 struct cfg80211_bss *res = &intbss->pub;
9caf0364 10067 const struct cfg80211_bss_ies *ies;
7b0a0e3c 10068 unsigned int link_id;
2a519311
JB
10069 void *hdr;
10070 struct nlattr *bss;
48ab905d
JB
10071
10072 ASSERT_WDEV_LOCK(wdev);
2a519311 10073
15e47304 10074 hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).portid, seq, flags,
2a519311
JB
10075 NL80211_CMD_NEW_SCAN_RESULTS);
10076 if (!hdr)
10077 return -1;
10078
0a833c29 10079 genl_dump_check_consistent(cb, hdr);
9720bb3a 10080
97990a06
JB
10081 if (nla_put_u32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation))
10082 goto nla_put_failure;
10083 if (wdev->netdev &&
9360ffd1
DM
10084 nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex))
10085 goto nla_put_failure;
2dad624e
ND
10086 if (nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
10087 NL80211_ATTR_PAD))
97990a06 10088 goto nla_put_failure;
2a519311 10089
ae0be8de 10090 bss = nla_nest_start_noflag(msg, NL80211_ATTR_BSS);
2a519311
JB
10091 if (!bss)
10092 goto nla_put_failure;
9360ffd1 10093 if ((!is_zero_ether_addr(res->bssid) &&
9caf0364 10094 nla_put(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid)))
9360ffd1 10095 goto nla_put_failure;
9caf0364
JB
10096
10097 rcu_read_lock();
0e227084
JB
10098 /* indicate whether we have probe response data or not */
10099 if (rcu_access_pointer(res->proberesp_ies) &&
10100 nla_put_flag(msg, NL80211_BSS_PRESP_DATA))
10101 goto fail_unlock_rcu;
10102
10103 /* this pointer prefers to be pointed to probe response data
10104 * but is always valid
10105 */
9caf0364 10106 ies = rcu_dereference(res->ies);
8cef2c9d 10107 if (ies) {
2dad624e
ND
10108 if (nla_put_u64_64bit(msg, NL80211_BSS_TSF, ies->tsf,
10109 NL80211_BSS_PAD))
8cef2c9d 10110 goto fail_unlock_rcu;
8cef2c9d
JB
10111 if (ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS,
10112 ies->len, ies->data))
10113 goto fail_unlock_rcu;
9caf0364 10114 }
0e227084
JB
10115
10116 /* and this pointer is always (unless driver didn't know) beacon data */
9caf0364 10117 ies = rcu_dereference(res->beacon_ies);
0e227084 10118 if (ies && ies->from_beacon) {
2dad624e
ND
10119 if (nla_put_u64_64bit(msg, NL80211_BSS_BEACON_TSF, ies->tsf,
10120 NL80211_BSS_PAD))
8cef2c9d
JB
10121 goto fail_unlock_rcu;
10122 if (ies->len && nla_put(msg, NL80211_BSS_BEACON_IES,
10123 ies->len, ies->data))
10124 goto fail_unlock_rcu;
9caf0364
JB
10125 }
10126 rcu_read_unlock();
10127
9360ffd1
DM
10128 if (res->beacon_interval &&
10129 nla_put_u16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval))
10130 goto nla_put_failure;
10131 if (nla_put_u16(msg, NL80211_BSS_CAPABILITY, res->capability) ||
10132 nla_put_u32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq) ||
942ba88b
TP
10133 nla_put_u32(msg, NL80211_BSS_FREQUENCY_OFFSET,
10134 res->channel->freq_offset) ||
dcd6eac1 10135 nla_put_u32(msg, NL80211_BSS_CHAN_WIDTH, res->scan_width) ||
9360ffd1
DM
10136 nla_put_u32(msg, NL80211_BSS_SEEN_MS_AGO,
10137 jiffies_to_msecs(jiffies - intbss->ts)))
10138 goto nla_put_failure;
2a519311 10139
1d76250b
AS
10140 if (intbss->parent_tsf &&
10141 (nla_put_u64_64bit(msg, NL80211_BSS_PARENT_TSF,
10142 intbss->parent_tsf, NL80211_BSS_PAD) ||
10143 nla_put(msg, NL80211_BSS_PARENT_BSSID, ETH_ALEN,
10144 intbss->parent_bssid)))
10145 goto nla_put_failure;
10146
6e19bc4b 10147 if (intbss->ts_boottime &&
2dad624e
ND
10148 nla_put_u64_64bit(msg, NL80211_BSS_LAST_SEEN_BOOTTIME,
10149 intbss->ts_boottime, NL80211_BSS_PAD))
6e19bc4b
DS
10150 goto nla_put_failure;
10151
983dafaa
SD
10152 if (!nl80211_put_signal(msg, intbss->pub.chains,
10153 intbss->pub.chain_signal,
10154 NL80211_BSS_CHAIN_SIGNAL))
10155 goto nla_put_failure;
10156
77965c97 10157 switch (rdev->wiphy.signal_type) {
2a519311 10158 case CFG80211_SIGNAL_TYPE_MBM:
9360ffd1
DM
10159 if (nla_put_u32(msg, NL80211_BSS_SIGNAL_MBM, res->signal))
10160 goto nla_put_failure;
2a519311
JB
10161 break;
10162 case CFG80211_SIGNAL_TYPE_UNSPEC:
9360ffd1
DM
10163 if (nla_put_u8(msg, NL80211_BSS_SIGNAL_UNSPEC, res->signal))
10164 goto nla_put_failure;
2a519311
JB
10165 break;
10166 default:
10167 break;
10168 }
10169
48ab905d 10170 switch (wdev->iftype) {
074ac8df 10171 case NL80211_IFTYPE_P2P_CLIENT:
48ab905d 10172 case NL80211_IFTYPE_STATION:
7b0a0e3c
JB
10173 for_each_valid_link(wdev, link_id) {
10174 if (intbss == wdev->links[link_id].client.current_bss &&
dd374f84
JB
10175 (nla_put_u32(msg, NL80211_BSS_STATUS,
10176 NL80211_BSS_STATUS_ASSOCIATED) ||
10177 (wdev->valid_links &&
3c512307
VJ
10178 nla_put_u8(msg, NL80211_BSS_MLO_LINK_ID,
10179 link_id))))
7b0a0e3c
JB
10180 goto nla_put_failure;
10181 }
48ab905d
JB
10182 break;
10183 case NL80211_IFTYPE_ADHOC:
7b0a0e3c 10184 if (intbss == wdev->u.ibss.current_bss &&
9360ffd1
DM
10185 nla_put_u32(msg, NL80211_BSS_STATUS,
10186 NL80211_BSS_STATUS_IBSS_JOINED))
10187 goto nla_put_failure;
48ab905d
JB
10188 break;
10189 default:
10190 break;
10191 }
10192
2a519311
JB
10193 nla_nest_end(msg, bss);
10194
053c095a
JB
10195 genlmsg_end(msg, hdr);
10196 return 0;
2a519311 10197
8cef2c9d
JB
10198 fail_unlock_rcu:
10199 rcu_read_unlock();
2a519311
JB
10200 nla_put_failure:
10201 genlmsg_cancel(msg, hdr);
10202 return -EMSGSIZE;
10203}
10204
97990a06 10205static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb)
2a519311 10206{
48ab905d 10207 struct cfg80211_registered_device *rdev;
2a519311 10208 struct cfg80211_internal_bss *scan;
48ab905d 10209 struct wireless_dev *wdev;
97990a06 10210 int start = cb->args[2], idx = 0;
2a519311
JB
10211 int err;
10212
ce6b6974 10213 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL);
a05829a7 10214 if (err)
67748893 10215 return err;
a05829a7
JB
10216 /* nl80211_prepare_wdev_dump acquired it in the successful case */
10217 __acquire(&rdev->wiphy.mtx);
2a519311 10218
48ab905d
JB
10219 wdev_lock(wdev);
10220 spin_lock_bh(&rdev->bss_lock);
d1e23c94
DK
10221
10222 /*
10223 * dump_scan will be called multiple times to break up the scan results
10224 * into multiple messages. It is unlikely that any more bss-es will be
10225 * expired after the first call, so only call only call this on the
10226 * first dump_scan invocation.
10227 */
10228 if (start == 0)
10229 cfg80211_bss_expire(rdev);
48ab905d 10230
9720bb3a
JB
10231 cb->seq = rdev->bss_generation;
10232
48ab905d 10233 list_for_each_entry(scan, &rdev->bss_list, list) {
2a519311
JB
10234 if (++idx <= start)
10235 continue;
9720bb3a 10236 if (nl80211_send_bss(skb, cb,
2a519311 10237 cb->nlh->nlmsg_seq, NLM_F_MULTI,
48ab905d 10238 rdev, wdev, scan) < 0) {
2a519311 10239 idx--;
67748893 10240 break;
2a519311
JB
10241 }
10242 }
10243
48ab905d
JB
10244 spin_unlock_bh(&rdev->bss_lock);
10245 wdev_unlock(wdev);
2a519311 10246
97990a06 10247 cb->args[2] = idx;
a05829a7 10248 wiphy_unlock(&rdev->wiphy);
2a519311 10249
67748893 10250 return skb->len;
2a519311
JB
10251}
10252
15e47304 10253static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq,
11f78ac3
JB
10254 int flags, struct net_device *dev,
10255 bool allow_radio_stats,
10256 struct survey_info *survey)
61fa713c
HS
10257{
10258 void *hdr;
10259 struct nlattr *infoattr;
10260
11f78ac3
JB
10261 /* skip radio stats if userspace didn't request them */
10262 if (!survey->channel && !allow_radio_stats)
10263 return 0;
10264
15e47304 10265 hdr = nl80211hdr_put(msg, portid, seq, flags,
61fa713c
HS
10266 NL80211_CMD_NEW_SURVEY_RESULTS);
10267 if (!hdr)
10268 return -ENOMEM;
10269
9360ffd1
DM
10270 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
10271 goto nla_put_failure;
61fa713c 10272
ae0be8de 10273 infoattr = nla_nest_start_noflag(msg, NL80211_ATTR_SURVEY_INFO);
61fa713c
HS
10274 if (!infoattr)
10275 goto nla_put_failure;
10276
11f78ac3
JB
10277 if (survey->channel &&
10278 nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY,
9360ffd1
DM
10279 survey->channel->center_freq))
10280 goto nla_put_failure;
58ef7c1b
TP
10281
10282 if (survey->channel && survey->channel->freq_offset &&
10283 nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY_OFFSET,
10284 survey->channel->freq_offset))
10285 goto nla_put_failure;
9360ffd1
DM
10286
10287 if ((survey->filled & SURVEY_INFO_NOISE_DBM) &&
10288 nla_put_u8(msg, NL80211_SURVEY_INFO_NOISE, survey->noise))
10289 goto nla_put_failure;
10290 if ((survey->filled & SURVEY_INFO_IN_USE) &&
10291 nla_put_flag(msg, NL80211_SURVEY_INFO_IN_USE))
10292 goto nla_put_failure;
4ed20beb 10293 if ((survey->filled & SURVEY_INFO_TIME) &&
2dad624e
ND
10294 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME,
10295 survey->time, NL80211_SURVEY_INFO_PAD))
9360ffd1 10296 goto nla_put_failure;
4ed20beb 10297 if ((survey->filled & SURVEY_INFO_TIME_BUSY) &&
2dad624e
ND
10298 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_BUSY,
10299 survey->time_busy, NL80211_SURVEY_INFO_PAD))
9360ffd1 10300 goto nla_put_failure;
4ed20beb 10301 if ((survey->filled & SURVEY_INFO_TIME_EXT_BUSY) &&
2dad624e
ND
10302 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_EXT_BUSY,
10303 survey->time_ext_busy, NL80211_SURVEY_INFO_PAD))
9360ffd1 10304 goto nla_put_failure;
4ed20beb 10305 if ((survey->filled & SURVEY_INFO_TIME_RX) &&
2dad624e
ND
10306 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_RX,
10307 survey->time_rx, NL80211_SURVEY_INFO_PAD))
9360ffd1 10308 goto nla_put_failure;
4ed20beb 10309 if ((survey->filled & SURVEY_INFO_TIME_TX) &&
2dad624e
ND
10310 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_TX,
10311 survey->time_tx, NL80211_SURVEY_INFO_PAD))
9360ffd1 10312 goto nla_put_failure;
052536ab 10313 if ((survey->filled & SURVEY_INFO_TIME_SCAN) &&
2dad624e
ND
10314 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_SCAN,
10315 survey->time_scan, NL80211_SURVEY_INFO_PAD))
052536ab 10316 goto nla_put_failure;
c8cd6e7f
FF
10317 if ((survey->filled & SURVEY_INFO_TIME_BSS_RX) &&
10318 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_BSS_RX,
10319 survey->time_bss_rx, NL80211_SURVEY_INFO_PAD))
10320 goto nla_put_failure;
61fa713c
HS
10321
10322 nla_nest_end(msg, infoattr);
10323
053c095a
JB
10324 genlmsg_end(msg, hdr);
10325 return 0;
61fa713c
HS
10326
10327 nla_put_failure:
10328 genlmsg_cancel(msg, hdr);
10329 return -EMSGSIZE;
10330}
10331
11f78ac3 10332static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
61fa713c 10333{
50508d94 10334 struct nlattr **attrbuf;
61fa713c 10335 struct survey_info survey;
1b8ec87a 10336 struct cfg80211_registered_device *rdev;
97990a06
JB
10337 struct wireless_dev *wdev;
10338 int survey_idx = cb->args[2];
61fa713c 10339 int res;
11f78ac3 10340 bool radio_stats;
61fa713c 10341
50508d94
JB
10342 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), GFP_KERNEL);
10343 if (!attrbuf)
10344 return -ENOMEM;
10345
ce6b6974 10346 res = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, attrbuf);
a05829a7
JB
10347 if (res) {
10348 kfree(attrbuf);
10349 return res;
10350 }
10351 /* nl80211_prepare_wdev_dump acquired it in the successful case */
10352 __acquire(&rdev->wiphy.mtx);
61fa713c 10353
11f78ac3 10354 /* prepare_wdev_dump parsed the attributes */
c90c39da 10355 radio_stats = attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS];
11f78ac3 10356
97990a06
JB
10357 if (!wdev->netdev) {
10358 res = -EINVAL;
10359 goto out_err;
10360 }
10361
1b8ec87a 10362 if (!rdev->ops->dump_survey) {
61fa713c
HS
10363 res = -EOPNOTSUPP;
10364 goto out_err;
10365 }
10366
10367 while (1) {
284b38b6 10368 wdev_lock(wdev);
1b8ec87a 10369 res = rdev_dump_survey(rdev, wdev->netdev, survey_idx, &survey);
284b38b6 10370 wdev_unlock(wdev);
61fa713c
HS
10371 if (res == -ENOENT)
10372 break;
10373 if (res)
10374 goto out_err;
10375
11f78ac3
JB
10376 /* don't send disabled channels, but do send non-channel data */
10377 if (survey.channel &&
10378 survey.channel->flags & IEEE80211_CHAN_DISABLED) {
180cdc79
LR
10379 survey_idx++;
10380 continue;
10381 }
10382
61fa713c 10383 if (nl80211_send_survey(skb,
15e47304 10384 NETLINK_CB(cb->skb).portid,
61fa713c 10385 cb->nlh->nlmsg_seq, NLM_F_MULTI,
11f78ac3 10386 wdev->netdev, radio_stats, &survey) < 0)
61fa713c
HS
10387 goto out;
10388 survey_idx++;
10389 }
10390
10391 out:
97990a06 10392 cb->args[2] = survey_idx;
61fa713c
HS
10393 res = skb->len;
10394 out_err:
50508d94 10395 kfree(attrbuf);
a05829a7 10396 wiphy_unlock(&rdev->wiphy);
61fa713c
HS
10397 return res;
10398}
10399
b23aa676
SO
10400static bool nl80211_valid_wpa_versions(u32 wpa_versions)
10401{
10402 return !(wpa_versions & ~(NL80211_WPA_VERSION_1 |
cc3e14c2
CHH
10403 NL80211_WPA_VERSION_2 |
10404 NL80211_WPA_VERSION_3));
b23aa676
SO
10405}
10406
636a5d36
JM
10407static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
10408{
4c476991
JB
10409 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10410 struct net_device *dev = info->user_ptr[1];
19957bb3 10411 struct ieee80211_channel *chan;
325839da
JB
10412 const u8 *bssid, *ssid;
10413 int err, ssid_len;
19957bb3 10414 enum nl80211_auth_type auth_type;
fffd0934 10415 struct key_parse key;
d5cdfacb 10416 bool local_state_change;
325839da 10417 struct cfg80211_auth_request req = {};
942ba88b 10418 u32 freq;
636a5d36 10419
f4a11bb0
JB
10420 if (!info->attrs[NL80211_ATTR_MAC])
10421 return -EINVAL;
10422
1778092e
JM
10423 if (!info->attrs[NL80211_ATTR_AUTH_TYPE])
10424 return -EINVAL;
10425
19957bb3
JB
10426 if (!info->attrs[NL80211_ATTR_SSID])
10427 return -EINVAL;
10428
10429 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
10430 return -EINVAL;
10431
fffd0934
JB
10432 err = nl80211_parse_key(info, &key);
10433 if (err)
10434 return err;
10435
10436 if (key.idx >= 0) {
e31b8213
JB
10437 if (key.type != -1 && key.type != NL80211_KEYTYPE_GROUP)
10438 return -EINVAL;
fffd0934
JB
10439 if (!key.p.key || !key.p.key_len)
10440 return -EINVAL;
10441 if ((key.p.cipher != WLAN_CIPHER_SUITE_WEP40 ||
10442 key.p.key_len != WLAN_KEY_LEN_WEP40) &&
10443 (key.p.cipher != WLAN_CIPHER_SUITE_WEP104 ||
10444 key.p.key_len != WLAN_KEY_LEN_WEP104))
10445 return -EINVAL;
b6b5555b 10446 if (key.idx > 3)
fffd0934
JB
10447 return -EINVAL;
10448 } else {
10449 key.p.key_len = 0;
10450 key.p.key = NULL;
10451 }
10452
afea0b7a
JB
10453 if (key.idx >= 0) {
10454 int i;
10455 bool ok = false;
7a087e74 10456
afea0b7a
JB
10457 for (i = 0; i < rdev->wiphy.n_cipher_suites; i++) {
10458 if (key.p.cipher == rdev->wiphy.cipher_suites[i]) {
10459 ok = true;
10460 break;
10461 }
10462 }
4c476991
JB
10463 if (!ok)
10464 return -EINVAL;
afea0b7a
JB
10465 }
10466
4c476991
JB
10467 if (!rdev->ops->auth)
10468 return -EOPNOTSUPP;
636a5d36 10469
074ac8df 10470 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
10471 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
10472 return -EOPNOTSUPP;
eec60b03 10473
19957bb3 10474 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
942ba88b
TP
10475 freq = MHZ_TO_KHZ(nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
10476 if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
10477 freq +=
10478 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
10479
10480 chan = nl80211_get_valid_chan(&rdev->wiphy, freq);
664834de 10481 if (!chan)
4c476991 10482 return -EINVAL;
636a5d36 10483
19957bb3
JB
10484 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
10485 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
636a5d36
JM
10486
10487 if (info->attrs[NL80211_ATTR_IE]) {
325839da
JB
10488 req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
10489 req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
10490 }
10491
19957bb3 10492 auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
e39e5b5e 10493 if (!nl80211_valid_auth_type(rdev, auth_type, NL80211_CMD_AUTHENTICATE))
4c476991 10494 return -EINVAL;
636a5d36 10495
63181060
JM
10496 if ((auth_type == NL80211_AUTHTYPE_SAE ||
10497 auth_type == NL80211_AUTHTYPE_FILS_SK ||
10498 auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
10499 auth_type == NL80211_AUTHTYPE_FILS_PK) &&
11b6b5a4 10500 !info->attrs[NL80211_ATTR_AUTH_DATA])
e39e5b5e
JM
10501 return -EINVAL;
10502
11b6b5a4 10503 if (info->attrs[NL80211_ATTR_AUTH_DATA]) {
63181060
JM
10504 if (auth_type != NL80211_AUTHTYPE_SAE &&
10505 auth_type != NL80211_AUTHTYPE_FILS_SK &&
10506 auth_type != NL80211_AUTHTYPE_FILS_SK_PFS &&
10507 auth_type != NL80211_AUTHTYPE_FILS_PK)
e39e5b5e 10508 return -EINVAL;
325839da
JB
10509 req.auth_data = nla_data(info->attrs[NL80211_ATTR_AUTH_DATA]);
10510 req.auth_data_len = nla_len(info->attrs[NL80211_ATTR_AUTH_DATA]);
e39e5b5e
JM
10511 }
10512
d5cdfacb
JM
10513 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
10514
95de817b
JB
10515 /*
10516 * Since we no longer track auth state, ignore
10517 * requests to only change local state.
10518 */
10519 if (local_state_change)
10520 return 0;
10521
325839da
JB
10522 req.auth_type = auth_type;
10523 req.key = key.p.key;
10524 req.key_len = key.p.key_len;
10525 req.key_idx = key.idx;
d648c230
JB
10526 req.link_id = nl80211_link_id_or_invalid(info->attrs);
10527 if (req.link_id >= 0) {
45aaf17c
JB
10528 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_MLO))
10529 return -EINVAL;
d648c230
JB
10530 if (!info->attrs[NL80211_ATTR_MLD_ADDR])
10531 return -EINVAL;
10532 req.ap_mld_addr = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
10533 }
325839da
JB
10534
10535 req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
10536 IEEE80211_BSS_TYPE_ESS,
10537 IEEE80211_PRIVACY_ANY);
10538 if (!req.bss)
10539 return -ENOENT;
10540
91bf9b26 10541 wdev_lock(dev->ieee80211_ptr);
325839da 10542 err = cfg80211_mlme_auth(rdev, dev, &req);
91bf9b26 10543 wdev_unlock(dev->ieee80211_ptr);
325839da
JB
10544
10545 cfg80211_put_bss(&rdev->wiphy, req.bss);
10546
91bf9b26 10547 return err;
636a5d36
JM
10548}
10549
64bf3d4b
DK
10550static int validate_pae_over_nl80211(struct cfg80211_registered_device *rdev,
10551 struct genl_info *info)
10552{
10553 if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
10554 GENL_SET_ERR_MSG(info, "SOCKET_OWNER not set");
10555 return -EINVAL;
10556 }
10557
10558 if (!rdev->ops->tx_control_port ||
10559 !wiphy_ext_feature_isset(&rdev->wiphy,
10560 NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211))
10561 return -EOPNOTSUPP;
10562
10563 return 0;
10564}
10565
c0692b8f
JB
10566static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
10567 struct genl_info *info,
3dc27d25
JB
10568 struct cfg80211_crypto_settings *settings,
10569 int cipher_limit)
b23aa676 10570{
c0b2bbd8
JB
10571 memset(settings, 0, sizeof(*settings));
10572
b23aa676
SO
10573 settings->control_port = info->attrs[NL80211_ATTR_CONTROL_PORT];
10574
c0692b8f
JB
10575 if (info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) {
10576 u16 proto;
7a087e74 10577
c0692b8f
JB
10578 proto = nla_get_u16(
10579 info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]);
10580 settings->control_port_ethertype = cpu_to_be16(proto);
10581 if (!(rdev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) &&
10582 proto != ETH_P_PAE)
10583 return -EINVAL;
10584 if (info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT])
10585 settings->control_port_no_encrypt = true;
10586 } else
10587 settings->control_port_ethertype = cpu_to_be16(ETH_P_PAE);
10588
64bf3d4b
DK
10589 if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) {
10590 int r = validate_pae_over_nl80211(rdev, info);
10591
10592 if (r < 0)
10593 return r;
10594
10595 settings->control_port_over_nl80211 = true;
7f3f96ce
MT
10596
10597 if (info->attrs[NL80211_ATTR_CONTROL_PORT_NO_PREAUTH])
10598 settings->control_port_no_preauth = true;
64bf3d4b
DK
10599 }
10600
b23aa676
SO
10601 if (info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]) {
10602 void *data;
10603 int len, i;
10604
10605 data = nla_data(info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]);
10606 len = nla_len(info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]);
10607 settings->n_ciphers_pairwise = len / sizeof(u32);
10608
10609 if (len % sizeof(u32))
10610 return -EINVAL;
10611
3dc27d25 10612 if (settings->n_ciphers_pairwise > cipher_limit)
b23aa676
SO
10613 return -EINVAL;
10614
10615 memcpy(settings->ciphers_pairwise, data, len);
10616
10617 for (i = 0; i < settings->n_ciphers_pairwise; i++)
38ba3c57
JM
10618 if (!cfg80211_supported_cipher_suite(
10619 &rdev->wiphy,
b23aa676
SO
10620 settings->ciphers_pairwise[i]))
10621 return -EINVAL;
10622 }
10623
10624 if (info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]) {
10625 settings->cipher_group =
10626 nla_get_u32(info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]);
38ba3c57
JM
10627 if (!cfg80211_supported_cipher_suite(&rdev->wiphy,
10628 settings->cipher_group))
b23aa676
SO
10629 return -EINVAL;
10630 }
10631
10632 if (info->attrs[NL80211_ATTR_WPA_VERSIONS]) {
10633 settings->wpa_versions =
10634 nla_get_u32(info->attrs[NL80211_ATTR_WPA_VERSIONS]);
10635 if (!nl80211_valid_wpa_versions(settings->wpa_versions))
10636 return -EINVAL;
10637 }
10638
10639 if (info->attrs[NL80211_ATTR_AKM_SUITES]) {
10640 void *data;
6d30240e 10641 int len;
b23aa676
SO
10642
10643 data = nla_data(info->attrs[NL80211_ATTR_AKM_SUITES]);
10644 len = nla_len(info->attrs[NL80211_ATTR_AKM_SUITES]);
10645 settings->n_akm_suites = len / sizeof(u32);
10646
10647 if (len % sizeof(u32))
10648 return -EINVAL;
10649
ecad3b0b 10650 if (settings->n_akm_suites > rdev->wiphy.max_num_akm_suites)
1b9ca027
JM
10651 return -EINVAL;
10652
b23aa676 10653 memcpy(settings->akm_suites, data, len);
b23aa676
SO
10654 }
10655
91b5ab62
EP
10656 if (info->attrs[NL80211_ATTR_PMK]) {
10657 if (nla_len(info->attrs[NL80211_ATTR_PMK]) != WLAN_PMK_LEN)
10658 return -EINVAL;
10659 if (!wiphy_ext_feature_isset(&rdev->wiphy,
f9662274
CHH
10660 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK) &&
10661 !wiphy_ext_feature_isset(&rdev->wiphy,
10662 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK))
91b5ab62
EP
10663 return -EINVAL;
10664 settings->psk = nla_data(info->attrs[NL80211_ATTR_PMK]);
10665 }
10666
26f7044e
CHH
10667 if (info->attrs[NL80211_ATTR_SAE_PASSWORD]) {
10668 if (!wiphy_ext_feature_isset(&rdev->wiphy,
2831a631
CHH
10669 NL80211_EXT_FEATURE_SAE_OFFLOAD) &&
10670 !wiphy_ext_feature_isset(&rdev->wiphy,
10671 NL80211_EXT_FEATURE_SAE_OFFLOAD_AP))
26f7044e
CHH
10672 return -EINVAL;
10673 settings->sae_pwd =
10674 nla_data(info->attrs[NL80211_ATTR_SAE_PASSWORD]);
10675 settings->sae_pwd_len =
10676 nla_len(info->attrs[NL80211_ATTR_SAE_PASSWORD]);
10677 }
10678
9f0ffa41
RD
10679 if (info->attrs[NL80211_ATTR_SAE_PWE])
10680 settings->sae_pwe =
10681 nla_get_u8(info->attrs[NL80211_ATTR_SAE_PWE]);
10682 else
10683 settings->sae_pwe = NL80211_SAE_PWE_UNSPECIFIED;
10684
b23aa676
SO
10685 return 0;
10686}
10687
9ecff10e
JB
10688static struct cfg80211_bss *nl80211_assoc_bss(struct cfg80211_registered_device *rdev,
10689 const u8 *ssid, int ssid_len,
10690 struct nlattr **attrs,
10691 const u8 **bssid_out)
10692{
10693 struct ieee80211_channel *chan;
10694 struct cfg80211_bss *bss;
10695 const u8 *bssid;
10696 u32 freq;
10697
10698 if (!attrs[NL80211_ATTR_MAC] || !attrs[NL80211_ATTR_WIPHY_FREQ])
10699 return ERR_PTR(-EINVAL);
10700
10701 bssid = nla_data(attrs[NL80211_ATTR_MAC]);
10702
10703 freq = MHZ_TO_KHZ(nla_get_u32(attrs[NL80211_ATTR_WIPHY_FREQ]));
10704 if (attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
10705 freq += nla_get_u32(attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
10706
10707 chan = nl80211_get_valid_chan(&rdev->wiphy, freq);
10708 if (!chan)
10709 return ERR_PTR(-EINVAL);
10710
10711 bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid,
10712 ssid, ssid_len,
10713 IEEE80211_BSS_TYPE_ESS,
10714 IEEE80211_PRIVACY_ANY);
10715 if (!bss)
10716 return ERR_PTR(-ENOENT);
10717
10718 *bssid_out = bssid;
10719 return bss;
10720}
10721
636a5d36
JM
10722static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
10723{
4c476991
JB
10724 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10725 struct net_device *dev = info->user_ptr[1];
f62fab73 10726 struct cfg80211_assoc_request req = {};
d648c230 10727 struct nlattr **attrs = NULL;
f62fab73 10728 const u8 *bssid, *ssid;
d648c230 10729 unsigned int link_id;
0f759448 10730 int err, ssid_len;
636a5d36 10731
bad29297
AZ
10732 if (dev->ieee80211_ptr->conn_owner_nlportid &&
10733 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
10734 return -EPERM;
10735
9ecff10e 10736 if (!info->attrs[NL80211_ATTR_SSID])
f4a11bb0
JB
10737 return -EINVAL;
10738
4c476991
JB
10739 if (!rdev->ops->assoc)
10740 return -EOPNOTSUPP;
636a5d36 10741
074ac8df 10742 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
10743 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
10744 return -EOPNOTSUPP;
eec60b03 10745
19957bb3
JB
10746 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
10747 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
636a5d36
JM
10748
10749 if (info->attrs[NL80211_ATTR_IE]) {
f62fab73
JB
10750 req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
10751 req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
df35f316
JB
10752
10753 if (cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
10754 req.ie, req.ie_len)) {
10755 GENL_SET_ERR_MSG(info,
10756 "non-inheritance makes no sense");
10757 return -EINVAL;
10758 }
636a5d36
JM
10759 }
10760
dc6382ce 10761 if (info->attrs[NL80211_ATTR_USE_MFP]) {
4f5dadce 10762 enum nl80211_mfp mfp =
dc6382ce 10763 nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
4f5dadce 10764 if (mfp == NL80211_MFP_REQUIRED)
f62fab73 10765 req.use_mfp = true;
4c476991
JB
10766 else if (mfp != NL80211_MFP_NO)
10767 return -EINVAL;
dc6382ce
JM
10768 }
10769
3e5d7649 10770 if (info->attrs[NL80211_ATTR_PREV_BSSID])
f62fab73 10771 req.prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
3e5d7649 10772
7e7c8926 10773 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
f62fab73 10774 req.flags |= ASSOC_REQ_DISABLE_HT;
7e7c8926
BG
10775
10776 if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
f62fab73
JB
10777 memcpy(&req.ht_capa_mask,
10778 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
10779 sizeof(req.ht_capa_mask));
7e7c8926
BG
10780
10781 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
f62fab73 10782 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
7e7c8926 10783 return -EINVAL;
f62fab73
JB
10784 memcpy(&req.ht_capa,
10785 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
10786 sizeof(req.ht_capa));
7e7c8926
BG
10787 }
10788
ee2aca34 10789 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT]))
f62fab73 10790 req.flags |= ASSOC_REQ_DISABLE_VHT;
ee2aca34 10791
b6db0f89
BG
10792 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HE]))
10793 req.flags |= ASSOC_REQ_DISABLE_HE;
10794
36f84235
MS
10795 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_EHT]))
10796 req.flags |= ASSOC_REQ_DISABLE_EHT;
10797
ee2aca34 10798 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
f62fab73
JB
10799 memcpy(&req.vht_capa_mask,
10800 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
10801 sizeof(req.vht_capa_mask));
ee2aca34
JB
10802
10803 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) {
f62fab73 10804 if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
ee2aca34 10805 return -EINVAL;
f62fab73
JB
10806 memcpy(&req.vht_capa,
10807 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]),
10808 sizeof(req.vht_capa));
ee2aca34
JB
10809 }
10810
bab5ab7d 10811 if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
0c9ca11b
BL
10812 if (!((rdev->wiphy.features &
10813 NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) &&
10814 (rdev->wiphy.features & NL80211_FEATURE_QUIET)) &&
10815 !wiphy_ext_feature_isset(&rdev->wiphy,
10816 NL80211_EXT_FEATURE_RRM))
bab5ab7d
AK
10817 return -EINVAL;
10818 req.flags |= ASSOC_REQ_USE_RRM;
10819 }
10820
348bd456
JM
10821 if (info->attrs[NL80211_ATTR_FILS_KEK]) {
10822 req.fils_kek = nla_data(info->attrs[NL80211_ATTR_FILS_KEK]);
10823 req.fils_kek_len = nla_len(info->attrs[NL80211_ATTR_FILS_KEK]);
10824 if (!info->attrs[NL80211_ATTR_FILS_NONCES])
10825 return -EINVAL;
10826 req.fils_nonces =
10827 nla_data(info->attrs[NL80211_ATTR_FILS_NONCES]);
10828 }
10829
d2b7588a
TP
10830 if (info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK]) {
10831 if (!info->attrs[NL80211_ATTR_S1G_CAPABILITY])
10832 return -EINVAL;
10833 memcpy(&req.s1g_capa_mask,
10834 nla_data(info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK]),
10835 sizeof(req.s1g_capa_mask));
10836 }
10837
10838 if (info->attrs[NL80211_ATTR_S1G_CAPABILITY]) {
10839 if (!info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK])
10840 return -EINVAL;
10841 memcpy(&req.s1g_capa,
10842 nla_data(info->attrs[NL80211_ATTR_S1G_CAPABILITY]),
10843 sizeof(req.s1g_capa));
10844 }
10845
d648c230
JB
10846 req.link_id = nl80211_link_id_or_invalid(info->attrs);
10847
10848 if (info->attrs[NL80211_ATTR_MLO_LINKS]) {
10849 unsigned int attrsize = NUM_NL80211_ATTR * sizeof(*attrs);
10850 struct nlattr *link;
10851 int rem = 0;
10852
10853 if (req.link_id < 0)
10854 return -EINVAL;
10855
10856 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_MLO))
10857 return -EINVAL;
10858
10859 if (info->attrs[NL80211_ATTR_MAC] ||
10860 info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
10861 !info->attrs[NL80211_ATTR_MLD_ADDR])
10862 return -EINVAL;
10863
10864 req.ap_mld_addr = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
10865
10866 attrs = kzalloc(attrsize, GFP_KERNEL);
10867 if (!attrs)
10868 return -ENOMEM;
10869
10870 nla_for_each_nested(link,
10871 info->attrs[NL80211_ATTR_MLO_LINKS],
10872 rem) {
10873 memset(attrs, 0, attrsize);
10874
10875 nla_parse_nested(attrs, NL80211_ATTR_MAX,
10876 link, NULL, NULL);
10877
10878 if (!attrs[NL80211_ATTR_MLO_LINK_ID]) {
10879 err = -EINVAL;
10880 goto free;
10881 }
10882
10883 link_id = nla_get_u8(attrs[NL80211_ATTR_MLO_LINK_ID]);
10884 /* cannot use the same link ID again */
10885 if (req.links[link_id].bss) {
10886 err = -EINVAL;
10887 goto free;
10888 }
10889 req.links[link_id].bss =
10890 nl80211_assoc_bss(rdev, ssid, ssid_len, attrs,
10891 &bssid);
10892 if (IS_ERR(req.links[link_id].bss)) {
10893 err = PTR_ERR(req.links[link_id].bss);
9b6bf4d6 10894 req.links[link_id].bss = NULL;
d648c230
JB
10895 goto free;
10896 }
10897
10898 if (attrs[NL80211_ATTR_IE]) {
10899 req.links[link_id].elems =
10900 nla_data(attrs[NL80211_ATTR_IE]);
10901 req.links[link_id].elems_len =
10902 nla_len(attrs[NL80211_ATTR_IE]);
df35f316
JB
10903
10904 if (cfg80211_find_elem(WLAN_EID_FRAGMENT,
10905 req.links[link_id].elems,
10906 req.links[link_id].elems_len)) {
10907 GENL_SET_ERR_MSG(info,
10908 "cannot deal with fragmentation");
10909 err = -EINVAL;
10910 goto free;
10911 }
10912
10913 if (cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
10914 req.links[link_id].elems,
10915 req.links[link_id].elems_len)) {
10916 GENL_SET_ERR_MSG(info,
10917 "cannot deal with non-inheritance");
10918 err = -EINVAL;
10919 goto free;
10920 }
d648c230
JB
10921 }
10922 }
10923
10924 if (!req.links[req.link_id].bss) {
10925 err = -EINVAL;
10926 goto free;
10927 }
10928
34d76a14
JB
10929 if (req.links[req.link_id].elems_len) {
10930 GENL_SET_ERR_MSG(info,
10931 "cannot have per-link elems on assoc link");
10932 err = -EINVAL;
10933 goto free;
10934 }
10935
d648c230
JB
10936 kfree(attrs);
10937 attrs = NULL;
10938 } else {
10939 if (req.link_id >= 0)
10940 return -EINVAL;
10941
10942 req.bss = nl80211_assoc_bss(rdev, ssid, ssid_len, info->attrs,
10943 &bssid);
10944 if (IS_ERR(req.bss))
10945 return PTR_ERR(req.bss);
10946 }
0f759448 10947
f62fab73 10948 err = nl80211_crypto_settings(rdev, info, &req.crypto, 1);
91bf9b26
JB
10949 if (!err) {
10950 wdev_lock(dev->ieee80211_ptr);
bd2522b1 10951
0f759448 10952 err = cfg80211_mlme_assoc(rdev, dev, &req);
bd2522b1
AZ
10953
10954 if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
10955 dev->ieee80211_ptr->conn_owner_nlportid =
10956 info->snd_portid;
10957 memcpy(dev->ieee80211_ptr->disconnect_bssid,
10958 bssid, ETH_ALEN);
10959 }
10960
91bf9b26
JB
10961 wdev_unlock(dev->ieee80211_ptr);
10962 }
636a5d36 10963
d648c230
JB
10964free:
10965 for (link_id = 0; link_id < ARRAY_SIZE(req.links); link_id++)
10966 cfg80211_put_bss(&rdev->wiphy, req.links[link_id].bss);
0f759448 10967 cfg80211_put_bss(&rdev->wiphy, req.bss);
d648c230 10968 kfree(attrs);
0f759448 10969
636a5d36
JM
10970 return err;
10971}
10972
10973static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
10974{
4c476991
JB
10975 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10976 struct net_device *dev = info->user_ptr[1];
19957bb3 10977 const u8 *ie = NULL, *bssid;
91bf9b26 10978 int ie_len = 0, err;
19957bb3 10979 u16 reason_code;
d5cdfacb 10980 bool local_state_change;
636a5d36 10981
bad29297
AZ
10982 if (dev->ieee80211_ptr->conn_owner_nlportid &&
10983 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
10984 return -EPERM;
10985
f4a11bb0
JB
10986 if (!info->attrs[NL80211_ATTR_MAC])
10987 return -EINVAL;
10988
10989 if (!info->attrs[NL80211_ATTR_REASON_CODE])
10990 return -EINVAL;
10991
4c476991
JB
10992 if (!rdev->ops->deauth)
10993 return -EOPNOTSUPP;
636a5d36 10994
074ac8df 10995 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
10996 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
10997 return -EOPNOTSUPP;
eec60b03 10998
19957bb3 10999 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
636a5d36 11000
19957bb3
JB
11001 reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
11002 if (reason_code == 0) {
f4a11bb0 11003 /* Reason Code 0 is reserved */
4c476991 11004 return -EINVAL;
255e737e 11005 }
636a5d36
JM
11006
11007 if (info->attrs[NL80211_ATTR_IE]) {
19957bb3
JB
11008 ie = nla_data(info->attrs[NL80211_ATTR_IE]);
11009 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
11010 }
11011
d5cdfacb
JM
11012 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
11013
91bf9b26
JB
11014 wdev_lock(dev->ieee80211_ptr);
11015 err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code,
11016 local_state_change);
11017 wdev_unlock(dev->ieee80211_ptr);
11018 return err;
636a5d36
JM
11019}
11020
11021static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
11022{
4c476991
JB
11023 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11024 struct net_device *dev = info->user_ptr[1];
19957bb3 11025 const u8 *ie = NULL, *bssid;
91bf9b26 11026 int ie_len = 0, err;
19957bb3 11027 u16 reason_code;
d5cdfacb 11028 bool local_state_change;
636a5d36 11029
bad29297
AZ
11030 if (dev->ieee80211_ptr->conn_owner_nlportid &&
11031 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
11032 return -EPERM;
11033
f4a11bb0
JB
11034 if (!info->attrs[NL80211_ATTR_MAC])
11035 return -EINVAL;
11036
11037 if (!info->attrs[NL80211_ATTR_REASON_CODE])
11038 return -EINVAL;
11039
4c476991
JB
11040 if (!rdev->ops->disassoc)
11041 return -EOPNOTSUPP;
636a5d36 11042
074ac8df 11043 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
11044 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
11045 return -EOPNOTSUPP;
eec60b03 11046
19957bb3 11047 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
636a5d36 11048
19957bb3
JB
11049 reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
11050 if (reason_code == 0) {
f4a11bb0 11051 /* Reason Code 0 is reserved */
4c476991 11052 return -EINVAL;
255e737e 11053 }
636a5d36
JM
11054
11055 if (info->attrs[NL80211_ATTR_IE]) {
19957bb3
JB
11056 ie = nla_data(info->attrs[NL80211_ATTR_IE]);
11057 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
11058 }
11059
d5cdfacb
JM
11060 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
11061
91bf9b26
JB
11062 wdev_lock(dev->ieee80211_ptr);
11063 err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code,
11064 local_state_change);
11065 wdev_unlock(dev->ieee80211_ptr);
11066 return err;
636a5d36
JM
11067}
11068
dd5b4cc7
FF
11069static bool
11070nl80211_parse_mcast_rate(struct cfg80211_registered_device *rdev,
57fbcce3 11071 int mcast_rate[NUM_NL80211_BANDS],
dd5b4cc7
FF
11072 int rateval)
11073{
11074 struct wiphy *wiphy = &rdev->wiphy;
11075 bool found = false;
11076 int band, i;
11077
57fbcce3 11078 for (band = 0; band < NUM_NL80211_BANDS; band++) {
dd5b4cc7
FF
11079 struct ieee80211_supported_band *sband;
11080
11081 sband = wiphy->bands[band];
11082 if (!sband)
11083 continue;
11084
11085 for (i = 0; i < sband->n_bitrates; i++) {
11086 if (sband->bitrates[i].bitrate == rateval) {
11087 mcast_rate[band] = i + 1;
11088 found = true;
11089 break;
11090 }
11091 }
11092 }
11093
11094 return found;
11095}
11096
04a773ad
JB
11097static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
11098{
4c476991
JB
11099 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11100 struct net_device *dev = info->user_ptr[1];
04a773ad
JB
11101 struct cfg80211_ibss_params ibss;
11102 struct wiphy *wiphy;
fffd0934 11103 struct cfg80211_cached_keys *connkeys = NULL;
04a773ad
JB
11104 int err;
11105
8e30bc55
JB
11106 memset(&ibss, 0, sizeof(ibss));
11107
683b6d3b 11108 if (!info->attrs[NL80211_ATTR_SSID] ||
04a773ad
JB
11109 !nla_len(info->attrs[NL80211_ATTR_SSID]))
11110 return -EINVAL;
11111
8e30bc55
JB
11112 ibss.beacon_interval = 100;
11113
12d20fc9 11114 if (info->attrs[NL80211_ATTR_BEACON_INTERVAL])
8e30bc55
JB
11115 ibss.beacon_interval =
11116 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
12d20fc9 11117
0c317a02
PK
11118 err = cfg80211_validate_beacon_int(rdev, NL80211_IFTYPE_ADHOC,
11119 ibss.beacon_interval);
12d20fc9
PK
11120 if (err)
11121 return err;
8e30bc55 11122
4c476991
JB
11123 if (!rdev->ops->join_ibss)
11124 return -EOPNOTSUPP;
04a773ad 11125
4c476991
JB
11126 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
11127 return -EOPNOTSUPP;
04a773ad 11128
79c97e97 11129 wiphy = &rdev->wiphy;
04a773ad 11130
39193498 11131 if (info->attrs[NL80211_ATTR_MAC]) {
04a773ad 11132 ibss.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
39193498
JB
11133
11134 if (!is_valid_ether_addr(ibss.bssid))
11135 return -EINVAL;
11136 }
04a773ad
JB
11137 ibss.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
11138 ibss.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
11139
11140 if (info->attrs[NL80211_ATTR_IE]) {
11141 ibss.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
11142 ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
11143 }
11144
683b6d3b
JB
11145 err = nl80211_parse_chandef(rdev, info, &ibss.chandef);
11146 if (err)
11147 return err;
04a773ad 11148
174e0cd2
IP
11149 if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef,
11150 NL80211_IFTYPE_ADHOC))
54858ee5
AS
11151 return -EINVAL;
11152
2f301ab2 11153 switch (ibss.chandef.width) {
bf372645
SW
11154 case NL80211_CHAN_WIDTH_5:
11155 case NL80211_CHAN_WIDTH_10:
2f301ab2
SW
11156 case NL80211_CHAN_WIDTH_20_NOHT:
11157 break;
11158 case NL80211_CHAN_WIDTH_20:
11159 case NL80211_CHAN_WIDTH_40:
ffc11991
JD
11160 if (!(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS))
11161 return -EINVAL;
11162 break;
11163 case NL80211_CHAN_WIDTH_80:
11164 case NL80211_CHAN_WIDTH_80P80:
11165 case NL80211_CHAN_WIDTH_160:
11166 if (!(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS))
11167 return -EINVAL;
11168 if (!wiphy_ext_feature_isset(&rdev->wiphy,
11169 NL80211_EXT_FEATURE_VHT_IBSS))
11170 return -EINVAL;
11171 break;
3743bec6
JD
11172 case NL80211_CHAN_WIDTH_320:
11173 return -EINVAL;
2f301ab2 11174 default:
c04d6150 11175 return -EINVAL;
2f301ab2 11176 }
db9c64cf 11177
04a773ad 11178 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
fffd0934
JB
11179 ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
11180
fbd2c8dc
TP
11181 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
11182 u8 *rates =
11183 nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
11184 int n_rates =
11185 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
11186 struct ieee80211_supported_band *sband =
683b6d3b 11187 wiphy->bands[ibss.chandef.chan->band];
fbd2c8dc 11188
34850ab2
JB
11189 err = ieee80211_get_ratemask(sband, rates, n_rates,
11190 &ibss.basic_rates);
11191 if (err)
11192 return err;
fbd2c8dc 11193 }
dd5b4cc7 11194
803768f5
SW
11195 if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
11196 memcpy(&ibss.ht_capa_mask,
11197 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
11198 sizeof(ibss.ht_capa_mask));
11199
11200 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
11201 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
11202 return -EINVAL;
11203 memcpy(&ibss.ht_capa,
11204 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
11205 sizeof(ibss.ht_capa));
11206 }
11207
dd5b4cc7
FF
11208 if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
11209 !nl80211_parse_mcast_rate(rdev, ibss.mcast_rate,
11210 nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE])))
11211 return -EINVAL;
fbd2c8dc 11212
4c476991 11213 if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
de7044ee
SM
11214 bool no_ht = false;
11215
768075eb 11216 connkeys = nl80211_parse_connkeys(rdev, info, &no_ht);
4c476991
JB
11217 if (IS_ERR(connkeys))
11218 return PTR_ERR(connkeys);
de7044ee 11219
3d9d1d66
JB
11220 if ((ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) &&
11221 no_ht) {
453431a5 11222 kfree_sensitive(connkeys);
de7044ee
SM
11223 return -EINVAL;
11224 }
4c476991 11225 }
04a773ad 11226
267335d6
AQ
11227 ibss.control_port =
11228 nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT]);
11229
c3bfe1f6
DK
11230 if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) {
11231 int r = validate_pae_over_nl80211(rdev, info);
11232
d350a0f4 11233 if (r < 0) {
453431a5 11234 kfree_sensitive(connkeys);
c3bfe1f6 11235 return r;
d350a0f4 11236 }
c3bfe1f6
DK
11237
11238 ibss.control_port_over_nl80211 = true;
11239 }
11240
5336fa88
SW
11241 ibss.userspace_handles_dfs =
11242 nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]);
11243
f8d16d3e
DK
11244 wdev_lock(dev->ieee80211_ptr);
11245 err = __cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
fffd0934 11246 if (err)
453431a5 11247 kfree_sensitive(connkeys);
f8d16d3e
DK
11248 else if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
11249 dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
11250 wdev_unlock(dev->ieee80211_ptr);
11251
04a773ad
JB
11252 return err;
11253}
11254
11255static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info)
11256{
4c476991
JB
11257 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11258 struct net_device *dev = info->user_ptr[1];
04a773ad 11259
4c476991
JB
11260 if (!rdev->ops->leave_ibss)
11261 return -EOPNOTSUPP;
04a773ad 11262
4c476991
JB
11263 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
11264 return -EOPNOTSUPP;
04a773ad 11265
4c476991 11266 return cfg80211_leave_ibss(rdev, dev, false);
04a773ad
JB
11267}
11268
f4e583c8
AQ
11269static int nl80211_set_mcast_rate(struct sk_buff *skb, struct genl_info *info)
11270{
11271 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11272 struct net_device *dev = info->user_ptr[1];
57fbcce3 11273 int mcast_rate[NUM_NL80211_BANDS];
f4e583c8
AQ
11274 u32 nla_rate;
11275 int err;
11276
11277 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
876dc930
BVB
11278 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
11279 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_OCB)
f4e583c8
AQ
11280 return -EOPNOTSUPP;
11281
11282 if (!rdev->ops->set_mcast_rate)
11283 return -EOPNOTSUPP;
11284
11285 memset(mcast_rate, 0, sizeof(mcast_rate));
11286
11287 if (!info->attrs[NL80211_ATTR_MCAST_RATE])
11288 return -EINVAL;
11289
11290 nla_rate = nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE]);
11291 if (!nl80211_parse_mcast_rate(rdev, mcast_rate, nla_rate))
11292 return -EINVAL;
11293
a1056b1b 11294 err = rdev_set_mcast_rate(rdev, dev, mcast_rate);
f4e583c8
AQ
11295
11296 return err;
11297}
11298
ad7e718c
JB
11299static struct sk_buff *
11300__cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev,
6c09e791
AK
11301 struct wireless_dev *wdev, int approxlen,
11302 u32 portid, u32 seq, enum nl80211_commands cmd,
567ffc35
JB
11303 enum nl80211_attrs attr,
11304 const struct nl80211_vendor_cmd_info *info,
11305 gfp_t gfp)
ad7e718c
JB
11306{
11307 struct sk_buff *skb;
11308 void *hdr;
11309 struct nlattr *data;
11310
11311 skb = nlmsg_new(approxlen + 100, gfp);
11312 if (!skb)
11313 return NULL;
11314
11315 hdr = nl80211hdr_put(skb, portid, seq, 0, cmd);
11316 if (!hdr) {
11317 kfree_skb(skb);
11318 return NULL;
11319 }
11320
11321 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
11322 goto nla_put_failure;
567ffc35
JB
11323
11324 if (info) {
11325 if (nla_put_u32(skb, NL80211_ATTR_VENDOR_ID,
11326 info->vendor_id))
11327 goto nla_put_failure;
11328 if (nla_put_u32(skb, NL80211_ATTR_VENDOR_SUBCMD,
11329 info->subcmd))
11330 goto nla_put_failure;
11331 }
11332
6c09e791 11333 if (wdev) {
2dad624e
ND
11334 if (nla_put_u64_64bit(skb, NL80211_ATTR_WDEV,
11335 wdev_id(wdev), NL80211_ATTR_PAD))
6c09e791
AK
11336 goto nla_put_failure;
11337 if (wdev->netdev &&
11338 nla_put_u32(skb, NL80211_ATTR_IFINDEX,
11339 wdev->netdev->ifindex))
11340 goto nla_put_failure;
11341 }
11342
ae0be8de 11343 data = nla_nest_start_noflag(skb, attr);
76e1fb4b
JB
11344 if (!data)
11345 goto nla_put_failure;
ad7e718c
JB
11346
11347 ((void **)skb->cb)[0] = rdev;
11348 ((void **)skb->cb)[1] = hdr;
11349 ((void **)skb->cb)[2] = data;
11350
11351 return skb;
11352
11353 nla_put_failure:
11354 kfree_skb(skb);
11355 return NULL;
11356}
f4e583c8 11357
e03ad6ea 11358struct sk_buff *__cfg80211_alloc_event_skb(struct wiphy *wiphy,
6c09e791 11359 struct wireless_dev *wdev,
e03ad6ea
JB
11360 enum nl80211_commands cmd,
11361 enum nl80211_attrs attr,
55c1fdf0 11362 unsigned int portid,
e03ad6ea
JB
11363 int vendor_event_idx,
11364 int approxlen, gfp_t gfp)
11365{
f26cbf40 11366 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
e03ad6ea
JB
11367 const struct nl80211_vendor_cmd_info *info;
11368
11369 switch (cmd) {
11370 case NL80211_CMD_TESTMODE:
11371 if (WARN_ON(vendor_event_idx != -1))
11372 return NULL;
11373 info = NULL;
11374 break;
11375 case NL80211_CMD_VENDOR:
11376 if (WARN_ON(vendor_event_idx < 0 ||
11377 vendor_event_idx >= wiphy->n_vendor_events))
11378 return NULL;
11379 info = &wiphy->vendor_events[vendor_event_idx];
11380 break;
11381 default:
11382 WARN_ON(1);
11383 return NULL;
11384 }
11385
55c1fdf0 11386 return __cfg80211_alloc_vendor_skb(rdev, wdev, approxlen, portid, 0,
e03ad6ea
JB
11387 cmd, attr, info, gfp);
11388}
11389EXPORT_SYMBOL(__cfg80211_alloc_event_skb);
11390
11391void __cfg80211_send_event_skb(struct sk_buff *skb, gfp_t gfp)
11392{
11393 struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
11394 void *hdr = ((void **)skb->cb)[1];
55c1fdf0 11395 struct nlmsghdr *nlhdr = nlmsg_hdr(skb);
e03ad6ea
JB
11396 struct nlattr *data = ((void **)skb->cb)[2];
11397 enum nl80211_multicast_groups mcgrp = NL80211_MCGRP_TESTMODE;
11398
bd8c78e7
JB
11399 /* clear CB data for netlink core to own from now on */
11400 memset(skb->cb, 0, sizeof(skb->cb));
11401
e03ad6ea
JB
11402 nla_nest_end(skb, data);
11403 genlmsg_end(skb, hdr);
11404
55c1fdf0
JB
11405 if (nlhdr->nlmsg_pid) {
11406 genlmsg_unicast(wiphy_net(&rdev->wiphy), skb,
11407 nlhdr->nlmsg_pid);
11408 } else {
11409 if (data->nla_type == NL80211_ATTR_VENDOR_DATA)
11410 mcgrp = NL80211_MCGRP_VENDOR;
e03ad6ea 11411
55c1fdf0
JB
11412 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
11413 skb, 0, mcgrp, gfp);
11414 }
e03ad6ea
JB
11415}
11416EXPORT_SYMBOL(__cfg80211_send_event_skb);
11417
aff89a9b 11418#ifdef CONFIG_NL80211_TESTMODE
aff89a9b
JB
11419static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
11420{
4c476991 11421 struct cfg80211_registered_device *rdev = info->user_ptr[0];
a05829a7 11422 struct wireless_dev *wdev;
aff89a9b
JB
11423 int err;
11424
a05829a7
JB
11425 lockdep_assert_held(&rdev->wiphy.mtx);
11426
11427 wdev = __cfg80211_wdev_from_attrs(rdev, genl_info_net(info),
11428 info->attrs);
11429
fc73f11f
DS
11430 if (!rdev->ops->testmode_cmd)
11431 return -EOPNOTSUPP;
11432
11433 if (IS_ERR(wdev)) {
11434 err = PTR_ERR(wdev);
11435 if (err != -EINVAL)
11436 return err;
11437 wdev = NULL;
11438 } else if (wdev->wiphy != &rdev->wiphy) {
11439 return -EINVAL;
11440 }
11441
aff89a9b
JB
11442 if (!info->attrs[NL80211_ATTR_TESTDATA])
11443 return -EINVAL;
11444
ad7e718c 11445 rdev->cur_cmd_info = info;
fc73f11f 11446 err = rdev_testmode_cmd(rdev, wdev,
aff89a9b
JB
11447 nla_data(info->attrs[NL80211_ATTR_TESTDATA]),
11448 nla_len(info->attrs[NL80211_ATTR_TESTDATA]));
ad7e718c 11449 rdev->cur_cmd_info = NULL;
aff89a9b 11450
aff89a9b
JB
11451 return err;
11452}
11453
71063f0e
WYG
11454static int nl80211_testmode_dump(struct sk_buff *skb,
11455 struct netlink_callback *cb)
11456{
00918d33 11457 struct cfg80211_registered_device *rdev;
50508d94 11458 struct nlattr **attrbuf = NULL;
71063f0e
WYG
11459 int err;
11460 long phy_idx;
11461 void *data = NULL;
11462 int data_len = 0;
11463
5fe231e8
JB
11464 rtnl_lock();
11465
71063f0e
WYG
11466 if (cb->args[0]) {
11467 /*
11468 * 0 is a valid index, but not valid for args[0],
11469 * so we need to offset by 1.
11470 */
11471 phy_idx = cb->args[0] - 1;
a4956dca
LC
11472
11473 rdev = cfg80211_rdev_by_wiphy_idx(phy_idx);
11474 if (!rdev) {
11475 err = -ENOENT;
11476 goto out_err;
11477 }
71063f0e 11478 } else {
50508d94
JB
11479 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf),
11480 GFP_KERNEL);
11481 if (!attrbuf) {
11482 err = -ENOMEM;
11483 goto out_err;
11484 }
c90c39da 11485
8cb08174
JB
11486 err = nlmsg_parse_deprecated(cb->nlh,
11487 GENL_HDRLEN + nl80211_fam.hdrsize,
11488 attrbuf, nl80211_fam.maxattr,
11489 nl80211_policy, NULL);
71063f0e 11490 if (err)
5fe231e8 11491 goto out_err;
00918d33 11492
c90c39da 11493 rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
2bd7e35d 11494 if (IS_ERR(rdev)) {
5fe231e8
JB
11495 err = PTR_ERR(rdev);
11496 goto out_err;
00918d33 11497 }
2bd7e35d 11498 phy_idx = rdev->wiphy_idx;
2bd7e35d 11499
c90c39da
JB
11500 if (attrbuf[NL80211_ATTR_TESTDATA])
11501 cb->args[1] = (long)attrbuf[NL80211_ATTR_TESTDATA];
71063f0e
WYG
11502 }
11503
11504 if (cb->args[1]) {
11505 data = nla_data((void *)cb->args[1]);
11506 data_len = nla_len((void *)cb->args[1]);
11507 }
11508
00918d33 11509 if (!rdev->ops->testmode_dump) {
71063f0e
WYG
11510 err = -EOPNOTSUPP;
11511 goto out_err;
11512 }
11513
11514 while (1) {
15e47304 11515 void *hdr = nl80211hdr_put(skb, NETLINK_CB(cb->skb).portid,
71063f0e
WYG
11516 cb->nlh->nlmsg_seq, NLM_F_MULTI,
11517 NL80211_CMD_TESTMODE);
11518 struct nlattr *tmdata;
11519
cb35fba3
DC
11520 if (!hdr)
11521 break;
11522
9360ffd1 11523 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, phy_idx)) {
71063f0e
WYG
11524 genlmsg_cancel(skb, hdr);
11525 break;
11526 }
11527
ae0be8de 11528 tmdata = nla_nest_start_noflag(skb, NL80211_ATTR_TESTDATA);
71063f0e
WYG
11529 if (!tmdata) {
11530 genlmsg_cancel(skb, hdr);
11531 break;
11532 }
e35e4d28 11533 err = rdev_testmode_dump(rdev, skb, cb, data, data_len);
71063f0e
WYG
11534 nla_nest_end(skb, tmdata);
11535
11536 if (err == -ENOBUFS || err == -ENOENT) {
11537 genlmsg_cancel(skb, hdr);
11538 break;
11539 } else if (err) {
11540 genlmsg_cancel(skb, hdr);
11541 goto out_err;
11542 }
11543
11544 genlmsg_end(skb, hdr);
11545 }
11546
11547 err = skb->len;
11548 /* see above */
11549 cb->args[0] = phy_idx + 1;
11550 out_err:
50508d94 11551 kfree(attrbuf);
5fe231e8 11552 rtnl_unlock();
71063f0e
WYG
11553 return err;
11554}
aff89a9b
JB
11555#endif
11556
b23aa676
SO
11557static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
11558{
4c476991
JB
11559 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11560 struct net_device *dev = info->user_ptr[1];
b23aa676
SO
11561 struct cfg80211_connect_params connect;
11562 struct wiphy *wiphy;
fffd0934 11563 struct cfg80211_cached_keys *connkeys = NULL;
942ba88b 11564 u32 freq = 0;
b23aa676
SO
11565 int err;
11566
11567 memset(&connect, 0, sizeof(connect));
11568
b23aa676
SO
11569 if (!info->attrs[NL80211_ATTR_SSID] ||
11570 !nla_len(info->attrs[NL80211_ATTR_SSID]))
11571 return -EINVAL;
11572
11573 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
11574 connect.auth_type =
11575 nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
e39e5b5e
JM
11576 if (!nl80211_valid_auth_type(rdev, connect.auth_type,
11577 NL80211_CMD_CONNECT))
b23aa676
SO
11578 return -EINVAL;
11579 } else
11580 connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
11581
11582 connect.privacy = info->attrs[NL80211_ATTR_PRIVACY];
11583
3a00df57
AS
11584 if (info->attrs[NL80211_ATTR_WANT_1X_4WAY_HS] &&
11585 !wiphy_ext_feature_isset(&rdev->wiphy,
11586 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
11587 return -EINVAL;
11588 connect.want_1x = info->attrs[NL80211_ATTR_WANT_1X_4WAY_HS];
11589
c0692b8f 11590 err = nl80211_crypto_settings(rdev, info, &connect.crypto,
3dc27d25 11591 NL80211_MAX_NR_CIPHER_SUITES);
b23aa676
SO
11592 if (err)
11593 return err;
b23aa676 11594
074ac8df 11595 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
11596 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
11597 return -EOPNOTSUPP;
b23aa676 11598
79c97e97 11599 wiphy = &rdev->wiphy;
b23aa676 11600
4486ea98
BS
11601 connect.bg_scan_period = -1;
11602 if (info->attrs[NL80211_ATTR_BG_SCAN_PERIOD] &&
11603 (wiphy->flags & WIPHY_FLAG_SUPPORTS_FW_ROAM)) {
11604 connect.bg_scan_period =
11605 nla_get_u16(info->attrs[NL80211_ATTR_BG_SCAN_PERIOD]);
11606 }
11607
b23aa676
SO
11608 if (info->attrs[NL80211_ATTR_MAC])
11609 connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
1df4a510
JM
11610 else if (info->attrs[NL80211_ATTR_MAC_HINT])
11611 connect.bssid_hint =
11612 nla_data(info->attrs[NL80211_ATTR_MAC_HINT]);
b23aa676
SO
11613 connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
11614 connect.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
11615
11616 if (info->attrs[NL80211_ATTR_IE]) {
11617 connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
11618 connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
11619 }
11620
cee00a95
JM
11621 if (info->attrs[NL80211_ATTR_USE_MFP]) {
11622 connect.mfp = nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
65026002
EG
11623 if (connect.mfp == NL80211_MFP_OPTIONAL &&
11624 !wiphy_ext_feature_isset(&rdev->wiphy,
11625 NL80211_EXT_FEATURE_MFP_OPTIONAL))
11626 return -EOPNOTSUPP;
cee00a95
JM
11627 } else {
11628 connect.mfp = NL80211_MFP_NO;
11629 }
11630
ba6fbacf
JM
11631 if (info->attrs[NL80211_ATTR_PREV_BSSID])
11632 connect.prev_bssid =
11633 nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
11634
942ba88b
TP
11635 if (info->attrs[NL80211_ATTR_WIPHY_FREQ])
11636 freq = MHZ_TO_KHZ(nla_get_u32(
11637 info->attrs[NL80211_ATTR_WIPHY_FREQ]));
11638 if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
11639 freq +=
11640 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
11641
11642 if (freq) {
11643 connect.channel = nl80211_get_valid_chan(wiphy, freq);
664834de 11644 if (!connect.channel)
1df4a510
JM
11645 return -EINVAL;
11646 } else if (info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]) {
942ba88b
TP
11647 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]);
11648 freq = MHZ_TO_KHZ(freq);
11649 connect.channel_hint = nl80211_get_valid_chan(wiphy, freq);
664834de 11650 if (!connect.channel_hint)
4c476991 11651 return -EINVAL;
b23aa676
SO
11652 }
11653
2a38075c
AAL
11654 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]) {
11655 connect.edmg.channels =
11656 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]);
11657
11658 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG])
11659 connect.edmg.bw_config =
11660 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]);
11661 }
11662
fffd0934 11663 if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) {
768075eb 11664 connkeys = nl80211_parse_connkeys(rdev, info, NULL);
4c476991
JB
11665 if (IS_ERR(connkeys))
11666 return PTR_ERR(connkeys);
fffd0934
JB
11667 }
11668
7e7c8926
BG
11669 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
11670 connect.flags |= ASSOC_REQ_DISABLE_HT;
11671
11672 if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
11673 memcpy(&connect.ht_capa_mask,
11674 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
11675 sizeof(connect.ht_capa_mask));
11676
11677 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
b4e4f47e 11678 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) {
453431a5 11679 kfree_sensitive(connkeys);
7e7c8926 11680 return -EINVAL;
b4e4f47e 11681 }
7e7c8926
BG
11682 memcpy(&connect.ht_capa,
11683 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
11684 sizeof(connect.ht_capa));
11685 }
11686
ee2aca34
JB
11687 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT]))
11688 connect.flags |= ASSOC_REQ_DISABLE_VHT;
11689
b6db0f89
BG
11690 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HE]))
11691 connect.flags |= ASSOC_REQ_DISABLE_HE;
11692
36f84235
MS
11693 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_EHT]))
11694 connect.flags |= ASSOC_REQ_DISABLE_EHT;
11695
ee2aca34
JB
11696 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
11697 memcpy(&connect.vht_capa_mask,
11698 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
11699 sizeof(connect.vht_capa_mask));
11700
11701 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) {
11702 if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) {
453431a5 11703 kfree_sensitive(connkeys);
ee2aca34
JB
11704 return -EINVAL;
11705 }
11706 memcpy(&connect.vht_capa,
11707 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]),
11708 sizeof(connect.vht_capa));
11709 }
11710
bab5ab7d 11711 if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
0c9ca11b
BL
11712 if (!((rdev->wiphy.features &
11713 NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) &&
11714 (rdev->wiphy.features & NL80211_FEATURE_QUIET)) &&
11715 !wiphy_ext_feature_isset(&rdev->wiphy,
11716 NL80211_EXT_FEATURE_RRM)) {
453431a5 11717 kfree_sensitive(connkeys);
bab5ab7d 11718 return -EINVAL;
707554b4 11719 }
bab5ab7d
AK
11720 connect.flags |= ASSOC_REQ_USE_RRM;
11721 }
11722
34d50519 11723 connect.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
57fbcce3 11724 if (connect.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) {
453431a5 11725 kfree_sensitive(connkeys);
34d50519
LD
11726 return -EOPNOTSUPP;
11727 }
11728
38de03d2
AS
11729 if (info->attrs[NL80211_ATTR_BSS_SELECT]) {
11730 /* bss selection makes no sense if bssid is set */
11731 if (connect.bssid) {
453431a5 11732 kfree_sensitive(connkeys);
38de03d2
AS
11733 return -EINVAL;
11734 }
11735
11736 err = parse_bss_select(info->attrs[NL80211_ATTR_BSS_SELECT],
11737 wiphy, &connect.bss_select);
11738 if (err) {
453431a5 11739 kfree_sensitive(connkeys);
38de03d2
AS
11740 return err;
11741 }
11742 }
11743
a3caf744
VK
11744 if (wiphy_ext_feature_isset(&rdev->wiphy,
11745 NL80211_EXT_FEATURE_FILS_SK_OFFLOAD) &&
11746 info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] &&
11747 info->attrs[NL80211_ATTR_FILS_ERP_REALM] &&
11748 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] &&
11749 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
11750 connect.fils_erp_username =
11751 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
11752 connect.fils_erp_username_len =
11753 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
11754 connect.fils_erp_realm =
11755 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
11756 connect.fils_erp_realm_len =
11757 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
11758 connect.fils_erp_next_seq_num =
11759 nla_get_u16(
11760 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM]);
11761 connect.fils_erp_rrk =
11762 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
11763 connect.fils_erp_rrk_len =
11764 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
11765 } else if (info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] ||
11766 info->attrs[NL80211_ATTR_FILS_ERP_REALM] ||
11767 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] ||
11768 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
453431a5 11769 kfree_sensitive(connkeys);
a3caf744
VK
11770 return -EINVAL;
11771 }
11772
40cbfa90
SD
11773 if (nla_get_flag(info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])) {
11774 if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
453431a5 11775 kfree_sensitive(connkeys);
40cbfa90
SD
11776 GENL_SET_ERR_MSG(info,
11777 "external auth requires connection ownership");
11778 return -EINVAL;
11779 }
11780 connect.flags |= CONNECT_REQ_EXTERNAL_AUTH_SUPPORT;
11781 }
11782
efbabc11
VJ
11783 if (nla_get_flag(info->attrs[NL80211_ATTR_MLO_SUPPORT]))
11784 connect.flags |= CONNECT_REQ_MLO_SUPPORT;
11785
83739b03 11786 wdev_lock(dev->ieee80211_ptr);
bd2522b1 11787
4ce2bd9c
JM
11788 err = cfg80211_connect(rdev, dev, &connect, connkeys,
11789 connect.prev_bssid);
fffd0934 11790 if (err)
453431a5 11791 kfree_sensitive(connkeys);
bd2522b1
AZ
11792
11793 if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
11794 dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
11795 if (connect.bssid)
11796 memcpy(dev->ieee80211_ptr->disconnect_bssid,
11797 connect.bssid, ETH_ALEN);
11798 else
3b1648f1 11799 eth_zero_addr(dev->ieee80211_ptr->disconnect_bssid);
bd2522b1
AZ
11800 }
11801
11802 wdev_unlock(dev->ieee80211_ptr);
11803
b23aa676
SO
11804 return err;
11805}
11806
088e8df8 11807static int nl80211_update_connect_params(struct sk_buff *skb,
11808 struct genl_info *info)
11809{
11810 struct cfg80211_connect_params connect = {};
11811 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11812 struct net_device *dev = info->user_ptr[1];
11813 struct wireless_dev *wdev = dev->ieee80211_ptr;
7f9a3e15
VK
11814 bool fils_sk_offload;
11815 u32 auth_type;
088e8df8 11816 u32 changed = 0;
11817 int ret;
11818
11819 if (!rdev->ops->update_connect_params)
11820 return -EOPNOTSUPP;
11821
11822 if (info->attrs[NL80211_ATTR_IE]) {
088e8df8 11823 connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
11824 connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
11825 changed |= UPDATE_ASSOC_IES;
11826 }
11827
7f9a3e15
VK
11828 fils_sk_offload = wiphy_ext_feature_isset(&rdev->wiphy,
11829 NL80211_EXT_FEATURE_FILS_SK_OFFLOAD);
11830
11831 /*
11832 * when driver supports fils-sk offload all attributes must be
11833 * provided. So the else covers "fils-sk-not-all" and
11834 * "no-fils-sk-any".
11835 */
11836 if (fils_sk_offload &&
11837 info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] &&
11838 info->attrs[NL80211_ATTR_FILS_ERP_REALM] &&
11839 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] &&
11840 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
11841 connect.fils_erp_username =
11842 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
11843 connect.fils_erp_username_len =
11844 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
11845 connect.fils_erp_realm =
11846 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
11847 connect.fils_erp_realm_len =
11848 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
11849 connect.fils_erp_next_seq_num =
11850 nla_get_u16(
11851 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM]);
11852 connect.fils_erp_rrk =
11853 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
11854 connect.fils_erp_rrk_len =
11855 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
11856 changed |= UPDATE_FILS_ERP_INFO;
11857 } else if (info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] ||
11858 info->attrs[NL80211_ATTR_FILS_ERP_REALM] ||
11859 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] ||
11860 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
11861 return -EINVAL;
11862 }
11863
11864 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
11865 auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
11866 if (!nl80211_valid_auth_type(rdev, auth_type,
11867 NL80211_CMD_CONNECT))
11868 return -EINVAL;
11869
11870 if (auth_type == NL80211_AUTHTYPE_FILS_SK &&
11871 fils_sk_offload && !(changed & UPDATE_FILS_ERP_INFO))
11872 return -EINVAL;
11873
11874 connect.auth_type = auth_type;
11875 changed |= UPDATE_AUTH_TYPE;
11876 }
11877
088e8df8 11878 wdev_lock(dev->ieee80211_ptr);
7b0a0e3c 11879 if (!wdev->connected)
088e8df8 11880 ret = -ENOLINK;
11881 else
11882 ret = rdev_update_connect_params(rdev, dev, &connect, changed);
11883 wdev_unlock(dev->ieee80211_ptr);
11884
11885 return ret;
11886}
11887
b23aa676
SO
11888static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
11889{
4c476991
JB
11890 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11891 struct net_device *dev = info->user_ptr[1];
b23aa676 11892 u16 reason;
83739b03 11893 int ret;
b23aa676 11894
bad29297
AZ
11895 if (dev->ieee80211_ptr->conn_owner_nlportid &&
11896 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
11897 return -EPERM;
11898
b23aa676
SO
11899 if (!info->attrs[NL80211_ATTR_REASON_CODE])
11900 reason = WLAN_REASON_DEAUTH_LEAVING;
11901 else
11902 reason = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
11903
11904 if (reason == 0)
11905 return -EINVAL;
11906
074ac8df 11907 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
11908 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
11909 return -EOPNOTSUPP;
b23aa676 11910
83739b03
JB
11911 wdev_lock(dev->ieee80211_ptr);
11912 ret = cfg80211_disconnect(rdev, dev, reason, true);
11913 wdev_unlock(dev->ieee80211_ptr);
11914 return ret;
b23aa676
SO
11915}
11916
463d0183
JB
11917static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
11918{
4c476991 11919 struct cfg80211_registered_device *rdev = info->user_ptr[0];
463d0183
JB
11920 struct net *net;
11921 int err;
463d0183 11922
4b681c82
VK
11923 if (info->attrs[NL80211_ATTR_PID]) {
11924 u32 pid = nla_get_u32(info->attrs[NL80211_ATTR_PID]);
11925
11926 net = get_net_ns_by_pid(pid);
11927 } else if (info->attrs[NL80211_ATTR_NETNS_FD]) {
11928 u32 fd = nla_get_u32(info->attrs[NL80211_ATTR_NETNS_FD]);
463d0183 11929
4b681c82
VK
11930 net = get_net_ns_by_fd(fd);
11931 } else {
11932 return -EINVAL;
11933 }
463d0183 11934
4c476991
JB
11935 if (IS_ERR(net))
11936 return PTR_ERR(net);
463d0183
JB
11937
11938 err = 0;
11939
11940 /* check if anything to do */
4c476991
JB
11941 if (!net_eq(wiphy_net(&rdev->wiphy), net))
11942 err = cfg80211_switch_netns(rdev, net);
463d0183 11943
463d0183 11944 put_net(net);
463d0183
JB
11945 return err;
11946}
11947
67fbb16b
SO
11948static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info)
11949{
4c476991 11950 struct cfg80211_registered_device *rdev = info->user_ptr[0];
67fbb16b
SO
11951 int (*rdev_ops)(struct wiphy *wiphy, struct net_device *dev,
11952 struct cfg80211_pmksa *pmksa) = NULL;
4c476991 11953 struct net_device *dev = info->user_ptr[1];
67fbb16b
SO
11954 struct cfg80211_pmksa pmksa;
11955
11956 memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
11957
67fbb16b
SO
11958 if (!info->attrs[NL80211_ATTR_PMKID])
11959 return -EINVAL;
11960
67fbb16b 11961 pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
a3caf744
VK
11962
11963 if (info->attrs[NL80211_ATTR_MAC]) {
11964 pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
11965 } else if (info->attrs[NL80211_ATTR_SSID] &&
11966 info->attrs[NL80211_ATTR_FILS_CACHE_ID] &&
11967 (info->genlhdr->cmd == NL80211_CMD_DEL_PMKSA ||
11968 info->attrs[NL80211_ATTR_PMK])) {
11969 pmksa.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
11970 pmksa.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
11971 pmksa.cache_id =
11972 nla_data(info->attrs[NL80211_ATTR_FILS_CACHE_ID]);
11973 } else {
11974 return -EINVAL;
11975 }
11976 if (info->attrs[NL80211_ATTR_PMK]) {
11977 pmksa.pmk = nla_data(info->attrs[NL80211_ATTR_PMK]);
11978 pmksa.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]);
11979 }
67fbb16b 11980
7fc82af8
VJ
11981 if (info->attrs[NL80211_ATTR_PMK_LIFETIME])
11982 pmksa.pmk_lifetime =
11983 nla_get_u32(info->attrs[NL80211_ATTR_PMK_LIFETIME]);
11984
11985 if (info->attrs[NL80211_ATTR_PMK_REAUTH_THRESHOLD])
11986 pmksa.pmk_reauth_threshold =
11987 nla_get_u8(
11988 info->attrs[NL80211_ATTR_PMK_REAUTH_THRESHOLD]);
11989
074ac8df 11990 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
6c900360
LD
11991 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
11992 !(dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP &&
11993 wiphy_ext_feature_isset(&rdev->wiphy,
11994 NL80211_EXT_FEATURE_AP_PMKSA_CACHING)))
4c476991 11995 return -EOPNOTSUPP;
67fbb16b
SO
11996
11997 switch (info->genlhdr->cmd) {
11998 case NL80211_CMD_SET_PMKSA:
11999 rdev_ops = rdev->ops->set_pmksa;
12000 break;
12001 case NL80211_CMD_DEL_PMKSA:
12002 rdev_ops = rdev->ops->del_pmksa;
12003 break;
12004 default:
12005 WARN_ON(1);
12006 break;
12007 }
12008
4c476991
JB
12009 if (!rdev_ops)
12010 return -EOPNOTSUPP;
67fbb16b 12011
4c476991 12012 return rdev_ops(&rdev->wiphy, dev, &pmksa);
67fbb16b
SO
12013}
12014
12015static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info)
12016{
4c476991
JB
12017 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12018 struct net_device *dev = info->user_ptr[1];
67fbb16b 12019
074ac8df 12020 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
12021 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
12022 return -EOPNOTSUPP;
67fbb16b 12023
4c476991
JB
12024 if (!rdev->ops->flush_pmksa)
12025 return -EOPNOTSUPP;
67fbb16b 12026
e35e4d28 12027 return rdev_flush_pmksa(rdev, dev);
67fbb16b
SO
12028}
12029
109086ce
AN
12030static int nl80211_tdls_mgmt(struct sk_buff *skb, struct genl_info *info)
12031{
12032 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12033 struct net_device *dev = info->user_ptr[1];
12034 u8 action_code, dialog_token;
df942e7b 12035 u32 peer_capability = 0;
109086ce
AN
12036 u16 status_code;
12037 u8 *peer;
31fa97c5 12038 bool initiator;
109086ce
AN
12039
12040 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
12041 !rdev->ops->tdls_mgmt)
12042 return -EOPNOTSUPP;
12043
12044 if (!info->attrs[NL80211_ATTR_TDLS_ACTION] ||
12045 !info->attrs[NL80211_ATTR_STATUS_CODE] ||
12046 !info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN] ||
12047 !info->attrs[NL80211_ATTR_IE] ||
12048 !info->attrs[NL80211_ATTR_MAC])
12049 return -EINVAL;
12050
12051 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
12052 action_code = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_ACTION]);
12053 status_code = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
12054 dialog_token = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN]);
31fa97c5 12055 initiator = nla_get_flag(info->attrs[NL80211_ATTR_TDLS_INITIATOR]);
df942e7b
SDU
12056 if (info->attrs[NL80211_ATTR_TDLS_PEER_CAPABILITY])
12057 peer_capability =
12058 nla_get_u32(info->attrs[NL80211_ATTR_TDLS_PEER_CAPABILITY]);
109086ce 12059
e35e4d28 12060 return rdev_tdls_mgmt(rdev, dev, peer, action_code,
df942e7b 12061 dialog_token, status_code, peer_capability,
31fa97c5 12062 initiator,
e35e4d28
HG
12063 nla_data(info->attrs[NL80211_ATTR_IE]),
12064 nla_len(info->attrs[NL80211_ATTR_IE]));
109086ce
AN
12065}
12066
12067static int nl80211_tdls_oper(struct sk_buff *skb, struct genl_info *info)
12068{
12069 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12070 struct net_device *dev = info->user_ptr[1];
12071 enum nl80211_tdls_operation operation;
12072 u8 *peer;
12073
12074 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
12075 !rdev->ops->tdls_oper)
12076 return -EOPNOTSUPP;
12077
12078 if (!info->attrs[NL80211_ATTR_TDLS_OPERATION] ||
12079 !info->attrs[NL80211_ATTR_MAC])
12080 return -EINVAL;
12081
12082 operation = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_OPERATION]);
12083 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
12084
e35e4d28 12085 return rdev_tdls_oper(rdev, dev, peer, operation);
109086ce
AN
12086}
12087
9588bbd5
JM
12088static int nl80211_remain_on_channel(struct sk_buff *skb,
12089 struct genl_info *info)
12090{
4c476991 12091 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c 12092 unsigned int link_id = nl80211_link_id(info->attrs);
71bbc994 12093 struct wireless_dev *wdev = info->user_ptr[1];
683b6d3b 12094 struct cfg80211_chan_def chandef;
9588bbd5
JM
12095 struct sk_buff *msg;
12096 void *hdr;
12097 u64 cookie;
683b6d3b 12098 u32 duration;
9588bbd5
JM
12099 int err;
12100
12101 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
12102 !info->attrs[NL80211_ATTR_DURATION])
12103 return -EINVAL;
12104
12105 duration = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
12106
ebf348fc
JB
12107 if (!rdev->ops->remain_on_channel ||
12108 !(rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL))
12109 return -EOPNOTSUPP;
12110
9588bbd5 12111 /*
ebf348fc
JB
12112 * We should be on that channel for at least a minimum amount of
12113 * time (10ms) but no longer than the driver supports.
9588bbd5 12114 */
ebf348fc 12115 if (duration < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
a293911d 12116 duration > rdev->wiphy.max_remain_on_channel_duration)
9588bbd5
JM
12117 return -EINVAL;
12118
683b6d3b
JB
12119 err = nl80211_parse_chandef(rdev, info, &chandef);
12120 if (err)
12121 return err;
9588bbd5 12122
34373d12 12123 wdev_lock(wdev);
7b0a0e3c
JB
12124 if (!cfg80211_off_channel_oper_allowed(wdev, chandef.chan)) {
12125 const struct cfg80211_chan_def *oper_chandef, *compat_chandef;
12126
12127 oper_chandef = wdev_chandef(wdev, link_id);
12128
12129 if (WARN_ON(!oper_chandef)) {
12130 /* cannot happen since we must beacon to get here */
12131 WARN_ON(1);
12132 wdev_unlock(wdev);
12133 return -EBUSY;
12134 }
12135
12136 /* note: returns first one if identical chandefs */
12137 compat_chandef = cfg80211_chandef_compatible(&chandef,
12138 oper_chandef);
12139
34373d12
VT
12140 if (compat_chandef != &chandef) {
12141 wdev_unlock(wdev);
12142 return -EBUSY;
12143 }
12144 }
12145 wdev_unlock(wdev);
12146
9588bbd5 12147 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
12148 if (!msg)
12149 return -ENOMEM;
9588bbd5 12150
15e47304 12151 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
9588bbd5 12152 NL80211_CMD_REMAIN_ON_CHANNEL);
cb35fba3
DC
12153 if (!hdr) {
12154 err = -ENOBUFS;
9588bbd5
JM
12155 goto free_msg;
12156 }
12157
683b6d3b
JB
12158 err = rdev_remain_on_channel(rdev, wdev, chandef.chan,
12159 duration, &cookie);
9588bbd5
JM
12160
12161 if (err)
12162 goto free_msg;
12163
2dad624e
ND
12164 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
12165 NL80211_ATTR_PAD))
9360ffd1 12166 goto nla_put_failure;
9588bbd5
JM
12167
12168 genlmsg_end(msg, hdr);
4c476991
JB
12169
12170 return genlmsg_reply(msg, info);
9588bbd5
JM
12171
12172 nla_put_failure:
12173 err = -ENOBUFS;
12174 free_msg:
12175 nlmsg_free(msg);
9588bbd5
JM
12176 return err;
12177}
12178
12179static int nl80211_cancel_remain_on_channel(struct sk_buff *skb,
12180 struct genl_info *info)
12181{
4c476991 12182 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 12183 struct wireless_dev *wdev = info->user_ptr[1];
9588bbd5 12184 u64 cookie;
9588bbd5
JM
12185
12186 if (!info->attrs[NL80211_ATTR_COOKIE])
12187 return -EINVAL;
12188
4c476991
JB
12189 if (!rdev->ops->cancel_remain_on_channel)
12190 return -EOPNOTSUPP;
9588bbd5 12191
9588bbd5
JM
12192 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
12193
e35e4d28 12194 return rdev_cancel_remain_on_channel(rdev, wdev, cookie);
9588bbd5
JM
12195}
12196
13ae75b1
JM
12197static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
12198 struct genl_info *info)
12199{
13ae75b1 12200 struct cfg80211_bitrate_mask mask;
7b0a0e3c 12201 unsigned int link_id = nl80211_link_id(info->attrs);
a7c7fbff 12202 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 12203 struct net_device *dev = info->user_ptr[1];
f971e188 12204 struct wireless_dev *wdev = dev->ieee80211_ptr;
a7c7fbff 12205 int err;
13ae75b1 12206
4c476991
JB
12207 if (!rdev->ops->set_bitrate_mask)
12208 return -EOPNOTSUPP;
13ae75b1 12209
f971e188 12210 wdev_lock(wdev);
9a5f6488 12211 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
eb89a6a6 12212 NL80211_ATTR_TX_RATES, &mask,
7b0a0e3c 12213 dev, true, link_id);
a7c7fbff 12214 if (err)
f971e188 12215 goto out;
13ae75b1 12216
7b0a0e3c 12217 err = rdev_set_bitrate_mask(rdev, dev, link_id, NULL, &mask);
f971e188
JB
12218out:
12219 wdev_unlock(wdev);
12220 return err;
13ae75b1
JM
12221}
12222
2e161f78 12223static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
026331c4 12224{
4c476991 12225 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 12226 struct wireless_dev *wdev = info->user_ptr[1];
2e161f78 12227 u16 frame_type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION;
026331c4
JM
12228
12229 if (!info->attrs[NL80211_ATTR_FRAME_MATCH])
12230 return -EINVAL;
12231
2e161f78
JB
12232 if (info->attrs[NL80211_ATTR_FRAME_TYPE])
12233 frame_type = nla_get_u16(info->attrs[NL80211_ATTR_FRAME_TYPE]);
026331c4 12234
71bbc994
JB
12235 switch (wdev->iftype) {
12236 case NL80211_IFTYPE_STATION:
12237 case NL80211_IFTYPE_ADHOC:
12238 case NL80211_IFTYPE_P2P_CLIENT:
12239 case NL80211_IFTYPE_AP:
12240 case NL80211_IFTYPE_AP_VLAN:
12241 case NL80211_IFTYPE_MESH_POINT:
12242 case NL80211_IFTYPE_P2P_GO:
98104fde 12243 case NL80211_IFTYPE_P2P_DEVICE:
71bbc994 12244 break;
cb3b7d87 12245 case NL80211_IFTYPE_NAN:
71bbc994 12246 default:
4c476991 12247 return -EOPNOTSUPP;
71bbc994 12248 }
026331c4
JM
12249
12250 /* not much point in registering if we can't reply */
4c476991
JB
12251 if (!rdev->ops->mgmt_tx)
12252 return -EOPNOTSUPP;
026331c4 12253
9dba48a6
JB
12254 if (info->attrs[NL80211_ATTR_RECEIVE_MULTICAST] &&
12255 !wiphy_ext_feature_isset(&rdev->wiphy,
12256 NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS)) {
12257 GENL_SET_ERR_MSG(info,
12258 "multicast RX registrations are not supported");
12259 return -EOPNOTSUPP;
12260 }
12261
15e47304 12262 return cfg80211_mlme_register_mgmt(wdev, info->snd_portid, frame_type,
ff74c51e
IP
12263 nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]),
12264 nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]),
9dba48a6 12265 info->attrs[NL80211_ATTR_RECEIVE_MULTICAST],
ff74c51e 12266 info->extack);
026331c4
JM
12267}
12268
2e161f78 12269static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
026331c4 12270{
4c476991 12271 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 12272 struct wireless_dev *wdev = info->user_ptr[1];
683b6d3b 12273 struct cfg80211_chan_def chandef;
026331c4 12274 int err;
d64d373f 12275 void *hdr = NULL;
026331c4 12276 u64 cookie;
e247bd90 12277 struct sk_buff *msg = NULL;
b176e629
AO
12278 struct cfg80211_mgmt_tx_params params = {
12279 .dont_wait_for_ack =
12280 info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK],
12281 };
026331c4 12282
683b6d3b 12283 if (!info->attrs[NL80211_ATTR_FRAME])
026331c4
JM
12284 return -EINVAL;
12285
4c476991
JB
12286 if (!rdev->ops->mgmt_tx)
12287 return -EOPNOTSUPP;
026331c4 12288
71bbc994 12289 switch (wdev->iftype) {
ea141b75
AQ
12290 case NL80211_IFTYPE_P2P_DEVICE:
12291 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
12292 return -EINVAL;
d7832c71 12293 break;
71bbc994
JB
12294 case NL80211_IFTYPE_STATION:
12295 case NL80211_IFTYPE_ADHOC:
12296 case NL80211_IFTYPE_P2P_CLIENT:
12297 case NL80211_IFTYPE_AP:
12298 case NL80211_IFTYPE_AP_VLAN:
12299 case NL80211_IFTYPE_MESH_POINT:
12300 case NL80211_IFTYPE_P2P_GO:
12301 break;
cb3b7d87 12302 case NL80211_IFTYPE_NAN:
71bbc994 12303 default:
4c476991 12304 return -EOPNOTSUPP;
71bbc994 12305 }
026331c4 12306
f7ca38df 12307 if (info->attrs[NL80211_ATTR_DURATION]) {
7c4ef712 12308 if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
f7ca38df 12309 return -EINVAL;
b176e629 12310 params.wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
ebf348fc
JB
12311
12312 /*
12313 * We should wait on the channel for at least a minimum amount
12314 * of time (10ms) but no longer than the driver supports.
12315 */
b176e629
AO
12316 if (params.wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
12317 params.wait > rdev->wiphy.max_remain_on_channel_duration)
ebf348fc 12318 return -EINVAL;
f7ca38df
JB
12319 }
12320
b176e629 12321 params.offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK];
f7ca38df 12322
b176e629 12323 if (params.offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
7c4ef712
JB
12324 return -EINVAL;
12325
b176e629 12326 params.no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
e9f935e3 12327
ea141b75
AQ
12328 /* get the channel if any has been specified, otherwise pass NULL to
12329 * the driver. The latter will use the current one
12330 */
12331 chandef.chan = NULL;
12332 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
12333 err = nl80211_parse_chandef(rdev, info, &chandef);
12334 if (err)
12335 return err;
12336 }
12337
b176e629 12338 if (!chandef.chan && params.offchan)
ea141b75 12339 return -EINVAL;
026331c4 12340
34373d12 12341 wdev_lock(wdev);
7b0a0e3c
JB
12342 if (params.offchan &&
12343 !cfg80211_off_channel_oper_allowed(wdev, chandef.chan)) {
34373d12
VT
12344 wdev_unlock(wdev);
12345 return -EBUSY;
12346 }
95f498bb
JB
12347
12348 params.link_id = nl80211_link_id_or_invalid(info->attrs);
12349 /*
12350 * This now races due to the unlock, but we cannot check
12351 * the valid links for the _station_ anyway, so that's up
12352 * to the driver.
12353 */
12354 if (params.link_id >= 0 &&
12355 !(wdev->valid_links & BIT(params.link_id))) {
12356 wdev_unlock(wdev);
12357 return -EINVAL;
12358 }
34373d12
VT
12359 wdev_unlock(wdev);
12360
34d22ce2
AO
12361 params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
12362 params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
12363
12364 if (info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]) {
12365 int len = nla_len(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]);
12366 int i;
12367
12368 if (len % sizeof(u16))
12369 return -EINVAL;
12370
12371 params.n_csa_offsets = len / sizeof(u16);
12372 params.csa_offsets =
12373 nla_data(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]);
12374
12375 /* check that all the offsets fit the frame */
12376 for (i = 0; i < params.n_csa_offsets; i++) {
12377 if (params.csa_offsets[i] >= params.len)
12378 return -EINVAL;
12379 }
12380 }
12381
b176e629 12382 if (!params.dont_wait_for_ack) {
e247bd90
JB
12383 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
12384 if (!msg)
12385 return -ENOMEM;
026331c4 12386
15e47304 12387 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
e247bd90 12388 NL80211_CMD_FRAME);
cb35fba3
DC
12389 if (!hdr) {
12390 err = -ENOBUFS;
e247bd90
JB
12391 goto free_msg;
12392 }
026331c4 12393 }
e247bd90 12394
b176e629
AO
12395 params.chan = chandef.chan;
12396 err = cfg80211_mlme_mgmt_tx(rdev, wdev, &params, &cookie);
026331c4
JM
12397 if (err)
12398 goto free_msg;
12399
e247bd90 12400 if (msg) {
2dad624e
ND
12401 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
12402 NL80211_ATTR_PAD))
9360ffd1 12403 goto nla_put_failure;
026331c4 12404
e247bd90
JB
12405 genlmsg_end(msg, hdr);
12406 return genlmsg_reply(msg, info);
12407 }
12408
12409 return 0;
026331c4
JM
12410
12411 nla_put_failure:
12412 err = -ENOBUFS;
12413 free_msg:
12414 nlmsg_free(msg);
026331c4
JM
12415 return err;
12416}
12417
f7ca38df
JB
12418static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *info)
12419{
12420 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 12421 struct wireless_dev *wdev = info->user_ptr[1];
f7ca38df
JB
12422 u64 cookie;
12423
12424 if (!info->attrs[NL80211_ATTR_COOKIE])
12425 return -EINVAL;
12426
12427 if (!rdev->ops->mgmt_tx_cancel_wait)
12428 return -EOPNOTSUPP;
12429
71bbc994
JB
12430 switch (wdev->iftype) {
12431 case NL80211_IFTYPE_STATION:
12432 case NL80211_IFTYPE_ADHOC:
12433 case NL80211_IFTYPE_P2P_CLIENT:
12434 case NL80211_IFTYPE_AP:
12435 case NL80211_IFTYPE_AP_VLAN:
12436 case NL80211_IFTYPE_P2P_GO:
98104fde 12437 case NL80211_IFTYPE_P2P_DEVICE:
71bbc994 12438 break;
cb3b7d87 12439 case NL80211_IFTYPE_NAN:
71bbc994 12440 default:
f7ca38df 12441 return -EOPNOTSUPP;
71bbc994 12442 }
f7ca38df
JB
12443
12444 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
12445
e35e4d28 12446 return rdev_mgmt_tx_cancel_wait(rdev, wdev, cookie);
f7ca38df
JB
12447}
12448
ffb9eb3d
KV
12449static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info)
12450{
4c476991 12451 struct cfg80211_registered_device *rdev = info->user_ptr[0];
ffb9eb3d 12452 struct wireless_dev *wdev;
4c476991 12453 struct net_device *dev = info->user_ptr[1];
ffb9eb3d
KV
12454 u8 ps_state;
12455 bool state;
12456 int err;
12457
4c476991
JB
12458 if (!info->attrs[NL80211_ATTR_PS_STATE])
12459 return -EINVAL;
ffb9eb3d
KV
12460
12461 ps_state = nla_get_u32(info->attrs[NL80211_ATTR_PS_STATE]);
12462
ffb9eb3d
KV
12463 wdev = dev->ieee80211_ptr;
12464
4c476991
JB
12465 if (!rdev->ops->set_power_mgmt)
12466 return -EOPNOTSUPP;
ffb9eb3d
KV
12467
12468 state = (ps_state == NL80211_PS_ENABLED) ? true : false;
12469
12470 if (state == wdev->ps)
4c476991 12471 return 0;
ffb9eb3d 12472
e35e4d28 12473 err = rdev_set_power_mgmt(rdev, dev, state, wdev->ps_timeout);
4c476991
JB
12474 if (!err)
12475 wdev->ps = state;
ffb9eb3d
KV
12476 return err;
12477}
12478
12479static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info)
12480{
4c476991 12481 struct cfg80211_registered_device *rdev = info->user_ptr[0];
ffb9eb3d
KV
12482 enum nl80211_ps_state ps_state;
12483 struct wireless_dev *wdev;
4c476991 12484 struct net_device *dev = info->user_ptr[1];
ffb9eb3d
KV
12485 struct sk_buff *msg;
12486 void *hdr;
12487 int err;
12488
ffb9eb3d
KV
12489 wdev = dev->ieee80211_ptr;
12490
4c476991
JB
12491 if (!rdev->ops->set_power_mgmt)
12492 return -EOPNOTSUPP;
ffb9eb3d
KV
12493
12494 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
12495 if (!msg)
12496 return -ENOMEM;
ffb9eb3d 12497
15e47304 12498 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
ffb9eb3d
KV
12499 NL80211_CMD_GET_POWER_SAVE);
12500 if (!hdr) {
4c476991 12501 err = -ENOBUFS;
ffb9eb3d
KV
12502 goto free_msg;
12503 }
12504
12505 if (wdev->ps)
12506 ps_state = NL80211_PS_ENABLED;
12507 else
12508 ps_state = NL80211_PS_DISABLED;
12509
9360ffd1
DM
12510 if (nla_put_u32(msg, NL80211_ATTR_PS_STATE, ps_state))
12511 goto nla_put_failure;
ffb9eb3d
KV
12512
12513 genlmsg_end(msg, hdr);
4c476991 12514 return genlmsg_reply(msg, info);
ffb9eb3d 12515
4c476991 12516 nla_put_failure:
ffb9eb3d 12517 err = -ENOBUFS;
4c476991 12518 free_msg:
ffb9eb3d 12519 nlmsg_free(msg);
ffb9eb3d
KV
12520 return err;
12521}
12522
94e860f1
JB
12523static const struct nla_policy
12524nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
4a4b8169 12525 [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_BINARY },
d6dc1a38
JO
12526 [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 },
12527 [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
84f10708
TP
12528 [NL80211_ATTR_CQM_TXE_RATE] = { .type = NLA_U32 },
12529 [NL80211_ATTR_CQM_TXE_PKTS] = { .type = NLA_U32 },
12530 [NL80211_ATTR_CQM_TXE_INTVL] = { .type = NLA_U32 },
bee427b8 12531 [NL80211_ATTR_CQM_RSSI_LEVEL] = { .type = NLA_S32 },
d6dc1a38
JO
12532};
12533
84f10708 12534static int nl80211_set_cqm_txe(struct genl_info *info,
d9d8b019 12535 u32 rate, u32 pkts, u32 intvl)
84f10708
TP
12536{
12537 struct cfg80211_registered_device *rdev = info->user_ptr[0];
84f10708 12538 struct net_device *dev = info->user_ptr[1];
1da5fcc8 12539 struct wireless_dev *wdev = dev->ieee80211_ptr;
84f10708 12540
d9d8b019 12541 if (rate > 100 || intvl > NL80211_CQM_TXE_MAX_INTVL)
84f10708
TP
12542 return -EINVAL;
12543
84f10708
TP
12544 if (!rdev->ops->set_cqm_txe_config)
12545 return -EOPNOTSUPP;
12546
12547 if (wdev->iftype != NL80211_IFTYPE_STATION &&
12548 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
12549 return -EOPNOTSUPP;
12550
e35e4d28 12551 return rdev_set_cqm_txe_config(rdev, dev, rate, pkts, intvl);
84f10708
TP
12552}
12553
4a4b8169
AZ
12554static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
12555 struct net_device *dev)
12556{
12557 struct wireless_dev *wdev = dev->ieee80211_ptr;
12558 s32 last, low, high;
12559 u32 hyst;
1222a160 12560 int i, n, low_index;
4a4b8169
AZ
12561 int err;
12562
12563 /* RSSI reporting disabled? */
12564 if (!wdev->cqm_config)
12565 return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0);
12566
12567 /*
12568 * Obtain current RSSI value if possible, if not and no RSSI threshold
12569 * event has been received yet, we should receive an event after a
12570 * connection is established and enough beacons received to calculate
12571 * the average.
12572 */
7b0a0e3c
JB
12573 if (!wdev->cqm_config->last_rssi_event_value &&
12574 wdev->links[0].client.current_bss &&
4a4b8169 12575 rdev->ops->get_station) {
73887fd9 12576 struct station_info sinfo = {};
4a4b8169
AZ
12577 u8 *mac_addr;
12578
7b0a0e3c 12579 mac_addr = wdev->links[0].client.current_bss->pub.bssid;
4a4b8169 12580
73887fd9
JB
12581 err = rdev_get_station(rdev, dev, mac_addr, &sinfo);
12582 if (err)
4a4b8169
AZ
12583 return err;
12584
df16737d 12585 cfg80211_sinfo_release_content(&sinfo);
397c657a 12586 if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG))
4a4b8169 12587 wdev->cqm_config->last_rssi_event_value =
73887fd9 12588 (s8) sinfo.rx_beacon_signal_avg;
4a4b8169
AZ
12589 }
12590
12591 last = wdev->cqm_config->last_rssi_event_value;
12592 hyst = wdev->cqm_config->rssi_hyst;
12593 n = wdev->cqm_config->n_rssi_thresholds;
12594
4b2c5a14
MH
12595 for (i = 0; i < n; i++) {
12596 i = array_index_nospec(i, n);
4a4b8169
AZ
12597 if (last < wdev->cqm_config->rssi_thresholds[i])
12598 break;
4b2c5a14 12599 }
4a4b8169 12600
1222a160
MH
12601 low_index = i - 1;
12602 if (low_index >= 0) {
12603 low_index = array_index_nospec(low_index, n);
12604 low = wdev->cqm_config->rssi_thresholds[low_index] - hyst;
12605 } else {
12606 low = S32_MIN;
12607 }
12608 if (i < n) {
12609 i = array_index_nospec(i, n);
12610 high = wdev->cqm_config->rssi_thresholds[i] + hyst - 1;
12611 } else {
12612 high = S32_MAX;
12613 }
4a4b8169
AZ
12614
12615 return rdev_set_cqm_rssi_range_config(rdev, dev, low, high);
12616}
12617
d6dc1a38 12618static int nl80211_set_cqm_rssi(struct genl_info *info,
4a4b8169
AZ
12619 const s32 *thresholds, int n_thresholds,
12620 u32 hysteresis)
d6dc1a38 12621{
4c476991 12622 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 12623 struct net_device *dev = info->user_ptr[1];
1da5fcc8 12624 struct wireless_dev *wdev = dev->ieee80211_ptr;
4a4b8169
AZ
12625 int i, err;
12626 s32 prev = S32_MIN;
d6dc1a38 12627
4a4b8169
AZ
12628 /* Check all values negative and sorted */
12629 for (i = 0; i < n_thresholds; i++) {
12630 if (thresholds[i] > 0 || thresholds[i] <= prev)
12631 return -EINVAL;
d6dc1a38 12632
4a4b8169
AZ
12633 prev = thresholds[i];
12634 }
d6dc1a38 12635
074ac8df 12636 if (wdev->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
12637 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
12638 return -EOPNOTSUPP;
d6dc1a38 12639
4a4b8169
AZ
12640 wdev_lock(wdev);
12641 cfg80211_cqm_config_free(wdev);
12642 wdev_unlock(wdev);
12643
12644 if (n_thresholds <= 1 && rdev->ops->set_cqm_rssi_config) {
12645 if (n_thresholds == 0 || thresholds[0] == 0) /* Disabling */
12646 return rdev_set_cqm_rssi_config(rdev, dev, 0, 0);
12647
12648 return rdev_set_cqm_rssi_config(rdev, dev,
12649 thresholds[0], hysteresis);
12650 }
12651
12652 if (!wiphy_ext_feature_isset(&rdev->wiphy,
12653 NL80211_EXT_FEATURE_CQM_RSSI_LIST))
12654 return -EOPNOTSUPP;
12655
12656 if (n_thresholds == 1 && thresholds[0] == 0) /* Disabling */
12657 n_thresholds = 0;
12658
12659 wdev_lock(wdev);
12660 if (n_thresholds) {
12661 struct cfg80211_cqm_config *cqm_config;
12662
40f231e7
LB
12663 cqm_config = kzalloc(struct_size(cqm_config, rssi_thresholds,
12664 n_thresholds),
12665 GFP_KERNEL);
4a4b8169
AZ
12666 if (!cqm_config) {
12667 err = -ENOMEM;
12668 goto unlock;
12669 }
12670
12671 cqm_config->rssi_hyst = hysteresis;
12672 cqm_config->n_rssi_thresholds = n_thresholds;
12673 memcpy(cqm_config->rssi_thresholds, thresholds,
40f231e7
LB
12674 flex_array_size(cqm_config, rssi_thresholds,
12675 n_thresholds));
4a4b8169
AZ
12676
12677 wdev->cqm_config = cqm_config;
12678 }
12679
12680 err = cfg80211_cqm_rssi_update(rdev, dev);
12681
12682unlock:
12683 wdev_unlock(wdev);
12684
12685 return err;
d6dc1a38
JO
12686}
12687
12688static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
12689{
12690 struct nlattr *attrs[NL80211_ATTR_CQM_MAX + 1];
12691 struct nlattr *cqm;
12692 int err;
12693
12694 cqm = info->attrs[NL80211_ATTR_CQM];
1da5fcc8
JB
12695 if (!cqm)
12696 return -EINVAL;
d6dc1a38 12697
8cb08174
JB
12698 err = nla_parse_nested_deprecated(attrs, NL80211_ATTR_CQM_MAX, cqm,
12699 nl80211_attr_cqm_policy,
12700 info->extack);
d6dc1a38 12701 if (err)
1da5fcc8 12702 return err;
d6dc1a38
JO
12703
12704 if (attrs[NL80211_ATTR_CQM_RSSI_THOLD] &&
12705 attrs[NL80211_ATTR_CQM_RSSI_HYST]) {
4a4b8169
AZ
12706 const s32 *thresholds =
12707 nla_data(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
12708 int len = nla_len(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
1da5fcc8 12709 u32 hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]);
d6dc1a38 12710
4a4b8169
AZ
12711 if (len % 4)
12712 return -EINVAL;
12713
12714 return nl80211_set_cqm_rssi(info, thresholds, len / 4,
12715 hysteresis);
1da5fcc8
JB
12716 }
12717
12718 if (attrs[NL80211_ATTR_CQM_TXE_RATE] &&
12719 attrs[NL80211_ATTR_CQM_TXE_PKTS] &&
12720 attrs[NL80211_ATTR_CQM_TXE_INTVL]) {
12721 u32 rate = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_RATE]);
12722 u32 pkts = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_PKTS]);
12723 u32 intvl = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_INTVL]);
12724
12725 return nl80211_set_cqm_txe(info, rate, pkts, intvl);
12726 }
12727
12728 return -EINVAL;
d6dc1a38
JO
12729}
12730
6e0bd6c3
RL
12731static int nl80211_join_ocb(struct sk_buff *skb, struct genl_info *info)
12732{
12733 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12734 struct net_device *dev = info->user_ptr[1];
12735 struct ocb_setup setup = {};
12736 int err;
12737
12738 err = nl80211_parse_chandef(rdev, info, &setup.chandef);
12739 if (err)
12740 return err;
12741
12742 return cfg80211_join_ocb(rdev, dev, &setup);
12743}
12744
12745static int nl80211_leave_ocb(struct sk_buff *skb, struct genl_info *info)
12746{
12747 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12748 struct net_device *dev = info->user_ptr[1];
12749
12750 return cfg80211_leave_ocb(rdev, dev);
12751}
12752
29cbe68c
JB
12753static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
12754{
12755 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12756 struct net_device *dev = info->user_ptr[1];
12757 struct mesh_config cfg;
c80d545d 12758 struct mesh_setup setup;
29cbe68c
JB
12759 int err;
12760
12761 /* start with default */
12762 memcpy(&cfg, &default_mesh_config, sizeof(cfg));
c80d545d 12763 memcpy(&setup, &default_mesh_setup, sizeof(setup));
29cbe68c 12764
24bdd9f4 12765 if (info->attrs[NL80211_ATTR_MESH_CONFIG]) {
29cbe68c 12766 /* and parse parameters if given */
24bdd9f4 12767 err = nl80211_parse_mesh_config(info, &cfg, NULL);
29cbe68c
JB
12768 if (err)
12769 return err;
12770 }
12771
12772 if (!info->attrs[NL80211_ATTR_MESH_ID] ||
12773 !nla_len(info->attrs[NL80211_ATTR_MESH_ID]))
12774 return -EINVAL;
12775
c80d545d
JC
12776 setup.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
12777 setup.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
12778
4bb62344
CYY
12779 if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
12780 !nl80211_parse_mcast_rate(rdev, setup.mcast_rate,
12781 nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE])))
12782 return -EINVAL;
12783
9bdbf04d
MP
12784 if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
12785 setup.beacon_interval =
12786 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
12d20fc9 12787
0c317a02
PK
12788 err = cfg80211_validate_beacon_int(rdev,
12789 NL80211_IFTYPE_MESH_POINT,
12790 setup.beacon_interval);
12d20fc9
PK
12791 if (err)
12792 return err;
9bdbf04d
MP
12793 }
12794
12795 if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
12796 setup.dtim_period =
12797 nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
12798 if (setup.dtim_period < 1 || setup.dtim_period > 100)
12799 return -EINVAL;
12800 }
12801
c80d545d
JC
12802 if (info->attrs[NL80211_ATTR_MESH_SETUP]) {
12803 /* parse additional setup parameters if given */
12804 err = nl80211_parse_mesh_setup(info, &setup);
12805 if (err)
12806 return err;
12807 }
12808
d37bb18a
TP
12809 if (setup.user_mpm)
12810 cfg.auto_open_plinks = false;
12811
cc1d2806 12812 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
683b6d3b
JB
12813 err = nl80211_parse_chandef(rdev, info, &setup.chandef);
12814 if (err)
12815 return err;
cc1d2806 12816 } else {
188c1b3c 12817 /* __cfg80211_join_mesh() will sort it out */
683b6d3b 12818 setup.chandef.chan = NULL;
cc1d2806
JB
12819 }
12820
ffb3cf30
AN
12821 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
12822 u8 *rates = nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
12823 int n_rates =
12824 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
12825 struct ieee80211_supported_band *sband;
12826
12827 if (!setup.chandef.chan)
12828 return -EINVAL;
12829
12830 sband = rdev->wiphy.bands[setup.chandef.chan->band];
12831
12832 err = ieee80211_get_ratemask(sband, rates, n_rates,
12833 &setup.basic_rates);
12834 if (err)
12835 return err;
12836 }
12837
8564e382 12838 if (info->attrs[NL80211_ATTR_TX_RATES]) {
9a5f6488
TC
12839 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
12840 NL80211_ATTR_TX_RATES,
eb89a6a6 12841 &setup.beacon_rate,
7b0a0e3c 12842 dev, false, 0);
8564e382
JB
12843 if (err)
12844 return err;
12845
265698d7
JB
12846 if (!setup.chandef.chan)
12847 return -EINVAL;
12848
8564e382
JB
12849 err = validate_beacon_tx_rate(rdev, setup.chandef.chan->band,
12850 &setup.beacon_rate);
12851 if (err)
12852 return err;
12853 }
12854
d37d49c2
BB
12855 setup.userspace_handles_dfs =
12856 nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]);
12857
1224f583
DK
12858 if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) {
12859 int r = validate_pae_over_nl80211(rdev, info);
12860
12861 if (r < 0)
12862 return r;
12863
12864 setup.control_port_over_nl80211 = true;
12865 }
12866
188c1b3c
DK
12867 wdev_lock(dev->ieee80211_ptr);
12868 err = __cfg80211_join_mesh(rdev, dev, &setup, &cfg);
12869 if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER])
12870 dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
12871 wdev_unlock(dev->ieee80211_ptr);
12872
12873 return err;
29cbe68c
JB
12874}
12875
12876static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info)
12877{
12878 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12879 struct net_device *dev = info->user_ptr[1];
12880
12881 return cfg80211_leave_mesh(rdev, dev);
12882}
12883
dfb89c56 12884#ifdef CONFIG_PM
bb92d199
AK
12885static int nl80211_send_wowlan_patterns(struct sk_buff *msg,
12886 struct cfg80211_registered_device *rdev)
12887{
6abb9cb9 12888 struct cfg80211_wowlan *wowlan = rdev->wiphy.wowlan_config;
bb92d199
AK
12889 struct nlattr *nl_pats, *nl_pat;
12890 int i, pat_len;
12891
6abb9cb9 12892 if (!wowlan->n_patterns)
bb92d199
AK
12893 return 0;
12894
ae0be8de 12895 nl_pats = nla_nest_start_noflag(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN);
bb92d199
AK
12896 if (!nl_pats)
12897 return -ENOBUFS;
12898
6abb9cb9 12899 for (i = 0; i < wowlan->n_patterns; i++) {
ae0be8de 12900 nl_pat = nla_nest_start_noflag(msg, i + 1);
bb92d199
AK
12901 if (!nl_pat)
12902 return -ENOBUFS;
6abb9cb9 12903 pat_len = wowlan->patterns[i].pattern_len;
50ac6607 12904 if (nla_put(msg, NL80211_PKTPAT_MASK, DIV_ROUND_UP(pat_len, 8),
6abb9cb9 12905 wowlan->patterns[i].mask) ||
50ac6607
AK
12906 nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
12907 wowlan->patterns[i].pattern) ||
12908 nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
6abb9cb9 12909 wowlan->patterns[i].pkt_offset))
bb92d199
AK
12910 return -ENOBUFS;
12911 nla_nest_end(msg, nl_pat);
12912 }
12913 nla_nest_end(msg, nl_pats);
12914
12915 return 0;
12916}
12917
2a0e047e
JB
12918static int nl80211_send_wowlan_tcp(struct sk_buff *msg,
12919 struct cfg80211_wowlan_tcp *tcp)
12920{
12921 struct nlattr *nl_tcp;
12922
12923 if (!tcp)
12924 return 0;
12925
ae0be8de
MK
12926 nl_tcp = nla_nest_start_noflag(msg,
12927 NL80211_WOWLAN_TRIG_TCP_CONNECTION);
2a0e047e
JB
12928 if (!nl_tcp)
12929 return -ENOBUFS;
12930
930345ea
JB
12931 if (nla_put_in_addr(msg, NL80211_WOWLAN_TCP_SRC_IPV4, tcp->src) ||
12932 nla_put_in_addr(msg, NL80211_WOWLAN_TCP_DST_IPV4, tcp->dst) ||
2a0e047e
JB
12933 nla_put(msg, NL80211_WOWLAN_TCP_DST_MAC, ETH_ALEN, tcp->dst_mac) ||
12934 nla_put_u16(msg, NL80211_WOWLAN_TCP_SRC_PORT, tcp->src_port) ||
12935 nla_put_u16(msg, NL80211_WOWLAN_TCP_DST_PORT, tcp->dst_port) ||
12936 nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
12937 tcp->payload_len, tcp->payload) ||
12938 nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
12939 tcp->data_interval) ||
12940 nla_put(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
12941 tcp->wake_len, tcp->wake_data) ||
12942 nla_put(msg, NL80211_WOWLAN_TCP_WAKE_MASK,
12943 DIV_ROUND_UP(tcp->wake_len, 8), tcp->wake_mask))
12944 return -ENOBUFS;
12945
12946 if (tcp->payload_seq.len &&
12947 nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ,
12948 sizeof(tcp->payload_seq), &tcp->payload_seq))
12949 return -ENOBUFS;
12950
12951 if (tcp->payload_tok.len &&
12952 nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
12953 sizeof(tcp->payload_tok) + tcp->tokens_size,
12954 &tcp->payload_tok))
12955 return -ENOBUFS;
12956
e248ad30
JB
12957 nla_nest_end(msg, nl_tcp);
12958
2a0e047e
JB
12959 return 0;
12960}
12961
75453ccb
LC
12962static int nl80211_send_wowlan_nd(struct sk_buff *msg,
12963 struct cfg80211_sched_scan_request *req)
12964{
3b06d277 12965 struct nlattr *nd, *freqs, *matches, *match, *scan_plans, *scan_plan;
75453ccb
LC
12966 int i;
12967
12968 if (!req)
12969 return 0;
12970
ae0be8de 12971 nd = nla_nest_start_noflag(msg, NL80211_WOWLAN_TRIG_NET_DETECT);
75453ccb
LC
12972 if (!nd)
12973 return -ENOBUFS;
12974
3b06d277
AS
12975 if (req->n_scan_plans == 1 &&
12976 nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL,
12977 req->scan_plans[0].interval * 1000))
75453ccb
LC
12978 return -ENOBUFS;
12979
21fea567
LC
12980 if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_DELAY, req->delay))
12981 return -ENOBUFS;
12982
bf95ecdb 12983 if (req->relative_rssi_set) {
12984 struct nl80211_bss_select_rssi_adjust rssi_adjust;
12985
12986 if (nla_put_s8(msg, NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI,
12987 req->relative_rssi))
12988 return -ENOBUFS;
12989
12990 rssi_adjust.band = req->rssi_adjust.band;
12991 rssi_adjust.delta = req->rssi_adjust.delta;
12992 if (nla_put(msg, NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST,
12993 sizeof(rssi_adjust), &rssi_adjust))
12994 return -ENOBUFS;
12995 }
12996
ae0be8de 12997 freqs = nla_nest_start_noflag(msg, NL80211_ATTR_SCAN_FREQUENCIES);
75453ccb
LC
12998 if (!freqs)
12999 return -ENOBUFS;
13000
53b18980
JB
13001 for (i = 0; i < req->n_channels; i++) {
13002 if (nla_put_u32(msg, i, req->channels[i]->center_freq))
13003 return -ENOBUFS;
13004 }
75453ccb
LC
13005
13006 nla_nest_end(msg, freqs);
13007
13008 if (req->n_match_sets) {
ae0be8de
MK
13009 matches = nla_nest_start_noflag(msg,
13010 NL80211_ATTR_SCHED_SCAN_MATCH);
76e1fb4b
JB
13011 if (!matches)
13012 return -ENOBUFS;
13013
75453ccb 13014 for (i = 0; i < req->n_match_sets; i++) {
ae0be8de 13015 match = nla_nest_start_noflag(msg, i);
76e1fb4b
JB
13016 if (!match)
13017 return -ENOBUFS;
13018
53b18980
JB
13019 if (nla_put(msg, NL80211_SCHED_SCAN_MATCH_ATTR_SSID,
13020 req->match_sets[i].ssid.ssid_len,
13021 req->match_sets[i].ssid.ssid))
13022 return -ENOBUFS;
75453ccb
LC
13023 nla_nest_end(msg, match);
13024 }
13025 nla_nest_end(msg, matches);
13026 }
13027
ae0be8de 13028 scan_plans = nla_nest_start_noflag(msg, NL80211_ATTR_SCHED_SCAN_PLANS);
3b06d277
AS
13029 if (!scan_plans)
13030 return -ENOBUFS;
13031
13032 for (i = 0; i < req->n_scan_plans; i++) {
ae0be8de 13033 scan_plan = nla_nest_start_noflag(msg, i + 1);
76e1fb4b
JB
13034 if (!scan_plan)
13035 return -ENOBUFS;
13036
67626964 13037 if (nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_INTERVAL,
3b06d277
AS
13038 req->scan_plans[i].interval) ||
13039 (req->scan_plans[i].iterations &&
13040 nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_ITERATIONS,
13041 req->scan_plans[i].iterations)))
13042 return -ENOBUFS;
13043 nla_nest_end(msg, scan_plan);
13044 }
13045 nla_nest_end(msg, scan_plans);
13046
75453ccb
LC
13047 nla_nest_end(msg, nd);
13048
13049 return 0;
13050}
13051
ff1b6e69
JB
13052static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
13053{
13054 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13055 struct sk_buff *msg;
13056 void *hdr;
2a0e047e 13057 u32 size = NLMSG_DEFAULT_SIZE;
ff1b6e69 13058
964dc9e2 13059 if (!rdev->wiphy.wowlan)
ff1b6e69
JB
13060 return -EOPNOTSUPP;
13061
6abb9cb9 13062 if (rdev->wiphy.wowlan_config && rdev->wiphy.wowlan_config->tcp) {
2a0e047e 13063 /* adjust size to have room for all the data */
6abb9cb9
JB
13064 size += rdev->wiphy.wowlan_config->tcp->tokens_size +
13065 rdev->wiphy.wowlan_config->tcp->payload_len +
13066 rdev->wiphy.wowlan_config->tcp->wake_len +
13067 rdev->wiphy.wowlan_config->tcp->wake_len / 8;
2a0e047e
JB
13068 }
13069
13070 msg = nlmsg_new(size, GFP_KERNEL);
ff1b6e69
JB
13071 if (!msg)
13072 return -ENOMEM;
13073
15e47304 13074 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
ff1b6e69
JB
13075 NL80211_CMD_GET_WOWLAN);
13076 if (!hdr)
13077 goto nla_put_failure;
13078
6abb9cb9 13079 if (rdev->wiphy.wowlan_config) {
ff1b6e69
JB
13080 struct nlattr *nl_wowlan;
13081
ae0be8de
MK
13082 nl_wowlan = nla_nest_start_noflag(msg,
13083 NL80211_ATTR_WOWLAN_TRIGGERS);
ff1b6e69
JB
13084 if (!nl_wowlan)
13085 goto nla_put_failure;
13086
6abb9cb9 13087 if ((rdev->wiphy.wowlan_config->any &&
9360ffd1 13088 nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
6abb9cb9 13089 (rdev->wiphy.wowlan_config->disconnect &&
9360ffd1 13090 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
6abb9cb9 13091 (rdev->wiphy.wowlan_config->magic_pkt &&
9360ffd1 13092 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
6abb9cb9 13093 (rdev->wiphy.wowlan_config->gtk_rekey_failure &&
9360ffd1 13094 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
6abb9cb9 13095 (rdev->wiphy.wowlan_config->eap_identity_req &&
9360ffd1 13096 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
6abb9cb9 13097 (rdev->wiphy.wowlan_config->four_way_handshake &&
9360ffd1 13098 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
6abb9cb9 13099 (rdev->wiphy.wowlan_config->rfkill_release &&
9360ffd1
DM
13100 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
13101 goto nla_put_failure;
2a0e047e 13102
bb92d199
AK
13103 if (nl80211_send_wowlan_patterns(msg, rdev))
13104 goto nla_put_failure;
2a0e047e 13105
6abb9cb9
JB
13106 if (nl80211_send_wowlan_tcp(msg,
13107 rdev->wiphy.wowlan_config->tcp))
2a0e047e 13108 goto nla_put_failure;
75453ccb
LC
13109
13110 if (nl80211_send_wowlan_nd(
13111 msg,
13112 rdev->wiphy.wowlan_config->nd_config))
13113 goto nla_put_failure;
2a0e047e 13114
ff1b6e69
JB
13115 nla_nest_end(msg, nl_wowlan);
13116 }
13117
13118 genlmsg_end(msg, hdr);
13119 return genlmsg_reply(msg, info);
13120
13121nla_put_failure:
13122 nlmsg_free(msg);
13123 return -ENOBUFS;
13124}
13125
2a0e047e
JB
13126static int nl80211_parse_wowlan_tcp(struct cfg80211_registered_device *rdev,
13127 struct nlattr *attr,
13128 struct cfg80211_wowlan *trig)
13129{
13130 struct nlattr *tb[NUM_NL80211_WOWLAN_TCP];
13131 struct cfg80211_wowlan_tcp *cfg;
13132 struct nl80211_wowlan_tcp_data_token *tok = NULL;
13133 struct nl80211_wowlan_tcp_data_seq *seq = NULL;
13134 u32 size;
13135 u32 data_size, wake_size, tokens_size = 0, wake_mask_size;
13136 int err, port;
13137
964dc9e2 13138 if (!rdev->wiphy.wowlan->tcp)
2a0e047e
JB
13139 return -EINVAL;
13140
8cb08174
JB
13141 err = nla_parse_nested_deprecated(tb, MAX_NL80211_WOWLAN_TCP, attr,
13142 nl80211_wowlan_tcp_policy, NULL);
2a0e047e
JB
13143 if (err)
13144 return err;
13145
13146 if (!tb[NL80211_WOWLAN_TCP_SRC_IPV4] ||
13147 !tb[NL80211_WOWLAN_TCP_DST_IPV4] ||
13148 !tb[NL80211_WOWLAN_TCP_DST_MAC] ||
13149 !tb[NL80211_WOWLAN_TCP_DST_PORT] ||
13150 !tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD] ||
13151 !tb[NL80211_WOWLAN_TCP_DATA_INTERVAL] ||
13152 !tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD] ||
13153 !tb[NL80211_WOWLAN_TCP_WAKE_MASK])
13154 return -EINVAL;
13155
13156 data_size = nla_len(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD]);
964dc9e2 13157 if (data_size > rdev->wiphy.wowlan->tcp->data_payload_max)
2a0e047e
JB
13158 return -EINVAL;
13159
13160 if (nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) >
964dc9e2 13161 rdev->wiphy.wowlan->tcp->data_interval_max ||
723d568a 13162 nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) == 0)
2a0e047e
JB
13163 return -EINVAL;
13164
13165 wake_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]);
964dc9e2 13166 if (wake_size > rdev->wiphy.wowlan->tcp->wake_payload_max)
2a0e047e
JB
13167 return -EINVAL;
13168
13169 wake_mask_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_MASK]);
13170 if (wake_mask_size != DIV_ROUND_UP(wake_size, 8))
13171 return -EINVAL;
13172
13173 if (tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]) {
13174 u32 tokln = nla_len(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]);
13175
13176 tok = nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]);
13177 tokens_size = tokln - sizeof(*tok);
13178
13179 if (!tok->len || tokens_size % tok->len)
13180 return -EINVAL;
964dc9e2 13181 if (!rdev->wiphy.wowlan->tcp->tok)
2a0e047e 13182 return -EINVAL;
964dc9e2 13183 if (tok->len > rdev->wiphy.wowlan->tcp->tok->max_len)
2a0e047e 13184 return -EINVAL;
964dc9e2 13185 if (tok->len < rdev->wiphy.wowlan->tcp->tok->min_len)
2a0e047e 13186 return -EINVAL;
964dc9e2 13187 if (tokens_size > rdev->wiphy.wowlan->tcp->tok->bufsize)
2a0e047e
JB
13188 return -EINVAL;
13189 if (tok->offset + tok->len > data_size)
13190 return -EINVAL;
13191 }
13192
13193 if (tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]) {
13194 seq = nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]);
964dc9e2 13195 if (!rdev->wiphy.wowlan->tcp->seq)
2a0e047e
JB
13196 return -EINVAL;
13197 if (seq->len == 0 || seq->len > 4)
13198 return -EINVAL;
13199 if (seq->len + seq->offset > data_size)
13200 return -EINVAL;
13201 }
13202
13203 size = sizeof(*cfg);
13204 size += data_size;
13205 size += wake_size + wake_mask_size;
13206 size += tokens_size;
13207
13208 cfg = kzalloc(size, GFP_KERNEL);
13209 if (!cfg)
13210 return -ENOMEM;
67b61f6c
JB
13211 cfg->src = nla_get_in_addr(tb[NL80211_WOWLAN_TCP_SRC_IPV4]);
13212 cfg->dst = nla_get_in_addr(tb[NL80211_WOWLAN_TCP_DST_IPV4]);
2a0e047e
JB
13213 memcpy(cfg->dst_mac, nla_data(tb[NL80211_WOWLAN_TCP_DST_MAC]),
13214 ETH_ALEN);
13215 if (tb[NL80211_WOWLAN_TCP_SRC_PORT])
13216 port = nla_get_u16(tb[NL80211_WOWLAN_TCP_SRC_PORT]);
13217 else
13218 port = 0;
13219#ifdef CONFIG_INET
13220 /* allocate a socket and port for it and use it */
13221 err = __sock_create(wiphy_net(&rdev->wiphy), PF_INET, SOCK_STREAM,
13222 IPPROTO_TCP, &cfg->sock, 1);
13223 if (err) {
13224 kfree(cfg);
13225 return err;
13226 }
13227 if (inet_csk_get_port(cfg->sock->sk, port)) {
13228 sock_release(cfg->sock);
13229 kfree(cfg);
13230 return -EADDRINUSE;
13231 }
13232 cfg->src_port = inet_sk(cfg->sock->sk)->inet_num;
13233#else
13234 if (!port) {
13235 kfree(cfg);
13236 return -EINVAL;
13237 }
13238 cfg->src_port = port;
13239#endif
13240
13241 cfg->dst_port = nla_get_u16(tb[NL80211_WOWLAN_TCP_DST_PORT]);
13242 cfg->payload_len = data_size;
13243 cfg->payload = (u8 *)cfg + sizeof(*cfg) + tokens_size;
13244 memcpy((void *)cfg->payload,
13245 nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD]),
13246 data_size);
13247 if (seq)
13248 cfg->payload_seq = *seq;
13249 cfg->data_interval = nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]);
13250 cfg->wake_len = wake_size;
13251 cfg->wake_data = (u8 *)cfg + sizeof(*cfg) + tokens_size + data_size;
13252 memcpy((void *)cfg->wake_data,
13253 nla_data(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]),
13254 wake_size);
13255 cfg->wake_mask = (u8 *)cfg + sizeof(*cfg) + tokens_size +
13256 data_size + wake_size;
13257 memcpy((void *)cfg->wake_mask,
13258 nla_data(tb[NL80211_WOWLAN_TCP_WAKE_MASK]),
13259 wake_mask_size);
13260 if (tok) {
13261 cfg->tokens_size = tokens_size;
13262 memcpy(&cfg->payload_tok, tok, sizeof(*tok) + tokens_size);
13263 }
13264
13265 trig->tcp = cfg;
13266
13267 return 0;
13268}
13269
8cd4d456
LC
13270static int nl80211_parse_wowlan_nd(struct cfg80211_registered_device *rdev,
13271 const struct wiphy_wowlan_support *wowlan,
13272 struct nlattr *attr,
13273 struct cfg80211_wowlan *trig)
13274{
13275 struct nlattr **tb;
13276 int err;
13277
6396bb22 13278 tb = kcalloc(NUM_NL80211_ATTR, sizeof(*tb), GFP_KERNEL);
8cd4d456
LC
13279 if (!tb)
13280 return -ENOMEM;
13281
13282 if (!(wowlan->flags & WIPHY_WOWLAN_NET_DETECT)) {
13283 err = -EOPNOTSUPP;
13284 goto out;
13285 }
13286
8cb08174
JB
13287 err = nla_parse_nested_deprecated(tb, NL80211_ATTR_MAX, attr,
13288 nl80211_policy, NULL);
8cd4d456
LC
13289 if (err)
13290 goto out;
13291
aad1e812
AVS
13292 trig->nd_config = nl80211_parse_sched_scan(&rdev->wiphy, NULL, tb,
13293 wowlan->max_nd_match_sets);
8cd4d456
LC
13294 err = PTR_ERR_OR_ZERO(trig->nd_config);
13295 if (err)
13296 trig->nd_config = NULL;
13297
13298out:
13299 kfree(tb);
13300 return err;
13301}
13302
ff1b6e69
JB
13303static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
13304{
13305 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13306 struct nlattr *tb[NUM_NL80211_WOWLAN_TRIG];
ff1b6e69 13307 struct cfg80211_wowlan new_triggers = {};
ae33bd81 13308 struct cfg80211_wowlan *ntrig;
964dc9e2 13309 const struct wiphy_wowlan_support *wowlan = rdev->wiphy.wowlan;
ff1b6e69 13310 int err, i;
6abb9cb9 13311 bool prev_enabled = rdev->wiphy.wowlan_config;
98fc4386 13312 bool regular = false;
ff1b6e69 13313
964dc9e2 13314 if (!wowlan)
ff1b6e69
JB
13315 return -EOPNOTSUPP;
13316
ae33bd81
JB
13317 if (!info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) {
13318 cfg80211_rdev_free_wowlan(rdev);
6abb9cb9 13319 rdev->wiphy.wowlan_config = NULL;
ae33bd81
JB
13320 goto set_wakeup;
13321 }
ff1b6e69 13322
8cb08174
JB
13323 err = nla_parse_nested_deprecated(tb, MAX_NL80211_WOWLAN_TRIG,
13324 info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS],
13325 nl80211_wowlan_policy, info->extack);
ff1b6e69
JB
13326 if (err)
13327 return err;
13328
13329 if (tb[NL80211_WOWLAN_TRIG_ANY]) {
13330 if (!(wowlan->flags & WIPHY_WOWLAN_ANY))
13331 return -EINVAL;
13332 new_triggers.any = true;
13333 }
13334
13335 if (tb[NL80211_WOWLAN_TRIG_DISCONNECT]) {
13336 if (!(wowlan->flags & WIPHY_WOWLAN_DISCONNECT))
13337 return -EINVAL;
13338 new_triggers.disconnect = true;
98fc4386 13339 regular = true;
ff1b6e69
JB
13340 }
13341
13342 if (tb[NL80211_WOWLAN_TRIG_MAGIC_PKT]) {
13343 if (!(wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT))
13344 return -EINVAL;
13345 new_triggers.magic_pkt = true;
98fc4386 13346 regular = true;
ff1b6e69
JB
13347 }
13348
77dbbb13
JB
13349 if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED])
13350 return -EINVAL;
13351
13352 if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE]) {
13353 if (!(wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE))
13354 return -EINVAL;
13355 new_triggers.gtk_rekey_failure = true;
98fc4386 13356 regular = true;
77dbbb13
JB
13357 }
13358
13359 if (tb[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST]) {
13360 if (!(wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ))
13361 return -EINVAL;
13362 new_triggers.eap_identity_req = true;
98fc4386 13363 regular = true;
77dbbb13
JB
13364 }
13365
13366 if (tb[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE]) {
13367 if (!(wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE))
13368 return -EINVAL;
13369 new_triggers.four_way_handshake = true;
98fc4386 13370 regular = true;
77dbbb13
JB
13371 }
13372
13373 if (tb[NL80211_WOWLAN_TRIG_RFKILL_RELEASE]) {
13374 if (!(wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE))
13375 return -EINVAL;
13376 new_triggers.rfkill_release = true;
98fc4386 13377 regular = true;
77dbbb13
JB
13378 }
13379
ff1b6e69
JB
13380 if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) {
13381 struct nlattr *pat;
13382 int n_patterns = 0;
bb92d199 13383 int rem, pat_len, mask_len, pkt_offset;
50ac6607 13384 struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
ff1b6e69 13385
98fc4386
JB
13386 regular = true;
13387
ff1b6e69
JB
13388 nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
13389 rem)
13390 n_patterns++;
13391 if (n_patterns > wowlan->n_patterns)
13392 return -EINVAL;
13393
13394 new_triggers.patterns = kcalloc(n_patterns,
13395 sizeof(new_triggers.patterns[0]),
13396 GFP_KERNEL);
13397 if (!new_triggers.patterns)
13398 return -ENOMEM;
13399
13400 new_triggers.n_patterns = n_patterns;
13401 i = 0;
13402
13403 nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
13404 rem) {
922bd80f
JB
13405 u8 *mask_pat;
13406
8cb08174
JB
13407 err = nla_parse_nested_deprecated(pat_tb,
13408 MAX_NL80211_PKTPAT,
13409 pat,
13410 nl80211_packet_pattern_policy,
13411 info->extack);
95bca62f
JB
13412 if (err)
13413 goto error;
13414
ff1b6e69 13415 err = -EINVAL;
50ac6607
AK
13416 if (!pat_tb[NL80211_PKTPAT_MASK] ||
13417 !pat_tb[NL80211_PKTPAT_PATTERN])
ff1b6e69 13418 goto error;
50ac6607 13419 pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
ff1b6e69 13420 mask_len = DIV_ROUND_UP(pat_len, 8);
50ac6607 13421 if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
ff1b6e69
JB
13422 goto error;
13423 if (pat_len > wowlan->pattern_max_len ||
13424 pat_len < wowlan->pattern_min_len)
13425 goto error;
13426
50ac6607 13427 if (!pat_tb[NL80211_PKTPAT_OFFSET])
bb92d199
AK
13428 pkt_offset = 0;
13429 else
13430 pkt_offset = nla_get_u32(
50ac6607 13431 pat_tb[NL80211_PKTPAT_OFFSET]);
bb92d199
AK
13432 if (pkt_offset > wowlan->max_pkt_offset)
13433 goto error;
13434 new_triggers.patterns[i].pkt_offset = pkt_offset;
13435
922bd80f
JB
13436 mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL);
13437 if (!mask_pat) {
ff1b6e69
JB
13438 err = -ENOMEM;
13439 goto error;
13440 }
922bd80f
JB
13441 new_triggers.patterns[i].mask = mask_pat;
13442 memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]),
ff1b6e69 13443 mask_len);
922bd80f
JB
13444 mask_pat += mask_len;
13445 new_triggers.patterns[i].pattern = mask_pat;
ff1b6e69 13446 new_triggers.patterns[i].pattern_len = pat_len;
922bd80f 13447 memcpy(mask_pat,
50ac6607 13448 nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
ff1b6e69
JB
13449 pat_len);
13450 i++;
13451 }
13452 }
13453
2a0e047e 13454 if (tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION]) {
98fc4386 13455 regular = true;
2a0e047e
JB
13456 err = nl80211_parse_wowlan_tcp(
13457 rdev, tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION],
13458 &new_triggers);
13459 if (err)
13460 goto error;
13461 }
13462
8cd4d456 13463 if (tb[NL80211_WOWLAN_TRIG_NET_DETECT]) {
98fc4386 13464 regular = true;
8cd4d456
LC
13465 err = nl80211_parse_wowlan_nd(
13466 rdev, wowlan, tb[NL80211_WOWLAN_TRIG_NET_DETECT],
13467 &new_triggers);
13468 if (err)
13469 goto error;
13470 }
13471
98fc4386
JB
13472 /* The 'any' trigger means the device continues operating more or less
13473 * as in its normal operation mode and wakes up the host on most of the
13474 * normal interrupts (like packet RX, ...)
13475 * It therefore makes little sense to combine with the more constrained
13476 * wakeup trigger modes.
13477 */
13478 if (new_triggers.any && regular) {
13479 err = -EINVAL;
13480 goto error;
13481 }
13482
ae33bd81
JB
13483 ntrig = kmemdup(&new_triggers, sizeof(new_triggers), GFP_KERNEL);
13484 if (!ntrig) {
13485 err = -ENOMEM;
13486 goto error;
ff1b6e69 13487 }
ae33bd81 13488 cfg80211_rdev_free_wowlan(rdev);
6abb9cb9 13489 rdev->wiphy.wowlan_config = ntrig;
ff1b6e69 13490
ae33bd81 13491 set_wakeup:
6abb9cb9
JB
13492 if (rdev->ops->set_wakeup &&
13493 prev_enabled != !!rdev->wiphy.wowlan_config)
13494 rdev_set_wakeup(rdev, rdev->wiphy.wowlan_config);
6d52563f 13495
ff1b6e69
JB
13496 return 0;
13497 error:
13498 for (i = 0; i < new_triggers.n_patterns; i++)
13499 kfree(new_triggers.patterns[i].mask);
13500 kfree(new_triggers.patterns);
2a0e047e
JB
13501 if (new_triggers.tcp && new_triggers.tcp->sock)
13502 sock_release(new_triggers.tcp->sock);
13503 kfree(new_triggers.tcp);
e5dbe070 13504 kfree(new_triggers.nd_config);
ff1b6e69
JB
13505 return err;
13506}
dfb89c56 13507#endif
ff1b6e69 13508
be29b99a
AK
13509static int nl80211_send_coalesce_rules(struct sk_buff *msg,
13510 struct cfg80211_registered_device *rdev)
13511{
13512 struct nlattr *nl_pats, *nl_pat, *nl_rule, *nl_rules;
13513 int i, j, pat_len;
13514 struct cfg80211_coalesce_rules *rule;
13515
13516 if (!rdev->coalesce->n_rules)
13517 return 0;
13518
ae0be8de 13519 nl_rules = nla_nest_start_noflag(msg, NL80211_ATTR_COALESCE_RULE);
be29b99a
AK
13520 if (!nl_rules)
13521 return -ENOBUFS;
13522
13523 for (i = 0; i < rdev->coalesce->n_rules; i++) {
ae0be8de 13524 nl_rule = nla_nest_start_noflag(msg, i + 1);
be29b99a
AK
13525 if (!nl_rule)
13526 return -ENOBUFS;
13527
13528 rule = &rdev->coalesce->rules[i];
13529 if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_DELAY,
13530 rule->delay))
13531 return -ENOBUFS;
13532
13533 if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_CONDITION,
13534 rule->condition))
13535 return -ENOBUFS;
13536
ae0be8de
MK
13537 nl_pats = nla_nest_start_noflag(msg,
13538 NL80211_ATTR_COALESCE_RULE_PKT_PATTERN);
be29b99a
AK
13539 if (!nl_pats)
13540 return -ENOBUFS;
13541
13542 for (j = 0; j < rule->n_patterns; j++) {
ae0be8de 13543 nl_pat = nla_nest_start_noflag(msg, j + 1);
be29b99a
AK
13544 if (!nl_pat)
13545 return -ENOBUFS;
13546 pat_len = rule->patterns[j].pattern_len;
13547 if (nla_put(msg, NL80211_PKTPAT_MASK,
13548 DIV_ROUND_UP(pat_len, 8),
13549 rule->patterns[j].mask) ||
13550 nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
13551 rule->patterns[j].pattern) ||
13552 nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
13553 rule->patterns[j].pkt_offset))
13554 return -ENOBUFS;
13555 nla_nest_end(msg, nl_pat);
13556 }
13557 nla_nest_end(msg, nl_pats);
13558 nla_nest_end(msg, nl_rule);
13559 }
13560 nla_nest_end(msg, nl_rules);
13561
13562 return 0;
13563}
13564
13565static int nl80211_get_coalesce(struct sk_buff *skb, struct genl_info *info)
13566{
13567 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13568 struct sk_buff *msg;
13569 void *hdr;
13570
13571 if (!rdev->wiphy.coalesce)
13572 return -EOPNOTSUPP;
13573
13574 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
13575 if (!msg)
13576 return -ENOMEM;
13577
13578 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
13579 NL80211_CMD_GET_COALESCE);
13580 if (!hdr)
13581 goto nla_put_failure;
13582
13583 if (rdev->coalesce && nl80211_send_coalesce_rules(msg, rdev))
13584 goto nla_put_failure;
13585
13586 genlmsg_end(msg, hdr);
13587 return genlmsg_reply(msg, info);
13588
13589nla_put_failure:
13590 nlmsg_free(msg);
13591 return -ENOBUFS;
13592}
13593
13594void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev)
13595{
13596 struct cfg80211_coalesce *coalesce = rdev->coalesce;
13597 int i, j;
13598 struct cfg80211_coalesce_rules *rule;
13599
13600 if (!coalesce)
13601 return;
13602
13603 for (i = 0; i < coalesce->n_rules; i++) {
13604 rule = &coalesce->rules[i];
13605 for (j = 0; j < rule->n_patterns; j++)
13606 kfree(rule->patterns[j].mask);
13607 kfree(rule->patterns);
13608 }
13609 kfree(coalesce->rules);
13610 kfree(coalesce);
13611 rdev->coalesce = NULL;
13612}
13613
13614static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev,
13615 struct nlattr *rule,
13616 struct cfg80211_coalesce_rules *new_rule)
13617{
13618 int err, i;
13619 const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce;
13620 struct nlattr *tb[NUM_NL80211_ATTR_COALESCE_RULE], *pat;
13621 int rem, pat_len, mask_len, pkt_offset, n_patterns = 0;
13622 struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
13623
8cb08174
JB
13624 err = nla_parse_nested_deprecated(tb, NL80211_ATTR_COALESCE_RULE_MAX,
13625 rule, nl80211_coalesce_policy, NULL);
be29b99a
AK
13626 if (err)
13627 return err;
13628
13629 if (tb[NL80211_ATTR_COALESCE_RULE_DELAY])
13630 new_rule->delay =
13631 nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_DELAY]);
13632 if (new_rule->delay > coalesce->max_delay)
13633 return -EINVAL;
13634
13635 if (tb[NL80211_ATTR_COALESCE_RULE_CONDITION])
13636 new_rule->condition =
13637 nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_CONDITION]);
be29b99a
AK
13638
13639 if (!tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN])
13640 return -EINVAL;
13641
13642 nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
13643 rem)
13644 n_patterns++;
13645 if (n_patterns > coalesce->n_patterns)
13646 return -EINVAL;
13647
13648 new_rule->patterns = kcalloc(n_patterns, sizeof(new_rule->patterns[0]),
13649 GFP_KERNEL);
13650 if (!new_rule->patterns)
13651 return -ENOMEM;
13652
13653 new_rule->n_patterns = n_patterns;
13654 i = 0;
13655
13656 nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
13657 rem) {
922bd80f
JB
13658 u8 *mask_pat;
13659
8cb08174
JB
13660 err = nla_parse_nested_deprecated(pat_tb, MAX_NL80211_PKTPAT,
13661 pat,
13662 nl80211_packet_pattern_policy,
13663 NULL);
95bca62f
JB
13664 if (err)
13665 return err;
13666
be29b99a
AK
13667 if (!pat_tb[NL80211_PKTPAT_MASK] ||
13668 !pat_tb[NL80211_PKTPAT_PATTERN])
13669 return -EINVAL;
13670 pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
13671 mask_len = DIV_ROUND_UP(pat_len, 8);
13672 if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
13673 return -EINVAL;
13674 if (pat_len > coalesce->pattern_max_len ||
13675 pat_len < coalesce->pattern_min_len)
13676 return -EINVAL;
13677
13678 if (!pat_tb[NL80211_PKTPAT_OFFSET])
13679 pkt_offset = 0;
13680 else
13681 pkt_offset = nla_get_u32(pat_tb[NL80211_PKTPAT_OFFSET]);
13682 if (pkt_offset > coalesce->max_pkt_offset)
13683 return -EINVAL;
13684 new_rule->patterns[i].pkt_offset = pkt_offset;
13685
922bd80f
JB
13686 mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL);
13687 if (!mask_pat)
be29b99a 13688 return -ENOMEM;
922bd80f
JB
13689
13690 new_rule->patterns[i].mask = mask_pat;
13691 memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]),
13692 mask_len);
13693
13694 mask_pat += mask_len;
13695 new_rule->patterns[i].pattern = mask_pat;
be29b99a 13696 new_rule->patterns[i].pattern_len = pat_len;
922bd80f
JB
13697 memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
13698 pat_len);
be29b99a
AK
13699 i++;
13700 }
13701
13702 return 0;
13703}
13704
13705static int nl80211_set_coalesce(struct sk_buff *skb, struct genl_info *info)
13706{
13707 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13708 const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce;
13709 struct cfg80211_coalesce new_coalesce = {};
13710 struct cfg80211_coalesce *n_coalesce;
13711 int err, rem_rule, n_rules = 0, i, j;
13712 struct nlattr *rule;
13713 struct cfg80211_coalesce_rules *tmp_rule;
13714
13715 if (!rdev->wiphy.coalesce || !rdev->ops->set_coalesce)
13716 return -EOPNOTSUPP;
13717
13718 if (!info->attrs[NL80211_ATTR_COALESCE_RULE]) {
13719 cfg80211_rdev_free_coalesce(rdev);
a1056b1b 13720 rdev_set_coalesce(rdev, NULL);
be29b99a
AK
13721 return 0;
13722 }
13723
13724 nla_for_each_nested(rule, info->attrs[NL80211_ATTR_COALESCE_RULE],
13725 rem_rule)
13726 n_rules++;
13727 if (n_rules > coalesce->n_rules)
13728 return -EINVAL;
13729
13730 new_coalesce.rules = kcalloc(n_rules, sizeof(new_coalesce.rules[0]),
13731 GFP_KERNEL);
13732 if (!new_coalesce.rules)
13733 return -ENOMEM;
13734
13735 new_coalesce.n_rules = n_rules;
13736 i = 0;
13737
13738 nla_for_each_nested(rule, info->attrs[NL80211_ATTR_COALESCE_RULE],
13739 rem_rule) {
13740 err = nl80211_parse_coalesce_rule(rdev, rule,
13741 &new_coalesce.rules[i]);
13742 if (err)
13743 goto error;
13744
13745 i++;
13746 }
13747
a1056b1b 13748 err = rdev_set_coalesce(rdev, &new_coalesce);
be29b99a
AK
13749 if (err)
13750 goto error;
13751
13752 n_coalesce = kmemdup(&new_coalesce, sizeof(new_coalesce), GFP_KERNEL);
13753 if (!n_coalesce) {
13754 err = -ENOMEM;
13755 goto error;
13756 }
13757 cfg80211_rdev_free_coalesce(rdev);
13758 rdev->coalesce = n_coalesce;
13759
13760 return 0;
13761error:
13762 for (i = 0; i < new_coalesce.n_rules; i++) {
13763 tmp_rule = &new_coalesce.rules[i];
13764 for (j = 0; j < tmp_rule->n_patterns; j++)
13765 kfree(tmp_rule->patterns[j].mask);
13766 kfree(tmp_rule->patterns);
13767 }
13768 kfree(new_coalesce.rules);
13769
13770 return err;
13771}
13772
e5497d76
JB
13773static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
13774{
13775 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13776 struct net_device *dev = info->user_ptr[1];
13777 struct wireless_dev *wdev = dev->ieee80211_ptr;
13778 struct nlattr *tb[NUM_NL80211_REKEY_DATA];
f495acd8 13779 struct cfg80211_gtk_rekey_data rekey_data = {};
e5497d76
JB
13780 int err;
13781
13782 if (!info->attrs[NL80211_ATTR_REKEY_DATA])
13783 return -EINVAL;
13784
8cb08174
JB
13785 err = nla_parse_nested_deprecated(tb, MAX_NL80211_REKEY_DATA,
13786 info->attrs[NL80211_ATTR_REKEY_DATA],
13787 nl80211_rekey_policy, info->extack);
e5497d76
JB
13788 if (err)
13789 return err;
13790
e785fa0a
VD
13791 if (!tb[NL80211_REKEY_DATA_REPLAY_CTR] || !tb[NL80211_REKEY_DATA_KEK] ||
13792 !tb[NL80211_REKEY_DATA_KCK])
13793 return -EINVAL;
093a48d2
NE
13794 if (nla_len(tb[NL80211_REKEY_DATA_KEK]) != NL80211_KEK_LEN &&
13795 !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK &&
13796 nla_len(tb[NL80211_REKEY_DATA_KEK]) == NL80211_KEK_EXT_LEN))
e5497d76 13797 return -ERANGE;
093a48d2
NE
13798 if (nla_len(tb[NL80211_REKEY_DATA_KCK]) != NL80211_KCK_LEN &&
13799 !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK &&
13800 nla_len(tb[NL80211_REKEY_DATA_KEK]) == NL80211_KCK_EXT_LEN))
e5497d76
JB
13801 return -ERANGE;
13802
78f686ca
JB
13803 rekey_data.kek = nla_data(tb[NL80211_REKEY_DATA_KEK]);
13804 rekey_data.kck = nla_data(tb[NL80211_REKEY_DATA_KCK]);
13805 rekey_data.replay_ctr = nla_data(tb[NL80211_REKEY_DATA_REPLAY_CTR]);
093a48d2
NE
13806 rekey_data.kek_len = nla_len(tb[NL80211_REKEY_DATA_KEK]);
13807 rekey_data.kck_len = nla_len(tb[NL80211_REKEY_DATA_KCK]);
13808 if (tb[NL80211_REKEY_DATA_AKM])
13809 rekey_data.akm = nla_get_u32(tb[NL80211_REKEY_DATA_AKM]);
e5497d76
JB
13810
13811 wdev_lock(wdev);
7b0a0e3c 13812 if (!wdev->connected) {
e5497d76
JB
13813 err = -ENOTCONN;
13814 goto out;
13815 }
13816
13817 if (!rdev->ops->set_rekey_data) {
13818 err = -EOPNOTSUPP;
13819 goto out;
13820 }
13821
e35e4d28 13822 err = rdev_set_rekey_data(rdev, dev, &rekey_data);
e5497d76
JB
13823 out:
13824 wdev_unlock(wdev);
13825 return err;
13826}
13827
28946da7
JB
13828static int nl80211_register_unexpected_frame(struct sk_buff *skb,
13829 struct genl_info *info)
13830{
13831 struct net_device *dev = info->user_ptr[1];
13832 struct wireless_dev *wdev = dev->ieee80211_ptr;
13833
13834 if (wdev->iftype != NL80211_IFTYPE_AP &&
13835 wdev->iftype != NL80211_IFTYPE_P2P_GO)
13836 return -EINVAL;
13837
15e47304 13838 if (wdev->ap_unexpected_nlportid)
28946da7
JB
13839 return -EBUSY;
13840
15e47304 13841 wdev->ap_unexpected_nlportid = info->snd_portid;
28946da7
JB
13842 return 0;
13843}
13844
7f6cf311
JB
13845static int nl80211_probe_client(struct sk_buff *skb,
13846 struct genl_info *info)
13847{
13848 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13849 struct net_device *dev = info->user_ptr[1];
13850 struct wireless_dev *wdev = dev->ieee80211_ptr;
13851 struct sk_buff *msg;
13852 void *hdr;
13853 const u8 *addr;
13854 u64 cookie;
13855 int err;
13856
13857 if (wdev->iftype != NL80211_IFTYPE_AP &&
13858 wdev->iftype != NL80211_IFTYPE_P2P_GO)
13859 return -EOPNOTSUPP;
13860
13861 if (!info->attrs[NL80211_ATTR_MAC])
13862 return -EINVAL;
13863
13864 if (!rdev->ops->probe_client)
13865 return -EOPNOTSUPP;
13866
13867 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
13868 if (!msg)
13869 return -ENOMEM;
13870
15e47304 13871 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
7f6cf311 13872 NL80211_CMD_PROBE_CLIENT);
cb35fba3
DC
13873 if (!hdr) {
13874 err = -ENOBUFS;
7f6cf311
JB
13875 goto free_msg;
13876 }
13877
13878 addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
13879
e35e4d28 13880 err = rdev_probe_client(rdev, dev, addr, &cookie);
7f6cf311
JB
13881 if (err)
13882 goto free_msg;
13883
2dad624e
ND
13884 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
13885 NL80211_ATTR_PAD))
9360ffd1 13886 goto nla_put_failure;
7f6cf311
JB
13887
13888 genlmsg_end(msg, hdr);
13889
13890 return genlmsg_reply(msg, info);
13891
13892 nla_put_failure:
13893 err = -ENOBUFS;
13894 free_msg:
13895 nlmsg_free(msg);
13896 return err;
13897}
13898
5e760230
JB
13899static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info)
13900{
13901 struct cfg80211_registered_device *rdev = info->user_ptr[0];
37c73b5f
BG
13902 struct cfg80211_beacon_registration *reg, *nreg;
13903 int rv;
5e760230
JB
13904
13905 if (!(rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS))
13906 return -EOPNOTSUPP;
13907
37c73b5f
BG
13908 nreg = kzalloc(sizeof(*nreg), GFP_KERNEL);
13909 if (!nreg)
13910 return -ENOMEM;
13911
13912 /* First, check if already registered. */
13913 spin_lock_bh(&rdev->beacon_registrations_lock);
13914 list_for_each_entry(reg, &rdev->beacon_registrations, list) {
13915 if (reg->nlportid == info->snd_portid) {
13916 rv = -EALREADY;
13917 goto out_err;
13918 }
13919 }
13920 /* Add it to the list */
13921 nreg->nlportid = info->snd_portid;
13922 list_add(&nreg->list, &rdev->beacon_registrations);
5e760230 13923
37c73b5f 13924 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230
JB
13925
13926 return 0;
37c73b5f
BG
13927out_err:
13928 spin_unlock_bh(&rdev->beacon_registrations_lock);
13929 kfree(nreg);
13930 return rv;
5e760230
JB
13931}
13932
98104fde
JB
13933static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
13934{
13935 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13936 struct wireless_dev *wdev = info->user_ptr[1];
13937 int err;
13938
13939 if (!rdev->ops->start_p2p_device)
13940 return -EOPNOTSUPP;
13941
13942 if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
13943 return -EOPNOTSUPP;
13944
73c7da3d 13945 if (wdev_running(wdev))
98104fde
JB
13946 return 0;
13947
358ae888 13948 if (rfkill_blocked(rdev->wiphy.rfkill))
b6a55015 13949 return -ERFKILL;
98104fde 13950
eeb126e9 13951 err = rdev_start_p2p_device(rdev, wdev);
98104fde
JB
13952 if (err)
13953 return err;
13954
73c7da3d 13955 wdev->is_running = true;
98104fde 13956 rdev->opencount++;
98104fde
JB
13957
13958 return 0;
13959}
13960
13961static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
13962{
13963 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13964 struct wireless_dev *wdev = info->user_ptr[1];
13965
13966 if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
13967 return -EOPNOTSUPP;
13968
13969 if (!rdev->ops->stop_p2p_device)
13970 return -EOPNOTSUPP;
13971
f9f47529 13972 cfg80211_stop_p2p_device(rdev, wdev);
98104fde
JB
13973
13974 return 0;
13975}
13976
cb3b7d87
AB
13977static int nl80211_start_nan(struct sk_buff *skb, struct genl_info *info)
13978{
13979 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13980 struct wireless_dev *wdev = info->user_ptr[1];
13981 struct cfg80211_nan_conf conf = {};
13982 int err;
13983
13984 if (wdev->iftype != NL80211_IFTYPE_NAN)
13985 return -EOPNOTSUPP;
13986
eeb04a96 13987 if (wdev_running(wdev))
cb3b7d87
AB
13988 return -EEXIST;
13989
358ae888 13990 if (rfkill_blocked(rdev->wiphy.rfkill))
cb3b7d87
AB
13991 return -ERFKILL;
13992
13993 if (!info->attrs[NL80211_ATTR_NAN_MASTER_PREF])
13994 return -EINVAL;
13995
cb3b7d87
AB
13996 conf.master_pref =
13997 nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]);
cb3b7d87 13998
8585989d
LC
13999 if (info->attrs[NL80211_ATTR_BANDS]) {
14000 u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]);
14001
14002 if (bands & ~(u32)wdev->wiphy->nan_supported_bands)
14003 return -EOPNOTSUPP;
14004
14005 if (bands && !(bands & BIT(NL80211_BAND_2GHZ)))
14006 return -EINVAL;
14007
14008 conf.bands = bands;
14009 }
cb3b7d87
AB
14010
14011 err = rdev_start_nan(rdev, wdev, &conf);
14012 if (err)
14013 return err;
14014
73c7da3d 14015 wdev->is_running = true;
cb3b7d87
AB
14016 rdev->opencount++;
14017
14018 return 0;
14019}
14020
14021static int nl80211_stop_nan(struct sk_buff *skb, struct genl_info *info)
14022{
14023 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14024 struct wireless_dev *wdev = info->user_ptr[1];
14025
14026 if (wdev->iftype != NL80211_IFTYPE_NAN)
14027 return -EOPNOTSUPP;
14028
14029 cfg80211_stop_nan(rdev, wdev);
14030
14031 return 0;
14032}
14033
a442b761
AB
14034static int validate_nan_filter(struct nlattr *filter_attr)
14035{
14036 struct nlattr *attr;
14037 int len = 0, n_entries = 0, rem;
14038
14039 nla_for_each_nested(attr, filter_attr, rem) {
14040 len += nla_len(attr);
14041 n_entries++;
14042 }
14043
14044 if (len >= U8_MAX)
14045 return -EINVAL;
14046
14047 return n_entries;
14048}
14049
14050static int handle_nan_filter(struct nlattr *attr_filter,
14051 struct cfg80211_nan_func *func,
14052 bool tx)
14053{
14054 struct nlattr *attr;
14055 int n_entries, rem, i;
14056 struct cfg80211_nan_func_filter *filter;
14057
14058 n_entries = validate_nan_filter(attr_filter);
14059 if (n_entries < 0)
14060 return n_entries;
14061
14062 BUILD_BUG_ON(sizeof(*func->rx_filters) != sizeof(*func->tx_filters));
14063
14064 filter = kcalloc(n_entries, sizeof(*func->rx_filters), GFP_KERNEL);
14065 if (!filter)
14066 return -ENOMEM;
14067
14068 i = 0;
14069 nla_for_each_nested(attr, attr_filter, rem) {
b15ca182 14070 filter[i].filter = nla_memdup(attr, GFP_KERNEL);
6ad27f52
JJ
14071 if (!filter[i].filter)
14072 goto err;
14073
a442b761
AB
14074 filter[i].len = nla_len(attr);
14075 i++;
14076 }
14077 if (tx) {
14078 func->num_tx_filters = n_entries;
14079 func->tx_filters = filter;
14080 } else {
14081 func->num_rx_filters = n_entries;
14082 func->rx_filters = filter;
14083 }
14084
14085 return 0;
6ad27f52
JJ
14086
14087err:
14088 i = 0;
14089 nla_for_each_nested(attr, attr_filter, rem) {
14090 kfree(filter[i].filter);
14091 i++;
14092 }
14093 kfree(filter);
14094 return -ENOMEM;
a442b761
AB
14095}
14096
14097static int nl80211_nan_add_func(struct sk_buff *skb,
14098 struct genl_info *info)
14099{
14100 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14101 struct wireless_dev *wdev = info->user_ptr[1];
14102 struct nlattr *tb[NUM_NL80211_NAN_FUNC_ATTR], *func_attr;
14103 struct cfg80211_nan_func *func;
14104 struct sk_buff *msg = NULL;
14105 void *hdr = NULL;
14106 int err = 0;
14107
14108 if (wdev->iftype != NL80211_IFTYPE_NAN)
14109 return -EOPNOTSUPP;
14110
73c7da3d 14111 if (!wdev_running(wdev))
a442b761
AB
14112 return -ENOTCONN;
14113
14114 if (!info->attrs[NL80211_ATTR_NAN_FUNC])
14115 return -EINVAL;
14116
8cb08174
JB
14117 err = nla_parse_nested_deprecated(tb, NL80211_NAN_FUNC_ATTR_MAX,
14118 info->attrs[NL80211_ATTR_NAN_FUNC],
14119 nl80211_nan_func_policy,
14120 info->extack);
a442b761
AB
14121 if (err)
14122 return err;
14123
14124 func = kzalloc(sizeof(*func), GFP_KERNEL);
14125 if (!func)
14126 return -ENOMEM;
14127
b60ad348 14128 func->cookie = cfg80211_assign_cookie(rdev);
a442b761 14129
cb9abd48 14130 if (!tb[NL80211_NAN_FUNC_TYPE]) {
a442b761
AB
14131 err = -EINVAL;
14132 goto out;
14133 }
14134
14135
14136 func->type = nla_get_u8(tb[NL80211_NAN_FUNC_TYPE]);
14137
14138 if (!tb[NL80211_NAN_FUNC_SERVICE_ID]) {
14139 err = -EINVAL;
14140 goto out;
14141 }
14142
14143 memcpy(func->service_id, nla_data(tb[NL80211_NAN_FUNC_SERVICE_ID]),
14144 sizeof(func->service_id));
14145
14146 func->close_range =
14147 nla_get_flag(tb[NL80211_NAN_FUNC_CLOSE_RANGE]);
14148
14149 if (tb[NL80211_NAN_FUNC_SERVICE_INFO]) {
14150 func->serv_spec_info_len =
14151 nla_len(tb[NL80211_NAN_FUNC_SERVICE_INFO]);
14152 func->serv_spec_info =
14153 kmemdup(nla_data(tb[NL80211_NAN_FUNC_SERVICE_INFO]),
14154 func->serv_spec_info_len,
14155 GFP_KERNEL);
14156 if (!func->serv_spec_info) {
14157 err = -ENOMEM;
14158 goto out;
14159 }
14160 }
14161
14162 if (tb[NL80211_NAN_FUNC_TTL])
14163 func->ttl = nla_get_u32(tb[NL80211_NAN_FUNC_TTL]);
14164
14165 switch (func->type) {
14166 case NL80211_NAN_FUNC_PUBLISH:
14167 if (!tb[NL80211_NAN_FUNC_PUBLISH_TYPE]) {
14168 err = -EINVAL;
14169 goto out;
14170 }
14171
14172 func->publish_type =
14173 nla_get_u8(tb[NL80211_NAN_FUNC_PUBLISH_TYPE]);
14174 func->publish_bcast =
14175 nla_get_flag(tb[NL80211_NAN_FUNC_PUBLISH_BCAST]);
14176
14177 if ((!(func->publish_type & NL80211_NAN_SOLICITED_PUBLISH)) &&
14178 func->publish_bcast) {
14179 err = -EINVAL;
14180 goto out;
14181 }
14182 break;
14183 case NL80211_NAN_FUNC_SUBSCRIBE:
14184 func->subscribe_active =
14185 nla_get_flag(tb[NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE]);
14186 break;
14187 case NL80211_NAN_FUNC_FOLLOW_UP:
14188 if (!tb[NL80211_NAN_FUNC_FOLLOW_UP_ID] ||
3ea15452
HC
14189 !tb[NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID] ||
14190 !tb[NL80211_NAN_FUNC_FOLLOW_UP_DEST]) {
a442b761
AB
14191 err = -EINVAL;
14192 goto out;
14193 }
14194
14195 func->followup_id =
14196 nla_get_u8(tb[NL80211_NAN_FUNC_FOLLOW_UP_ID]);
14197 func->followup_reqid =
14198 nla_get_u8(tb[NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID]);
14199 memcpy(func->followup_dest.addr,
14200 nla_data(tb[NL80211_NAN_FUNC_FOLLOW_UP_DEST]),
14201 sizeof(func->followup_dest.addr));
14202 if (func->ttl) {
14203 err = -EINVAL;
14204 goto out;
14205 }
14206 break;
14207 default:
14208 err = -EINVAL;
14209 goto out;
14210 }
14211
14212 if (tb[NL80211_NAN_FUNC_SRF]) {
14213 struct nlattr *srf_tb[NUM_NL80211_NAN_SRF_ATTR];
14214
8cb08174
JB
14215 err = nla_parse_nested_deprecated(srf_tb,
14216 NL80211_NAN_SRF_ATTR_MAX,
14217 tb[NL80211_NAN_FUNC_SRF],
14218 nl80211_nan_srf_policy,
14219 info->extack);
a442b761
AB
14220 if (err)
14221 goto out;
14222
14223 func->srf_include =
14224 nla_get_flag(srf_tb[NL80211_NAN_SRF_INCLUDE]);
14225
14226 if (srf_tb[NL80211_NAN_SRF_BF]) {
14227 if (srf_tb[NL80211_NAN_SRF_MAC_ADDRS] ||
14228 !srf_tb[NL80211_NAN_SRF_BF_IDX]) {
14229 err = -EINVAL;
14230 goto out;
14231 }
14232
14233 func->srf_bf_len =
14234 nla_len(srf_tb[NL80211_NAN_SRF_BF]);
14235 func->srf_bf =
14236 kmemdup(nla_data(srf_tb[NL80211_NAN_SRF_BF]),
14237 func->srf_bf_len, GFP_KERNEL);
14238 if (!func->srf_bf) {
14239 err = -ENOMEM;
14240 goto out;
14241 }
14242
14243 func->srf_bf_idx =
14244 nla_get_u8(srf_tb[NL80211_NAN_SRF_BF_IDX]);
14245 } else {
14246 struct nlattr *attr, *mac_attr =
14247 srf_tb[NL80211_NAN_SRF_MAC_ADDRS];
14248 int n_entries, rem, i = 0;
14249
14250 if (!mac_attr) {
14251 err = -EINVAL;
14252 goto out;
14253 }
14254
14255 n_entries = validate_acl_mac_addrs(mac_attr);
14256 if (n_entries <= 0) {
14257 err = -EINVAL;
14258 goto out;
14259 }
14260
14261 func->srf_num_macs = n_entries;
14262 func->srf_macs =
6396bb22 14263 kcalloc(n_entries, sizeof(*func->srf_macs),
a442b761
AB
14264 GFP_KERNEL);
14265 if (!func->srf_macs) {
14266 err = -ENOMEM;
14267 goto out;
14268 }
14269
14270 nla_for_each_nested(attr, mac_attr, rem)
14271 memcpy(func->srf_macs[i++].addr, nla_data(attr),
14272 sizeof(*func->srf_macs));
14273 }
14274 }
14275
14276 if (tb[NL80211_NAN_FUNC_TX_MATCH_FILTER]) {
14277 err = handle_nan_filter(tb[NL80211_NAN_FUNC_TX_MATCH_FILTER],
14278 func, true);
14279 if (err)
14280 goto out;
14281 }
14282
14283 if (tb[NL80211_NAN_FUNC_RX_MATCH_FILTER]) {
14284 err = handle_nan_filter(tb[NL80211_NAN_FUNC_RX_MATCH_FILTER],
14285 func, false);
14286 if (err)
14287 goto out;
14288 }
14289
14290 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
14291 if (!msg) {
14292 err = -ENOMEM;
14293 goto out;
14294 }
14295
14296 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
14297 NL80211_CMD_ADD_NAN_FUNCTION);
14298 /* This can't really happen - we just allocated 4KB */
14299 if (WARN_ON(!hdr)) {
14300 err = -ENOMEM;
14301 goto out;
14302 }
14303
14304 err = rdev_add_nan_func(rdev, wdev, func);
14305out:
14306 if (err < 0) {
14307 cfg80211_free_nan_func(func);
14308 nlmsg_free(msg);
14309 return err;
14310 }
14311
14312 /* propagate the instance id and cookie to userspace */
14313 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, func->cookie,
14314 NL80211_ATTR_PAD))
14315 goto nla_put_failure;
14316
ae0be8de 14317 func_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_FUNC);
a442b761
AB
14318 if (!func_attr)
14319 goto nla_put_failure;
14320
14321 if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID,
14322 func->instance_id))
14323 goto nla_put_failure;
14324
14325 nla_nest_end(msg, func_attr);
14326
14327 genlmsg_end(msg, hdr);
14328 return genlmsg_reply(msg, info);
14329
14330nla_put_failure:
14331 nlmsg_free(msg);
14332 return -ENOBUFS;
14333}
14334
14335static int nl80211_nan_del_func(struct sk_buff *skb,
14336 struct genl_info *info)
14337{
14338 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14339 struct wireless_dev *wdev = info->user_ptr[1];
14340 u64 cookie;
14341
14342 if (wdev->iftype != NL80211_IFTYPE_NAN)
14343 return -EOPNOTSUPP;
14344
73c7da3d 14345 if (!wdev_running(wdev))
a442b761
AB
14346 return -ENOTCONN;
14347
14348 if (!info->attrs[NL80211_ATTR_COOKIE])
14349 return -EINVAL;
14350
a442b761
AB
14351 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
14352
14353 rdev_del_nan_func(rdev, wdev, cookie);
14354
14355 return 0;
14356}
14357
a5a9dcf2
AB
14358static int nl80211_nan_change_config(struct sk_buff *skb,
14359 struct genl_info *info)
14360{
14361 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14362 struct wireless_dev *wdev = info->user_ptr[1];
14363 struct cfg80211_nan_conf conf = {};
14364 u32 changed = 0;
14365
14366 if (wdev->iftype != NL80211_IFTYPE_NAN)
14367 return -EOPNOTSUPP;
14368
73c7da3d 14369 if (!wdev_running(wdev))
a5a9dcf2
AB
14370 return -ENOTCONN;
14371
14372 if (info->attrs[NL80211_ATTR_NAN_MASTER_PREF]) {
14373 conf.master_pref =
14374 nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]);
14375 if (conf.master_pref <= 1 || conf.master_pref == 255)
14376 return -EINVAL;
14377
14378 changed |= CFG80211_NAN_CONF_CHANGED_PREF;
14379 }
14380
8585989d
LC
14381 if (info->attrs[NL80211_ATTR_BANDS]) {
14382 u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]);
14383
14384 if (bands & ~(u32)wdev->wiphy->nan_supported_bands)
14385 return -EOPNOTSUPP;
14386
14387 if (bands && !(bands & BIT(NL80211_BAND_2GHZ)))
14388 return -EINVAL;
14389
14390 conf.bands = bands;
14391 changed |= CFG80211_NAN_CONF_CHANGED_BANDS;
a5a9dcf2
AB
14392 }
14393
14394 if (!changed)
14395 return -EINVAL;
14396
14397 return rdev_nan_change_conf(rdev, wdev, &conf, changed);
14398}
14399
50bcd31d
AB
14400void cfg80211_nan_match(struct wireless_dev *wdev,
14401 struct cfg80211_nan_match_params *match, gfp_t gfp)
14402{
14403 struct wiphy *wiphy = wdev->wiphy;
14404 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
14405 struct nlattr *match_attr, *local_func_attr, *peer_func_attr;
14406 struct sk_buff *msg;
14407 void *hdr;
14408
14409 if (WARN_ON(!match->inst_id || !match->peer_inst_id || !match->addr))
14410 return;
14411
14412 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
14413 if (!msg)
14414 return;
14415
14416 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NAN_MATCH);
14417 if (!hdr) {
14418 nlmsg_free(msg);
14419 return;
14420 }
14421
14422 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
14423 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
14424 wdev->netdev->ifindex)) ||
14425 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
14426 NL80211_ATTR_PAD))
14427 goto nla_put_failure;
14428
14429 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, match->cookie,
14430 NL80211_ATTR_PAD) ||
14431 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, match->addr))
14432 goto nla_put_failure;
14433
ae0be8de 14434 match_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_MATCH);
50bcd31d
AB
14435 if (!match_attr)
14436 goto nla_put_failure;
14437
ae0be8de
MK
14438 local_func_attr = nla_nest_start_noflag(msg,
14439 NL80211_NAN_MATCH_FUNC_LOCAL);
50bcd31d
AB
14440 if (!local_func_attr)
14441 goto nla_put_failure;
14442
14443 if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, match->inst_id))
14444 goto nla_put_failure;
14445
14446 nla_nest_end(msg, local_func_attr);
14447
ae0be8de
MK
14448 peer_func_attr = nla_nest_start_noflag(msg,
14449 NL80211_NAN_MATCH_FUNC_PEER);
50bcd31d
AB
14450 if (!peer_func_attr)
14451 goto nla_put_failure;
14452
14453 if (nla_put_u8(msg, NL80211_NAN_FUNC_TYPE, match->type) ||
14454 nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, match->peer_inst_id))
14455 goto nla_put_failure;
14456
14457 if (match->info && match->info_len &&
14458 nla_put(msg, NL80211_NAN_FUNC_SERVICE_INFO, match->info_len,
14459 match->info))
14460 goto nla_put_failure;
14461
14462 nla_nest_end(msg, peer_func_attr);
14463 nla_nest_end(msg, match_attr);
14464 genlmsg_end(msg, hdr);
14465
14466 if (!wdev->owner_nlportid)
14467 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
14468 msg, 0, NL80211_MCGRP_NAN, gfp);
14469 else
14470 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
14471 wdev->owner_nlportid);
14472
14473 return;
14474
14475nla_put_failure:
14476 nlmsg_free(msg);
14477}
14478EXPORT_SYMBOL(cfg80211_nan_match);
14479
368e5a7b
AB
14480void cfg80211_nan_func_terminated(struct wireless_dev *wdev,
14481 u8 inst_id,
14482 enum nl80211_nan_func_term_reason reason,
14483 u64 cookie, gfp_t gfp)
14484{
14485 struct wiphy *wiphy = wdev->wiphy;
14486 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
14487 struct sk_buff *msg;
14488 struct nlattr *func_attr;
14489 void *hdr;
14490
14491 if (WARN_ON(!inst_id))
14492 return;
14493
14494 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
14495 if (!msg)
14496 return;
14497
14498 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DEL_NAN_FUNCTION);
14499 if (!hdr) {
14500 nlmsg_free(msg);
14501 return;
14502 }
14503
14504 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
14505 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
14506 wdev->netdev->ifindex)) ||
14507 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
14508 NL80211_ATTR_PAD))
14509 goto nla_put_failure;
14510
14511 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
14512 NL80211_ATTR_PAD))
14513 goto nla_put_failure;
14514
ae0be8de 14515 func_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_FUNC);
368e5a7b
AB
14516 if (!func_attr)
14517 goto nla_put_failure;
14518
14519 if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, inst_id) ||
14520 nla_put_u8(msg, NL80211_NAN_FUNC_TERM_REASON, reason))
14521 goto nla_put_failure;
14522
14523 nla_nest_end(msg, func_attr);
14524 genlmsg_end(msg, hdr);
14525
14526 if (!wdev->owner_nlportid)
14527 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
14528 msg, 0, NL80211_MCGRP_NAN, gfp);
14529 else
14530 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
14531 wdev->owner_nlportid);
14532
14533 return;
14534
14535nla_put_failure:
14536 nlmsg_free(msg);
14537}
14538EXPORT_SYMBOL(cfg80211_nan_func_terminated);
14539
3713b4e3
JB
14540static int nl80211_get_protocol_features(struct sk_buff *skb,
14541 struct genl_info *info)
14542{
14543 void *hdr;
14544 struct sk_buff *msg;
14545
14546 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
14547 if (!msg)
14548 return -ENOMEM;
14549
14550 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
14551 NL80211_CMD_GET_PROTOCOL_FEATURES);
14552 if (!hdr)
14553 goto nla_put_failure;
14554
14555 if (nla_put_u32(msg, NL80211_ATTR_PROTOCOL_FEATURES,
14556 NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP))
14557 goto nla_put_failure;
14558
14559 genlmsg_end(msg, hdr);
14560 return genlmsg_reply(msg, info);
14561
14562 nla_put_failure:
14563 kfree_skb(msg);
14564 return -ENOBUFS;
14565}
14566
355199e0
JM
14567static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info)
14568{
14569 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14570 struct cfg80211_update_ft_ies_params ft_params;
14571 struct net_device *dev = info->user_ptr[1];
14572
14573 if (!rdev->ops->update_ft_ies)
14574 return -EOPNOTSUPP;
14575
14576 if (!info->attrs[NL80211_ATTR_MDID] ||
3d7af878 14577 !info->attrs[NL80211_ATTR_IE])
355199e0
JM
14578 return -EINVAL;
14579
14580 memset(&ft_params, 0, sizeof(ft_params));
14581 ft_params.md = nla_get_u16(info->attrs[NL80211_ATTR_MDID]);
14582 ft_params.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
14583 ft_params.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
14584
14585 return rdev_update_ft_ies(rdev, dev, &ft_params);
14586}
14587
5de17984
AS
14588static int nl80211_crit_protocol_start(struct sk_buff *skb,
14589 struct genl_info *info)
14590{
14591 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14592 struct wireless_dev *wdev = info->user_ptr[1];
14593 enum nl80211_crit_proto_id proto = NL80211_CRIT_PROTO_UNSPEC;
14594 u16 duration;
14595 int ret;
14596
14597 if (!rdev->ops->crit_proto_start)
14598 return -EOPNOTSUPP;
14599
14600 if (WARN_ON(!rdev->ops->crit_proto_stop))
14601 return -EINVAL;
14602
14603 if (rdev->crit_proto_nlportid)
14604 return -EBUSY;
14605
14606 /* determine protocol if provided */
14607 if (info->attrs[NL80211_ATTR_CRIT_PROT_ID])
14608 proto = nla_get_u16(info->attrs[NL80211_ATTR_CRIT_PROT_ID]);
14609
14610 if (proto >= NUM_NL80211_CRIT_PROTO)
14611 return -EINVAL;
14612
14613 /* timeout must be provided */
14614 if (!info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION])
14615 return -EINVAL;
14616
14617 duration =
14618 nla_get_u16(info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION]);
14619
5de17984
AS
14620 ret = rdev_crit_proto_start(rdev, wdev, proto, duration);
14621 if (!ret)
14622 rdev->crit_proto_nlportid = info->snd_portid;
14623
14624 return ret;
14625}
14626
14627static int nl80211_crit_protocol_stop(struct sk_buff *skb,
14628 struct genl_info *info)
14629{
14630 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14631 struct wireless_dev *wdev = info->user_ptr[1];
14632
14633 if (!rdev->ops->crit_proto_stop)
14634 return -EOPNOTSUPP;
14635
14636 if (rdev->crit_proto_nlportid) {
14637 rdev->crit_proto_nlportid = 0;
14638 rdev_crit_proto_stop(rdev, wdev);
14639 }
14640 return 0;
14641}
14642
901bb989
JB
14643static int nl80211_vendor_check_policy(const struct wiphy_vendor_command *vcmd,
14644 struct nlattr *attr,
14645 struct netlink_ext_ack *extack)
14646{
14647 if (vcmd->policy == VENDOR_CMD_RAW_DATA) {
14648 if (attr->nla_type & NLA_F_NESTED) {
14649 NL_SET_ERR_MSG_ATTR(extack, attr,
14650 "unexpected nested data");
14651 return -EINVAL;
14652 }
14653
14654 return 0;
14655 }
14656
14657 if (!(attr->nla_type & NLA_F_NESTED)) {
14658 NL_SET_ERR_MSG_ATTR(extack, attr, "expected nested data");
14659 return -EINVAL;
14660 }
14661
32d5109a 14662 return nla_validate_nested(attr, vcmd->maxattr, vcmd->policy, extack);
901bb989
JB
14663}
14664
ad7e718c
JB
14665static int nl80211_vendor_cmd(struct sk_buff *skb, struct genl_info *info)
14666{
14667 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14668 struct wireless_dev *wdev =
a05829a7
JB
14669 __cfg80211_wdev_from_attrs(rdev, genl_info_net(info),
14670 info->attrs);
ad7e718c
JB
14671 int i, err;
14672 u32 vid, subcmd;
14673
14674 if (!rdev->wiphy.vendor_commands)
14675 return -EOPNOTSUPP;
14676
14677 if (IS_ERR(wdev)) {
14678 err = PTR_ERR(wdev);
14679 if (err != -EINVAL)
14680 return err;
14681 wdev = NULL;
14682 } else if (wdev->wiphy != &rdev->wiphy) {
14683 return -EINVAL;
14684 }
14685
14686 if (!info->attrs[NL80211_ATTR_VENDOR_ID] ||
14687 !info->attrs[NL80211_ATTR_VENDOR_SUBCMD])
14688 return -EINVAL;
14689
14690 vid = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_ID]);
14691 subcmd = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_SUBCMD]);
14692 for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) {
14693 const struct wiphy_vendor_command *vcmd;
14694 void *data = NULL;
14695 int len = 0;
14696
14697 vcmd = &rdev->wiphy.vendor_commands[i];
14698
14699 if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd)
14700 continue;
14701
14702 if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV |
14703 WIPHY_VENDOR_CMD_NEED_NETDEV)) {
14704 if (!wdev)
14705 return -EINVAL;
14706 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV &&
14707 !wdev->netdev)
14708 return -EINVAL;
14709
14710 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
73c7da3d 14711 if (!wdev_running(wdev))
ad7e718c
JB
14712 return -ENETDOWN;
14713 }
14714 } else {
14715 wdev = NULL;
14716 }
14717
4052d3d2
JS
14718 if (!vcmd->doit)
14719 return -EOPNOTSUPP;
14720
ad7e718c
JB
14721 if (info->attrs[NL80211_ATTR_VENDOR_DATA]) {
14722 data = nla_data(info->attrs[NL80211_ATTR_VENDOR_DATA]);
14723 len = nla_len(info->attrs[NL80211_ATTR_VENDOR_DATA]);
901bb989
JB
14724
14725 err = nl80211_vendor_check_policy(vcmd,
14726 info->attrs[NL80211_ATTR_VENDOR_DATA],
14727 info->extack);
14728 if (err)
14729 return err;
ad7e718c
JB
14730 }
14731
14732 rdev->cur_cmd_info = info;
901bb989 14733 err = vcmd->doit(&rdev->wiphy, wdev, data, len);
ad7e718c
JB
14734 rdev->cur_cmd_info = NULL;
14735 return err;
14736 }
14737
14738 return -EOPNOTSUPP;
14739}
14740
7bdbe400
JB
14741static int nl80211_prepare_vendor_dump(struct sk_buff *skb,
14742 struct netlink_callback *cb,
14743 struct cfg80211_registered_device **rdev,
14744 struct wireless_dev **wdev)
14745{
50508d94 14746 struct nlattr **attrbuf;
7bdbe400
JB
14747 u32 vid, subcmd;
14748 unsigned int i;
14749 int vcmd_idx = -1;
14750 int err;
14751 void *data = NULL;
14752 unsigned int data_len = 0;
14753
7bdbe400
JB
14754 if (cb->args[0]) {
14755 /* subtract the 1 again here */
14756 struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
14757 struct wireless_dev *tmp;
14758
ea90e0dc
JB
14759 if (!wiphy)
14760 return -ENODEV;
7bdbe400
JB
14761 *rdev = wiphy_to_rdev(wiphy);
14762 *wdev = NULL;
14763
14764 if (cb->args[1]) {
53873f13 14765 list_for_each_entry(tmp, &wiphy->wdev_list, list) {
7bdbe400
JB
14766 if (tmp->identifier == cb->args[1] - 1) {
14767 *wdev = tmp;
14768 break;
14769 }
14770 }
14771 }
14772
14773 /* keep rtnl locked in successful case */
14774 return 0;
14775 }
14776
50508d94
JB
14777 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), GFP_KERNEL);
14778 if (!attrbuf)
14779 return -ENOMEM;
14780
8cb08174
JB
14781 err = nlmsg_parse_deprecated(cb->nlh,
14782 GENL_HDRLEN + nl80211_fam.hdrsize,
14783 attrbuf, nl80211_fam.maxattr,
14784 nl80211_policy, NULL);
7bdbe400 14785 if (err)
50508d94 14786 goto out;
7bdbe400 14787
c90c39da 14788 if (!attrbuf[NL80211_ATTR_VENDOR_ID] ||
50508d94
JB
14789 !attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) {
14790 err = -EINVAL;
14791 goto out;
14792 }
7bdbe400 14793
a05829a7 14794 *wdev = __cfg80211_wdev_from_attrs(NULL, sock_net(skb->sk), attrbuf);
7bdbe400
JB
14795 if (IS_ERR(*wdev))
14796 *wdev = NULL;
14797
c90c39da 14798 *rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
50508d94
JB
14799 if (IS_ERR(*rdev)) {
14800 err = PTR_ERR(*rdev);
14801 goto out;
14802 }
7bdbe400 14803
c90c39da
JB
14804 vid = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_ID]);
14805 subcmd = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_SUBCMD]);
7bdbe400
JB
14806
14807 for (i = 0; i < (*rdev)->wiphy.n_vendor_commands; i++) {
14808 const struct wiphy_vendor_command *vcmd;
14809
14810 vcmd = &(*rdev)->wiphy.vendor_commands[i];
14811
14812 if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd)
14813 continue;
14814
50508d94
JB
14815 if (!vcmd->dumpit) {
14816 err = -EOPNOTSUPP;
14817 goto out;
14818 }
7bdbe400
JB
14819
14820 vcmd_idx = i;
14821 break;
14822 }
14823
50508d94
JB
14824 if (vcmd_idx < 0) {
14825 err = -EOPNOTSUPP;
14826 goto out;
14827 }
7bdbe400 14828
c90c39da
JB
14829 if (attrbuf[NL80211_ATTR_VENDOR_DATA]) {
14830 data = nla_data(attrbuf[NL80211_ATTR_VENDOR_DATA]);
14831 data_len = nla_len(attrbuf[NL80211_ATTR_VENDOR_DATA]);
901bb989
JB
14832
14833 err = nl80211_vendor_check_policy(
14834 &(*rdev)->wiphy.vendor_commands[vcmd_idx],
14835 attrbuf[NL80211_ATTR_VENDOR_DATA],
14836 cb->extack);
14837 if (err)
50508d94 14838 goto out;
7bdbe400
JB
14839 }
14840
14841 /* 0 is the first index - add 1 to parse only once */
14842 cb->args[0] = (*rdev)->wiphy_idx + 1;
14843 /* add 1 to know if it was NULL */
14844 cb->args[1] = *wdev ? (*wdev)->identifier + 1 : 0;
14845 cb->args[2] = vcmd_idx;
14846 cb->args[3] = (unsigned long)data;
14847 cb->args[4] = data_len;
14848
14849 /* keep rtnl locked in successful case */
50508d94
JB
14850 err = 0;
14851out:
14852 kfree(attrbuf);
14853 return err;
7bdbe400
JB
14854}
14855
14856static int nl80211_vendor_cmd_dump(struct sk_buff *skb,
14857 struct netlink_callback *cb)
14858{
14859 struct cfg80211_registered_device *rdev;
14860 struct wireless_dev *wdev;
14861 unsigned int vcmd_idx;
14862 const struct wiphy_vendor_command *vcmd;
14863 void *data;
14864 int data_len;
14865 int err;
14866 struct nlattr *vendor_data;
14867
ea90e0dc 14868 rtnl_lock();
7bdbe400
JB
14869 err = nl80211_prepare_vendor_dump(skb, cb, &rdev, &wdev);
14870 if (err)
ea90e0dc 14871 goto out;
7bdbe400
JB
14872
14873 vcmd_idx = cb->args[2];
14874 data = (void *)cb->args[3];
14875 data_len = cb->args[4];
14876 vcmd = &rdev->wiphy.vendor_commands[vcmd_idx];
14877
14878 if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV |
14879 WIPHY_VENDOR_CMD_NEED_NETDEV)) {
ea90e0dc
JB
14880 if (!wdev) {
14881 err = -EINVAL;
14882 goto out;
14883 }
7bdbe400 14884 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV &&
ea90e0dc
JB
14885 !wdev->netdev) {
14886 err = -EINVAL;
14887 goto out;
14888 }
7bdbe400
JB
14889
14890 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
ea90e0dc
JB
14891 if (!wdev_running(wdev)) {
14892 err = -ENETDOWN;
14893 goto out;
14894 }
7bdbe400
JB
14895 }
14896 }
14897
14898 while (1) {
14899 void *hdr = nl80211hdr_put(skb, NETLINK_CB(cb->skb).portid,
14900 cb->nlh->nlmsg_seq, NLM_F_MULTI,
14901 NL80211_CMD_VENDOR);
14902 if (!hdr)
14903 break;
14904
14905 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
2dad624e
ND
14906 (wdev && nla_put_u64_64bit(skb, NL80211_ATTR_WDEV,
14907 wdev_id(wdev),
14908 NL80211_ATTR_PAD))) {
7bdbe400
JB
14909 genlmsg_cancel(skb, hdr);
14910 break;
14911 }
14912
ae0be8de
MK
14913 vendor_data = nla_nest_start_noflag(skb,
14914 NL80211_ATTR_VENDOR_DATA);
7bdbe400
JB
14915 if (!vendor_data) {
14916 genlmsg_cancel(skb, hdr);
14917 break;
14918 }
14919
14920 err = vcmd->dumpit(&rdev->wiphy, wdev, skb, data, data_len,
14921 (unsigned long *)&cb->args[5]);
14922 nla_nest_end(skb, vendor_data);
14923
14924 if (err == -ENOBUFS || err == -ENOENT) {
14925 genlmsg_cancel(skb, hdr);
14926 break;
9c167b2d 14927 } else if (err <= 0) {
7bdbe400
JB
14928 genlmsg_cancel(skb, hdr);
14929 goto out;
14930 }
14931
14932 genlmsg_end(skb, hdr);
14933 }
14934
14935 err = skb->len;
14936 out:
14937 rtnl_unlock();
14938 return err;
14939}
14940
ad7e718c
JB
14941struct sk_buff *__cfg80211_alloc_reply_skb(struct wiphy *wiphy,
14942 enum nl80211_commands cmd,
14943 enum nl80211_attrs attr,
14944 int approxlen)
14945{
f26cbf40 14946 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
ad7e718c
JB
14947
14948 if (WARN_ON(!rdev->cur_cmd_info))
14949 return NULL;
14950
6c09e791 14951 return __cfg80211_alloc_vendor_skb(rdev, NULL, approxlen,
ad7e718c
JB
14952 rdev->cur_cmd_info->snd_portid,
14953 rdev->cur_cmd_info->snd_seq,
567ffc35 14954 cmd, attr, NULL, GFP_KERNEL);
ad7e718c
JB
14955}
14956EXPORT_SYMBOL(__cfg80211_alloc_reply_skb);
14957
14958int cfg80211_vendor_cmd_reply(struct sk_buff *skb)
14959{
14960 struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
14961 void *hdr = ((void **)skb->cb)[1];
14962 struct nlattr *data = ((void **)skb->cb)[2];
14963
bd8c78e7
JB
14964 /* clear CB data for netlink core to own from now on */
14965 memset(skb->cb, 0, sizeof(skb->cb));
14966
ad7e718c
JB
14967 if (WARN_ON(!rdev->cur_cmd_info)) {
14968 kfree_skb(skb);
14969 return -EINVAL;
14970 }
14971
14972 nla_nest_end(skb, data);
14973 genlmsg_end(skb, hdr);
14974 return genlmsg_reply(skb, rdev->cur_cmd_info);
14975}
14976EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_reply);
14977
55c1fdf0
JB
14978unsigned int cfg80211_vendor_cmd_get_sender(struct wiphy *wiphy)
14979{
14980 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
14981
14982 if (WARN_ON(!rdev->cur_cmd_info))
14983 return 0;
14984
14985 return rdev->cur_cmd_info->snd_portid;
14986}
14987EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_get_sender);
14988
fa9ffc74
KP
14989static int nl80211_set_qos_map(struct sk_buff *skb,
14990 struct genl_info *info)
14991{
14992 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14993 struct cfg80211_qos_map *qos_map = NULL;
14994 struct net_device *dev = info->user_ptr[1];
14995 u8 *pos, len, num_des, des_len, des;
14996 int ret;
14997
14998 if (!rdev->ops->set_qos_map)
14999 return -EOPNOTSUPP;
15000
15001 if (info->attrs[NL80211_ATTR_QOS_MAP]) {
15002 pos = nla_data(info->attrs[NL80211_ATTR_QOS_MAP]);
15003 len = nla_len(info->attrs[NL80211_ATTR_QOS_MAP]);
15004
c8b82802 15005 if (len % 2)
fa9ffc74
KP
15006 return -EINVAL;
15007
15008 qos_map = kzalloc(sizeof(struct cfg80211_qos_map), GFP_KERNEL);
15009 if (!qos_map)
15010 return -ENOMEM;
15011
15012 num_des = (len - IEEE80211_QOS_MAP_LEN_MIN) >> 1;
15013 if (num_des) {
15014 des_len = num_des *
15015 sizeof(struct cfg80211_dscp_exception);
15016 memcpy(qos_map->dscp_exception, pos, des_len);
15017 qos_map->num_des = num_des;
15018 for (des = 0; des < num_des; des++) {
15019 if (qos_map->dscp_exception[des].up > 7) {
15020 kfree(qos_map);
15021 return -EINVAL;
15022 }
15023 }
15024 pos += des_len;
15025 }
15026 memcpy(qos_map->up, pos, IEEE80211_QOS_MAP_LEN_MIN);
15027 }
15028
15029 wdev_lock(dev->ieee80211_ptr);
15030 ret = nl80211_key_allowed(dev->ieee80211_ptr);
15031 if (!ret)
15032 ret = rdev_set_qos_map(rdev, dev, qos_map);
15033 wdev_unlock(dev->ieee80211_ptr);
15034
15035 kfree(qos_map);
15036 return ret;
15037}
15038
960d01ac
JB
15039static int nl80211_add_tx_ts(struct sk_buff *skb, struct genl_info *info)
15040{
15041 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15042 struct net_device *dev = info->user_ptr[1];
15043 struct wireless_dev *wdev = dev->ieee80211_ptr;
15044 const u8 *peer;
15045 u8 tsid, up;
15046 u16 admitted_time = 0;
15047 int err;
15048
723e73ac 15049 if (!(rdev->wiphy.features & NL80211_FEATURE_SUPPORTS_WMM_ADMISSION))
960d01ac
JB
15050 return -EOPNOTSUPP;
15051
15052 if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC] ||
15053 !info->attrs[NL80211_ATTR_USER_PRIO])
15054 return -EINVAL;
15055
15056 tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
960d01ac 15057 up = nla_get_u8(info->attrs[NL80211_ATTR_USER_PRIO]);
960d01ac
JB
15058
15059 /* WMM uses TIDs 0-7 even for TSPEC */
723e73ac 15060 if (tsid >= IEEE80211_FIRST_TSPEC_TSID) {
960d01ac 15061 /* TODO: handle 802.11 TSPEC/admission control
723e73ac
JB
15062 * need more attributes for that (e.g. BA session requirement);
15063 * change the WMM adminssion test above to allow both then
960d01ac
JB
15064 */
15065 return -EINVAL;
15066 }
15067
15068 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
15069
15070 if (info->attrs[NL80211_ATTR_ADMITTED_TIME]) {
15071 admitted_time =
15072 nla_get_u16(info->attrs[NL80211_ATTR_ADMITTED_TIME]);
15073 if (!admitted_time)
15074 return -EINVAL;
15075 }
15076
15077 wdev_lock(wdev);
15078 switch (wdev->iftype) {
15079 case NL80211_IFTYPE_STATION:
15080 case NL80211_IFTYPE_P2P_CLIENT:
7b0a0e3c 15081 if (wdev->connected)
960d01ac
JB
15082 break;
15083 err = -ENOTCONN;
15084 goto out;
15085 default:
15086 err = -EOPNOTSUPP;
15087 goto out;
15088 }
15089
15090 err = rdev_add_tx_ts(rdev, dev, tsid, peer, up, admitted_time);
15091
15092 out:
15093 wdev_unlock(wdev);
15094 return err;
15095}
15096
15097static int nl80211_del_tx_ts(struct sk_buff *skb, struct genl_info *info)
15098{
15099 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15100 struct net_device *dev = info->user_ptr[1];
15101 struct wireless_dev *wdev = dev->ieee80211_ptr;
15102 const u8 *peer;
15103 u8 tsid;
15104 int err;
15105
15106 if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC])
15107 return -EINVAL;
15108
15109 tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
15110 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
15111
15112 wdev_lock(wdev);
15113 err = rdev_del_tx_ts(rdev, dev, tsid, peer);
15114 wdev_unlock(wdev);
15115
15116 return err;
15117}
15118
1057d35e
AN
15119static int nl80211_tdls_channel_switch(struct sk_buff *skb,
15120 struct genl_info *info)
15121{
15122 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15123 struct net_device *dev = info->user_ptr[1];
15124 struct wireless_dev *wdev = dev->ieee80211_ptr;
15125 struct cfg80211_chan_def chandef = {};
15126 const u8 *addr;
15127 u8 oper_class;
15128 int err;
15129
15130 if (!rdev->ops->tdls_channel_switch ||
15131 !(rdev->wiphy.features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH))
15132 return -EOPNOTSUPP;
15133
15134 switch (dev->ieee80211_ptr->iftype) {
15135 case NL80211_IFTYPE_STATION:
15136 case NL80211_IFTYPE_P2P_CLIENT:
15137 break;
15138 default:
15139 return -EOPNOTSUPP;
15140 }
15141
15142 if (!info->attrs[NL80211_ATTR_MAC] ||
15143 !info->attrs[NL80211_ATTR_OPER_CLASS])
15144 return -EINVAL;
15145
15146 err = nl80211_parse_chandef(rdev, info, &chandef);
15147 if (err)
15148 return err;
15149
15150 /*
15151 * Don't allow wide channels on the 2.4Ghz band, as per IEEE802.11-2012
15152 * section 10.22.6.2.1. Disallow 5/10Mhz channels as well for now, the
15153 * specification is not defined for them.
15154 */
57fbcce3 15155 if (chandef.chan->band == NL80211_BAND_2GHZ &&
1057d35e
AN
15156 chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
15157 chandef.width != NL80211_CHAN_WIDTH_20)
15158 return -EINVAL;
15159
15160 /* we will be active on the TDLS link */
923b352f
AN
15161 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
15162 wdev->iftype))
1057d35e
AN
15163 return -EINVAL;
15164
15165 /* don't allow switching to DFS channels */
15166 if (cfg80211_chandef_dfs_required(wdev->wiphy, &chandef, wdev->iftype))
15167 return -EINVAL;
15168
15169 addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
15170 oper_class = nla_get_u8(info->attrs[NL80211_ATTR_OPER_CLASS]);
15171
15172 wdev_lock(wdev);
15173 err = rdev_tdls_channel_switch(rdev, dev, addr, oper_class, &chandef);
15174 wdev_unlock(wdev);
15175
15176 return err;
15177}
15178
15179static int nl80211_tdls_cancel_channel_switch(struct sk_buff *skb,
15180 struct genl_info *info)
15181{
15182 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15183 struct net_device *dev = info->user_ptr[1];
15184 struct wireless_dev *wdev = dev->ieee80211_ptr;
15185 const u8 *addr;
15186
15187 if (!rdev->ops->tdls_channel_switch ||
15188 !rdev->ops->tdls_cancel_channel_switch ||
15189 !(rdev->wiphy.features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH))
15190 return -EOPNOTSUPP;
15191
15192 switch (dev->ieee80211_ptr->iftype) {
15193 case NL80211_IFTYPE_STATION:
15194 case NL80211_IFTYPE_P2P_CLIENT:
15195 break;
15196 default:
15197 return -EOPNOTSUPP;
15198 }
15199
15200 if (!info->attrs[NL80211_ATTR_MAC])
15201 return -EINVAL;
15202
15203 addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
15204
15205 wdev_lock(wdev);
15206 rdev_tdls_cancel_channel_switch(rdev, dev, addr);
15207 wdev_unlock(wdev);
15208
15209 return 0;
15210}
15211
ce0ce13a
MB
15212static int nl80211_set_multicast_to_unicast(struct sk_buff *skb,
15213 struct genl_info *info)
15214{
15215 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15216 struct net_device *dev = info->user_ptr[1];
15217 struct wireless_dev *wdev = dev->ieee80211_ptr;
15218 const struct nlattr *nla;
15219 bool enabled;
15220
ce0ce13a
MB
15221 if (!rdev->ops->set_multicast_to_unicast)
15222 return -EOPNOTSUPP;
15223
15224 if (wdev->iftype != NL80211_IFTYPE_AP &&
15225 wdev->iftype != NL80211_IFTYPE_P2P_GO)
15226 return -EOPNOTSUPP;
15227
15228 nla = info->attrs[NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED];
15229 enabled = nla_get_flag(nla);
15230
15231 return rdev_set_multicast_to_unicast(rdev, dev, enabled);
15232}
15233
3a00df57
AS
15234static int nl80211_set_pmk(struct sk_buff *skb, struct genl_info *info)
15235{
15236 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15237 struct net_device *dev = info->user_ptr[1];
15238 struct wireless_dev *wdev = dev->ieee80211_ptr;
15239 struct cfg80211_pmk_conf pmk_conf = {};
15240 int ret;
15241
15242 if (wdev->iftype != NL80211_IFTYPE_STATION &&
15243 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
15244 return -EOPNOTSUPP;
15245
15246 if (!wiphy_ext_feature_isset(&rdev->wiphy,
15247 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
15248 return -EOPNOTSUPP;
15249
15250 if (!info->attrs[NL80211_ATTR_MAC] || !info->attrs[NL80211_ATTR_PMK])
15251 return -EINVAL;
15252
15253 wdev_lock(wdev);
7b0a0e3c 15254 if (!wdev->connected) {
3a00df57
AS
15255 ret = -ENOTCONN;
15256 goto out;
15257 }
15258
15259 pmk_conf.aa = nla_data(info->attrs[NL80211_ATTR_MAC]);
7b0a0e3c 15260 if (memcmp(pmk_conf.aa, wdev->u.client.connected_addr, ETH_ALEN)) {
3a00df57
AS
15261 ret = -EINVAL;
15262 goto out;
15263 }
15264
15265 pmk_conf.pmk = nla_data(info->attrs[NL80211_ATTR_PMK]);
15266 pmk_conf.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]);
15267 if (pmk_conf.pmk_len != WLAN_PMK_LEN &&
15268 pmk_conf.pmk_len != WLAN_PMK_LEN_SUITE_B_192) {
15269 ret = -EINVAL;
15270 goto out;
15271 }
15272
cb9abd48 15273 if (info->attrs[NL80211_ATTR_PMKR0_NAME])
3a00df57
AS
15274 pmk_conf.pmk_r0_name =
15275 nla_data(info->attrs[NL80211_ATTR_PMKR0_NAME]);
3a00df57
AS
15276
15277 ret = rdev_set_pmk(rdev, dev, &pmk_conf);
15278out:
15279 wdev_unlock(wdev);
15280 return ret;
15281}
15282
15283static int nl80211_del_pmk(struct sk_buff *skb, struct genl_info *info)
15284{
15285 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15286 struct net_device *dev = info->user_ptr[1];
15287 struct wireless_dev *wdev = dev->ieee80211_ptr;
15288 const u8 *aa;
15289 int ret;
15290
15291 if (wdev->iftype != NL80211_IFTYPE_STATION &&
15292 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
15293 return -EOPNOTSUPP;
15294
15295 if (!wiphy_ext_feature_isset(&rdev->wiphy,
15296 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
15297 return -EOPNOTSUPP;
15298
15299 if (!info->attrs[NL80211_ATTR_MAC])
15300 return -EINVAL;
15301
15302 wdev_lock(wdev);
15303 aa = nla_data(info->attrs[NL80211_ATTR_MAC]);
15304 ret = rdev_del_pmk(rdev, dev, aa);
15305 wdev_unlock(wdev);
15306
15307 return ret;
15308}
15309
40cbfa90
SD
15310static int nl80211_external_auth(struct sk_buff *skb, struct genl_info *info)
15311{
15312 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15313 struct net_device *dev = info->user_ptr[1];
15314 struct cfg80211_external_auth_params params;
15315
db8d93a7 15316 if (!rdev->ops->external_auth)
40cbfa90
SD
15317 return -EOPNOTSUPP;
15318
fe494370
SD
15319 if (!info->attrs[NL80211_ATTR_SSID] &&
15320 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
15321 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
40cbfa90
SD
15322 return -EINVAL;
15323
15324 if (!info->attrs[NL80211_ATTR_BSSID])
15325 return -EINVAL;
15326
15327 if (!info->attrs[NL80211_ATTR_STATUS_CODE])
15328 return -EINVAL;
15329
15330 memset(&params, 0, sizeof(params));
15331
fe494370
SD
15332 if (info->attrs[NL80211_ATTR_SSID]) {
15333 params.ssid.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
cb9abd48 15334 if (params.ssid.ssid_len == 0)
fe494370
SD
15335 return -EINVAL;
15336 memcpy(params.ssid.ssid,
15337 nla_data(info->attrs[NL80211_ATTR_SSID]),
15338 params.ssid.ssid_len);
15339 }
40cbfa90
SD
15340
15341 memcpy(params.bssid, nla_data(info->attrs[NL80211_ATTR_BSSID]),
15342 ETH_ALEN);
15343
15344 params.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
15345
fe494370
SD
15346 if (info->attrs[NL80211_ATTR_PMKID])
15347 params.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
15348
40cbfa90
SD
15349 return rdev_external_auth(rdev, dev, &params);
15350}
15351
2576a9ac
DK
15352static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
15353{
dca9ca2d 15354 bool dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK];
2576a9ac
DK
15355 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15356 struct net_device *dev = info->user_ptr[1];
15357 struct wireless_dev *wdev = dev->ieee80211_ptr;
15358 const u8 *buf;
15359 size_t len;
15360 u8 *dest;
15361 u16 proto;
15362 bool noencrypt;
dca9ca2d 15363 u64 cookie = 0;
67207bab 15364 int link_id;
2576a9ac
DK
15365 int err;
15366
15367 if (!wiphy_ext_feature_isset(&rdev->wiphy,
15368 NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211))
15369 return -EOPNOTSUPP;
15370
15371 if (!rdev->ops->tx_control_port)
15372 return -EOPNOTSUPP;
15373
15374 if (!info->attrs[NL80211_ATTR_FRAME] ||
15375 !info->attrs[NL80211_ATTR_MAC] ||
15376 !info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) {
15377 GENL_SET_ERR_MSG(info, "Frame, MAC or ethertype missing");
15378 return -EINVAL;
15379 }
15380
15381 wdev_lock(wdev);
15382
15383 switch (wdev->iftype) {
15384 case NL80211_IFTYPE_AP:
15385 case NL80211_IFTYPE_P2P_GO:
15386 case NL80211_IFTYPE_MESH_POINT:
15387 break;
15388 case NL80211_IFTYPE_ADHOC:
7b0a0e3c
JB
15389 if (wdev->u.ibss.current_bss)
15390 break;
15391 err = -ENOTCONN;
15392 goto out;
2576a9ac
DK
15393 case NL80211_IFTYPE_STATION:
15394 case NL80211_IFTYPE_P2P_CLIENT:
7b0a0e3c 15395 if (wdev->connected)
2576a9ac
DK
15396 break;
15397 err = -ENOTCONN;
15398 goto out;
15399 default:
15400 err = -EOPNOTSUPP;
15401 goto out;
15402 }
15403
15404 wdev_unlock(wdev);
15405
15406 buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
15407 len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
15408 dest = nla_data(info->attrs[NL80211_ATTR_MAC]);
15409 proto = nla_get_u16(info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]);
15410 noencrypt =
15411 nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]);
15412
67207bab
AO
15413 link_id = nl80211_link_id_or_invalid(info->attrs);
15414
dca9ca2d 15415 err = rdev_tx_control_port(rdev, dev, buf, len,
67207bab 15416 dest, cpu_to_be16(proto), noencrypt, link_id,
dca9ca2d
MT
15417 dont_wait_for_ack ? NULL : &cookie);
15418 if (!err && !dont_wait_for_ack)
15419 nl_set_extack_cookie_u64(info->extack, cookie);
15420 return err;
2576a9ac
DK
15421 out:
15422 wdev_unlock(wdev);
15423 return err;
15424}
15425
81e54d08
PKC
15426static int nl80211_get_ftm_responder_stats(struct sk_buff *skb,
15427 struct genl_info *info)
15428{
15429 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15430 struct net_device *dev = info->user_ptr[1];
15431 struct wireless_dev *wdev = dev->ieee80211_ptr;
15432 struct cfg80211_ftm_responder_stats ftm_stats = {};
7b0a0e3c 15433 unsigned int link_id = nl80211_link_id(info->attrs);
81e54d08
PKC
15434 struct sk_buff *msg;
15435 void *hdr;
15436 struct nlattr *ftm_stats_attr;
15437 int err;
15438
7b0a0e3c
JB
15439 if (wdev->iftype != NL80211_IFTYPE_AP ||
15440 !wdev->links[link_id].ap.beacon_interval)
81e54d08
PKC
15441 return -EOPNOTSUPP;
15442
15443 err = rdev_get_ftm_responder_stats(rdev, dev, &ftm_stats);
15444 if (err)
15445 return err;
15446
15447 if (!ftm_stats.filled)
15448 return -ENODATA;
15449
15450 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
15451 if (!msg)
15452 return -ENOMEM;
15453
15454 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
15455 NL80211_CMD_GET_FTM_RESPONDER_STATS);
15456 if (!hdr)
1399c59f 15457 goto nla_put_failure;
81e54d08
PKC
15458
15459 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
15460 goto nla_put_failure;
15461
ae0be8de
MK
15462 ftm_stats_attr = nla_nest_start_noflag(msg,
15463 NL80211_ATTR_FTM_RESPONDER_STATS);
81e54d08
PKC
15464 if (!ftm_stats_attr)
15465 goto nla_put_failure;
15466
15467#define SET_FTM(field, name, type) \
15468 do { if ((ftm_stats.filled & BIT(NL80211_FTM_STATS_ ## name)) && \
15469 nla_put_ ## type(msg, NL80211_FTM_STATS_ ## name, \
15470 ftm_stats.field)) \
15471 goto nla_put_failure; } while (0)
15472#define SET_FTM_U64(field, name) \
15473 do { if ((ftm_stats.filled & BIT(NL80211_FTM_STATS_ ## name)) && \
15474 nla_put_u64_64bit(msg, NL80211_FTM_STATS_ ## name, \
15475 ftm_stats.field, NL80211_FTM_STATS_PAD)) \
15476 goto nla_put_failure; } while (0)
15477
15478 SET_FTM(success_num, SUCCESS_NUM, u32);
15479 SET_FTM(partial_num, PARTIAL_NUM, u32);
15480 SET_FTM(failed_num, FAILED_NUM, u32);
15481 SET_FTM(asap_num, ASAP_NUM, u32);
15482 SET_FTM(non_asap_num, NON_ASAP_NUM, u32);
15483 SET_FTM_U64(total_duration_ms, TOTAL_DURATION_MSEC);
15484 SET_FTM(unknown_triggers_num, UNKNOWN_TRIGGERS_NUM, u32);
15485 SET_FTM(reschedule_requests_num, RESCHEDULE_REQUESTS_NUM, u32);
15486 SET_FTM(out_of_window_triggers_num, OUT_OF_WINDOW_TRIGGERS_NUM, u32);
15487#undef SET_FTM
15488
15489 nla_nest_end(msg, ftm_stats_attr);
15490
15491 genlmsg_end(msg, hdr);
15492 return genlmsg_reply(msg, info);
15493
15494nla_put_failure:
15495 nlmsg_free(msg);
15496 return -ENOBUFS;
15497}
15498
cb74e977
SD
15499static int nl80211_update_owe_info(struct sk_buff *skb, struct genl_info *info)
15500{
15501 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15502 struct cfg80211_update_owe_info owe_info;
15503 struct net_device *dev = info->user_ptr[1];
15504
15505 if (!rdev->ops->update_owe_info)
15506 return -EOPNOTSUPP;
15507
15508 if (!info->attrs[NL80211_ATTR_STATUS_CODE] ||
15509 !info->attrs[NL80211_ATTR_MAC])
15510 return -EINVAL;
15511
15512 memset(&owe_info, 0, sizeof(owe_info));
15513 owe_info.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
15514 nla_memcpy(owe_info.peer, info->attrs[NL80211_ATTR_MAC], ETH_ALEN);
15515
15516 if (info->attrs[NL80211_ATTR_IE]) {
15517 owe_info.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
15518 owe_info.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
15519 }
15520
15521 return rdev_update_owe_info(rdev, dev, &owe_info);
15522}
15523
5ab92e7f
RM
15524static int nl80211_probe_mesh_link(struct sk_buff *skb, struct genl_info *info)
15525{
15526 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15527 struct net_device *dev = info->user_ptr[1];
15528 struct wireless_dev *wdev = dev->ieee80211_ptr;
15529 struct station_info sinfo = {};
15530 const u8 *buf;
15531 size_t len;
15532 u8 *dest;
15533 int err;
15534
15535 if (!rdev->ops->probe_mesh_link || !rdev->ops->get_station)
15536 return -EOPNOTSUPP;
15537
15538 if (!info->attrs[NL80211_ATTR_MAC] ||
15539 !info->attrs[NL80211_ATTR_FRAME]) {
15540 GENL_SET_ERR_MSG(info, "Frame or MAC missing");
15541 return -EINVAL;
15542 }
15543
15544 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
15545 return -EOPNOTSUPP;
15546
15547 dest = nla_data(info->attrs[NL80211_ATTR_MAC]);
15548 buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
15549 len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
15550
15551 if (len < sizeof(struct ethhdr))
15552 return -EINVAL;
15553
15554 if (!ether_addr_equal(buf, dest) || is_multicast_ether_addr(buf) ||
15555 !ether_addr_equal(buf + ETH_ALEN, dev->dev_addr))
15556 return -EINVAL;
15557
15558 err = rdev_get_station(rdev, dev, dest, &sinfo);
15559 if (err)
15560 return err;
15561
2a279b34
FF
15562 cfg80211_sinfo_release_content(&sinfo);
15563
5ab92e7f
RM
15564 return rdev_probe_mesh_link(rdev, dev, dest, buf, len);
15565}
15566
77f576de
T
15567static int parse_tid_conf(struct cfg80211_registered_device *rdev,
15568 struct nlattr *attrs[], struct net_device *dev,
3710a8a6 15569 struct cfg80211_tid_cfg *tid_conf,
7b0a0e3c
JB
15570 struct genl_info *info, const u8 *peer,
15571 unsigned int link_id)
77f576de
T
15572{
15573 struct netlink_ext_ack *extack = info->extack;
3710a8a6 15574 u64 mask;
77f576de
T
15575 int err;
15576
15577 if (!attrs[NL80211_TID_CONFIG_ATTR_TIDS])
15578 return -EINVAL;
15579
15580 tid_conf->config_override =
15581 nla_get_flag(attrs[NL80211_TID_CONFIG_ATTR_OVERRIDE]);
3710a8a6 15582 tid_conf->tids = nla_get_u16(attrs[NL80211_TID_CONFIG_ATTR_TIDS]);
77f576de
T
15583
15584 if (tid_conf->config_override) {
15585 if (rdev->ops->reset_tid_config) {
15586 err = rdev_reset_tid_config(rdev, dev, peer,
3710a8a6 15587 tid_conf->tids);
c0336955 15588 if (err)
77f576de
T
15589 return err;
15590 } else {
15591 return -EINVAL;
15592 }
15593 }
15594
15595 if (attrs[NL80211_TID_CONFIG_ATTR_NOACK]) {
3710a8a6 15596 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_NOACK);
77f576de
T
15597 tid_conf->noack =
15598 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_NOACK]);
15599 }
15600
6a21d16c
T
15601 if (attrs[NL80211_TID_CONFIG_ATTR_RETRY_SHORT]) {
15602 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RETRY_SHORT);
15603 tid_conf->retry_short =
15604 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RETRY_SHORT]);
15605
15606 if (tid_conf->retry_short > rdev->wiphy.max_data_retry_count)
15607 return -EINVAL;
15608 }
15609
15610 if (attrs[NL80211_TID_CONFIG_ATTR_RETRY_LONG]) {
15611 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RETRY_LONG);
15612 tid_conf->retry_long =
15613 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RETRY_LONG]);
15614
15615 if (tid_conf->retry_long > rdev->wiphy.max_data_retry_count)
15616 return -EINVAL;
15617 }
15618
ade274b2
T
15619 if (attrs[NL80211_TID_CONFIG_ATTR_AMPDU_CTRL]) {
15620 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL);
15621 tid_conf->ampdu =
15622 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_AMPDU_CTRL]);
15623 }
15624
04f7d142
T
15625 if (attrs[NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL]) {
15626 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL);
15627 tid_conf->rtscts =
15628 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL]);
15629 }
15630
33462e68
SM
15631 if (attrs[NL80211_TID_CONFIG_ATTR_AMSDU_CTRL]) {
15632 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_AMSDU_CTRL);
15633 tid_conf->amsdu =
15634 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_AMSDU_CTRL]);
15635 }
15636
9a5f6488
TC
15637 if (attrs[NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE]) {
15638 u32 idx = NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE, attr;
15639
15640 tid_conf->txrate_type = nla_get_u8(attrs[idx]);
15641
15642 if (tid_conf->txrate_type != NL80211_TX_RATE_AUTOMATIC) {
15643 attr = NL80211_TID_CONFIG_ATTR_TX_RATE;
15644 err = nl80211_parse_tx_bitrate_mask(info, attrs, attr,
857b34c4 15645 &tid_conf->txrate_mask, dev,
7b0a0e3c 15646 true, link_id);
9a5f6488
TC
15647 if (err)
15648 return err;
15649
15650 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_TX_RATE);
15651 }
15652 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE);
15653 }
15654
3710a8a6
JB
15655 if (peer)
15656 mask = rdev->wiphy.tid_config_support.peer;
15657 else
15658 mask = rdev->wiphy.tid_config_support.vif;
15659
15660 if (tid_conf->mask & ~mask) {
15661 NL_SET_ERR_MSG(extack, "unsupported TID configuration");
15662 return -ENOTSUPP;
15663 }
15664
77f576de
T
15665 return 0;
15666}
15667
15668static int nl80211_set_tid_config(struct sk_buff *skb,
15669 struct genl_info *info)
15670{
15671 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15672 struct nlattr *attrs[NL80211_TID_CONFIG_ATTR_MAX + 1];
7b0a0e3c 15673 unsigned int link_id = nl80211_link_id(info->attrs);
77f576de 15674 struct net_device *dev = info->user_ptr[1];
3710a8a6 15675 struct cfg80211_tid_config *tid_config;
77f576de
T
15676 struct nlattr *tid;
15677 int conf_idx = 0, rem_conf;
15678 int ret = -EINVAL;
15679 u32 num_conf = 0;
15680
15681 if (!info->attrs[NL80211_ATTR_TID_CONFIG])
15682 return -EINVAL;
15683
15684 if (!rdev->ops->set_tid_config)
15685 return -EOPNOTSUPP;
15686
15687 nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
15688 rem_conf)
15689 num_conf++;
15690
15691 tid_config = kzalloc(struct_size(tid_config, tid_conf, num_conf),
15692 GFP_KERNEL);
15693 if (!tid_config)
15694 return -ENOMEM;
15695
15696 tid_config->n_tid_conf = num_conf;
15697
15698 if (info->attrs[NL80211_ATTR_MAC])
15699 tid_config->peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
15700
206bbcf7
JB
15701 wdev_lock(dev->ieee80211_ptr);
15702
77f576de
T
15703 nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
15704 rem_conf) {
15705 ret = nla_parse_nested(attrs, NL80211_TID_CONFIG_ATTR_MAX,
15706 tid, NULL, NULL);
15707
15708 if (ret)
15709 goto bad_tid_conf;
15710
15711 ret = parse_tid_conf(rdev, attrs, dev,
15712 &tid_config->tid_conf[conf_idx],
7b0a0e3c 15713 info, tid_config->peer, link_id);
77f576de
T
15714 if (ret)
15715 goto bad_tid_conf;
15716
15717 conf_idx++;
15718 }
15719
15720 ret = rdev_set_tid_config(rdev, dev, tid_config);
15721
15722bad_tid_conf:
15723 kfree(tid_config);
206bbcf7 15724 wdev_unlock(dev->ieee80211_ptr);
77f576de
T
15725 return ret;
15726}
15727
0d2ab3ae
JC
15728static int nl80211_color_change(struct sk_buff *skb, struct genl_info *info)
15729{
15730 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15731 struct cfg80211_color_change_settings params = {};
15732 struct net_device *dev = info->user_ptr[1];
15733 struct wireless_dev *wdev = dev->ieee80211_ptr;
15734 struct nlattr **tb;
15735 u16 offset;
15736 int err;
15737
15738 if (!rdev->ops->color_change)
15739 return -EOPNOTSUPP;
15740
15741 if (!wiphy_ext_feature_isset(&rdev->wiphy,
15742 NL80211_EXT_FEATURE_BSS_COLOR))
15743 return -EOPNOTSUPP;
15744
15745 if (wdev->iftype != NL80211_IFTYPE_AP)
15746 return -EOPNOTSUPP;
15747
15748 if (!info->attrs[NL80211_ATTR_COLOR_CHANGE_COUNT] ||
15749 !info->attrs[NL80211_ATTR_COLOR_CHANGE_COLOR] ||
15750 !info->attrs[NL80211_ATTR_COLOR_CHANGE_ELEMS])
15751 return -EINVAL;
15752
15753 params.count = nla_get_u8(info->attrs[NL80211_ATTR_COLOR_CHANGE_COUNT]);
15754 params.color = nla_get_u8(info->attrs[NL80211_ATTR_COLOR_CHANGE_COLOR]);
15755
15756 err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon_next);
15757 if (err)
15758 return err;
15759
15760 tb = kcalloc(NL80211_ATTR_MAX + 1, sizeof(*tb), GFP_KERNEL);
15761 if (!tb)
15762 return -ENOMEM;
15763
15764 err = nla_parse_nested(tb, NL80211_ATTR_MAX,
15765 info->attrs[NL80211_ATTR_COLOR_CHANGE_ELEMS],
15766 nl80211_policy, info->extack);
15767 if (err)
15768 goto out;
15769
15770 err = nl80211_parse_beacon(rdev, tb, &params.beacon_color_change);
15771 if (err)
15772 goto out;
15773
15774 if (!tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]) {
15775 err = -EINVAL;
15776 goto out;
15777 }
15778
15779 if (nla_len(tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]) != sizeof(u16)) {
15780 err = -EINVAL;
15781 goto out;
15782 }
15783
15784 offset = nla_get_u16(tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
15785 if (offset >= params.beacon_color_change.tail_len) {
15786 err = -EINVAL;
15787 goto out;
15788 }
15789
15790 if (params.beacon_color_change.tail[offset] != params.count) {
15791 err = -EINVAL;
15792 goto out;
15793 }
15794
15795 params.counter_offset_beacon = offset;
15796
15797 if (tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]) {
15798 if (nla_len(tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]) !=
15799 sizeof(u16)) {
15800 err = -EINVAL;
15801 goto out;
15802 }
15803
15804 offset = nla_get_u16(tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
15805 if (offset >= params.beacon_color_change.probe_resp_len) {
15806 err = -EINVAL;
15807 goto out;
15808 }
15809
15810 if (params.beacon_color_change.probe_resp[offset] !=
15811 params.count) {
15812 err = -EINVAL;
15813 goto out;
15814 }
15815
15816 params.counter_offset_presp = offset;
15817 }
15818
15819 wdev_lock(wdev);
15820 err = rdev_color_change(rdev, dev, &params);
15821 wdev_unlock(wdev);
15822
15823out:
dc1e3cb8
JC
15824 kfree(params.beacon_next.mbssid_ies);
15825 kfree(params.beacon_color_change.mbssid_ies);
0d2ab3ae
JC
15826 kfree(tb);
15827 return err;
15828}
15829
e306784a
SM
15830static int nl80211_set_fils_aad(struct sk_buff *skb,
15831 struct genl_info *info)
15832{
15833 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15834 struct net_device *dev = info->user_ptr[1];
15835 struct cfg80211_fils_aad fils_aad = {};
15836 u8 *nonces;
15837
15838 if (!info->attrs[NL80211_ATTR_MAC] ||
15839 !info->attrs[NL80211_ATTR_FILS_KEK] ||
15840 !info->attrs[NL80211_ATTR_FILS_NONCES])
15841 return -EINVAL;
15842
15843 fils_aad.macaddr = nla_data(info->attrs[NL80211_ATTR_MAC]);
15844 fils_aad.kek_len = nla_len(info->attrs[NL80211_ATTR_FILS_KEK]);
15845 fils_aad.kek = nla_data(info->attrs[NL80211_ATTR_FILS_KEK]);
15846 nonces = nla_data(info->attrs[NL80211_ATTR_FILS_NONCES]);
15847 fils_aad.snonce = nonces;
15848 fils_aad.anonce = nonces + FILS_NONCE_LEN;
15849
15850 return rdev_set_fils_aad(rdev, dev, &fils_aad);
15851}
15852
7b0a0e3c
JB
15853static int nl80211_add_link(struct sk_buff *skb, struct genl_info *info)
15854{
f2a0290b 15855 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7b0a0e3c
JB
15856 unsigned int link_id = nl80211_link_id(info->attrs);
15857 struct net_device *dev = info->user_ptr[1];
15858 struct wireless_dev *wdev = dev->ieee80211_ptr;
f2a0290b 15859 int ret;
7b0a0e3c
JB
15860
15861 if (!(wdev->wiphy->flags & WIPHY_FLAG_SUPPORTS_MLO))
15862 return -EINVAL;
15863
15864 switch (wdev->iftype) {
15865 case NL80211_IFTYPE_AP:
15866 break;
15867 default:
15868 return -EINVAL;
15869 }
15870
15871 if (!info->attrs[NL80211_ATTR_MAC] ||
15872 !is_valid_ether_addr(nla_data(info->attrs[NL80211_ATTR_MAC])))
15873 return -EINVAL;
15874
15875 wdev_lock(wdev);
15876 wdev->valid_links |= BIT(link_id);
15877 ether_addr_copy(wdev->links[link_id].addr,
15878 nla_data(info->attrs[NL80211_ATTR_MAC]));
f2a0290b
JB
15879
15880 ret = rdev_add_intf_link(rdev, wdev, link_id);
15881 if (ret) {
15882 wdev->valid_links &= ~BIT(link_id);
15883 eth_zero_addr(wdev->links[link_id].addr);
15884 }
7b0a0e3c
JB
15885 wdev_unlock(wdev);
15886
f2a0290b 15887 return ret;
7b0a0e3c
JB
15888}
15889
15890static int nl80211_remove_link(struct sk_buff *skb, struct genl_info *info)
15891{
15892 unsigned int link_id = nl80211_link_id(info->attrs);
15893 struct net_device *dev = info->user_ptr[1];
15894 struct wireless_dev *wdev = dev->ieee80211_ptr;
15895
15896 /* cannot remove if there's no link */
15897 if (!info->attrs[NL80211_ATTR_MLO_LINK_ID])
15898 return -EINVAL;
15899
15900 switch (wdev->iftype) {
15901 case NL80211_IFTYPE_AP:
15902 break;
15903 default:
15904 return -EINVAL;
15905 }
15906
7b0a0e3c 15907 wdev_lock(wdev);
cdf0a0a8 15908 cfg80211_remove_link(wdev, link_id);
7b0a0e3c
JB
15909 wdev_unlock(wdev);
15910
15911 return 0;
15912}
15913
577e5b8c
ST
15914static int
15915nl80211_add_mod_link_station(struct sk_buff *skb, struct genl_info *info,
15916 bool add)
15917{
15918 struct link_station_parameters params = {};
15919 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15920 struct net_device *dev = info->user_ptr[1];
15921 int err;
15922
15923 if ((add && !rdev->ops->add_link_station) ||
15924 (!add && !rdev->ops->mod_link_station))
15925 return -EOPNOTSUPP;
15926
15927 if (add && !info->attrs[NL80211_ATTR_MAC])
15928 return -EINVAL;
15929
8876c67e 15930 if (!info->attrs[NL80211_ATTR_MLD_ADDR])
577e5b8c
ST
15931 return -EINVAL;
15932
15933 if (add && !info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
15934 return -EINVAL;
15935
8876c67e 15936 params.mld_mac = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
577e5b8c
ST
15937
15938 if (info->attrs[NL80211_ATTR_MAC]) {
15939 params.link_mac = nla_data(info->attrs[NL80211_ATTR_MAC]);
15940 if (!is_valid_ether_addr(params.link_mac))
15941 return -EINVAL;
15942 }
15943
15944 if (!info->attrs[NL80211_ATTR_MLO_LINK_ID])
15945 return -EINVAL;
15946
15947 params.link_id = nla_get_u8(info->attrs[NL80211_ATTR_MLO_LINK_ID]);
15948
15949 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
15950 params.supported_rates =
15951 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
15952 params.supported_rates_len =
15953 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
15954 }
15955
15956 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
15957 params.ht_capa =
15958 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
15959
15960 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
15961 params.vht_capa =
15962 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
15963
15964 if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
15965 params.he_capa =
15966 nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
15967 params.he_capa_len =
15968 nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
15969
15970 if (info->attrs[NL80211_ATTR_EHT_CAPABILITY]) {
15971 params.eht_capa =
15972 nla_data(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
15973 params.eht_capa_len =
15974 nla_len(info->attrs[NL80211_ATTR_EHT_CAPABILITY]);
15975
15976 if (!ieee80211_eht_capa_size_ok((const u8 *)params.he_capa,
15977 (const u8 *)params.eht_capa,
ea5cba26
JB
15978 params.eht_capa_len,
15979 false))
577e5b8c
ST
15980 return -EINVAL;
15981 }
15982 }
15983
15984 if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
15985 params.he_6ghz_capa =
15986 nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
15987
15988 if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
15989 params.opmode_notif_used = true;
15990 params.opmode_notif =
15991 nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
15992 }
15993
15994 err = nl80211_parse_sta_txpower_setting(info, &params.txpwr,
15995 &params.txpwr_set);
15996 if (err)
15997 return err;
15998
858fd188 15999 wdev_lock(dev->ieee80211_ptr);
577e5b8c 16000 if (add)
858fd188
JB
16001 err = rdev_add_link_station(rdev, dev, &params);
16002 else
16003 err = rdev_mod_link_station(rdev, dev, &params);
16004 wdev_unlock(dev->ieee80211_ptr);
16005
16006 return err;
577e5b8c
ST
16007}
16008
16009static int
16010nl80211_add_link_station(struct sk_buff *skb, struct genl_info *info)
16011{
16012 return nl80211_add_mod_link_station(skb, info, true);
16013}
16014
16015static int
16016nl80211_modify_link_station(struct sk_buff *skb, struct genl_info *info)
16017{
16018 return nl80211_add_mod_link_station(skb, info, false);
16019}
16020
16021static int
16022nl80211_remove_link_station(struct sk_buff *skb, struct genl_info *info)
16023{
16024 struct link_station_del_parameters params = {};
16025 struct cfg80211_registered_device *rdev = info->user_ptr[0];
16026 struct net_device *dev = info->user_ptr[1];
858fd188 16027 int ret;
577e5b8c
ST
16028
16029 if (!rdev->ops->del_link_station)
16030 return -EOPNOTSUPP;
16031
16032 if (!info->attrs[NL80211_ATTR_MLD_ADDR] ||
16033 !info->attrs[NL80211_ATTR_MLO_LINK_ID])
16034 return -EINVAL;
16035
16036 params.mld_mac = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
16037 params.link_id = nla_get_u8(info->attrs[NL80211_ATTR_MLO_LINK_ID]);
16038
858fd188
JB
16039 wdev_lock(dev->ieee80211_ptr);
16040 ret = rdev_del_link_station(rdev, dev, &params);
16041 wdev_unlock(dev->ieee80211_ptr);
16042
16043 return ret;
577e5b8c
ST
16044}
16045
4c476991
JB
16046#define NL80211_FLAG_NEED_WIPHY 0x01
16047#define NL80211_FLAG_NEED_NETDEV 0x02
16048#define NL80211_FLAG_NEED_RTNL 0x04
41265714
JB
16049#define NL80211_FLAG_CHECK_NETDEV_UP 0x08
16050#define NL80211_FLAG_NEED_NETDEV_UP (NL80211_FLAG_NEED_NETDEV |\
16051 NL80211_FLAG_CHECK_NETDEV_UP)
1bf614ef 16052#define NL80211_FLAG_NEED_WDEV 0x10
98104fde 16053/* If a netdev is associated, it must be UP, P2P must be started */
1bf614ef
JB
16054#define NL80211_FLAG_NEED_WDEV_UP (NL80211_FLAG_NEED_WDEV |\
16055 NL80211_FLAG_CHECK_NETDEV_UP)
5393b917 16056#define NL80211_FLAG_CLEAR_SKB 0x20
77cbf790 16057#define NL80211_FLAG_NO_WIPHY_MTX 0x40
7b0a0e3c
JB
16058#define NL80211_FLAG_MLO_VALID_LINK_ID 0x80
16059#define NL80211_FLAG_MLO_UNSUPPORTED 0x100
4c476991 16060
2182db91
JB
16061#define INTERNAL_FLAG_SELECTORS(__sel) \
16062 SELECTOR(__sel, NONE, 0) /* must be first */ \
16063 SELECTOR(__sel, WIPHY, \
16064 NL80211_FLAG_NEED_WIPHY) \
16065 SELECTOR(__sel, WDEV, \
16066 NL80211_FLAG_NEED_WDEV) \
16067 SELECTOR(__sel, NETDEV, \
16068 NL80211_FLAG_NEED_NETDEV) \
7b0a0e3c
JB
16069 SELECTOR(__sel, NETDEV_LINK, \
16070 NL80211_FLAG_NEED_NETDEV | \
16071 NL80211_FLAG_MLO_VALID_LINK_ID) \
16072 SELECTOR(__sel, NETDEV_NO_MLO, \
16073 NL80211_FLAG_NEED_NETDEV | \
16074 NL80211_FLAG_MLO_UNSUPPORTED) \
2182db91
JB
16075 SELECTOR(__sel, WIPHY_RTNL, \
16076 NL80211_FLAG_NEED_WIPHY | \
16077 NL80211_FLAG_NEED_RTNL) \
16078 SELECTOR(__sel, WIPHY_RTNL_NOMTX, \
16079 NL80211_FLAG_NEED_WIPHY | \
16080 NL80211_FLAG_NEED_RTNL | \
16081 NL80211_FLAG_NO_WIPHY_MTX) \
16082 SELECTOR(__sel, WDEV_RTNL, \
16083 NL80211_FLAG_NEED_WDEV | \
16084 NL80211_FLAG_NEED_RTNL) \
16085 SELECTOR(__sel, NETDEV_RTNL, \
16086 NL80211_FLAG_NEED_NETDEV | \
16087 NL80211_FLAG_NEED_RTNL) \
16088 SELECTOR(__sel, NETDEV_UP, \
16089 NL80211_FLAG_NEED_NETDEV_UP) \
7b0a0e3c
JB
16090 SELECTOR(__sel, NETDEV_UP_LINK, \
16091 NL80211_FLAG_NEED_NETDEV_UP | \
16092 NL80211_FLAG_MLO_VALID_LINK_ID) \
16093 SELECTOR(__sel, NETDEV_UP_NO_MLO, \
16094 NL80211_FLAG_NEED_NETDEV_UP | \
16095 NL80211_FLAG_MLO_UNSUPPORTED) \
16096 SELECTOR(__sel, NETDEV_UP_NO_MLO_CLEAR, \
16097 NL80211_FLAG_NEED_NETDEV_UP | \
16098 NL80211_FLAG_CLEAR_SKB | \
16099 NL80211_FLAG_MLO_UNSUPPORTED) \
2182db91
JB
16100 SELECTOR(__sel, NETDEV_UP_NOTMX, \
16101 NL80211_FLAG_NEED_NETDEV_UP | \
16102 NL80211_FLAG_NO_WIPHY_MTX) \
7b0a0e3c
JB
16103 SELECTOR(__sel, NETDEV_UP_NOTMX_NOMLO, \
16104 NL80211_FLAG_NEED_NETDEV_UP | \
16105 NL80211_FLAG_NO_WIPHY_MTX | \
16106 NL80211_FLAG_MLO_UNSUPPORTED) \
2182db91
JB
16107 SELECTOR(__sel, NETDEV_UP_CLEAR, \
16108 NL80211_FLAG_NEED_NETDEV_UP | \
16109 NL80211_FLAG_CLEAR_SKB) \
16110 SELECTOR(__sel, WDEV_UP, \
16111 NL80211_FLAG_NEED_WDEV_UP) \
7b0a0e3c
JB
16112 SELECTOR(__sel, WDEV_UP_LINK, \
16113 NL80211_FLAG_NEED_WDEV_UP | \
16114 NL80211_FLAG_MLO_VALID_LINK_ID) \
2182db91
JB
16115 SELECTOR(__sel, WDEV_UP_RTNL, \
16116 NL80211_FLAG_NEED_WDEV_UP | \
16117 NL80211_FLAG_NEED_RTNL) \
16118 SELECTOR(__sel, WIPHY_CLEAR, \
16119 NL80211_FLAG_NEED_WIPHY | \
16120 NL80211_FLAG_CLEAR_SKB)
16121
16122enum nl80211_internal_flags_selector {
16123#define SELECTOR(_, name, value) NL80211_IFL_SEL_##name,
16124 INTERNAL_FLAG_SELECTORS(_)
16125#undef SELECTOR
16126};
16127
16128static u32 nl80211_internal_flags[] = {
16129#define SELECTOR(_, name, value) [NL80211_IFL_SEL_##name] = value,
16130 INTERNAL_FLAG_SELECTORS(_)
16131#undef SELECTOR
16132};
16133
f84f771d 16134static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
4c476991
JB
16135 struct genl_info *info)
16136{
a05829a7 16137 struct cfg80211_registered_device *rdev = NULL;
7b0a0e3c
JB
16138 struct wireless_dev *wdev = NULL;
16139 struct net_device *dev = NULL;
2182db91 16140 u32 internal_flags;
7b0a0e3c 16141 int err;
2182db91
JB
16142
16143 if (WARN_ON(ops->internal_flags >= ARRAY_SIZE(nl80211_internal_flags)))
16144 return -EINVAL;
16145
16146 internal_flags = nl80211_internal_flags[ops->internal_flags];
4c476991 16147
a05829a7 16148 rtnl_lock();
2182db91 16149 if (internal_flags & NL80211_FLAG_NEED_WIPHY) {
4f7eff10 16150 rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
4c476991 16151 if (IS_ERR(rdev)) {
7b0a0e3c
JB
16152 err = PTR_ERR(rdev);
16153 goto out_unlock;
4c476991
JB
16154 }
16155 info->user_ptr[0] = rdev;
2182db91
JB
16156 } else if (internal_flags & NL80211_FLAG_NEED_NETDEV ||
16157 internal_flags & NL80211_FLAG_NEED_WDEV) {
a05829a7 16158 wdev = __cfg80211_wdev_from_attrs(NULL, genl_info_net(info),
89a54e48
JB
16159 info->attrs);
16160 if (IS_ERR(wdev)) {
7b0a0e3c
JB
16161 err = PTR_ERR(wdev);
16162 goto out_unlock;
4c476991 16163 }
89a54e48 16164
89a54e48 16165 dev = wdev->netdev;
7b0a0e3c 16166 dev_hold(dev);
f26cbf40 16167 rdev = wiphy_to_rdev(wdev->wiphy);
89a54e48 16168
2182db91 16169 if (internal_flags & NL80211_FLAG_NEED_NETDEV) {
1bf614ef 16170 if (!dev) {
7b0a0e3c
JB
16171 err = -EINVAL;
16172 goto out_unlock;
1bf614ef
JB
16173 }
16174
16175 info->user_ptr[1] = dev;
16176 } else {
16177 info->user_ptr[1] = wdev;
41265714 16178 }
1bf614ef 16179
2182db91 16180 if (internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
73c7da3d 16181 !wdev_running(wdev)) {
7b0a0e3c
JB
16182 err = -ENETDOWN;
16183 goto out_unlock;
73c7da3d 16184 }
1bf614ef 16185
4c476991 16186 info->user_ptr[0] = rdev;
4c476991
JB
16187 }
16188
7b0a0e3c
JB
16189 if (internal_flags & NL80211_FLAG_MLO_VALID_LINK_ID) {
16190 struct nlattr *link_id = info->attrs[NL80211_ATTR_MLO_LINK_ID];
16191
16192 if (!wdev) {
16193 err = -EINVAL;
16194 goto out_unlock;
16195 }
16196
16197 /* MLO -> require valid link ID */
16198 if (wdev->valid_links &&
16199 (!link_id ||
ff3821bc 16200 !(wdev->valid_links & BIT(nla_get_u8(link_id))))) {
7b0a0e3c
JB
16201 err = -EINVAL;
16202 goto out_unlock;
16203 }
16204
16205 /* non-MLO -> no link ID attribute accepted */
16206 if (!wdev->valid_links && link_id) {
16207 err = -EINVAL;
16208 goto out_unlock;
16209 }
16210 }
16211
16212 if (internal_flags & NL80211_FLAG_MLO_UNSUPPORTED) {
16213 if (info->attrs[NL80211_ATTR_MLO_LINK_ID] ||
16214 (wdev && wdev->valid_links)) {
16215 err = -EINVAL;
16216 goto out_unlock;
16217 }
16218 }
16219
2182db91 16220 if (rdev && !(internal_flags & NL80211_FLAG_NO_WIPHY_MTX)) {
a05829a7
JB
16221 wiphy_lock(&rdev->wiphy);
16222 /* we keep the mutex locked until post_doit */
16223 __release(&rdev->wiphy.mtx);
16224 }
2182db91 16225 if (!(internal_flags & NL80211_FLAG_NEED_RTNL))
a05829a7
JB
16226 rtnl_unlock();
16227
4c476991 16228 return 0;
7b0a0e3c
JB
16229out_unlock:
16230 rtnl_unlock();
16231 dev_put(dev);
16232 return err;
4c476991
JB
16233}
16234
f84f771d 16235static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
4c476991
JB
16236 struct genl_info *info)
16237{
2182db91
JB
16238 u32 internal_flags = nl80211_internal_flags[ops->internal_flags];
16239
1bf614ef 16240 if (info->user_ptr[1]) {
2182db91 16241 if (internal_flags & NL80211_FLAG_NEED_WDEV) {
1bf614ef
JB
16242 struct wireless_dev *wdev = info->user_ptr[1];
16243
1160dfa1 16244 dev_put(wdev->netdev);
1bf614ef
JB
16245 } else {
16246 dev_put(info->user_ptr[1]);
16247 }
16248 }
5393b917 16249
77cbf790 16250 if (info->user_ptr[0] &&
2182db91 16251 !(internal_flags & NL80211_FLAG_NO_WIPHY_MTX)) {
a05829a7
JB
16252 struct cfg80211_registered_device *rdev = info->user_ptr[0];
16253
16254 /* we kept the mutex locked since pre_doit */
16255 __acquire(&rdev->wiphy.mtx);
16256 wiphy_unlock(&rdev->wiphy);
16257 }
16258
2182db91 16259 if (internal_flags & NL80211_FLAG_NEED_RTNL)
4c476991 16260 rtnl_unlock();
5393b917
JB
16261
16262 /* If needed, clear the netlink message payload from the SKB
16263 * as it might contain key data that shouldn't stick around on
16264 * the heap after the SKB is freed. The netlink message header
16265 * is still needed for further processing, so leave it intact.
16266 */
2182db91 16267 if (internal_flags & NL80211_FLAG_CLEAR_SKB) {
5393b917
JB
16268 struct nlmsghdr *nlh = nlmsg_hdr(skb);
16269
16270 memset(nlmsg_data(nlh), 0, nlmsg_len(nlh));
16271 }
4c476991
JB
16272}
16273
6bdb68ce
CH
16274static int nl80211_set_sar_sub_specs(struct cfg80211_registered_device *rdev,
16275 struct cfg80211_sar_specs *sar_specs,
16276 struct nlattr *spec[], int index)
16277{
16278 u32 range_index, i;
16279
16280 if (!sar_specs || !spec)
16281 return -EINVAL;
16282
16283 if (!spec[NL80211_SAR_ATTR_SPECS_POWER] ||
16284 !spec[NL80211_SAR_ATTR_SPECS_RANGE_INDEX])
16285 return -EINVAL;
16286
16287 range_index = nla_get_u32(spec[NL80211_SAR_ATTR_SPECS_RANGE_INDEX]);
16288
16289 /* check if range_index exceeds num_freq_ranges */
16290 if (range_index >= rdev->wiphy.sar_capa->num_freq_ranges)
16291 return -EINVAL;
16292
16293 /* check if range_index duplicates */
16294 for (i = 0; i < index; i++) {
16295 if (sar_specs->sub_specs[i].freq_range_index == range_index)
16296 return -EINVAL;
16297 }
16298
16299 sar_specs->sub_specs[index].power =
16300 nla_get_s32(spec[NL80211_SAR_ATTR_SPECS_POWER]);
16301
16302 sar_specs->sub_specs[index].freq_range_index = range_index;
16303
16304 return 0;
16305}
16306
16307static int nl80211_set_sar_specs(struct sk_buff *skb, struct genl_info *info)
16308{
16309 struct cfg80211_registered_device *rdev = info->user_ptr[0];
16310 struct nlattr *spec[NL80211_SAR_ATTR_SPECS_MAX + 1];
16311 struct nlattr *tb[NL80211_SAR_ATTR_MAX + 1];
16312 struct cfg80211_sar_specs *sar_spec;
16313 enum nl80211_sar_type type;
16314 struct nlattr *spec_list;
16315 u32 specs;
16316 int rem, err;
16317
16318 if (!rdev->wiphy.sar_capa || !rdev->ops->set_sar_specs)
16319 return -EOPNOTSUPP;
16320
16321 if (!info->attrs[NL80211_ATTR_SAR_SPEC])
16322 return -EINVAL;
16323
16324 nla_parse_nested(tb, NL80211_SAR_ATTR_MAX,
16325 info->attrs[NL80211_ATTR_SAR_SPEC],
16326 NULL, NULL);
16327
16328 if (!tb[NL80211_SAR_ATTR_TYPE] || !tb[NL80211_SAR_ATTR_SPECS])
16329 return -EINVAL;
16330
16331 type = nla_get_u32(tb[NL80211_SAR_ATTR_TYPE]);
16332 if (type != rdev->wiphy.sar_capa->type)
16333 return -EINVAL;
16334
16335 specs = 0;
16336 nla_for_each_nested(spec_list, tb[NL80211_SAR_ATTR_SPECS], rem)
16337 specs++;
16338
16339 if (specs > rdev->wiphy.sar_capa->num_freq_ranges)
16340 return -EINVAL;
16341
40f231e7 16342 sar_spec = kzalloc(struct_size(sar_spec, sub_specs, specs), GFP_KERNEL);
6bdb68ce
CH
16343 if (!sar_spec)
16344 return -ENOMEM;
16345
16346 sar_spec->type = type;
16347 specs = 0;
16348 nla_for_each_nested(spec_list, tb[NL80211_SAR_ATTR_SPECS], rem) {
16349 nla_parse_nested(spec, NL80211_SAR_ATTR_SPECS_MAX,
16350 spec_list, NULL, NULL);
16351
16352 switch (type) {
16353 case NL80211_SAR_TYPE_POWER:
16354 if (nl80211_set_sar_sub_specs(rdev, sar_spec,
16355 spec, specs)) {
16356 err = -EINVAL;
16357 goto error;
16358 }
16359 break;
16360 default:
16361 err = -EINVAL;
16362 goto error;
16363 }
16364 specs++;
16365 }
16366
16367 sar_spec->num_sub_specs = specs;
16368
16369 rdev->cur_cmd_info = info;
16370 err = rdev_set_sar_specs(rdev, sar_spec);
16371 rdev->cur_cmd_info = NULL;
16372error:
16373 kfree(sar_spec);
16374 return err;
16375}
16376
2182db91
JB
16377#define SELECTOR(__sel, name, value) \
16378 ((__sel) == (value)) ? NL80211_IFL_SEL_##name :
16379int __missing_selector(void);
16380#define IFLAGS(__val) INTERNAL_FLAG_SELECTORS(__val) __missing_selector()
16381
4534de83 16382static const struct genl_ops nl80211_ops[] = {
55682965
JB
16383 {
16384 .cmd = NL80211_CMD_GET_WIPHY,
ef6243ac 16385 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965
JB
16386 .doit = nl80211_get_wiphy,
16387 .dumpit = nl80211_dump_wiphy,
86e8cf98 16388 .done = nl80211_dump_wiphy_done,
55682965 16389 /* can be retrieved by unprivileged users */
2182db91 16390 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
55682965 16391 },
66a9b928
JK
16392};
16393
16394static const struct genl_small_ops nl80211_small_ops[] = {
55682965
JB
16395 {
16396 .cmd = NL80211_CMD_SET_WIPHY,
ef6243ac 16397 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 16398 .doit = nl80211_set_wiphy,
5617c6cd 16399 .flags = GENL_UNS_ADMIN_PERM,
55682965
JB
16400 },
16401 {
16402 .cmd = NL80211_CMD_GET_INTERFACE,
ef6243ac 16403 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965
JB
16404 .doit = nl80211_get_interface,
16405 .dumpit = nl80211_dump_interface,
55682965 16406 /* can be retrieved by unprivileged users */
2182db91 16407 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV),
55682965
JB
16408 },
16409 {
16410 .cmd = NL80211_CMD_SET_INTERFACE,
ef6243ac 16411 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 16412 .doit = nl80211_set_interface,
5617c6cd 16413 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16414 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
16415 NL80211_FLAG_NEED_RTNL),
55682965
JB
16416 },
16417 {
16418 .cmd = NL80211_CMD_NEW_INTERFACE,
ef6243ac 16419 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 16420 .doit = nl80211_new_interface,
5617c6cd 16421 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16422 .internal_flags =
16423 IFLAGS(NL80211_FLAG_NEED_WIPHY |
16424 NL80211_FLAG_NEED_RTNL |
16425 /* we take the wiphy mutex later ourselves */
16426 NL80211_FLAG_NO_WIPHY_MTX),
55682965
JB
16427 },
16428 {
16429 .cmd = NL80211_CMD_DEL_INTERFACE,
ef6243ac 16430 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 16431 .doit = nl80211_del_interface,
5617c6cd 16432 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16433 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV |
16434 NL80211_FLAG_NEED_RTNL),
41ade00f
JB
16435 },
16436 {
16437 .cmd = NL80211_CMD_GET_KEY,
ef6243ac 16438 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 16439 .doit = nl80211_get_key,
5617c6cd 16440 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16441 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
41ade00f
JB
16442 },
16443 {
16444 .cmd = NL80211_CMD_SET_KEY,
ef6243ac 16445 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 16446 .doit = nl80211_set_key,
5617c6cd 16447 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c 16448 /* cannot use NL80211_FLAG_MLO_VALID_LINK_ID, depends on key */
2182db91
JB
16449 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16450 NL80211_FLAG_CLEAR_SKB),
41ade00f
JB
16451 },
16452 {
16453 .cmd = NL80211_CMD_NEW_KEY,
ef6243ac 16454 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 16455 .doit = nl80211_new_key,
5617c6cd 16456 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16457 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16458 NL80211_FLAG_CLEAR_SKB),
41ade00f
JB
16459 },
16460 {
16461 .cmd = NL80211_CMD_DEL_KEY,
ef6243ac 16462 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 16463 .doit = nl80211_del_key,
5617c6cd 16464 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16465 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
55682965 16466 },
ed1b6cc7
JB
16467 {
16468 .cmd = NL80211_CMD_SET_BEACON,
ef6243ac 16469 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5617c6cd 16470 .flags = GENL_UNS_ADMIN_PERM,
8860020e 16471 .doit = nl80211_set_beacon,
7b0a0e3c
JB
16472 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16473 NL80211_FLAG_MLO_VALID_LINK_ID),
ed1b6cc7
JB
16474 },
16475 {
8860020e 16476 .cmd = NL80211_CMD_START_AP,
ef6243ac 16477 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5617c6cd 16478 .flags = GENL_UNS_ADMIN_PERM,
8860020e 16479 .doit = nl80211_start_ap,
7b0a0e3c
JB
16480 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16481 NL80211_FLAG_MLO_VALID_LINK_ID),
ed1b6cc7
JB
16482 },
16483 {
8860020e 16484 .cmd = NL80211_CMD_STOP_AP,
ef6243ac 16485 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5617c6cd 16486 .flags = GENL_UNS_ADMIN_PERM,
8860020e 16487 .doit = nl80211_stop_ap,
7b0a0e3c
JB
16488 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16489 NL80211_FLAG_MLO_VALID_LINK_ID),
ed1b6cc7 16490 },
5727ef1b
JB
16491 {
16492 .cmd = NL80211_CMD_GET_STATION,
ef6243ac 16493 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 16494 .doit = nl80211_get_station,
2ec600d6 16495 .dumpit = nl80211_dump_station,
2182db91 16496 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
5727ef1b
JB
16497 },
16498 {
16499 .cmd = NL80211_CMD_SET_STATION,
ef6243ac 16500 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 16501 .doit = nl80211_set_station,
5617c6cd 16502 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16503 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
5727ef1b
JB
16504 },
16505 {
16506 .cmd = NL80211_CMD_NEW_STATION,
ef6243ac 16507 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 16508 .doit = nl80211_new_station,
5617c6cd 16509 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16510 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
5727ef1b
JB
16511 },
16512 {
16513 .cmd = NL80211_CMD_DEL_STATION,
ef6243ac 16514 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 16515 .doit = nl80211_del_station,
5617c6cd 16516 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16517 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
2ec600d6
LCC
16518 },
16519 {
16520 .cmd = NL80211_CMD_GET_MPATH,
ef6243ac 16521 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6
LCC
16522 .doit = nl80211_get_mpath,
16523 .dumpit = nl80211_dump_mpath,
5617c6cd 16524 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16525 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
2ec600d6 16526 },
66be7d2b
HR
16527 {
16528 .cmd = NL80211_CMD_GET_MPP,
ef6243ac 16529 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
66be7d2b
HR
16530 .doit = nl80211_get_mpp,
16531 .dumpit = nl80211_dump_mpp,
5617c6cd 16532 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16533 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
66be7d2b 16534 },
2ec600d6
LCC
16535 {
16536 .cmd = NL80211_CMD_SET_MPATH,
ef6243ac 16537 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6 16538 .doit = nl80211_set_mpath,
5617c6cd 16539 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16540 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
2ec600d6
LCC
16541 },
16542 {
16543 .cmd = NL80211_CMD_NEW_MPATH,
ef6243ac 16544 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6 16545 .doit = nl80211_new_mpath,
5617c6cd 16546 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16547 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
2ec600d6
LCC
16548 },
16549 {
16550 .cmd = NL80211_CMD_DEL_MPATH,
ef6243ac 16551 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6 16552 .doit = nl80211_del_mpath,
5617c6cd 16553 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16554 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
9f1ba906
JM
16555 },
16556 {
16557 .cmd = NL80211_CMD_SET_BSS,
ef6243ac 16558 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9f1ba906 16559 .doit = nl80211_set_bss,
5617c6cd 16560 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16561 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
b2e1b302 16562 },
f130347c
LR
16563 {
16564 .cmd = NL80211_CMD_GET_REG,
ef6243ac 16565 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ad30ca2c
AN
16566 .doit = nl80211_get_reg_do,
16567 .dumpit = nl80211_get_reg_dump,
f130347c
LR
16568 /* can be retrieved by unprivileged users */
16569 },
b6863036 16570#ifdef CONFIG_CFG80211_CRDA_SUPPORT
b2e1b302
LR
16571 {
16572 .cmd = NL80211_CMD_SET_REG,
ef6243ac 16573 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b2e1b302 16574 .doit = nl80211_set_reg,
b2e1b302
LR
16575 .flags = GENL_ADMIN_PERM,
16576 },
b6863036 16577#endif
b2e1b302
LR
16578 {
16579 .cmd = NL80211_CMD_REQ_SET_REG,
ef6243ac 16580 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b2e1b302 16581 .doit = nl80211_req_set_reg,
93da9cc1 16582 .flags = GENL_ADMIN_PERM,
16583 },
1ea4ff3e
JB
16584 {
16585 .cmd = NL80211_CMD_RELOAD_REGDB,
ef6243ac 16586 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1ea4ff3e 16587 .doit = nl80211_reload_regdb,
1ea4ff3e
JB
16588 .flags = GENL_ADMIN_PERM,
16589 },
93da9cc1 16590 {
24bdd9f4 16591 .cmd = NL80211_CMD_GET_MESH_CONFIG,
ef6243ac 16592 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
24bdd9f4 16593 .doit = nl80211_get_mesh_config,
93da9cc1 16594 /* can be retrieved by unprivileged users */
2182db91 16595 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
93da9cc1 16596 },
16597 {
24bdd9f4 16598 .cmd = NL80211_CMD_SET_MESH_CONFIG,
ef6243ac 16599 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
24bdd9f4 16600 .doit = nl80211_update_mesh_config,
5617c6cd 16601 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16602 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
9aed3cc1 16603 },
2a519311
JB
16604 {
16605 .cmd = NL80211_CMD_TRIGGER_SCAN,
ef6243ac 16606 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2a519311 16607 .doit = nl80211_trigger_scan,
5617c6cd 16608 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16609 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
2a519311 16610 },
91d3ab46
VK
16611 {
16612 .cmd = NL80211_CMD_ABORT_SCAN,
ef6243ac 16613 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
91d3ab46 16614 .doit = nl80211_abort_scan,
5617c6cd 16615 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16616 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
91d3ab46 16617 },
2a519311
JB
16618 {
16619 .cmd = NL80211_CMD_GET_SCAN,
ef6243ac 16620 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2a519311
JB
16621 .dumpit = nl80211_dump_scan,
16622 },
807f8a8c
LC
16623 {
16624 .cmd = NL80211_CMD_START_SCHED_SCAN,
ef6243ac 16625 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
807f8a8c 16626 .doit = nl80211_start_sched_scan,
5617c6cd 16627 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16628 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
807f8a8c
LC
16629 },
16630 {
16631 .cmd = NL80211_CMD_STOP_SCHED_SCAN,
ef6243ac 16632 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
807f8a8c 16633 .doit = nl80211_stop_sched_scan,
5617c6cd 16634 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16635 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
807f8a8c 16636 },
636a5d36
JM
16637 {
16638 .cmd = NL80211_CMD_AUTHENTICATE,
ef6243ac 16639 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 16640 .doit = nl80211_authenticate,
5617c6cd 16641 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16642 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16643 NL80211_FLAG_CLEAR_SKB),
636a5d36
JM
16644 },
16645 {
16646 .cmd = NL80211_CMD_ASSOCIATE,
ef6243ac 16647 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 16648 .doit = nl80211_associate,
5617c6cd 16649 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16650 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16651 NL80211_FLAG_CLEAR_SKB),
636a5d36
JM
16652 },
16653 {
16654 .cmd = NL80211_CMD_DEAUTHENTICATE,
ef6243ac 16655 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 16656 .doit = nl80211_deauthenticate,
5617c6cd 16657 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16658 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
636a5d36
JM
16659 },
16660 {
16661 .cmd = NL80211_CMD_DISASSOCIATE,
ef6243ac 16662 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 16663 .doit = nl80211_disassociate,
5617c6cd 16664 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16665 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
636a5d36 16666 },
04a773ad
JB
16667 {
16668 .cmd = NL80211_CMD_JOIN_IBSS,
ef6243ac 16669 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
04a773ad 16670 .doit = nl80211_join_ibss,
5617c6cd 16671 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16672 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
04a773ad
JB
16673 },
16674 {
16675 .cmd = NL80211_CMD_LEAVE_IBSS,
ef6243ac 16676 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
04a773ad 16677 .doit = nl80211_leave_ibss,
5617c6cd 16678 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16679 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
04a773ad 16680 },
aff89a9b
JB
16681#ifdef CONFIG_NL80211_TESTMODE
16682 {
16683 .cmd = NL80211_CMD_TESTMODE,
ef6243ac 16684 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
aff89a9b 16685 .doit = nl80211_testmode_do,
71063f0e 16686 .dumpit = nl80211_testmode_dump,
5617c6cd 16687 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16688 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
aff89a9b
JB
16689 },
16690#endif
b23aa676
SO
16691 {
16692 .cmd = NL80211_CMD_CONNECT,
ef6243ac 16693 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b23aa676 16694 .doit = nl80211_connect,
5617c6cd 16695 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16696 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16697 NL80211_FLAG_CLEAR_SKB),
b23aa676 16698 },
088e8df8 16699 {
16700 .cmd = NL80211_CMD_UPDATE_CONNECT_PARAMS,
ef6243ac 16701 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
088e8df8 16702 .doit = nl80211_update_connect_params,
088e8df8 16703 .flags = GENL_ADMIN_PERM,
2182db91
JB
16704 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16705 NL80211_FLAG_CLEAR_SKB),
088e8df8 16706 },
b23aa676
SO
16707 {
16708 .cmd = NL80211_CMD_DISCONNECT,
ef6243ac 16709 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b23aa676 16710 .doit = nl80211_disconnect,
5617c6cd 16711 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16712 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
b23aa676 16713 },
463d0183
JB
16714 {
16715 .cmd = NL80211_CMD_SET_WIPHY_NETNS,
ef6243ac 16716 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
463d0183 16717 .doit = nl80211_wiphy_netns,
5617c6cd 16718 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16719 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY |
16720 NL80211_FLAG_NEED_RTNL |
16721 NL80211_FLAG_NO_WIPHY_MTX),
463d0183 16722 },
61fa713c
HS
16723 {
16724 .cmd = NL80211_CMD_GET_SURVEY,
ef6243ac 16725 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
61fa713c
HS
16726 .dumpit = nl80211_dump_survey,
16727 },
67fbb16b
SO
16728 {
16729 .cmd = NL80211_CMD_SET_PMKSA,
ef6243ac 16730 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
67fbb16b 16731 .doit = nl80211_setdel_pmksa,
5617c6cd 16732 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16733 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16734 NL80211_FLAG_CLEAR_SKB),
67fbb16b
SO
16735 },
16736 {
16737 .cmd = NL80211_CMD_DEL_PMKSA,
ef6243ac 16738 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
67fbb16b 16739 .doit = nl80211_setdel_pmksa,
5617c6cd 16740 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16741 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
67fbb16b
SO
16742 },
16743 {
16744 .cmd = NL80211_CMD_FLUSH_PMKSA,
ef6243ac 16745 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
67fbb16b 16746 .doit = nl80211_flush_pmksa,
5617c6cd 16747 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16748 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
67fbb16b 16749 },
9588bbd5
JM
16750 {
16751 .cmd = NL80211_CMD_REMAIN_ON_CHANNEL,
ef6243ac 16752 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9588bbd5 16753 .doit = nl80211_remain_on_channel,
5617c6cd 16754 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
16755 /* FIXME: requiring a link ID here is probably not good */
16756 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |
16757 NL80211_FLAG_MLO_VALID_LINK_ID),
9588bbd5
JM
16758 },
16759 {
16760 .cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
ef6243ac 16761 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9588bbd5 16762 .doit = nl80211_cancel_remain_on_channel,
5617c6cd 16763 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16764 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
9588bbd5 16765 },
13ae75b1
JM
16766 {
16767 .cmd = NL80211_CMD_SET_TX_BITRATE_MASK,
ef6243ac 16768 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
13ae75b1 16769 .doit = nl80211_set_tx_bitrate_mask,
5617c6cd 16770 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
16771 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
16772 NL80211_FLAG_MLO_VALID_LINK_ID),
13ae75b1 16773 },
026331c4 16774 {
2e161f78 16775 .cmd = NL80211_CMD_REGISTER_FRAME,
ef6243ac 16776 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2e161f78 16777 .doit = nl80211_register_mgmt,
5617c6cd 16778 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16779 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV),
026331c4
JM
16780 },
16781 {
2e161f78 16782 .cmd = NL80211_CMD_FRAME,
ef6243ac 16783 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2e161f78 16784 .doit = nl80211_tx_mgmt,
5617c6cd 16785 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16786 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
f7ca38df
JB
16787 },
16788 {
16789 .cmd = NL80211_CMD_FRAME_WAIT_CANCEL,
ef6243ac 16790 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
f7ca38df 16791 .doit = nl80211_tx_mgmt_cancel_wait,
5617c6cd 16792 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16793 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
026331c4 16794 },
ffb9eb3d
KV
16795 {
16796 .cmd = NL80211_CMD_SET_POWER_SAVE,
ef6243ac 16797 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ffb9eb3d 16798 .doit = nl80211_set_power_save,
5617c6cd 16799 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16800 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
ffb9eb3d
KV
16801 },
16802 {
16803 .cmd = NL80211_CMD_GET_POWER_SAVE,
ef6243ac 16804 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ffb9eb3d 16805 .doit = nl80211_get_power_save,
ffb9eb3d 16806 /* can be retrieved by unprivileged users */
2182db91 16807 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
ffb9eb3d 16808 },
d6dc1a38
JO
16809 {
16810 .cmd = NL80211_CMD_SET_CQM,
ef6243ac 16811 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
d6dc1a38 16812 .doit = nl80211_set_cqm,
5617c6cd 16813 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16814 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
d6dc1a38 16815 },
f444de05
JB
16816 {
16817 .cmd = NL80211_CMD_SET_CHANNEL,
ef6243ac 16818 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
f444de05 16819 .doit = nl80211_set_channel,
5617c6cd 16820 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
16821 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
16822 NL80211_FLAG_MLO_VALID_LINK_ID),
f444de05 16823 },
29cbe68c
JB
16824 {
16825 .cmd = NL80211_CMD_JOIN_MESH,
ef6243ac 16826 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
29cbe68c 16827 .doit = nl80211_join_mesh,
5617c6cd 16828 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16829 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
29cbe68c
JB
16830 },
16831 {
16832 .cmd = NL80211_CMD_LEAVE_MESH,
ef6243ac 16833 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
29cbe68c 16834 .doit = nl80211_leave_mesh,
5617c6cd 16835 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16836 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
29cbe68c 16837 },
6e0bd6c3
RL
16838 {
16839 .cmd = NL80211_CMD_JOIN_OCB,
ef6243ac 16840 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6e0bd6c3 16841 .doit = nl80211_join_ocb,
5617c6cd 16842 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16843 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
6e0bd6c3
RL
16844 },
16845 {
16846 .cmd = NL80211_CMD_LEAVE_OCB,
ef6243ac 16847 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6e0bd6c3 16848 .doit = nl80211_leave_ocb,
5617c6cd 16849 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16850 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
6e0bd6c3 16851 },
dfb89c56 16852#ifdef CONFIG_PM
ff1b6e69
JB
16853 {
16854 .cmd = NL80211_CMD_GET_WOWLAN,
ef6243ac 16855 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ff1b6e69 16856 .doit = nl80211_get_wowlan,
ff1b6e69 16857 /* can be retrieved by unprivileged users */
2182db91 16858 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
ff1b6e69
JB
16859 },
16860 {
16861 .cmd = NL80211_CMD_SET_WOWLAN,
ef6243ac 16862 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ff1b6e69 16863 .doit = nl80211_set_wowlan,
5617c6cd 16864 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16865 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
ff1b6e69 16866 },
dfb89c56 16867#endif
e5497d76
JB
16868 {
16869 .cmd = NL80211_CMD_SET_REKEY_OFFLOAD,
ef6243ac 16870 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
e5497d76 16871 .doit = nl80211_set_rekey_data,
5617c6cd 16872 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16873 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
16874 NL80211_FLAG_CLEAR_SKB),
e5497d76 16875 },
109086ce
AN
16876 {
16877 .cmd = NL80211_CMD_TDLS_MGMT,
ef6243ac 16878 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
109086ce 16879 .doit = nl80211_tdls_mgmt,
5617c6cd 16880 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16881 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
109086ce
AN
16882 },
16883 {
16884 .cmd = NL80211_CMD_TDLS_OPER,
ef6243ac 16885 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
109086ce 16886 .doit = nl80211_tdls_oper,
5617c6cd 16887 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16888 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
109086ce 16889 },
28946da7
JB
16890 {
16891 .cmd = NL80211_CMD_UNEXPECTED_FRAME,
ef6243ac 16892 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
28946da7 16893 .doit = nl80211_register_unexpected_frame,
5617c6cd 16894 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16895 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
28946da7 16896 },
7f6cf311
JB
16897 {
16898 .cmd = NL80211_CMD_PROBE_CLIENT,
ef6243ac 16899 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
7f6cf311 16900 .doit = nl80211_probe_client,
5617c6cd 16901 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16902 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
7f6cf311 16903 },
5e760230
JB
16904 {
16905 .cmd = NL80211_CMD_REGISTER_BEACONS,
ef6243ac 16906 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5e760230 16907 .doit = nl80211_register_beacons,
5617c6cd 16908 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16909 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
5e760230 16910 },
1d9d9213
SW
16911 {
16912 .cmd = NL80211_CMD_SET_NOACK_MAP,
ef6243ac 16913 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1d9d9213 16914 .doit = nl80211_set_noack_map,
5617c6cd 16915 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16916 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
1d9d9213 16917 },
98104fde
JB
16918 {
16919 .cmd = NL80211_CMD_START_P2P_DEVICE,
ef6243ac 16920 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
98104fde 16921 .doit = nl80211_start_p2p_device,
5617c6cd 16922 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16923 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV |
16924 NL80211_FLAG_NEED_RTNL),
98104fde
JB
16925 },
16926 {
16927 .cmd = NL80211_CMD_STOP_P2P_DEVICE,
ef6243ac 16928 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
98104fde 16929 .doit = nl80211_stop_p2p_device,
5617c6cd 16930 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
16931 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |
16932 NL80211_FLAG_NEED_RTNL),
cb3b7d87
AB
16933 },
16934 {
16935 .cmd = NL80211_CMD_START_NAN,
ef6243ac 16936 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
cb3b7d87 16937 .doit = nl80211_start_nan,
cb3b7d87 16938 .flags = GENL_ADMIN_PERM,
2182db91
JB
16939 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV |
16940 NL80211_FLAG_NEED_RTNL),
cb3b7d87
AB
16941 },
16942 {
16943 .cmd = NL80211_CMD_STOP_NAN,
ef6243ac 16944 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
cb3b7d87 16945 .doit = nl80211_stop_nan,
cb3b7d87 16946 .flags = GENL_ADMIN_PERM,
2182db91
JB
16947 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |
16948 NL80211_FLAG_NEED_RTNL),
a442b761
AB
16949 },
16950 {
16951 .cmd = NL80211_CMD_ADD_NAN_FUNCTION,
ef6243ac 16952 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
a442b761 16953 .doit = nl80211_nan_add_func,
a442b761 16954 .flags = GENL_ADMIN_PERM,
2182db91 16955 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
a442b761
AB
16956 },
16957 {
16958 .cmd = NL80211_CMD_DEL_NAN_FUNCTION,
ef6243ac 16959 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
a442b761 16960 .doit = nl80211_nan_del_func,
a442b761 16961 .flags = GENL_ADMIN_PERM,
2182db91 16962 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
a5a9dcf2
AB
16963 },
16964 {
16965 .cmd = NL80211_CMD_CHANGE_NAN_CONFIG,
ef6243ac 16966 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
a5a9dcf2 16967 .doit = nl80211_nan_change_config,
a5a9dcf2 16968 .flags = GENL_ADMIN_PERM,
2182db91 16969 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
98104fde 16970 },
f4e583c8
AQ
16971 {
16972 .cmd = NL80211_CMD_SET_MCAST_RATE,
ef6243ac 16973 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
f4e583c8 16974 .doit = nl80211_set_mcast_rate,
5617c6cd 16975 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16976 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
77765eaf
VT
16977 },
16978 {
16979 .cmd = NL80211_CMD_SET_MAC_ACL,
ef6243ac 16980 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
77765eaf 16981 .doit = nl80211_set_mac_acl,
5617c6cd 16982 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
16983 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
16984 NL80211_FLAG_MLO_UNSUPPORTED),
f4e583c8 16985 },
04f39047
SW
16986 {
16987 .cmd = NL80211_CMD_RADAR_DETECT,
ef6243ac 16988 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
04f39047 16989 .doit = nl80211_start_radar_detection,
5617c6cd 16990 .flags = GENL_UNS_ADMIN_PERM,
2182db91 16991 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
7b0a0e3c
JB
16992 NL80211_FLAG_NO_WIPHY_MTX |
16993 NL80211_FLAG_MLO_UNSUPPORTED),
04f39047 16994 },
3713b4e3
JB
16995 {
16996 .cmd = NL80211_CMD_GET_PROTOCOL_FEATURES,
ef6243ac 16997 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3713b4e3 16998 .doit = nl80211_get_protocol_features,
3713b4e3 16999 },
355199e0
JM
17000 {
17001 .cmd = NL80211_CMD_UPDATE_FT_IES,
ef6243ac 17002 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
355199e0 17003 .doit = nl80211_update_ft_ies,
5617c6cd 17004 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17005 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
355199e0 17006 },
5de17984
AS
17007 {
17008 .cmd = NL80211_CMD_CRIT_PROTOCOL_START,
ef6243ac 17009 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5de17984 17010 .doit = nl80211_crit_protocol_start,
5617c6cd 17011 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17012 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
5de17984
AS
17013 },
17014 {
17015 .cmd = NL80211_CMD_CRIT_PROTOCOL_STOP,
ef6243ac 17016 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5de17984 17017 .doit = nl80211_crit_protocol_stop,
5617c6cd 17018 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17019 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
be29b99a
AK
17020 },
17021 {
17022 .cmd = NL80211_CMD_GET_COALESCE,
ef6243ac 17023 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
be29b99a 17024 .doit = nl80211_get_coalesce,
2182db91 17025 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
be29b99a
AK
17026 },
17027 {
17028 .cmd = NL80211_CMD_SET_COALESCE,
ef6243ac 17029 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
be29b99a 17030 .doit = nl80211_set_coalesce,
5617c6cd 17031 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17032 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
16ef1fe2
SW
17033 },
17034 {
17035 .cmd = NL80211_CMD_CHANNEL_SWITCH,
ef6243ac 17036 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
16ef1fe2 17037 .doit = nl80211_channel_switch,
5617c6cd 17038 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
17039 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17040 NL80211_FLAG_MLO_VALID_LINK_ID),
16ef1fe2 17041 },
ad7e718c
JB
17042 {
17043 .cmd = NL80211_CMD_VENDOR,
ef6243ac 17044 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ad7e718c 17045 .doit = nl80211_vendor_cmd,
7bdbe400 17046 .dumpit = nl80211_vendor_cmd_dump,
5617c6cd 17047 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
17048 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY |
17049 NL80211_FLAG_CLEAR_SKB),
ad7e718c 17050 },
fa9ffc74
KP
17051 {
17052 .cmd = NL80211_CMD_SET_QOS_MAP,
ef6243ac 17053 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
fa9ffc74 17054 .doit = nl80211_set_qos_map,
5617c6cd 17055 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17056 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
fa9ffc74 17057 },
960d01ac
JB
17058 {
17059 .cmd = NL80211_CMD_ADD_TX_TS,
ef6243ac 17060 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
960d01ac 17061 .doit = nl80211_add_tx_ts,
5617c6cd 17062 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
17063 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17064 NL80211_FLAG_MLO_UNSUPPORTED),
960d01ac
JB
17065 },
17066 {
17067 .cmd = NL80211_CMD_DEL_TX_TS,
ef6243ac 17068 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
960d01ac 17069 .doit = nl80211_del_tx_ts,
5617c6cd 17070 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17071 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
960d01ac 17072 },
1057d35e
AN
17073 {
17074 .cmd = NL80211_CMD_TDLS_CHANNEL_SWITCH,
ef6243ac 17075 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1057d35e 17076 .doit = nl80211_tdls_channel_switch,
5617c6cd 17077 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17078 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
1057d35e
AN
17079 },
17080 {
17081 .cmd = NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH,
ef6243ac 17082 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1057d35e 17083 .doit = nl80211_tdls_cancel_channel_switch,
5617c6cd 17084 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17085 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
1057d35e 17086 },
ce0ce13a
MB
17087 {
17088 .cmd = NL80211_CMD_SET_MULTICAST_TO_UNICAST,
ef6243ac 17089 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ce0ce13a 17090 .doit = nl80211_set_multicast_to_unicast,
ce0ce13a 17091 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17092 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
ce0ce13a 17093 },
3a00df57
AS
17094 {
17095 .cmd = NL80211_CMD_SET_PMK,
ef6243ac 17096 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3a00df57 17097 .doit = nl80211_set_pmk,
2182db91
JB
17098 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17099 NL80211_FLAG_CLEAR_SKB),
3a00df57
AS
17100 },
17101 {
17102 .cmd = NL80211_CMD_DEL_PMK,
ef6243ac 17103 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3a00df57 17104 .doit = nl80211_del_pmk,
2182db91 17105 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
3a00df57 17106 },
40cbfa90
SD
17107 {
17108 .cmd = NL80211_CMD_EXTERNAL_AUTH,
ef6243ac 17109 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
40cbfa90 17110 .doit = nl80211_external_auth,
40cbfa90 17111 .flags = GENL_ADMIN_PERM,
2182db91 17112 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
40cbfa90 17113 },
2576a9ac
DK
17114 {
17115 .cmd = NL80211_CMD_CONTROL_PORT_FRAME,
ef6243ac 17116 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2576a9ac 17117 .doit = nl80211_tx_control_port,
2576a9ac 17118 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17119 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
2576a9ac 17120 },
81e54d08
PKC
17121 {
17122 .cmd = NL80211_CMD_GET_FTM_RESPONDER_STATS,
ef6243ac 17123 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
81e54d08 17124 .doit = nl80211_get_ftm_responder_stats,
7b0a0e3c
JB
17125 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
17126 NL80211_FLAG_MLO_VALID_LINK_ID),
81e54d08 17127 },
9bb7e0f2
JB
17128 {
17129 .cmd = NL80211_CMD_PEER_MEASUREMENT_START,
ef6243ac 17130 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9bb7e0f2 17131 .doit = nl80211_pmsr_start,
9bb7e0f2 17132 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17133 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
9bb7e0f2 17134 },
30c63115
S
17135 {
17136 .cmd = NL80211_CMD_NOTIFY_RADAR,
ef6243ac 17137 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
30c63115 17138 .doit = nl80211_notify_radar_detection,
30c63115 17139 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17140 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
30c63115 17141 },
cb74e977
SD
17142 {
17143 .cmd = NL80211_CMD_UPDATE_OWE_INFO,
17144 .doit = nl80211_update_owe_info,
17145 .flags = GENL_ADMIN_PERM,
2182db91 17146 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
5ab92e7f
RM
17147 },
17148 {
17149 .cmd = NL80211_CMD_PROBE_MESH_LINK,
17150 .doit = nl80211_probe_mesh_link,
17151 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17152 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
cb74e977 17153 },
77f576de
T
17154 {
17155 .cmd = NL80211_CMD_SET_TID_CONFIG,
17156 .doit = nl80211_set_tid_config,
17157 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
17158 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
17159 NL80211_FLAG_MLO_VALID_LINK_ID),
77f576de 17160 },
6bdb68ce
CH
17161 {
17162 .cmd = NL80211_CMD_SET_SAR_SPECS,
17163 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
17164 .doit = nl80211_set_sar_specs,
17165 .flags = GENL_UNS_ADMIN_PERM,
2182db91
JB
17166 .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY |
17167 NL80211_FLAG_NEED_RTNL),
6bdb68ce 17168 },
0d2ab3ae
JC
17169 {
17170 .cmd = NL80211_CMD_COLOR_CHANGE_REQUEST,
17171 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
17172 .doit = nl80211_color_change,
17173 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17174 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
0d2ab3ae 17175 },
e306784a
SM
17176 {
17177 .cmd = NL80211_CMD_SET_FILS_AAD,
17178 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
17179 .doit = nl80211_set_fils_aad,
17180 .flags = GENL_UNS_ADMIN_PERM,
2182db91 17181 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
e306784a 17182 },
7b0a0e3c
JB
17183 {
17184 .cmd = NL80211_CMD_ADD_LINK,
17185 .doit = nl80211_add_link,
17186 .flags = GENL_UNS_ADMIN_PERM,
17187 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
17188 },
17189 {
17190 .cmd = NL80211_CMD_REMOVE_LINK,
17191 .doit = nl80211_remove_link,
17192 .flags = GENL_UNS_ADMIN_PERM,
577e5b8c
ST
17193 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17194 NL80211_FLAG_MLO_VALID_LINK_ID),
17195 },
17196 {
17197 .cmd = NL80211_CMD_ADD_LINK_STA,
17198 .doit = nl80211_add_link_station,
17199 .flags = GENL_UNS_ADMIN_PERM,
17200 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17201 NL80211_FLAG_MLO_VALID_LINK_ID),
17202 },
17203 {
17204 .cmd = NL80211_CMD_MODIFY_LINK_STA,
17205 .doit = nl80211_modify_link_station,
17206 .flags = GENL_UNS_ADMIN_PERM,
17207 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17208 NL80211_FLAG_MLO_VALID_LINK_ID),
17209 },
17210 {
17211 .cmd = NL80211_CMD_REMOVE_LINK_STA,
17212 .doit = nl80211_remove_link_station,
17213 .flags = GENL_UNS_ADMIN_PERM,
7b0a0e3c
JB
17214 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
17215 NL80211_FLAG_MLO_VALID_LINK_ID),
17216 },
55682965 17217};
9588bbd5 17218
56989f6d 17219static struct genl_family nl80211_fam __ro_after_init = {
489111e5
JB
17220 .name = NL80211_GENL_NAME, /* have users key off the name instead */
17221 .hdrsize = 0, /* no private header */
17222 .version = 1, /* no particular meaning now */
17223 .maxattr = NL80211_ATTR_MAX,
3b0f31f2 17224 .policy = nl80211_policy,
489111e5
JB
17225 .netnsok = true,
17226 .pre_doit = nl80211_pre_doit,
17227 .post_doit = nl80211_post_doit,
17228 .module = THIS_MODULE,
17229 .ops = nl80211_ops,
17230 .n_ops = ARRAY_SIZE(nl80211_ops),
66a9b928
JK
17231 .small_ops = nl80211_small_ops,
17232 .n_small_ops = ARRAY_SIZE(nl80211_small_ops),
489111e5
JB
17233 .mcgrps = nl80211_mcgrps,
17234 .n_mcgrps = ARRAY_SIZE(nl80211_mcgrps),
50508d94 17235 .parallel_ops = true,
489111e5
JB
17236};
17237
55682965
JB
17238/* notification functions */
17239
3bb20556
JB
17240void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev,
17241 enum nl80211_commands cmd)
55682965
JB
17242{
17243 struct sk_buff *msg;
86e8cf98 17244 struct nl80211_dump_wiphy_state state = {};
55682965 17245
3bb20556
JB
17246 WARN_ON(cmd != NL80211_CMD_NEW_WIPHY &&
17247 cmd != NL80211_CMD_DEL_WIPHY);
17248
fd2120ca 17249 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
55682965
JB
17250 if (!msg)
17251 return;
17252
3bb20556 17253 if (nl80211_send_wiphy(rdev, cmd, msg, 0, 0, 0, &state) < 0) {
55682965
JB
17254 nlmsg_free(msg);
17255 return;
17256 }
17257
68eb5503 17258 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17259 NL80211_MCGRP_CONFIG, GFP_KERNEL);
55682965
JB
17260}
17261
896ff063
DK
17262void nl80211_notify_iface(struct cfg80211_registered_device *rdev,
17263 struct wireless_dev *wdev,
17264 enum nl80211_commands cmd)
17265{
17266 struct sk_buff *msg;
17267
896ff063
DK
17268 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
17269 if (!msg)
17270 return;
17271
3d1a5bbf 17272 if (nl80211_send_iface(msg, 0, 0, 0, rdev, wdev, cmd) < 0) {
896ff063
DK
17273 nlmsg_free(msg);
17274 return;
17275 }
17276
17277 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
17278 NL80211_MCGRP_CONFIG, GFP_KERNEL);
17279}
17280
362a415d
JB
17281static int nl80211_add_scan_req(struct sk_buff *msg,
17282 struct cfg80211_registered_device *rdev)
17283{
17284 struct cfg80211_scan_request *req = rdev->scan_req;
17285 struct nlattr *nest;
17286 int i;
c8cb5b85 17287 struct cfg80211_scan_info *info;
362a415d
JB
17288
17289 if (WARN_ON(!req))
17290 return 0;
17291
ae0be8de 17292 nest = nla_nest_start_noflag(msg, NL80211_ATTR_SCAN_SSIDS);
362a415d
JB
17293 if (!nest)
17294 goto nla_put_failure;
9360ffd1
DM
17295 for (i = 0; i < req->n_ssids; i++) {
17296 if (nla_put(msg, i, req->ssids[i].ssid_len, req->ssids[i].ssid))
17297 goto nla_put_failure;
17298 }
362a415d
JB
17299 nla_nest_end(msg, nest);
17300
2032f3b2
TP
17301 if (req->flags & NL80211_SCAN_FLAG_FREQ_KHZ) {
17302 nest = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQ_KHZ);
17303 if (!nest)
17304 goto nla_put_failure;
17305 for (i = 0; i < req->n_channels; i++) {
17306 if (nla_put_u32(msg, i,
17307 ieee80211_channel_to_khz(req->channels[i])))
17308 goto nla_put_failure;
17309 }
17310 nla_nest_end(msg, nest);
17311 } else {
17312 nest = nla_nest_start_noflag(msg,
17313 NL80211_ATTR_SCAN_FREQUENCIES);
17314 if (!nest)
9360ffd1 17315 goto nla_put_failure;
2032f3b2
TP
17316 for (i = 0; i < req->n_channels; i++) {
17317 if (nla_put_u32(msg, i, req->channels[i]->center_freq))
17318 goto nla_put_failure;
17319 }
17320 nla_nest_end(msg, nest);
9360ffd1 17321 }
362a415d 17322
9360ffd1
DM
17323 if (req->ie &&
17324 nla_put(msg, NL80211_ATTR_IE, req->ie_len, req->ie))
17325 goto nla_put_failure;
362a415d 17326
ae917c9f
JB
17327 if (req->flags &&
17328 nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags))
17329 goto nla_put_failure;
ed473771 17330
c8cb5b85
TM
17331 info = rdev->int_scan_req ? &rdev->int_scan_req->info :
17332 &rdev->scan_req->info;
17333 if (info->scan_start_tsf &&
1d76250b 17334 (nla_put_u64_64bit(msg, NL80211_ATTR_SCAN_START_TIME_TSF,
c8cb5b85 17335 info->scan_start_tsf, NL80211_BSS_PAD) ||
1d76250b 17336 nla_put(msg, NL80211_ATTR_SCAN_START_TIME_TSF_BSSID, ETH_ALEN,
c8cb5b85 17337 info->tsf_bssid)))
1d76250b
AS
17338 goto nla_put_failure;
17339
362a415d
JB
17340 return 0;
17341 nla_put_failure:
17342 return -ENOBUFS;
17343}
17344
505a2e88 17345static int nl80211_prep_scan_msg(struct sk_buff *msg,
a538e2d5 17346 struct cfg80211_registered_device *rdev,
fd014284 17347 struct wireless_dev *wdev,
15e47304 17348 u32 portid, u32 seq, int flags,
a538e2d5 17349 u32 cmd)
2a519311
JB
17350{
17351 void *hdr;
17352
15e47304 17353 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
2a519311
JB
17354 if (!hdr)
17355 return -1;
17356
9360ffd1 17357 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
fd014284
JB
17358 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
17359 wdev->netdev->ifindex)) ||
2dad624e
ND
17360 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
17361 NL80211_ATTR_PAD))
9360ffd1 17362 goto nla_put_failure;
2a519311 17363
362a415d
JB
17364 /* ignore errors and send incomplete event anyway */
17365 nl80211_add_scan_req(msg, rdev);
2a519311 17366
053c095a
JB
17367 genlmsg_end(msg, hdr);
17368 return 0;
2a519311
JB
17369
17370 nla_put_failure:
17371 genlmsg_cancel(msg, hdr);
17372 return -EMSGSIZE;
17373}
17374
807f8a8c 17375static int
505a2e88 17376nl80211_prep_sched_scan_msg(struct sk_buff *msg,
96b08fd6 17377 struct cfg80211_sched_scan_request *req, u32 cmd)
807f8a8c
LC
17378{
17379 void *hdr;
17380
96b08fd6 17381 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
807f8a8c
LC
17382 if (!hdr)
17383 return -1;
17384
96b08fd6
AVS
17385 if (nla_put_u32(msg, NL80211_ATTR_WIPHY,
17386 wiphy_to_rdev(req->wiphy)->wiphy_idx) ||
17387 nla_put_u32(msg, NL80211_ATTR_IFINDEX, req->dev->ifindex) ||
17388 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, req->reqid,
17389 NL80211_ATTR_PAD))
9360ffd1 17390 goto nla_put_failure;
807f8a8c 17391
053c095a
JB
17392 genlmsg_end(msg, hdr);
17393 return 0;
807f8a8c
LC
17394
17395 nla_put_failure:
17396 genlmsg_cancel(msg, hdr);
17397 return -EMSGSIZE;
17398}
17399
a538e2d5 17400void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
fd014284 17401 struct wireless_dev *wdev)
a538e2d5
JB
17402{
17403 struct sk_buff *msg;
17404
58050fce 17405 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
a538e2d5
JB
17406 if (!msg)
17407 return;
17408
505a2e88 17409 if (nl80211_prep_scan_msg(msg, rdev, wdev, 0, 0, 0,
a538e2d5
JB
17410 NL80211_CMD_TRIGGER_SCAN) < 0) {
17411 nlmsg_free(msg);
17412 return;
17413 }
17414
68eb5503 17415 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17416 NL80211_MCGRP_SCAN, GFP_KERNEL);
a538e2d5
JB
17417}
17418
f9d15d16
JB
17419struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
17420 struct wireless_dev *wdev, bool aborted)
2a519311
JB
17421{
17422 struct sk_buff *msg;
17423
fd2120ca 17424 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2a519311 17425 if (!msg)
f9d15d16 17426 return NULL;
2a519311 17427
505a2e88 17428 if (nl80211_prep_scan_msg(msg, rdev, wdev, 0, 0, 0,
f9d15d16
JB
17429 aborted ? NL80211_CMD_SCAN_ABORTED :
17430 NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
2a519311 17431 nlmsg_free(msg);
f9d15d16 17432 return NULL;
2a519311
JB
17433 }
17434
f9d15d16 17435 return msg;
2a519311
JB
17436}
17437
505a2e88
AVS
17438/* send message created by nl80211_build_scan_msg() */
17439void nl80211_send_scan_msg(struct cfg80211_registered_device *rdev,
17440 struct sk_buff *msg)
807f8a8c 17441{
807f8a8c
LC
17442 if (!msg)
17443 return;
17444
68eb5503 17445 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17446 NL80211_MCGRP_SCAN, GFP_KERNEL);
807f8a8c
LC
17447}
17448
96b08fd6 17449void nl80211_send_sched_scan(struct cfg80211_sched_scan_request *req, u32 cmd)
807f8a8c
LC
17450{
17451 struct sk_buff *msg;
17452
58050fce 17453 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
807f8a8c
LC
17454 if (!msg)
17455 return;
17456
96b08fd6 17457 if (nl80211_prep_sched_scan_msg(msg, req, cmd) < 0) {
807f8a8c
LC
17458 nlmsg_free(msg);
17459 return;
17460 }
17461
96b08fd6 17462 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(req->wiphy), msg, 0,
2a94fe48 17463 NL80211_MCGRP_SCAN, GFP_KERNEL);
807f8a8c
LC
17464}
17465
b0d7aa59
JD
17466static bool nl80211_reg_change_event_fill(struct sk_buff *msg,
17467 struct regulatory_request *request)
73d54c9e 17468{
73d54c9e 17469 /* Userspace can always count this one always being set */
9360ffd1
DM
17470 if (nla_put_u8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator))
17471 goto nla_put_failure;
17472
17473 if (request->alpha2[0] == '0' && request->alpha2[1] == '0') {
17474 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
17475 NL80211_REGDOM_TYPE_WORLD))
17476 goto nla_put_failure;
17477 } else if (request->alpha2[0] == '9' && request->alpha2[1] == '9') {
17478 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
17479 NL80211_REGDOM_TYPE_CUSTOM_WORLD))
17480 goto nla_put_failure;
17481 } else if ((request->alpha2[0] == '9' && request->alpha2[1] == '8') ||
17482 request->intersect) {
17483 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
17484 NL80211_REGDOM_TYPE_INTERSECTION))
17485 goto nla_put_failure;
17486 } else {
17487 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
17488 NL80211_REGDOM_TYPE_COUNTRY) ||
17489 nla_put_string(msg, NL80211_ATTR_REG_ALPHA2,
17490 request->alpha2))
17491 goto nla_put_failure;
17492 }
17493
ad30ca2c
AN
17494 if (request->wiphy_idx != WIPHY_IDX_INVALID) {
17495 struct wiphy *wiphy = wiphy_idx_to_wiphy(request->wiphy_idx);
17496
17497 if (wiphy &&
17498 nla_put_u32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx))
17499 goto nla_put_failure;
1bdd716c
AN
17500
17501 if (wiphy &&
17502 wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
17503 nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
17504 goto nla_put_failure;
ad30ca2c 17505 }
73d54c9e 17506
b0d7aa59
JD
17507 return true;
17508
17509nla_put_failure:
17510 return false;
17511}
17512
17513/*
17514 * This can happen on global regulatory changes or device specific settings
17515 * based on custom regulatory domains.
17516 */
17517void nl80211_common_reg_change_event(enum nl80211_commands cmd_id,
17518 struct regulatory_request *request)
17519{
17520 struct sk_buff *msg;
17521 void *hdr;
17522
17523 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
17524 if (!msg)
17525 return;
17526
17527 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd_id);
24f6d765 17528 if (!hdr)
17529 goto nla_put_failure;
b0d7aa59 17530
24f6d765 17531 if (!nl80211_reg_change_event_fill(msg, request))
b0d7aa59
JD
17532 goto nla_put_failure;
17533
3b7b72ee 17534 genlmsg_end(msg, hdr);
73d54c9e 17535
bc43b28c 17536 rcu_read_lock();
68eb5503 17537 genlmsg_multicast_allns(&nl80211_fam, msg, 0,
2a94fe48 17538 NL80211_MCGRP_REGULATORY, GFP_ATOMIC);
bc43b28c 17539 rcu_read_unlock();
73d54c9e
LR
17540
17541 return;
17542
17543nla_put_failure:
73d54c9e
LR
17544 nlmsg_free(msg);
17545}
17546
6039f6d2
JM
17547static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
17548 struct net_device *netdev,
17549 const u8 *buf, size_t len,
b0b6aa2c 17550 enum nl80211_commands cmd, gfp_t gfp,
4d9ec73d 17551 int uapsd_queues, const u8 *req_ies,
3bb02143 17552 size_t req_ies_len, bool reconnect)
6039f6d2
JM
17553{
17554 struct sk_buff *msg;
17555 void *hdr;
17556
4d9ec73d 17557 msg = nlmsg_new(100 + len + req_ies_len, gfp);
6039f6d2
JM
17558 if (!msg)
17559 return;
17560
17561 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
17562 if (!hdr) {
17563 nlmsg_free(msg);
17564 return;
17565 }
17566
9360ffd1
DM
17567 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17568 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
4d9ec73d
JM
17569 nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
17570 (req_ies &&
17571 nla_put(msg, NL80211_ATTR_REQ_IE, req_ies_len, req_ies)))
9360ffd1 17572 goto nla_put_failure;
6039f6d2 17573
3bb02143
JB
17574 if (reconnect && nla_put_flag(msg, NL80211_ATTR_RECONNECT_REQUESTED))
17575 goto nla_put_failure;
17576
b0b6aa2c
EP
17577 if (uapsd_queues >= 0) {
17578 struct nlattr *nla_wmm =
ae0be8de 17579 nla_nest_start_noflag(msg, NL80211_ATTR_STA_WME);
b0b6aa2c
EP
17580 if (!nla_wmm)
17581 goto nla_put_failure;
17582
17583 if (nla_put_u8(msg, NL80211_STA_WME_UAPSD_QUEUES,
17584 uapsd_queues))
17585 goto nla_put_failure;
17586
17587 nla_nest_end(msg, nla_wmm);
17588 }
17589
3b7b72ee 17590 genlmsg_end(msg, hdr);
6039f6d2 17591
68eb5503 17592 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17593 NL80211_MCGRP_MLME, gfp);
6039f6d2
JM
17594 return;
17595
17596 nla_put_failure:
6039f6d2
JM
17597 nlmsg_free(msg);
17598}
17599
17600void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
e6d6e342
JB
17601 struct net_device *netdev, const u8 *buf,
17602 size_t len, gfp_t gfp)
6039f6d2
JM
17603{
17604 nl80211_send_mlme_event(rdev, netdev, buf, len,
3bb02143
JB
17605 NL80211_CMD_AUTHENTICATE, gfp, -1, NULL, 0,
17606 false);
6039f6d2
JM
17607}
17608
17609void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
cd47c0f5
JB
17610 struct net_device *netdev,
17611 struct cfg80211_rx_assoc_resp *data)
6039f6d2 17612{
cd47c0f5
JB
17613 nl80211_send_mlme_event(rdev, netdev, data->buf, data->len,
17614 NL80211_CMD_ASSOCIATE, GFP_KERNEL,
17615 data->uapsd_queues,
17616 data->req_ies, data->req_ies_len, false);
6039f6d2
JM
17617}
17618
53b46b84 17619void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
e6d6e342 17620 struct net_device *netdev, const u8 *buf,
3bb02143 17621 size_t len, bool reconnect, gfp_t gfp)
6039f6d2
JM
17622{
17623 nl80211_send_mlme_event(rdev, netdev, buf, len,
3bb02143
JB
17624 NL80211_CMD_DEAUTHENTICATE, gfp, -1, NULL, 0,
17625 reconnect);
6039f6d2
JM
17626}
17627
53b46b84
JM
17628void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
17629 struct net_device *netdev, const u8 *buf,
3bb02143 17630 size_t len, bool reconnect, gfp_t gfp)
6039f6d2
JM
17631{
17632 nl80211_send_mlme_event(rdev, netdev, buf, len,
3bb02143
JB
17633 NL80211_CMD_DISASSOCIATE, gfp, -1, NULL, 0,
17634 reconnect);
6039f6d2
JM
17635}
17636
6ff57cf8
JB
17637void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf,
17638 size_t len)
cf4e594e 17639{
947add36
JB
17640 struct wireless_dev *wdev = dev->ieee80211_ptr;
17641 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 17642 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
6ff57cf8
JB
17643 const struct ieee80211_mgmt *mgmt = (void *)buf;
17644 u32 cmd;
947add36 17645
6ff57cf8
JB
17646 if (WARN_ON(len < 2))
17647 return;
cf4e594e 17648
4d797fce 17649 if (ieee80211_is_deauth(mgmt->frame_control)) {
6ff57cf8 17650 cmd = NL80211_CMD_UNPROT_DEAUTHENTICATE;
4d797fce 17651 } else if (ieee80211_is_disassoc(mgmt->frame_control)) {
6ff57cf8 17652 cmd = NL80211_CMD_UNPROT_DISASSOCIATE;
4d797fce
JM
17653 } else if (ieee80211_is_beacon(mgmt->frame_control)) {
17654 if (wdev->unprot_beacon_reported &&
17655 elapsed_jiffies_msecs(wdev->unprot_beacon_reported) < 10000)
17656 return;
17657 cmd = NL80211_CMD_UNPROT_BEACON;
17658 wdev->unprot_beacon_reported = jiffies;
17659 } else {
17660 return;
17661 }
947add36 17662
6ff57cf8 17663 trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len);
4d9ec73d 17664 nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1,
3bb02143 17665 NULL, 0, false);
cf4e594e 17666}
6ff57cf8 17667EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt);
cf4e594e 17668
1b06bb40
LR
17669static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev,
17670 struct net_device *netdev, int cmd,
e6d6e342 17671 const u8 *addr, gfp_t gfp)
1965c853
JM
17672{
17673 struct sk_buff *msg;
17674 void *hdr;
17675
e6d6e342 17676 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
1965c853
JM
17677 if (!msg)
17678 return;
17679
17680 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
17681 if (!hdr) {
17682 nlmsg_free(msg);
17683 return;
17684 }
17685
9360ffd1
DM
17686 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17687 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
17688 nla_put_flag(msg, NL80211_ATTR_TIMED_OUT) ||
17689 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
17690 goto nla_put_failure;
1965c853 17691
3b7b72ee 17692 genlmsg_end(msg, hdr);
1965c853 17693
68eb5503 17694 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17695 NL80211_MCGRP_MLME, gfp);
1965c853
JM
17696 return;
17697
17698 nla_put_failure:
1965c853
JM
17699 nlmsg_free(msg);
17700}
17701
17702void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
e6d6e342
JB
17703 struct net_device *netdev, const u8 *addr,
17704 gfp_t gfp)
1965c853
JM
17705{
17706 nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_AUTHENTICATE,
e6d6e342 17707 addr, gfp);
1965c853
JM
17708}
17709
17710void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev,
e6d6e342
JB
17711 struct net_device *netdev, const u8 *addr,
17712 gfp_t gfp)
1965c853 17713{
e6d6e342
JB
17714 nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_ASSOCIATE,
17715 addr, gfp);
1965c853
JM
17716}
17717
b23aa676 17718void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
5349a0f7
VK
17719 struct net_device *netdev,
17720 struct cfg80211_connect_resp_params *cr,
3093ebbe 17721 gfp_t gfp)
b23aa676
SO
17722{
17723 struct sk_buff *msg;
17724 void *hdr;
efbabc11
VJ
17725 unsigned int link;
17726 size_t link_info_size = 0;
17727 const u8 *connected_addr = cr->valid_links ?
17728 cr->ap_mld_addr : cr->links[0].bssid;
17729
17730 if (cr->valid_links) {
17731 for_each_valid_link(cr, link) {
17732 /* Nested attribute header */
17733 link_info_size += NLA_HDRLEN;
17734 /* Link ID */
17735 link_info_size += nla_total_size(sizeof(u8));
17736 link_info_size += cr->links[link].addr ?
17737 nla_total_size(ETH_ALEN) : 0;
17738 link_info_size += (cr->links[link].bssid ||
17739 cr->links[link].bss) ?
17740 nla_total_size(ETH_ALEN) : 0;
17741 }
17742 }
b23aa676 17743
a3caf744 17744 msg = nlmsg_new(100 + cr->req_ie_len + cr->resp_ie_len +
76804d28 17745 cr->fils.kek_len + cr->fils.pmk_len +
efbabc11
VJ
17746 (cr->fils.pmkid ? WLAN_PMKID_LEN : 0) + link_info_size,
17747 gfp);
b23aa676
SO
17748 if (!msg)
17749 return;
17750
17751 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONNECT);
17752 if (!hdr) {
17753 nlmsg_free(msg);
17754 return;
17755 }
17756
9360ffd1
DM
17757 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17758 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
efbabc11
VJ
17759 (connected_addr &&
17760 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, connected_addr)) ||
bf1ecd21 17761 nla_put_u16(msg, NL80211_ATTR_STATUS_CODE,
5349a0f7
VK
17762 cr->status < 0 ? WLAN_STATUS_UNSPECIFIED_FAILURE :
17763 cr->status) ||
17764 (cr->status < 0 &&
3093ebbe 17765 (nla_put_flag(msg, NL80211_ATTR_TIMED_OUT) ||
5349a0f7
VK
17766 nla_put_u32(msg, NL80211_ATTR_TIMEOUT_REASON,
17767 cr->timeout_reason))) ||
17768 (cr->req_ie &&
17769 nla_put(msg, NL80211_ATTR_REQ_IE, cr->req_ie_len, cr->req_ie)) ||
17770 (cr->resp_ie &&
17771 nla_put(msg, NL80211_ATTR_RESP_IE, cr->resp_ie_len,
a3caf744 17772 cr->resp_ie)) ||
76804d28 17773 (cr->fils.update_erp_next_seq_num &&
a3caf744 17774 nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM,
76804d28 17775 cr->fils.erp_next_seq_num)) ||
a3caf744 17776 (cr->status == WLAN_STATUS_SUCCESS &&
76804d28
AVS
17777 ((cr->fils.kek &&
17778 nla_put(msg, NL80211_ATTR_FILS_KEK, cr->fils.kek_len,
17779 cr->fils.kek)) ||
17780 (cr->fils.pmk &&
17781 nla_put(msg, NL80211_ATTR_PMK, cr->fils.pmk_len, cr->fils.pmk)) ||
17782 (cr->fils.pmkid &&
17783 nla_put(msg, NL80211_ATTR_PMKID, WLAN_PMKID_LEN, cr->fils.pmkid)))))
9360ffd1 17784 goto nla_put_failure;
b23aa676 17785
efbabc11
VJ
17786 if (cr->valid_links) {
17787 int i = 1;
17788 struct nlattr *nested;
17789
17790 nested = nla_nest_start(msg, NL80211_ATTR_MLO_LINKS);
17791 if (!nested)
17792 goto nla_put_failure;
17793
17794 for_each_valid_link(cr, link) {
17795 struct nlattr *nested_mlo_links;
17796 const u8 *bssid = cr->links[link].bss ?
17797 cr->links[link].bss->bssid :
17798 cr->links[link].bssid;
17799
17800 nested_mlo_links = nla_nest_start(msg, i);
17801 if (!nested_mlo_links)
17802 goto nla_put_failure;
17803
17804 if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link) ||
17805 (bssid &&
17806 nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, bssid)) ||
17807 (cr->links[link].addr &&
17808 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
17809 cr->links[link].addr)))
17810 goto nla_put_failure;
17811
17812 nla_nest_end(msg, nested_mlo_links);
17813 i++;
17814 }
17815 nla_nest_end(msg, nested);
17816 }
17817
3b7b72ee 17818 genlmsg_end(msg, hdr);
b23aa676 17819
68eb5503 17820 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17821 NL80211_MCGRP_MLME, gfp);
b23aa676
SO
17822 return;
17823
17824 nla_put_failure:
b23aa676 17825 nlmsg_free(msg);
b23aa676
SO
17826}
17827
17828void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
29ce6ecb
AS
17829 struct net_device *netdev,
17830 struct cfg80211_roam_info *info, gfp_t gfp)
b23aa676
SO
17831{
17832 struct sk_buff *msg;
17833 void *hdr;
efbabc11
VJ
17834 size_t link_info_size = 0;
17835 unsigned int link;
17836 const u8 *connected_addr = info->ap_mld_addr ?
17837 info->ap_mld_addr :
17838 (info->links[0].bss ?
17839 info->links[0].bss->bssid :
17840 info->links[0].bssid);
17841
17842 if (info->valid_links) {
17843 for_each_valid_link(info, link) {
17844 /* Nested attribute header */
17845 link_info_size += NLA_HDRLEN;
17846 /* Link ID */
17847 link_info_size += nla_total_size(sizeof(u8));
17848 link_info_size += info->links[link].addr ?
17849 nla_total_size(ETH_ALEN) : 0;
17850 link_info_size += (info->links[link].bssid ||
17851 info->links[link].bss) ?
17852 nla_total_size(ETH_ALEN) : 0;
17853 }
17854 }
b23aa676 17855
e841b7b1
AVS
17856 msg = nlmsg_new(100 + info->req_ie_len + info->resp_ie_len +
17857 info->fils.kek_len + info->fils.pmk_len +
efbabc11
VJ
17858 (info->fils.pmkid ? WLAN_PMKID_LEN : 0) +
17859 link_info_size, gfp);
b23aa676
SO
17860 if (!msg)
17861 return;
17862
17863 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ROAM);
17864 if (!hdr) {
17865 nlmsg_free(msg);
17866 return;
17867 }
17868
9360ffd1
DM
17869 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17870 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
efbabc11 17871 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, connected_addr) ||
29ce6ecb
AS
17872 (info->req_ie &&
17873 nla_put(msg, NL80211_ATTR_REQ_IE, info->req_ie_len,
17874 info->req_ie)) ||
17875 (info->resp_ie &&
17876 nla_put(msg, NL80211_ATTR_RESP_IE, info->resp_ie_len,
e841b7b1
AVS
17877 info->resp_ie)) ||
17878 (info->fils.update_erp_next_seq_num &&
17879 nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM,
17880 info->fils.erp_next_seq_num)) ||
17881 (info->fils.kek &&
17882 nla_put(msg, NL80211_ATTR_FILS_KEK, info->fils.kek_len,
17883 info->fils.kek)) ||
17884 (info->fils.pmk &&
17885 nla_put(msg, NL80211_ATTR_PMK, info->fils.pmk_len, info->fils.pmk)) ||
17886 (info->fils.pmkid &&
17887 nla_put(msg, NL80211_ATTR_PMKID, WLAN_PMKID_LEN, info->fils.pmkid)))
9360ffd1 17888 goto nla_put_failure;
b23aa676 17889
efbabc11
VJ
17890 if (info->valid_links) {
17891 int i = 1;
17892 struct nlattr *nested;
17893
17894 nested = nla_nest_start(msg, NL80211_ATTR_MLO_LINKS);
17895 if (!nested)
17896 goto nla_put_failure;
17897
17898 for_each_valid_link(info, link) {
17899 struct nlattr *nested_mlo_links;
17900 const u8 *bssid = info->links[link].bss ?
17901 info->links[link].bss->bssid :
17902 info->links[link].bssid;
17903
17904 nested_mlo_links = nla_nest_start(msg, i);
17905 if (!nested_mlo_links)
17906 goto nla_put_failure;
17907
17908 if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link) ||
17909 (bssid &&
17910 nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, bssid)) ||
17911 (info->links[link].addr &&
17912 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
17913 info->links[link].addr)))
17914 goto nla_put_failure;
17915
17916 nla_nest_end(msg, nested_mlo_links);
17917 i++;
17918 }
17919 nla_nest_end(msg, nested);
17920 }
17921
3b7b72ee 17922 genlmsg_end(msg, hdr);
b23aa676 17923
68eb5503 17924 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17925 NL80211_MCGRP_MLME, gfp);
b23aa676
SO
17926 return;
17927
503c1fb9 17928 nla_put_failure:
503c1fb9
AS
17929 nlmsg_free(msg);
17930}
17931
17932void nl80211_send_port_authorized(struct cfg80211_registered_device *rdev,
17933 struct net_device *netdev, const u8 *bssid)
17934{
17935 struct sk_buff *msg;
17936 void *hdr;
17937
17938 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
17939 if (!msg)
17940 return;
17941
17942 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PORT_AUTHORIZED);
17943 if (!hdr) {
17944 nlmsg_free(msg);
17945 return;
17946 }
17947
f4d75993
CHH
17948 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17949 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
17950 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
503c1fb9
AS
17951 goto nla_put_failure;
17952
17953 genlmsg_end(msg, hdr);
17954
17955 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
17956 NL80211_MCGRP_MLME, GFP_KERNEL);
17957 return;
17958
b23aa676 17959 nla_put_failure:
b23aa676 17960 nlmsg_free(msg);
b23aa676
SO
17961}
17962
17963void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
17964 struct net_device *netdev, u16 reason,
667503dd 17965 const u8 *ie, size_t ie_len, bool from_ap)
b23aa676
SO
17966{
17967 struct sk_buff *msg;
17968 void *hdr;
17969
4ef8c1c9 17970 msg = nlmsg_new(100 + ie_len, GFP_KERNEL);
b23aa676
SO
17971 if (!msg)
17972 return;
17973
17974 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DISCONNECT);
17975 if (!hdr) {
17976 nlmsg_free(msg);
17977 return;
17978 }
17979
9360ffd1
DM
17980 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17981 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
86b6c465 17982 (reason &&
9360ffd1
DM
17983 nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason)) ||
17984 (from_ap &&
17985 nla_put_flag(msg, NL80211_ATTR_DISCONNECTED_BY_AP)) ||
17986 (ie && nla_put(msg, NL80211_ATTR_IE, ie_len, ie)))
17987 goto nla_put_failure;
b23aa676 17988
3b7b72ee 17989 genlmsg_end(msg, hdr);
b23aa676 17990
68eb5503 17991 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17992 NL80211_MCGRP_MLME, GFP_KERNEL);
b23aa676
SO
17993 return;
17994
17995 nla_put_failure:
b23aa676 17996 nlmsg_free(msg);
b23aa676
SO
17997}
17998
04a773ad
JB
17999void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
18000 struct net_device *netdev, const u8 *bssid,
18001 gfp_t gfp)
18002{
18003 struct sk_buff *msg;
18004 void *hdr;
18005
fd2120ca 18006 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
04a773ad
JB
18007 if (!msg)
18008 return;
18009
18010 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_JOIN_IBSS);
18011 if (!hdr) {
18012 nlmsg_free(msg);
18013 return;
18014 }
18015
9360ffd1
DM
18016 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18017 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
18018 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
18019 goto nla_put_failure;
04a773ad 18020
3b7b72ee 18021 genlmsg_end(msg, hdr);
04a773ad 18022
68eb5503 18023 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18024 NL80211_MCGRP_MLME, gfp);
04a773ad
JB
18025 return;
18026
18027 nla_put_failure:
04a773ad
JB
18028 nlmsg_free(msg);
18029}
18030
947add36 18031void cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr,
ecbc12ad
BC
18032 const u8 *ie, u8 ie_len,
18033 int sig_dbm, gfp_t gfp)
c93b5e71 18034{
947add36 18035 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 18036 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
c93b5e71
JC
18037 struct sk_buff *msg;
18038 void *hdr;
18039
947add36
JB
18040 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT))
18041 return;
18042
18043 trace_cfg80211_notify_new_peer_candidate(dev, addr);
18044
4ef8c1c9 18045 msg = nlmsg_new(100 + ie_len, gfp);
c93b5e71
JC
18046 if (!msg)
18047 return;
18048
18049 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NEW_PEER_CANDIDATE);
18050 if (!hdr) {
18051 nlmsg_free(msg);
18052 return;
18053 }
18054
9360ffd1 18055 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
947add36
JB
18056 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
18057 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
9360ffd1 18058 (ie_len && ie &&
ecbc12ad
BC
18059 nla_put(msg, NL80211_ATTR_IE, ie_len, ie)) ||
18060 (sig_dbm &&
18061 nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)))
9360ffd1 18062 goto nla_put_failure;
c93b5e71 18063
3b7b72ee 18064 genlmsg_end(msg, hdr);
c93b5e71 18065
68eb5503 18066 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18067 NL80211_MCGRP_MLME, gfp);
c93b5e71
JC
18068 return;
18069
18070 nla_put_failure:
c93b5e71
JC
18071 nlmsg_free(msg);
18072}
947add36 18073EXPORT_SYMBOL(cfg80211_notify_new_peer_candidate);
c93b5e71 18074
a3b8b056
JM
18075void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
18076 struct net_device *netdev, const u8 *addr,
18077 enum nl80211_key_type key_type, int key_id,
e6d6e342 18078 const u8 *tsc, gfp_t gfp)
a3b8b056
JM
18079{
18080 struct sk_buff *msg;
18081 void *hdr;
18082
e6d6e342 18083 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
a3b8b056
JM
18084 if (!msg)
18085 return;
18086
18087 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_MICHAEL_MIC_FAILURE);
18088 if (!hdr) {
18089 nlmsg_free(msg);
18090 return;
18091 }
18092
9360ffd1
DM
18093 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18094 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
18095 (addr && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) ||
18096 nla_put_u32(msg, NL80211_ATTR_KEY_TYPE, key_type) ||
18097 (key_id != -1 &&
18098 nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_id)) ||
18099 (tsc && nla_put(msg, NL80211_ATTR_KEY_SEQ, 6, tsc)))
18100 goto nla_put_failure;
a3b8b056 18101
3b7b72ee 18102 genlmsg_end(msg, hdr);
a3b8b056 18103
68eb5503 18104 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18105 NL80211_MCGRP_MLME, gfp);
a3b8b056
JM
18106 return;
18107
18108 nla_put_failure:
a3b8b056
JM
18109 nlmsg_free(msg);
18110}
18111
6bad8766
LR
18112void nl80211_send_beacon_hint_event(struct wiphy *wiphy,
18113 struct ieee80211_channel *channel_before,
18114 struct ieee80211_channel *channel_after)
18115{
18116 struct sk_buff *msg;
18117 void *hdr;
18118 struct nlattr *nl_freq;
18119
fd2120ca 18120 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
6bad8766
LR
18121 if (!msg)
18122 return;
18123
18124 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_BEACON_HINT);
18125 if (!hdr) {
18126 nlmsg_free(msg);
18127 return;
18128 }
18129
18130 /*
18131 * Since we are applying the beacon hint to a wiphy we know its
18132 * wiphy_idx is valid
18133 */
9360ffd1
DM
18134 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
18135 goto nla_put_failure;
6bad8766
LR
18136
18137 /* Before */
ae0be8de 18138 nl_freq = nla_nest_start_noflag(msg, NL80211_ATTR_FREQ_BEFORE);
6bad8766
LR
18139 if (!nl_freq)
18140 goto nla_put_failure;
50f32718
HD
18141
18142 if (nl80211_msg_put_channel(msg, wiphy, channel_before, false))
6bad8766
LR
18143 goto nla_put_failure;
18144 nla_nest_end(msg, nl_freq);
18145
18146 /* After */
ae0be8de 18147 nl_freq = nla_nest_start_noflag(msg, NL80211_ATTR_FREQ_AFTER);
6bad8766
LR
18148 if (!nl_freq)
18149 goto nla_put_failure;
50f32718
HD
18150
18151 if (nl80211_msg_put_channel(msg, wiphy, channel_after, false))
6bad8766
LR
18152 goto nla_put_failure;
18153 nla_nest_end(msg, nl_freq);
18154
3b7b72ee 18155 genlmsg_end(msg, hdr);
6bad8766 18156
463d0183 18157 rcu_read_lock();
68eb5503 18158 genlmsg_multicast_allns(&nl80211_fam, msg, 0,
2a94fe48 18159 NL80211_MCGRP_REGULATORY, GFP_ATOMIC);
463d0183 18160 rcu_read_unlock();
6bad8766
LR
18161
18162 return;
18163
18164nla_put_failure:
6bad8766
LR
18165 nlmsg_free(msg);
18166}
18167
9588bbd5
JM
18168static void nl80211_send_remain_on_chan_event(
18169 int cmd, struct cfg80211_registered_device *rdev,
71bbc994 18170 struct wireless_dev *wdev, u64 cookie,
9588bbd5 18171 struct ieee80211_channel *chan,
9588bbd5
JM
18172 unsigned int duration, gfp_t gfp)
18173{
18174 struct sk_buff *msg;
18175 void *hdr;
18176
18177 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
18178 if (!msg)
18179 return;
18180
18181 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
18182 if (!hdr) {
18183 nlmsg_free(msg);
18184 return;
18185 }
18186
9360ffd1 18187 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
71bbc994
JB
18188 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
18189 wdev->netdev->ifindex)) ||
2dad624e
ND
18190 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
18191 NL80211_ATTR_PAD) ||
9360ffd1 18192 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq) ||
42d97a59
JB
18193 nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
18194 NL80211_CHAN_NO_HT) ||
2dad624e
ND
18195 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
18196 NL80211_ATTR_PAD))
9360ffd1 18197 goto nla_put_failure;
9588bbd5 18198
9360ffd1
DM
18199 if (cmd == NL80211_CMD_REMAIN_ON_CHANNEL &&
18200 nla_put_u32(msg, NL80211_ATTR_DURATION, duration))
18201 goto nla_put_failure;
9588bbd5 18202
3b7b72ee 18203 genlmsg_end(msg, hdr);
9588bbd5 18204
68eb5503 18205 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18206 NL80211_MCGRP_MLME, gfp);
9588bbd5
JM
18207 return;
18208
18209 nla_put_failure:
9588bbd5
JM
18210 nlmsg_free(msg);
18211}
18212
a083ee8a 18213void cfg80211_assoc_comeback(struct net_device *netdev,
e69dac88 18214 const u8 *ap_addr, u32 timeout)
a083ee8a
IP
18215{
18216 struct wireless_dev *wdev = netdev->ieee80211_ptr;
18217 struct wiphy *wiphy = wdev->wiphy;
18218 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
18219 struct sk_buff *msg;
18220 void *hdr;
18221
e69dac88 18222 trace_cfg80211_assoc_comeback(wdev, ap_addr, timeout);
a083ee8a
IP
18223
18224 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
18225 if (!msg)
18226 return;
18227
18228 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ASSOC_COMEBACK);
18229 if (!hdr) {
18230 nlmsg_free(msg);
18231 return;
18232 }
18233
18234 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18235 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
e69dac88 18236 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ap_addr) ||
a083ee8a
IP
18237 nla_put_u32(msg, NL80211_ATTR_TIMEOUT, timeout))
18238 goto nla_put_failure;
18239
18240 genlmsg_end(msg, hdr);
18241
18242 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
18243 NL80211_MCGRP_MLME, GFP_KERNEL);
18244 return;
18245
18246 nla_put_failure:
18247 nlmsg_free(msg);
18248}
18249EXPORT_SYMBOL(cfg80211_assoc_comeback);
18250
947add36
JB
18251void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
18252 struct ieee80211_channel *chan,
18253 unsigned int duration, gfp_t gfp)
9588bbd5 18254{
947add36 18255 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 18256 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
18257
18258 trace_cfg80211_ready_on_channel(wdev, cookie, chan, duration);
9588bbd5 18259 nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL,
71bbc994 18260 rdev, wdev, cookie, chan,
42d97a59 18261 duration, gfp);
9588bbd5 18262}
947add36 18263EXPORT_SYMBOL(cfg80211_ready_on_channel);
9588bbd5 18264
947add36
JB
18265void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
18266 struct ieee80211_channel *chan,
18267 gfp_t gfp)
9588bbd5 18268{
947add36 18269 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 18270 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
18271
18272 trace_cfg80211_ready_on_channel_expired(wdev, cookie, chan);
9588bbd5 18273 nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
42d97a59 18274 rdev, wdev, cookie, chan, 0, gfp);
9588bbd5 18275}
947add36 18276EXPORT_SYMBOL(cfg80211_remain_on_channel_expired);
9588bbd5 18277
1c38c7f2
JP
18278void cfg80211_tx_mgmt_expired(struct wireless_dev *wdev, u64 cookie,
18279 struct ieee80211_channel *chan,
18280 gfp_t gfp)
18281{
18282 struct wiphy *wiphy = wdev->wiphy;
18283 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
18284
18285 trace_cfg80211_tx_mgmt_expired(wdev, cookie, chan);
18286 nl80211_send_remain_on_chan_event(NL80211_CMD_FRAME_WAIT_CANCEL,
18287 rdev, wdev, cookie, chan, 0, gfp);
18288}
18289EXPORT_SYMBOL(cfg80211_tx_mgmt_expired);
18290
947add36
JB
18291void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
18292 struct station_info *sinfo, gfp_t gfp)
98b62183 18293{
947add36 18294 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
f26cbf40 18295 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
98b62183
JB
18296 struct sk_buff *msg;
18297
947add36
JB
18298 trace_cfg80211_new_sta(dev, mac_addr, sinfo);
18299
58050fce 18300 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
98b62183
JB
18301 if (!msg)
18302 return;
18303
cf5ead82 18304 if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION, 0, 0, 0,
66266b3a 18305 rdev, dev, mac_addr, sinfo) < 0) {
98b62183
JB
18306 nlmsg_free(msg);
18307 return;
18308 }
18309
68eb5503 18310 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18311 NL80211_MCGRP_MLME, gfp);
98b62183 18312}
947add36 18313EXPORT_SYMBOL(cfg80211_new_sta);
98b62183 18314
cf5ead82
JB
18315void cfg80211_del_sta_sinfo(struct net_device *dev, const u8 *mac_addr,
18316 struct station_info *sinfo, gfp_t gfp)
ec15e68b 18317{
947add36 18318 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
f26cbf40 18319 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
ec15e68b 18320 struct sk_buff *msg;
73887fd9 18321 struct station_info empty_sinfo = {};
cf5ead82 18322
73887fd9
JB
18323 if (!sinfo)
18324 sinfo = &empty_sinfo;
ec15e68b 18325
947add36
JB
18326 trace_cfg80211_del_sta(dev, mac_addr);
18327
58050fce 18328 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
7ea3e110
JB
18329 if (!msg) {
18330 cfg80211_sinfo_release_content(sinfo);
73887fd9 18331 return;
7ea3e110 18332 }
ec15e68b 18333
cf5ead82 18334 if (nl80211_send_station(msg, NL80211_CMD_DEL_STATION, 0, 0, 0,
57007121 18335 rdev, dev, mac_addr, sinfo) < 0) {
ec15e68b 18336 nlmsg_free(msg);
73887fd9 18337 return;
ec15e68b
JM
18338 }
18339
68eb5503 18340 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18341 NL80211_MCGRP_MLME, gfp);
ec15e68b 18342}
cf5ead82 18343EXPORT_SYMBOL(cfg80211_del_sta_sinfo);
ec15e68b 18344
947add36
JB
18345void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr,
18346 enum nl80211_connect_failed_reason reason,
18347 gfp_t gfp)
ed44a951 18348{
947add36 18349 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
f26cbf40 18350 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
ed44a951
PP
18351 struct sk_buff *msg;
18352 void *hdr;
18353
18354 msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
18355 if (!msg)
18356 return;
18357
18358 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONN_FAILED);
18359 if (!hdr) {
18360 nlmsg_free(msg);
18361 return;
18362 }
18363
18364 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
18365 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) ||
18366 nla_put_u32(msg, NL80211_ATTR_CONN_FAILED_REASON, reason))
18367 goto nla_put_failure;
18368
18369 genlmsg_end(msg, hdr);
18370
68eb5503 18371 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18372 NL80211_MCGRP_MLME, gfp);
ed44a951
PP
18373 return;
18374
18375 nla_put_failure:
ed44a951
PP
18376 nlmsg_free(msg);
18377}
947add36 18378EXPORT_SYMBOL(cfg80211_conn_failed);
ed44a951 18379
b92ab5d8
JB
18380static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd,
18381 const u8 *addr, gfp_t gfp)
28946da7
JB
18382{
18383 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 18384 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
28946da7
JB
18385 struct sk_buff *msg;
18386 void *hdr;
6aa7de05 18387 u32 nlportid = READ_ONCE(wdev->ap_unexpected_nlportid);
28946da7 18388
15e47304 18389 if (!nlportid)
28946da7
JB
18390 return false;
18391
18392 msg = nlmsg_new(100, gfp);
18393 if (!msg)
18394 return true;
18395
b92ab5d8 18396 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
28946da7
JB
18397 if (!hdr) {
18398 nlmsg_free(msg);
18399 return true;
18400 }
18401
9360ffd1
DM
18402 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18403 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
18404 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
18405 goto nla_put_failure;
28946da7 18406
9c90a9f6 18407 genlmsg_end(msg, hdr);
15e47304 18408 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
28946da7
JB
18409 return true;
18410
18411 nla_put_failure:
28946da7
JB
18412 nlmsg_free(msg);
18413 return true;
18414}
18415
947add36
JB
18416bool cfg80211_rx_spurious_frame(struct net_device *dev,
18417 const u8 *addr, gfp_t gfp)
b92ab5d8 18418{
947add36
JB
18419 struct wireless_dev *wdev = dev->ieee80211_ptr;
18420 bool ret;
18421
18422 trace_cfg80211_rx_spurious_frame(dev, addr);
18423
18424 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
18425 wdev->iftype != NL80211_IFTYPE_P2P_GO)) {
18426 trace_cfg80211_return_bool(false);
18427 return false;
18428 }
18429 ret = __nl80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME,
18430 addr, gfp);
18431 trace_cfg80211_return_bool(ret);
18432 return ret;
b92ab5d8 18433}
947add36 18434EXPORT_SYMBOL(cfg80211_rx_spurious_frame);
b92ab5d8 18435
947add36
JB
18436bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
18437 const u8 *addr, gfp_t gfp)
b92ab5d8 18438{
947add36
JB
18439 struct wireless_dev *wdev = dev->ieee80211_ptr;
18440 bool ret;
18441
18442 trace_cfg80211_rx_unexpected_4addr_frame(dev, addr);
18443
18444 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
18445 wdev->iftype != NL80211_IFTYPE_P2P_GO &&
18446 wdev->iftype != NL80211_IFTYPE_AP_VLAN)) {
18447 trace_cfg80211_return_bool(false);
18448 return false;
18449 }
18450 ret = __nl80211_unexpected_frame(dev,
18451 NL80211_CMD_UNEXPECTED_4ADDR_FRAME,
18452 addr, gfp);
18453 trace_cfg80211_return_bool(ret);
18454 return ret;
b92ab5d8 18455}
947add36 18456EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame);
b92ab5d8 18457
2e161f78 18458int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
15e47304 18459 struct wireless_dev *wdev, u32 nlportid,
00b3d840 18460 struct cfg80211_rx_info *info, gfp_t gfp)
026331c4 18461{
71bbc994 18462 struct net_device *netdev = wdev->netdev;
026331c4
JM
18463 struct sk_buff *msg;
18464 void *hdr;
026331c4 18465
00b3d840 18466 msg = nlmsg_new(100 + info->len, gfp);
026331c4
JM
18467 if (!msg)
18468 return -ENOMEM;
18469
2e161f78 18470 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME);
026331c4
JM
18471 if (!hdr) {
18472 nlmsg_free(msg);
18473 return -ENOMEM;
18474 }
18475
9360ffd1 18476 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
71bbc994
JB
18477 (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
18478 netdev->ifindex)) ||
2dad624e
ND
18479 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
18480 NL80211_ATTR_PAD) ||
6074c9e5
JB
18481 (info->have_link_id &&
18482 nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, info->link_id)) ||
00b3d840
AS
18483 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, KHZ_TO_MHZ(info->freq)) ||
18484 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET, info->freq % 1000) ||
18485 (info->sig_dbm &&
18486 nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, info->sig_dbm)) ||
18487 nla_put(msg, NL80211_ATTR_FRAME, info->len, info->buf) ||
18488 (info->flags &&
1ff715ff
AS
18489 nla_put_u32(msg, NL80211_ATTR_RXMGMT_FLAGS, info->flags)) ||
18490 (info->rx_tstamp && nla_put_u64_64bit(msg,
18491 NL80211_ATTR_RX_HW_TIMESTAMP,
18492 info->rx_tstamp,
18493 NL80211_ATTR_PAD)) ||
18494 (info->ack_tstamp && nla_put_u64_64bit(msg,
18495 NL80211_ATTR_TX_HW_TIMESTAMP,
18496 info->ack_tstamp,
18497 NL80211_ATTR_PAD)))
9360ffd1 18498 goto nla_put_failure;
026331c4 18499
3b7b72ee 18500 genlmsg_end(msg, hdr);
026331c4 18501
15e47304 18502 return genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
026331c4
JM
18503
18504 nla_put_failure:
026331c4
JM
18505 nlmsg_free(msg);
18506 return -ENOBUFS;
18507}
18508
ea7d50c9
AS
18509static void nl80211_frame_tx_status(struct wireless_dev *wdev,
18510 struct cfg80211_tx_status *status,
dca9ca2d 18511 gfp_t gfp, enum nl80211_commands command)
026331c4 18512{
947add36 18513 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 18514 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
71bbc994 18515 struct net_device *netdev = wdev->netdev;
026331c4
JM
18516 struct sk_buff *msg;
18517 void *hdr;
18518
dca9ca2d 18519 if (command == NL80211_CMD_FRAME_TX_STATUS)
ea7d50c9
AS
18520 trace_cfg80211_mgmt_tx_status(wdev, status->cookie,
18521 status->ack);
dca9ca2d 18522 else
ea7d50c9
AS
18523 trace_cfg80211_control_port_tx_status(wdev, status->cookie,
18524 status->ack);
947add36 18525
ea7d50c9 18526 msg = nlmsg_new(100 + status->len, gfp);
026331c4
JM
18527 if (!msg)
18528 return;
18529
dca9ca2d 18530 hdr = nl80211hdr_put(msg, 0, 0, 0, command);
026331c4
JM
18531 if (!hdr) {
18532 nlmsg_free(msg);
18533 return;
18534 }
18535
9360ffd1 18536 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
71bbc994
JB
18537 (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
18538 netdev->ifindex)) ||
2dad624e
ND
18539 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
18540 NL80211_ATTR_PAD) ||
ea7d50c9
AS
18541 nla_put(msg, NL80211_ATTR_FRAME, status->len, status->buf) ||
18542 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, status->cookie,
2dad624e 18543 NL80211_ATTR_PAD) ||
ea7d50c9
AS
18544 (status->ack && nla_put_flag(msg, NL80211_ATTR_ACK)) ||
18545 (status->tx_tstamp &&
18546 nla_put_u64_64bit(msg, NL80211_ATTR_TX_HW_TIMESTAMP,
18547 status->tx_tstamp, NL80211_ATTR_PAD)) ||
18548 (status->ack_tstamp &&
18549 nla_put_u64_64bit(msg, NL80211_ATTR_RX_HW_TIMESTAMP,
18550 status->ack_tstamp, NL80211_ATTR_PAD)))
9360ffd1 18551 goto nla_put_failure;
026331c4 18552
3b7b72ee 18553 genlmsg_end(msg, hdr);
026331c4 18554
68eb5503 18555 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18556 NL80211_MCGRP_MLME, gfp);
026331c4
JM
18557 return;
18558
dca9ca2d 18559nla_put_failure:
026331c4
JM
18560 nlmsg_free(msg);
18561}
dca9ca2d
MT
18562
18563void cfg80211_control_port_tx_status(struct wireless_dev *wdev, u64 cookie,
18564 const u8 *buf, size_t len, bool ack,
18565 gfp_t gfp)
18566{
ea7d50c9
AS
18567 struct cfg80211_tx_status status = {
18568 .cookie = cookie,
18569 .buf = buf,
18570 .len = len,
18571 .ack = ack
18572 };
18573
18574 nl80211_frame_tx_status(wdev, &status, gfp,
dca9ca2d
MT
18575 NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS);
18576}
18577EXPORT_SYMBOL(cfg80211_control_port_tx_status);
18578
ea7d50c9
AS
18579void cfg80211_mgmt_tx_status_ext(struct wireless_dev *wdev,
18580 struct cfg80211_tx_status *status, gfp_t gfp)
dca9ca2d 18581{
ea7d50c9 18582 nl80211_frame_tx_status(wdev, status, gfp, NL80211_CMD_FRAME_TX_STATUS);
dca9ca2d 18583}
ea7d50c9 18584EXPORT_SYMBOL(cfg80211_mgmt_tx_status_ext);
026331c4 18585
6a671a50 18586static int __nl80211_rx_control_port(struct net_device *dev,
a948f713 18587 struct sk_buff *skb,
6a671a50
DK
18588 bool unencrypted, gfp_t gfp)
18589{
18590 struct wireless_dev *wdev = dev->ieee80211_ptr;
18591 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
a948f713 18592 struct ethhdr *ehdr = eth_hdr(skb);
8d74a623 18593 const u8 *addr = ehdr->h_source;
a948f713 18594 u16 proto = be16_to_cpu(skb->protocol);
6a671a50
DK
18595 struct sk_buff *msg;
18596 void *hdr;
a948f713
DK
18597 struct nlattr *frame;
18598
6a671a50
DK
18599 u32 nlportid = READ_ONCE(wdev->conn_owner_nlportid);
18600
18601 if (!nlportid)
18602 return -ENOENT;
18603
a948f713 18604 msg = nlmsg_new(100 + skb->len, gfp);
6a671a50
DK
18605 if (!msg)
18606 return -ENOMEM;
18607
18608 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONTROL_PORT_FRAME);
18609 if (!hdr) {
18610 nlmsg_free(msg);
18611 return -ENOBUFS;
18612 }
18613
18614 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18615 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
18616 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
18617 NL80211_ATTR_PAD) ||
8d74a623 18618 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
6a671a50
DK
18619 nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, proto) ||
18620 (unencrypted && nla_put_flag(msg,
18621 NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)))
18622 goto nla_put_failure;
18623
a948f713
DK
18624 frame = nla_reserve(msg, NL80211_ATTR_FRAME, skb->len);
18625 if (!frame)
18626 goto nla_put_failure;
18627
18628 skb_copy_bits(skb, 0, nla_data(frame), skb->len);
6a671a50
DK
18629 genlmsg_end(msg, hdr);
18630
18631 return genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
18632
18633 nla_put_failure:
18634 nlmsg_free(msg);
18635 return -ENOBUFS;
18636}
18637
18638bool cfg80211_rx_control_port(struct net_device *dev,
a948f713 18639 struct sk_buff *skb, bool unencrypted)
6a671a50
DK
18640{
18641 int ret;
18642
a948f713
DK
18643 trace_cfg80211_rx_control_port(dev, skb, unencrypted);
18644 ret = __nl80211_rx_control_port(dev, skb, unencrypted, GFP_ATOMIC);
6a671a50
DK
18645 trace_cfg80211_return_bool(ret == 0);
18646 return ret == 0;
18647}
18648EXPORT_SYMBOL(cfg80211_rx_control_port);
18649
5b97f49d
JB
18650static struct sk_buff *cfg80211_prepare_cqm(struct net_device *dev,
18651 const char *mac, gfp_t gfp)
d6dc1a38 18652{
947add36 18653 struct wireless_dev *wdev = dev->ieee80211_ptr;
5b97f49d
JB
18654 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
18655 struct sk_buff *msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
18656 void **cb;
947add36 18657
d6dc1a38 18658 if (!msg)
5b97f49d 18659 return NULL;
d6dc1a38 18660
5b97f49d
JB
18661 cb = (void **)msg->cb;
18662
18663 cb[0] = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_CQM);
18664 if (!cb[0]) {
d6dc1a38 18665 nlmsg_free(msg);
5b97f49d 18666 return NULL;
d6dc1a38
JO
18667 }
18668
9360ffd1 18669 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
947add36 18670 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
9360ffd1 18671 goto nla_put_failure;
d6dc1a38 18672
5b97f49d 18673 if (mac && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac))
d6dc1a38
JO
18674 goto nla_put_failure;
18675
ae0be8de 18676 cb[1] = nla_nest_start_noflag(msg, NL80211_ATTR_CQM);
5b97f49d 18677 if (!cb[1])
9360ffd1 18678 goto nla_put_failure;
d6dc1a38 18679
5b97f49d 18680 cb[2] = rdev;
d6dc1a38 18681
5b97f49d
JB
18682 return msg;
18683 nla_put_failure:
18684 nlmsg_free(msg);
18685 return NULL;
18686}
18687
18688static void cfg80211_send_cqm(struct sk_buff *msg, gfp_t gfp)
18689{
18690 void **cb = (void **)msg->cb;
18691 struct cfg80211_registered_device *rdev = cb[2];
18692
18693 nla_nest_end(msg, cb[1]);
18694 genlmsg_end(msg, cb[0]);
18695
18696 memset(msg->cb, 0, sizeof(msg->cb));
d6dc1a38 18697
68eb5503 18698 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18699 NL80211_MCGRP_MLME, gfp);
5b97f49d
JB
18700}
18701
18702void cfg80211_cqm_rssi_notify(struct net_device *dev,
18703 enum nl80211_cqm_rssi_threshold_event rssi_event,
bee427b8 18704 s32 rssi_level, gfp_t gfp)
5b97f49d
JB
18705{
18706 struct sk_buff *msg;
4a4b8169
AZ
18707 struct wireless_dev *wdev = dev->ieee80211_ptr;
18708 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
5b97f49d 18709
bee427b8 18710 trace_cfg80211_cqm_rssi_notify(dev, rssi_event, rssi_level);
5b97f49d 18711
98f03342
JB
18712 if (WARN_ON(rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW &&
18713 rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH))
18714 return;
18715
4a4b8169
AZ
18716 if (wdev->cqm_config) {
18717 wdev->cqm_config->last_rssi_event_value = rssi_level;
18718
18719 cfg80211_cqm_rssi_update(rdev, dev);
18720
18721 if (rssi_level == 0)
18722 rssi_level = wdev->cqm_config->last_rssi_event_value;
18723 }
18724
5b97f49d
JB
18725 msg = cfg80211_prepare_cqm(dev, NULL, gfp);
18726 if (!msg)
18727 return;
18728
18729 if (nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT,
18730 rssi_event))
18731 goto nla_put_failure;
18732
bee427b8
AZ
18733 if (rssi_level && nla_put_s32(msg, NL80211_ATTR_CQM_RSSI_LEVEL,
18734 rssi_level))
18735 goto nla_put_failure;
18736
5b97f49d
JB
18737 cfg80211_send_cqm(msg, gfp);
18738
d6dc1a38
JO
18739 return;
18740
18741 nla_put_failure:
d6dc1a38
JO
18742 nlmsg_free(msg);
18743}
947add36 18744EXPORT_SYMBOL(cfg80211_cqm_rssi_notify);
d6dc1a38 18745
5b97f49d
JB
18746void cfg80211_cqm_txe_notify(struct net_device *dev,
18747 const u8 *peer, u32 num_packets,
18748 u32 rate, u32 intvl, gfp_t gfp)
18749{
18750 struct sk_buff *msg;
18751
18752 msg = cfg80211_prepare_cqm(dev, peer, gfp);
18753 if (!msg)
18754 return;
18755
18756 if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_PKTS, num_packets))
18757 goto nla_put_failure;
18758
18759 if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_RATE, rate))
18760 goto nla_put_failure;
18761
18762 if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_INTVL, intvl))
18763 goto nla_put_failure;
18764
18765 cfg80211_send_cqm(msg, gfp);
18766 return;
18767
18768 nla_put_failure:
18769 nlmsg_free(msg);
18770}
18771EXPORT_SYMBOL(cfg80211_cqm_txe_notify);
18772
18773void cfg80211_cqm_pktloss_notify(struct net_device *dev,
18774 const u8 *peer, u32 num_packets, gfp_t gfp)
18775{
18776 struct sk_buff *msg;
18777
18778 trace_cfg80211_cqm_pktloss_notify(dev, peer, num_packets);
18779
18780 msg = cfg80211_prepare_cqm(dev, peer, gfp);
18781 if (!msg)
18782 return;
18783
18784 if (nla_put_u32(msg, NL80211_ATTR_CQM_PKT_LOSS_EVENT, num_packets))
18785 goto nla_put_failure;
18786
18787 cfg80211_send_cqm(msg, gfp);
18788 return;
18789
18790 nla_put_failure:
18791 nlmsg_free(msg);
18792}
18793EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify);
18794
98f03342
JB
18795void cfg80211_cqm_beacon_loss_notify(struct net_device *dev, gfp_t gfp)
18796{
18797 struct sk_buff *msg;
18798
18799 msg = cfg80211_prepare_cqm(dev, NULL, gfp);
18800 if (!msg)
18801 return;
18802
18803 if (nla_put_flag(msg, NL80211_ATTR_CQM_BEACON_LOSS_EVENT))
18804 goto nla_put_failure;
18805
18806 cfg80211_send_cqm(msg, gfp);
18807 return;
18808
18809 nla_put_failure:
18810 nlmsg_free(msg);
18811}
18812EXPORT_SYMBOL(cfg80211_cqm_beacon_loss_notify);
18813
947add36
JB
18814static void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
18815 struct net_device *netdev, const u8 *bssid,
18816 const u8 *replay_ctr, gfp_t gfp)
e5497d76
JB
18817{
18818 struct sk_buff *msg;
18819 struct nlattr *rekey_attr;
18820 void *hdr;
18821
58050fce 18822 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
e5497d76
JB
18823 if (!msg)
18824 return;
18825
18826 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_REKEY_OFFLOAD);
18827 if (!hdr) {
18828 nlmsg_free(msg);
18829 return;
18830 }
18831
9360ffd1
DM
18832 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18833 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
18834 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
18835 goto nla_put_failure;
e5497d76 18836
ae0be8de 18837 rekey_attr = nla_nest_start_noflag(msg, NL80211_ATTR_REKEY_DATA);
e5497d76
JB
18838 if (!rekey_attr)
18839 goto nla_put_failure;
18840
9360ffd1
DM
18841 if (nla_put(msg, NL80211_REKEY_DATA_REPLAY_CTR,
18842 NL80211_REPLAY_CTR_LEN, replay_ctr))
18843 goto nla_put_failure;
e5497d76
JB
18844
18845 nla_nest_end(msg, rekey_attr);
18846
3b7b72ee 18847 genlmsg_end(msg, hdr);
e5497d76 18848
68eb5503 18849 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18850 NL80211_MCGRP_MLME, gfp);
e5497d76
JB
18851 return;
18852
18853 nla_put_failure:
e5497d76
JB
18854 nlmsg_free(msg);
18855}
18856
947add36
JB
18857void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,
18858 const u8 *replay_ctr, gfp_t gfp)
18859{
18860 struct wireless_dev *wdev = dev->ieee80211_ptr;
18861 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 18862 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
18863
18864 trace_cfg80211_gtk_rekey_notify(dev, bssid);
18865 nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp);
18866}
18867EXPORT_SYMBOL(cfg80211_gtk_rekey_notify);
18868
18869static void
18870nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev,
18871 struct net_device *netdev, int index,
18872 const u8 *bssid, bool preauth, gfp_t gfp)
c9df56b4
JM
18873{
18874 struct sk_buff *msg;
18875 struct nlattr *attr;
18876 void *hdr;
18877
58050fce 18878 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
c9df56b4
JM
18879 if (!msg)
18880 return;
18881
18882 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PMKSA_CANDIDATE);
18883 if (!hdr) {
18884 nlmsg_free(msg);
18885 return;
18886 }
18887
9360ffd1
DM
18888 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18889 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
18890 goto nla_put_failure;
c9df56b4 18891
ae0be8de 18892 attr = nla_nest_start_noflag(msg, NL80211_ATTR_PMKSA_CANDIDATE);
c9df56b4
JM
18893 if (!attr)
18894 goto nla_put_failure;
18895
9360ffd1
DM
18896 if (nla_put_u32(msg, NL80211_PMKSA_CANDIDATE_INDEX, index) ||
18897 nla_put(msg, NL80211_PMKSA_CANDIDATE_BSSID, ETH_ALEN, bssid) ||
18898 (preauth &&
18899 nla_put_flag(msg, NL80211_PMKSA_CANDIDATE_PREAUTH)))
18900 goto nla_put_failure;
c9df56b4
JM
18901
18902 nla_nest_end(msg, attr);
18903
3b7b72ee 18904 genlmsg_end(msg, hdr);
c9df56b4 18905
68eb5503 18906 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18907 NL80211_MCGRP_MLME, gfp);
c9df56b4
JM
18908 return;
18909
18910 nla_put_failure:
c9df56b4
JM
18911 nlmsg_free(msg);
18912}
18913
947add36
JB
18914void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
18915 const u8 *bssid, bool preauth, gfp_t gfp)
18916{
18917 struct wireless_dev *wdev = dev->ieee80211_ptr;
18918 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 18919 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
18920
18921 trace_cfg80211_pmksa_candidate_notify(dev, index, bssid, preauth);
18922 nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp);
18923}
18924EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
18925
18926static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
18927 struct net_device *netdev,
18928 struct cfg80211_chan_def *chandef,
f8d7552e
LC
18929 gfp_t gfp,
18930 enum nl80211_commands notif,
669b8413 18931 u8 count, bool quiet)
5314526b
TP
18932{
18933 struct sk_buff *msg;
18934 void *hdr;
18935
58050fce 18936 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
5314526b
TP
18937 if (!msg)
18938 return;
18939
f8d7552e 18940 hdr = nl80211hdr_put(msg, 0, 0, 0, notif);
5314526b
TP
18941 if (!hdr) {
18942 nlmsg_free(msg);
18943 return;
18944 }
18945
683b6d3b
JB
18946 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
18947 goto nla_put_failure;
18948
18949 if (nl80211_send_chandef(msg, chandef))
7eab0f64 18950 goto nla_put_failure;
5314526b 18951
669b8413
JB
18952 if (notif == NL80211_CMD_CH_SWITCH_STARTED_NOTIFY) {
18953 if (nla_put_u32(msg, NL80211_ATTR_CH_SWITCH_COUNT, count))
f8d7552e 18954 goto nla_put_failure;
669b8413
JB
18955 if (quiet &&
18956 nla_put_flag(msg, NL80211_ATTR_CH_SWITCH_BLOCK_TX))
f8d7552e 18957 goto nla_put_failure;
669b8413 18958 }
f8d7552e 18959
5314526b
TP
18960 genlmsg_end(msg, hdr);
18961
68eb5503 18962 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18963 NL80211_MCGRP_MLME, gfp);
5314526b
TP
18964 return;
18965
18966 nla_put_failure:
5314526b
TP
18967 nlmsg_free(msg);
18968}
18969
947add36 18970void cfg80211_ch_switch_notify(struct net_device *dev,
7b0a0e3c
JB
18971 struct cfg80211_chan_def *chandef,
18972 unsigned int link_id)
84f10708 18973{
947add36
JB
18974 struct wireless_dev *wdev = dev->ieee80211_ptr;
18975 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 18976 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36 18977
e487eaeb 18978 ASSERT_WDEV_LOCK(wdev);
7b0a0e3c 18979 WARN_INVALID_LINK_ID(wdev, link_id);
947add36 18980
7b0a0e3c 18981 trace_cfg80211_ch_switch_notify(dev, chandef, link_id);
5dc8cdce 18982
7b0a0e3c
JB
18983 switch (wdev->iftype) {
18984 case NL80211_IFTYPE_STATION:
18985 case NL80211_IFTYPE_P2P_CLIENT:
18986 if (!WARN_ON(!wdev->links[link_id].client.current_bss))
18987 cfg80211_update_assoc_bss_entry(wdev, link_id,
18988 chandef->chan);
18989 break;
18990 case NL80211_IFTYPE_MESH_POINT:
18991 wdev->u.mesh.chandef = *chandef;
18992 wdev->u.mesh.preset_chandef = *chandef;
18993 break;
18994 case NL80211_IFTYPE_AP:
18995 case NL80211_IFTYPE_P2P_GO:
18996 wdev->links[link_id].ap.chandef = *chandef;
18997 break;
77e7b6ba
JB
18998 case NL80211_IFTYPE_ADHOC:
18999 wdev->u.ibss.chandef = *chandef;
19000 break;
7b0a0e3c
JB
19001 default:
19002 WARN_ON(1);
19003 break;
19004 }
5dc8cdce 19005
d34990bb
MV
19006 cfg80211_sched_dfs_chan_update(rdev);
19007
f8d7552e 19008 nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
669b8413 19009 NL80211_CMD_CH_SWITCH_NOTIFY, 0, false);
947add36
JB
19010}
19011EXPORT_SYMBOL(cfg80211_ch_switch_notify);
19012
f8d7552e
LC
19013void cfg80211_ch_switch_started_notify(struct net_device *dev,
19014 struct cfg80211_chan_def *chandef,
669b8413 19015 u8 count, bool quiet)
f8d7552e
LC
19016{
19017 struct wireless_dev *wdev = dev->ieee80211_ptr;
19018 struct wiphy *wiphy = wdev->wiphy;
19019 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
19020
19021 trace_cfg80211_ch_switch_started_notify(dev, chandef);
19022
19023 nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
669b8413
JB
19024 NL80211_CMD_CH_SWITCH_STARTED_NOTIFY,
19025 count, quiet);
f8d7552e
LC
19026}
19027EXPORT_SYMBOL(cfg80211_ch_switch_started_notify);
19028
0d2ab3ae
JC
19029int cfg80211_bss_color_notify(struct net_device *dev, gfp_t gfp,
19030 enum nl80211_commands cmd, u8 count,
19031 u64 color_bitmap)
19032{
19033 struct wireless_dev *wdev = dev->ieee80211_ptr;
19034 struct wiphy *wiphy = wdev->wiphy;
19035 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
19036 struct sk_buff *msg;
19037 void *hdr;
19038
19039 ASSERT_WDEV_LOCK(wdev);
19040
19041 trace_cfg80211_bss_color_notify(dev, cmd, count, color_bitmap);
19042
19043 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
19044 if (!msg)
19045 return -ENOMEM;
19046
19047 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
19048 if (!hdr)
19049 goto nla_put_failure;
19050
19051 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
19052 goto nla_put_failure;
19053
19054 if (cmd == NL80211_CMD_COLOR_CHANGE_STARTED &&
19055 nla_put_u32(msg, NL80211_ATTR_COLOR_CHANGE_COUNT, count))
19056 goto nla_put_failure;
19057
19058 if (cmd == NL80211_CMD_OBSS_COLOR_COLLISION &&
19059 nla_put_u64_64bit(msg, NL80211_ATTR_OBSS_COLOR_BITMAP,
19060 color_bitmap, NL80211_ATTR_PAD))
19061 goto nla_put_failure;
19062
19063 genlmsg_end(msg, hdr);
19064
19065 return genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
19066 msg, 0, NL80211_MCGRP_MLME, gfp);
19067
19068nla_put_failure:
19069 nlmsg_free(msg);
19070 return -EINVAL;
19071}
19072EXPORT_SYMBOL(cfg80211_bss_color_notify);
19073
04f39047
SW
19074void
19075nl80211_radar_notify(struct cfg80211_registered_device *rdev,
d2859df5 19076 const struct cfg80211_chan_def *chandef,
04f39047
SW
19077 enum nl80211_radar_event event,
19078 struct net_device *netdev, gfp_t gfp)
19079{
19080 struct sk_buff *msg;
19081 void *hdr;
19082
19083 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
19084 if (!msg)
19085 return;
19086
19087 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_RADAR_DETECT);
19088 if (!hdr) {
19089 nlmsg_free(msg);
19090 return;
19091 }
19092
19093 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
19094 goto nla_put_failure;
19095
19096 /* NOP and radar events don't need a netdev parameter */
19097 if (netdev) {
19098 struct wireless_dev *wdev = netdev->ieee80211_ptr;
19099
19100 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
2dad624e
ND
19101 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
19102 NL80211_ATTR_PAD))
04f39047
SW
19103 goto nla_put_failure;
19104 }
19105
19106 if (nla_put_u32(msg, NL80211_ATTR_RADAR_EVENT, event))
19107 goto nla_put_failure;
19108
19109 if (nl80211_send_chandef(msg, chandef))
19110 goto nla_put_failure;
19111
9c90a9f6 19112 genlmsg_end(msg, hdr);
04f39047 19113
68eb5503 19114 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19115 NL80211_MCGRP_MLME, gfp);
04f39047
SW
19116 return;
19117
19118 nla_put_failure:
04f39047
SW
19119 nlmsg_free(msg);
19120}
19121
466b9936 19122void cfg80211_sta_opmode_change_notify(struct net_device *dev, const u8 *mac,
19123 struct sta_opmode_info *sta_opmode,
19124 gfp_t gfp)
19125{
19126 struct sk_buff *msg;
19127 struct wireless_dev *wdev = dev->ieee80211_ptr;
19128 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
19129 void *hdr;
19130
19131 if (WARN_ON(!mac))
19132 return;
19133
19134 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
19135 if (!msg)
19136 return;
19137
19138 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STA_OPMODE_CHANGED);
19139 if (!hdr) {
19140 nlmsg_free(msg);
19141 return;
19142 }
19143
19144 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
19145 goto nla_put_failure;
19146
19147 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
19148 goto nla_put_failure;
19149
19150 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac))
19151 goto nla_put_failure;
19152
19153 if ((sta_opmode->changed & STA_OPMODE_SMPS_MODE_CHANGED) &&
19154 nla_put_u8(msg, NL80211_ATTR_SMPS_MODE, sta_opmode->smps_mode))
19155 goto nla_put_failure;
19156
19157 if ((sta_opmode->changed & STA_OPMODE_MAX_BW_CHANGED) &&
0016d320 19158 nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, sta_opmode->bw))
466b9936 19159 goto nla_put_failure;
19160
19161 if ((sta_opmode->changed & STA_OPMODE_N_SS_CHANGED) &&
19162 nla_put_u8(msg, NL80211_ATTR_NSS, sta_opmode->rx_nss))
19163 goto nla_put_failure;
19164
19165 genlmsg_end(msg, hdr);
19166
19167 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
19168 NL80211_MCGRP_MLME, gfp);
19169
19170 return;
19171
19172nla_put_failure:
19173 nlmsg_free(msg);
19174}
19175EXPORT_SYMBOL(cfg80211_sta_opmode_change_notify);
19176
7f6cf311 19177void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
c4b50cd3
VN
19178 u64 cookie, bool acked, s32 ack_signal,
19179 bool is_valid_ack_signal, gfp_t gfp)
7f6cf311
JB
19180{
19181 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 19182 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
7f6cf311
JB
19183 struct sk_buff *msg;
19184 void *hdr;
7f6cf311 19185
4ee3e063
BL
19186 trace_cfg80211_probe_status(dev, addr, cookie, acked);
19187
58050fce 19188 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
4ee3e063 19189
7f6cf311
JB
19190 if (!msg)
19191 return;
19192
19193 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PROBE_CLIENT);
19194 if (!hdr) {
19195 nlmsg_free(msg);
19196 return;
19197 }
19198
9360ffd1
DM
19199 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
19200 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
19201 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
2dad624e
ND
19202 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
19203 NL80211_ATTR_PAD) ||
c4b50cd3
VN
19204 (acked && nla_put_flag(msg, NL80211_ATTR_ACK)) ||
19205 (is_valid_ack_signal && nla_put_s32(msg, NL80211_ATTR_ACK_SIGNAL,
19206 ack_signal)))
9360ffd1 19207 goto nla_put_failure;
7f6cf311 19208
9c90a9f6 19209 genlmsg_end(msg, hdr);
7f6cf311 19210
68eb5503 19211 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19212 NL80211_MCGRP_MLME, gfp);
7f6cf311
JB
19213 return;
19214
19215 nla_put_failure:
7f6cf311
JB
19216 nlmsg_free(msg);
19217}
19218EXPORT_SYMBOL(cfg80211_probe_status);
19219
e76fede8
TP
19220void cfg80211_report_obss_beacon_khz(struct wiphy *wiphy, const u8 *frame,
19221 size_t len, int freq, int sig_dbm)
5e760230 19222{
f26cbf40 19223 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
5e760230
JB
19224 struct sk_buff *msg;
19225 void *hdr;
37c73b5f 19226 struct cfg80211_beacon_registration *reg;
5e760230 19227
4ee3e063
BL
19228 trace_cfg80211_report_obss_beacon(wiphy, frame, len, freq, sig_dbm);
19229
37c73b5f
BG
19230 spin_lock_bh(&rdev->beacon_registrations_lock);
19231 list_for_each_entry(reg, &rdev->beacon_registrations, list) {
19232 msg = nlmsg_new(len + 100, GFP_ATOMIC);
19233 if (!msg) {
19234 spin_unlock_bh(&rdev->beacon_registrations_lock);
19235 return;
19236 }
5e760230 19237
37c73b5f
BG
19238 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME);
19239 if (!hdr)
19240 goto nla_put_failure;
5e760230 19241
37c73b5f
BG
19242 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
19243 (freq &&
942ba88b
TP
19244 (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
19245 KHZ_TO_MHZ(freq)) ||
19246 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
19247 freq % 1000))) ||
37c73b5f
BG
19248 (sig_dbm &&
19249 nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||
19250 nla_put(msg, NL80211_ATTR_FRAME, len, frame))
19251 goto nla_put_failure;
5e760230 19252
37c73b5f 19253 genlmsg_end(msg, hdr);
5e760230 19254
37c73b5f
BG
19255 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, reg->nlportid);
19256 }
19257 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230
JB
19258 return;
19259
19260 nla_put_failure:
37c73b5f 19261 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230
JB
19262 nlmsg_free(msg);
19263}
e76fede8 19264EXPORT_SYMBOL(cfg80211_report_obss_beacon_khz);
5e760230 19265
cd8f7cb4 19266#ifdef CONFIG_PM
8cd4d456
LC
19267static int cfg80211_net_detect_results(struct sk_buff *msg,
19268 struct cfg80211_wowlan_wakeup *wakeup)
19269{
19270 struct cfg80211_wowlan_nd_info *nd = wakeup->net_detect;
19271 struct nlattr *nl_results, *nl_match, *nl_freqs;
19272 int i, j;
19273
ae0be8de
MK
19274 nl_results = nla_nest_start_noflag(msg,
19275 NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS);
8cd4d456
LC
19276 if (!nl_results)
19277 return -EMSGSIZE;
19278
19279 for (i = 0; i < nd->n_matches; i++) {
19280 struct cfg80211_wowlan_nd_match *match = nd->matches[i];
19281
ae0be8de 19282 nl_match = nla_nest_start_noflag(msg, i);
8cd4d456
LC
19283 if (!nl_match)
19284 break;
19285
19286 /* The SSID attribute is optional in nl80211, but for
19287 * simplicity reasons it's always present in the
19288 * cfg80211 structure. If a driver can't pass the
19289 * SSID, that needs to be changed. A zero length SSID
19290 * is still a valid SSID (wildcard), so it cannot be
19291 * used for this purpose.
19292 */
19293 if (nla_put(msg, NL80211_ATTR_SSID, match->ssid.ssid_len,
19294 match->ssid.ssid)) {
19295 nla_nest_cancel(msg, nl_match);
19296 goto out;
19297 }
19298
19299 if (match->n_channels) {
ae0be8de
MK
19300 nl_freqs = nla_nest_start_noflag(msg,
19301 NL80211_ATTR_SCAN_FREQUENCIES);
8cd4d456
LC
19302 if (!nl_freqs) {
19303 nla_nest_cancel(msg, nl_match);
19304 goto out;
19305 }
19306
19307 for (j = 0; j < match->n_channels; j++) {
5528fae8 19308 if (nla_put_u32(msg, j, match->channels[j])) {
8cd4d456
LC
19309 nla_nest_cancel(msg, nl_freqs);
19310 nla_nest_cancel(msg, nl_match);
19311 goto out;
19312 }
19313 }
19314
19315 nla_nest_end(msg, nl_freqs);
19316 }
19317
19318 nla_nest_end(msg, nl_match);
19319 }
19320
19321out:
19322 nla_nest_end(msg, nl_results);
19323 return 0;
19324}
19325
cd8f7cb4
JB
19326void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
19327 struct cfg80211_wowlan_wakeup *wakeup,
19328 gfp_t gfp)
19329{
f26cbf40 19330 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
cd8f7cb4
JB
19331 struct sk_buff *msg;
19332 void *hdr;
9c90a9f6 19333 int size = 200;
cd8f7cb4
JB
19334
19335 trace_cfg80211_report_wowlan_wakeup(wdev->wiphy, wdev, wakeup);
19336
19337 if (wakeup)
19338 size += wakeup->packet_present_len;
19339
19340 msg = nlmsg_new(size, gfp);
19341 if (!msg)
19342 return;
19343
19344 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_WOWLAN);
19345 if (!hdr)
19346 goto free_msg;
19347
19348 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
2dad624e
ND
19349 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
19350 NL80211_ATTR_PAD))
cd8f7cb4
JB
19351 goto free_msg;
19352
19353 if (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
19354 wdev->netdev->ifindex))
19355 goto free_msg;
19356
19357 if (wakeup) {
19358 struct nlattr *reasons;
19359
ae0be8de
MK
19360 reasons = nla_nest_start_noflag(msg,
19361 NL80211_ATTR_WOWLAN_TRIGGERS);
7fa322c8
JB
19362 if (!reasons)
19363 goto free_msg;
cd8f7cb4
JB
19364
19365 if (wakeup->disconnect &&
19366 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT))
19367 goto free_msg;
19368 if (wakeup->magic_pkt &&
19369 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT))
19370 goto free_msg;
19371 if (wakeup->gtk_rekey_failure &&
19372 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE))
19373 goto free_msg;
19374 if (wakeup->eap_identity_req &&
19375 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST))
19376 goto free_msg;
19377 if (wakeup->four_way_handshake &&
19378 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE))
19379 goto free_msg;
19380 if (wakeup->rfkill_release &&
19381 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))
19382 goto free_msg;
19383
19384 if (wakeup->pattern_idx >= 0 &&
19385 nla_put_u32(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
19386 wakeup->pattern_idx))
19387 goto free_msg;
19388
ae917c9f
JB
19389 if (wakeup->tcp_match &&
19390 nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH))
19391 goto free_msg;
2a0e047e 19392
ae917c9f
JB
19393 if (wakeup->tcp_connlost &&
19394 nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST))
19395 goto free_msg;
2a0e047e 19396
ae917c9f
JB
19397 if (wakeup->tcp_nomoretokens &&
19398 nla_put_flag(msg,
19399 NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS))
19400 goto free_msg;
2a0e047e 19401
cd8f7cb4
JB
19402 if (wakeup->packet) {
19403 u32 pkt_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211;
19404 u32 len_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN;
19405
19406 if (!wakeup->packet_80211) {
19407 pkt_attr =
19408 NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023;
19409 len_attr =
19410 NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN;
19411 }
19412
19413 if (wakeup->packet_len &&
19414 nla_put_u32(msg, len_attr, wakeup->packet_len))
19415 goto free_msg;
19416
19417 if (nla_put(msg, pkt_attr, wakeup->packet_present_len,
19418 wakeup->packet))
19419 goto free_msg;
19420 }
19421
8cd4d456
LC
19422 if (wakeup->net_detect &&
19423 cfg80211_net_detect_results(msg, wakeup))
19424 goto free_msg;
19425
cd8f7cb4
JB
19426 nla_nest_end(msg, reasons);
19427 }
19428
9c90a9f6 19429 genlmsg_end(msg, hdr);
cd8f7cb4 19430
68eb5503 19431 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19432 NL80211_MCGRP_MLME, gfp);
cd8f7cb4
JB
19433 return;
19434
19435 free_msg:
19436 nlmsg_free(msg);
19437}
19438EXPORT_SYMBOL(cfg80211_report_wowlan_wakeup);
19439#endif
19440
3475b094
JM
19441void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer,
19442 enum nl80211_tdls_operation oper,
19443 u16 reason_code, gfp_t gfp)
19444{
19445 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 19446 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
3475b094
JM
19447 struct sk_buff *msg;
19448 void *hdr;
3475b094
JM
19449
19450 trace_cfg80211_tdls_oper_request(wdev->wiphy, dev, peer, oper,
19451 reason_code);
19452
19453 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
19454 if (!msg)
19455 return;
19456
19457 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_TDLS_OPER);
19458 if (!hdr) {
19459 nlmsg_free(msg);
19460 return;
19461 }
19462
19463 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
19464 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
19465 nla_put_u8(msg, NL80211_ATTR_TDLS_OPERATION, oper) ||
19466 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer) ||
19467 (reason_code > 0 &&
19468 nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code)))
19469 goto nla_put_failure;
19470
9c90a9f6 19471 genlmsg_end(msg, hdr);
3475b094 19472
68eb5503 19473 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19474 NL80211_MCGRP_MLME, gfp);
3475b094
JM
19475 return;
19476
19477 nla_put_failure:
3475b094
JM
19478 nlmsg_free(msg);
19479}
19480EXPORT_SYMBOL(cfg80211_tdls_oper_request);
19481
026331c4
JM
19482static int nl80211_netlink_notify(struct notifier_block * nb,
19483 unsigned long state,
19484 void *_notify)
19485{
19486 struct netlink_notify *notify = _notify;
19487 struct cfg80211_registered_device *rdev;
19488 struct wireless_dev *wdev;
37c73b5f 19489 struct cfg80211_beacon_registration *reg, *tmp;
026331c4 19490
8f815cdd 19491 if (state != NETLINK_URELEASE || notify->protocol != NETLINK_GENERIC)
026331c4
JM
19492 return NOTIFY_DONE;
19493
19494 rcu_read_lock();
19495
5e760230 19496 list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
ca986ad9 19497 struct cfg80211_sched_scan_request *sched_scan_req;
753aacfd 19498
ca986ad9
AVS
19499 list_for_each_entry_rcu(sched_scan_req,
19500 &rdev->sched_scan_req_list,
19501 list) {
19502 if (sched_scan_req->owner_nlportid == notify->portid) {
19503 sched_scan_req->nl_owner_dead = true;
753aacfd 19504 schedule_work(&rdev->sched_scan_stop_wk);
ca986ad9 19505 }
753aacfd 19506 }
78f22b6a 19507
53873f13 19508 list_for_each_entry_rcu(wdev, &rdev->wiphy.wdev_list, list) {
15e47304 19509 cfg80211_mlme_unregister_socket(wdev, notify->portid);
37c73b5f 19510
ab81007a
JB
19511 if (wdev->owner_nlportid == notify->portid) {
19512 wdev->nl_owner_dead = true;
19513 schedule_work(&rdev->destroy_work);
19514 } else if (wdev->conn_owner_nlportid == notify->portid) {
bd2522b1 19515 schedule_work(&wdev->disconnect_wk);
ab81007a 19516 }
9bb7e0f2
JB
19517
19518 cfg80211_release_pmsr(wdev, notify->portid);
78f22b6a
JB
19519 }
19520
37c73b5f
BG
19521 spin_lock_bh(&rdev->beacon_registrations_lock);
19522 list_for_each_entry_safe(reg, tmp, &rdev->beacon_registrations,
19523 list) {
19524 if (reg->nlportid == notify->portid) {
19525 list_del(&reg->list);
19526 kfree(reg);
19527 break;
19528 }
19529 }
19530 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230 19531 }
026331c4
JM
19532
19533 rcu_read_unlock();
19534
05050753
I
19535 /*
19536 * It is possible that the user space process that is controlling the
19537 * indoor setting disappeared, so notify the regulatory core.
19538 */
19539 regulatory_netlink_notify(notify->portid);
6784c7db 19540 return NOTIFY_OK;
026331c4
JM
19541}
19542
19543static struct notifier_block nl80211_netlink_notifier = {
19544 .notifier_call = nl80211_netlink_notify,
19545};
19546
355199e0
JM
19547void cfg80211_ft_event(struct net_device *netdev,
19548 struct cfg80211_ft_event_params *ft_event)
19549{
19550 struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy;
f26cbf40 19551 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
355199e0
JM
19552 struct sk_buff *msg;
19553 void *hdr;
355199e0
JM
19554
19555 trace_cfg80211_ft_event(wiphy, netdev, ft_event);
19556
19557 if (!ft_event->target_ap)
19558 return;
19559
1039d081
DL
19560 msg = nlmsg_new(100 + ft_event->ies_len + ft_event->ric_ies_len,
19561 GFP_KERNEL);
355199e0
JM
19562 if (!msg)
19563 return;
19564
19565 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FT_EVENT);
ae917c9f
JB
19566 if (!hdr)
19567 goto out;
355199e0 19568
ae917c9f
JB
19569 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
19570 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
19571 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ft_event->target_ap))
19572 goto out;
355199e0 19573
ae917c9f
JB
19574 if (ft_event->ies &&
19575 nla_put(msg, NL80211_ATTR_IE, ft_event->ies_len, ft_event->ies))
19576 goto out;
19577 if (ft_event->ric_ies &&
19578 nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len,
19579 ft_event->ric_ies))
19580 goto out;
355199e0 19581
9c90a9f6 19582 genlmsg_end(msg, hdr);
355199e0 19583
68eb5503 19584 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 19585 NL80211_MCGRP_MLME, GFP_KERNEL);
ae917c9f
JB
19586 return;
19587 out:
19588 nlmsg_free(msg);
355199e0
JM
19589}
19590EXPORT_SYMBOL(cfg80211_ft_event);
19591
5de17984
AS
19592void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp)
19593{
19594 struct cfg80211_registered_device *rdev;
19595 struct sk_buff *msg;
19596 void *hdr;
19597 u32 nlportid;
19598
f26cbf40 19599 rdev = wiphy_to_rdev(wdev->wiphy);
5de17984
AS
19600 if (!rdev->crit_proto_nlportid)
19601 return;
19602
19603 nlportid = rdev->crit_proto_nlportid;
19604 rdev->crit_proto_nlportid = 0;
19605
19606 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
19607 if (!msg)
19608 return;
19609
19610 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CRIT_PROTOCOL_STOP);
19611 if (!hdr)
19612 goto nla_put_failure;
19613
19614 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
2dad624e
ND
19615 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
19616 NL80211_ATTR_PAD))
5de17984
AS
19617 goto nla_put_failure;
19618
19619 genlmsg_end(msg, hdr);
19620
19621 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
19622 return;
19623
19624 nla_put_failure:
5de17984 19625 nlmsg_free(msg);
5de17984
AS
19626}
19627EXPORT_SYMBOL(cfg80211_crit_proto_stopped);
19628
348baf0e
JB
19629void nl80211_send_ap_stopped(struct wireless_dev *wdev)
19630{
19631 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 19632 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
348baf0e
JB
19633 struct sk_buff *msg;
19634 void *hdr;
19635
19636 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
19637 if (!msg)
19638 return;
19639
19640 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STOP_AP);
19641 if (!hdr)
19642 goto out;
19643
19644 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
19645 nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) ||
2dad624e
ND
19646 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
19647 NL80211_ATTR_PAD))
348baf0e
JB
19648 goto out;
19649
19650 genlmsg_end(msg, hdr);
19651
19652 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0,
19653 NL80211_MCGRP_MLME, GFP_KERNEL);
19654 return;
19655 out:
19656 nlmsg_free(msg);
19657}
19658
40cbfa90
SD
19659int cfg80211_external_auth_request(struct net_device *dev,
19660 struct cfg80211_external_auth_params *params,
19661 gfp_t gfp)
19662{
19663 struct wireless_dev *wdev = dev->ieee80211_ptr;
19664 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
19665 struct sk_buff *msg;
19666 void *hdr;
19667
19668 if (!wdev->conn_owner_nlportid)
19669 return -EINVAL;
19670
19671 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
19672 if (!msg)
19673 return -ENOMEM;
19674
19675 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_EXTERNAL_AUTH);
19676 if (!hdr)
19677 goto nla_put_failure;
19678
19679 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
19680 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
19681 nla_put_u32(msg, NL80211_ATTR_AKM_SUITES, params->key_mgmt_suite) ||
19682 nla_put_u32(msg, NL80211_ATTR_EXTERNAL_AUTH_ACTION,
19683 params->action) ||
19684 nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, params->bssid) ||
19685 nla_put(msg, NL80211_ATTR_SSID, params->ssid.ssid_len,
19686 params->ssid.ssid))
19687 goto nla_put_failure;
19688
19689 genlmsg_end(msg, hdr);
19690 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
19691 wdev->conn_owner_nlportid);
19692 return 0;
19693
19694 nla_put_failure:
19695 nlmsg_free(msg);
19696 return -ENOBUFS;
19697}
19698EXPORT_SYMBOL(cfg80211_external_auth_request);
19699
cb74e977
SD
19700void cfg80211_update_owe_info_event(struct net_device *netdev,
19701 struct cfg80211_update_owe_info *owe_info,
19702 gfp_t gfp)
19703{
19704 struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy;
19705 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
19706 struct sk_buff *msg;
19707 void *hdr;
19708
19709 trace_cfg80211_update_owe_info_event(wiphy, netdev, owe_info);
19710
19711 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
19712 if (!msg)
19713 return;
19714
19715 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_UPDATE_OWE_INFO);
19716 if (!hdr)
19717 goto nla_put_failure;
19718
19719 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
19720 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
19721 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, owe_info->peer))
19722 goto nla_put_failure;
19723
19724 if (!owe_info->ie_len ||
19725 nla_put(msg, NL80211_ATTR_IE, owe_info->ie_len, owe_info->ie))
19726 goto nla_put_failure;
19727
19728 genlmsg_end(msg, hdr);
19729
19730 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
19731 NL80211_MCGRP_MLME, gfp);
19732 return;
19733
19734nla_put_failure:
19735 genlmsg_cancel(msg, hdr);
19736 nlmsg_free(msg);
19737}
19738EXPORT_SYMBOL(cfg80211_update_owe_info_event);
19739
55682965
JB
19740/* initialisation/exit functions */
19741
56989f6d 19742int __init nl80211_init(void)
55682965 19743{
0d63cbb5 19744 int err;
55682965 19745
489111e5 19746 err = genl_register_family(&nl80211_fam);
55682965
JB
19747 if (err)
19748 return err;
19749
026331c4
JM
19750 err = netlink_register_notifier(&nl80211_netlink_notifier);
19751 if (err)
19752 goto err_out;
19753
55682965
JB
19754 return 0;
19755 err_out:
19756 genl_unregister_family(&nl80211_fam);
19757 return err;
19758}
19759
19760void nl80211_exit(void)
19761{
026331c4 19762 netlink_unregister_notifier(&nl80211_netlink_notifier);
55682965
JB
19763 genl_unregister_family(&nl80211_fam);
19764}