nl80211: vendor-cmd: intel: add more details for IWL_MVM_VENDOR_CMD_HOST_GET_OWNERSHIP
[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
abaf94ec 8 * Copyright (C) 2018-2021 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
55682965 288/* policy for the attributes */
d15da2a2
JB
289static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR];
290
81e54d08
PKC
291static const struct nla_policy
292nl80211_ftm_responder_policy[NL80211_FTM_RESP_ATTR_MAX + 1] = {
293 [NL80211_FTM_RESP_ATTR_ENABLED] = { .type = NLA_FLAG, },
294 [NL80211_FTM_RESP_ATTR_LCI] = { .type = NLA_BINARY,
295 .len = U8_MAX },
296 [NL80211_FTM_RESP_ATTR_CIVICLOC] = { .type = NLA_BINARY,
297 .len = U8_MAX },
298};
299
9bb7e0f2
JB
300static const struct nla_policy
301nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = {
302 [NL80211_PMSR_FTM_REQ_ATTR_ASAP] = { .type = NLA_FLAG },
303 [NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE] = { .type = NLA_U32 },
304 [NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP] =
305 NLA_POLICY_MAX(NLA_U8, 15),
306 [NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD] = { .type = NLA_U16 },
307 [NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION] =
308 NLA_POLICY_MAX(NLA_U8, 15),
309 [NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST] =
ea18709a 310 NLA_POLICY_MAX(NLA_U8, 31),
9bb7e0f2
JB
311 [NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES] = { .type = NLA_U8 },
312 [NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI] = { .type = NLA_FLAG },
313 [NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC] = { .type = NLA_FLAG },
efb5520d
AS
314 [NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED] = { .type = NLA_FLAG },
315 [NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED] = { .type = NLA_FLAG },
73807523 316 [NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK] = { .type = NLA_FLAG },
9bb7e0f2
JB
317};
318
319static const struct nla_policy
320nl80211_pmsr_req_data_policy[NL80211_PMSR_TYPE_MAX + 1] = {
321 [NL80211_PMSR_TYPE_FTM] =
23323289 322 NLA_POLICY_NESTED(nl80211_pmsr_ftm_req_attr_policy),
9bb7e0f2
JB
323};
324
325static const struct nla_policy
326nl80211_pmsr_req_attr_policy[NL80211_PMSR_REQ_ATTR_MAX + 1] = {
327 [NL80211_PMSR_REQ_ATTR_DATA] =
23323289 328 NLA_POLICY_NESTED(nl80211_pmsr_req_data_policy),
9bb7e0f2
JB
329 [NL80211_PMSR_REQ_ATTR_GET_AP_TSF] = { .type = NLA_FLAG },
330};
331
332static const struct nla_policy
aeddc05f 333nl80211_pmsr_peer_attr_policy[NL80211_PMSR_PEER_ATTR_MAX + 1] = {
9bb7e0f2 334 [NL80211_PMSR_PEER_ATTR_ADDR] = NLA_POLICY_ETH_ADDR,
d15da2a2 335 [NL80211_PMSR_PEER_ATTR_CHAN] = NLA_POLICY_NESTED(nl80211_policy),
9bb7e0f2 336 [NL80211_PMSR_PEER_ATTR_REQ] =
23323289 337 NLA_POLICY_NESTED(nl80211_pmsr_req_attr_policy),
9bb7e0f2
JB
338 [NL80211_PMSR_PEER_ATTR_RESP] = { .type = NLA_REJECT },
339};
340
341static const struct nla_policy
342nl80211_pmsr_attr_policy[NL80211_PMSR_ATTR_MAX + 1] = {
343 [NL80211_PMSR_ATTR_MAX_PEERS] = { .type = NLA_REJECT },
344 [NL80211_PMSR_ATTR_REPORT_AP_TSF] = { .type = NLA_REJECT },
345 [NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR] = { .type = NLA_REJECT },
346 [NL80211_PMSR_ATTR_TYPE_CAPA] = { .type = NLA_REJECT },
347 [NL80211_PMSR_ATTR_PEERS] =
aeddc05f 348 NLA_POLICY_NESTED_ARRAY(nl80211_pmsr_peer_attr_policy),
9bb7e0f2
JB
349};
350
796e90f4
JC
351static const struct nla_policy
352he_obss_pd_policy[NL80211_HE_OBSS_PD_ATTR_MAX + 1] = {
353 [NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET] =
354 NLA_POLICY_RANGE(NLA_U8, 1, 20),
355 [NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET] =
356 NLA_POLICY_RANGE(NLA_U8, 1, 20),
f5bec330
RM
357 [NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET] =
358 NLA_POLICY_RANGE(NLA_U8, 1, 20),
359 [NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP] =
360 NLA_POLICY_EXACT_LEN(8),
361 [NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP] =
362 NLA_POLICY_EXACT_LEN(8),
363 [NL80211_HE_OBSS_PD_ATTR_SR_CTRL] = { .type = NLA_U8 },
796e90f4
JC
364};
365
5c5e52d1
JC
366static const struct nla_policy
367he_bss_color_policy[NL80211_HE_BSS_COLOR_ATTR_MAX + 1] = {
368 [NL80211_HE_BSS_COLOR_ATTR_COLOR] = NLA_POLICY_RANGE(NLA_U8, 1, 63),
369 [NL80211_HE_BSS_COLOR_ATTR_DISABLED] = { .type = NLA_FLAG },
370 [NL80211_HE_BSS_COLOR_ATTR_PARTIAL] = { .type = NLA_FLAG },
371};
372
9a5f6488
TC
373static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = {
374 [NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY,
375 .len = NL80211_MAX_SUPP_RATES },
376 [NL80211_TXRATE_HT] = { .type = NLA_BINARY,
377 .len = NL80211_MAX_SUPP_HT_RATES },
378 [NL80211_TXRATE_VHT] = NLA_POLICY_EXACT_LEN_WARN(sizeof(struct nl80211_txrate_vht)),
379 [NL80211_TXRATE_GI] = { .type = NLA_U8 },
eb89a6a6
MH
380 [NL80211_TXRATE_HE] = NLA_POLICY_EXACT_LEN(sizeof(struct nl80211_txrate_he)),
381 [NL80211_TXRATE_HE_GI] = NLA_POLICY_RANGE(NLA_U8,
382 NL80211_RATE_INFO_HE_GI_0_8,
383 NL80211_RATE_INFO_HE_GI_3_2),
384 [NL80211_TXRATE_HE_LTF] = NLA_POLICY_RANGE(NLA_U8,
385 NL80211_RATE_INFO_HE_1XLTF,
386 NL80211_RATE_INFO_HE_4XLTF),
9a5f6488
TC
387};
388
77f576de
T
389static const struct nla_policy
390nl80211_tid_config_attr_policy[NL80211_TID_CONFIG_ATTR_MAX + 1] = {
3710a8a6
JB
391 [NL80211_TID_CONFIG_ATTR_VIF_SUPP] = { .type = NLA_U64 },
392 [NL80211_TID_CONFIG_ATTR_PEER_SUPP] = { .type = NLA_U64 },
77f576de 393 [NL80211_TID_CONFIG_ATTR_OVERRIDE] = { .type = NLA_FLAG },
3710a8a6 394 [NL80211_TID_CONFIG_ATTR_TIDS] = NLA_POLICY_RANGE(NLA_U16, 1, 0xff),
77f576de
T
395 [NL80211_TID_CONFIG_ATTR_NOACK] =
396 NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
6a21d16c
T
397 [NL80211_TID_CONFIG_ATTR_RETRY_SHORT] = NLA_POLICY_MIN(NLA_U8, 1),
398 [NL80211_TID_CONFIG_ATTR_RETRY_LONG] = NLA_POLICY_MIN(NLA_U8, 1),
ade274b2
T
399 [NL80211_TID_CONFIG_ATTR_AMPDU_CTRL] =
400 NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
04f7d142
T
401 [NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL] =
402 NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
33462e68
SM
403 [NL80211_TID_CONFIG_ATTR_AMSDU_CTRL] =
404 NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
9a5f6488
TC
405 [NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE] =
406 NLA_POLICY_MAX(NLA_U8, NL80211_TX_RATE_FIXED),
407 [NL80211_TID_CONFIG_ATTR_TX_RATE] =
408 NLA_POLICY_NESTED(nl80211_txattr_policy),
77f576de
T
409};
410
291c49de
AD
411static const struct nla_policy
412nl80211_fils_discovery_policy[NL80211_FILS_DISCOVERY_ATTR_MAX + 1] = {
413 [NL80211_FILS_DISCOVERY_ATTR_INT_MIN] = NLA_POLICY_MAX(NLA_U32, 10000),
414 [NL80211_FILS_DISCOVERY_ATTR_INT_MAX] = NLA_POLICY_MAX(NLA_U32, 10000),
272cd0e8
AD
415 [NL80211_FILS_DISCOVERY_ATTR_TMPL] =
416 NLA_POLICY_RANGE(NLA_BINARY,
417 NL80211_FILS_DISCOVERY_TMPL_MIN_LEN,
418 IEEE80211_MAX_DATA_LEN),
291c49de
AD
419};
420
7443dcd1
AD
421static const struct nla_policy
422nl80211_unsol_bcast_probe_resp_policy[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX + 1] = {
423 [NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT] = NLA_POLICY_MAX(NLA_U32, 20),
424 [NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL] = { .type = NLA_BINARY,
425 .len = IEEE80211_MAX_DATA_LEN }
426};
427
6bdb68ce
CH
428static const struct nla_policy
429sar_specs_policy[NL80211_SAR_ATTR_SPECS_MAX + 1] = {
430 [NL80211_SAR_ATTR_SPECS_POWER] = { .type = NLA_S32 },
431 [NL80211_SAR_ATTR_SPECS_RANGE_INDEX] = {.type = NLA_U32 },
432};
433
434static const struct nla_policy
435sar_policy[NL80211_SAR_ATTR_MAX + 1] = {
436 [NL80211_SAR_ATTR_TYPE] = NLA_POLICY_MAX(NLA_U32, NUM_NL80211_SAR_TYPE),
437 [NL80211_SAR_ATTR_SPECS] = NLA_POLICY_NESTED_ARRAY(sar_specs_policy),
438};
439
dc1e3cb8
JC
440static const struct nla_policy
441nl80211_mbssid_config_policy[NL80211_MBSSID_CONFIG_ATTR_MAX + 1] = {
442 [NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES] = NLA_POLICY_MIN(NLA_U8, 2),
443 [NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY] =
444 NLA_POLICY_MIN(NLA_U8, 1),
445 [NL80211_MBSSID_CONFIG_ATTR_INDEX] = { .type = NLA_U8 },
446 [NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX] = { .type = NLA_U32 },
447 [NL80211_MBSSID_CONFIG_ATTR_EMA] = { .type = NLA_FLAG },
448};
449
d15da2a2 450static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
6d4dd4ef 451 [0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD },
55682965
JB
452 [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
453 [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
079e24ed 454 .len = 20-1 },
31888487 455 [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED },
3d9d1d66 456
72bdcf34 457 [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
094d05dc 458 [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 },
2a38075c
AAL
459 [NL80211_ATTR_WIPHY_EDMG_CHANNELS] = NLA_POLICY_RANGE(NLA_U8,
460 NL80211_EDMG_CHANNELS_MIN,
461 NL80211_EDMG_CHANNELS_MAX),
462 [NL80211_ATTR_WIPHY_EDMG_BW_CONFIG] = NLA_POLICY_RANGE(NLA_U8,
463 NL80211_EDMG_BW_CONFIG_MIN,
464 NL80211_EDMG_BW_CONFIG_MAX),
465
3d9d1d66
JB
466 [NL80211_ATTR_CHANNEL_WIDTH] = { .type = NLA_U32 },
467 [NL80211_ATTR_CENTER_FREQ1] = { .type = NLA_U32 },
942ba88b 468 [NL80211_ATTR_CENTER_FREQ1_OFFSET] = NLA_POLICY_RANGE(NLA_U32, 0, 999),
3d9d1d66
JB
469 [NL80211_ATTR_CENTER_FREQ2] = { .type = NLA_U32 },
470
ab0d76f6
JB
471 [NL80211_ATTR_WIPHY_RETRY_SHORT] = NLA_POLICY_MIN(NLA_U8, 1),
472 [NL80211_ATTR_WIPHY_RETRY_LONG] = NLA_POLICY_MIN(NLA_U8, 1),
b9a5f8ca
JM
473 [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 },
474 [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 },
81077e82 475 [NL80211_ATTR_WIPHY_COVERAGE_CLASS] = { .type = NLA_U8 },
3057dbfd 476 [NL80211_ATTR_WIPHY_DYN_ACK] = { .type = NLA_FLAG },
55682965 477
ab0d76f6 478 [NL80211_ATTR_IFTYPE] = NLA_POLICY_MAX(NLA_U32, NL80211_IFTYPE_MAX),
55682965
JB
479 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
480 [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
41ade00f 481
c7721c05
JB
482 [NL80211_ATTR_MAC] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
483 [NL80211_ATTR_PREV_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
41ade00f 484
b9454e83 485 [NL80211_ATTR_KEY] = { .type = NLA_NESTED, },
41ade00f
JB
486 [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
487 .len = WLAN_MAX_KEY_LEN },
56be393f 488 [NL80211_ATTR_KEY_IDX] = NLA_POLICY_MAX(NLA_U8, 7),
41ade00f
JB
489 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
490 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
81962267 491 [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
ab0d76f6
JB
492 [NL80211_ATTR_KEY_TYPE] =
493 NLA_POLICY_MAX(NLA_U32, NUM_NL80211_KEYTYPES),
ed1b6cc7
JB
494
495 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
496 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
f88eb7c0
JB
497 [NL80211_ATTR_BEACON_HEAD] =
498 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_beacon_head,
499 IEEE80211_MAX_DATA_LEN),
3d7af878
JB
500 [NL80211_ATTR_BEACON_TAIL] =
501 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
502 IEEE80211_MAX_DATA_LEN),
ab0d76f6
JB
503 [NL80211_ATTR_STA_AID] =
504 NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
5727ef1b
JB
505 [NL80211_ATTR_STA_FLAGS] = { .type = NLA_NESTED },
506 [NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 },
507 [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
508 .len = NL80211_MAX_SUPP_RATES },
ab0d76f6
JB
509 [NL80211_ATTR_STA_PLINK_ACTION] =
510 NLA_POLICY_MAX(NLA_U8, NUM_NL80211_PLINK_ACTIONS - 1),
e96d1cd2
ARN
511 [NL80211_ATTR_STA_TX_POWER_SETTING] =
512 NLA_POLICY_RANGE(NLA_U8,
513 NL80211_TX_POWER_AUTOMATIC,
514 NL80211_TX_POWER_FIXED),
515 [NL80211_ATTR_STA_TX_POWER] = { .type = NLA_S16 },
5727ef1b 516 [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
0a9542ee 517 [NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ },
2ec600d6 518 [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
a4f606ea 519 .len = IEEE80211_MAX_MESH_ID_LEN },
1fab1b89 520 [NL80211_ATTR_MPATH_NEXT_HOP] = NLA_POLICY_ETH_ADDR_COMPAT,
9f1ba906 521
b2e1b302
LR
522 [NL80211_ATTR_REG_ALPHA2] = { .type = NLA_STRING, .len = 2 },
523 [NL80211_ATTR_REG_RULES] = { .type = NLA_NESTED },
524
9f1ba906
JM
525 [NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 },
526 [NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 },
527 [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 },
90c97a04
JM
528 [NL80211_ATTR_BSS_BASIC_RATES] = { .type = NLA_BINARY,
529 .len = NL80211_MAX_SUPP_RATES },
50b12f59 530 [NL80211_ATTR_BSS_HT_OPMODE] = { .type = NLA_U16 },
36aedc90 531
24bdd9f4 532 [NL80211_ATTR_MESH_CONFIG] = { .type = NLA_NESTED },
15d5dda6 533 [NL80211_ATTR_SUPPORT_MESH_AUTH] = { .type = NLA_FLAG },
93da9cc1 534
c7721c05 535 [NL80211_ATTR_HT_CAPABILITY] = NLA_POLICY_EXACT_LEN_WARN(NL80211_HT_CAPABILITY_LEN),
9aed3cc1
JM
536
537 [NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 },
3d7af878
JB
538 [NL80211_ATTR_IE] = NLA_POLICY_VALIDATE_FN(NLA_BINARY,
539 validate_ie_attr,
540 IEEE80211_MAX_DATA_LEN),
2a519311
JB
541 [NL80211_ATTR_SCAN_FREQUENCIES] = { .type = NLA_NESTED },
542 [NL80211_ATTR_SCAN_SSIDS] = { .type = NLA_NESTED },
636a5d36
JM
543
544 [NL80211_ATTR_SSID] = { .type = NLA_BINARY,
545 .len = IEEE80211_MAX_SSID_LEN },
546 [NL80211_ATTR_AUTH_TYPE] = { .type = NLA_U32 },
547 [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 },
04a773ad 548 [NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG },
1965c853 549 [NL80211_ATTR_TIMED_OUT] = { .type = NLA_FLAG },
ab0d76f6
JB
550 [NL80211_ATTR_USE_MFP] = NLA_POLICY_RANGE(NLA_U32,
551 NL80211_MFP_NO,
552 NL80211_MFP_OPTIONAL),
eccb8e8f
JB
553 [NL80211_ATTR_STA_FLAGS2] = {
554 .len = sizeof(struct nl80211_sta_flag_update),
555 },
3f77316c 556 [NL80211_ATTR_CONTROL_PORT] = { .type = NLA_FLAG },
c0692b8f
JB
557 [NL80211_ATTR_CONTROL_PORT_ETHERTYPE] = { .type = NLA_U16 },
558 [NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT] = { .type = NLA_FLAG },
64bf3d4b 559 [NL80211_ATTR_CONTROL_PORT_OVER_NL80211] = { .type = NLA_FLAG },
b23aa676 560 [NL80211_ATTR_PRIVACY] = { .type = NLA_FLAG },
ea750801 561 [NL80211_ATTR_STATUS_CODE] = { .type = NLA_U16 },
b23aa676
SO
562 [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 },
563 [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
463d0183 564 [NL80211_ATTR_PID] = { .type = NLA_U32 },
8b787643 565 [NL80211_ATTR_4ADDR] = { .type = NLA_U8 },
c7721c05 566 [NL80211_ATTR_PMKID] = NLA_POLICY_EXACT_LEN_WARN(WLAN_PMKID_LEN),
9588bbd5
JM
567 [NL80211_ATTR_DURATION] = { .type = NLA_U32 },
568 [NL80211_ATTR_COOKIE] = { .type = NLA_U64 },
13ae75b1 569 [NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED },
026331c4
JM
570 [NL80211_ATTR_FRAME] = { .type = NLA_BINARY,
571 .len = IEEE80211_MAX_DATA_LEN },
572 [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, },
ab0d76f6
JB
573 [NL80211_ATTR_PS_STATE] = NLA_POLICY_RANGE(NLA_U32,
574 NL80211_PS_DISABLED,
575 NL80211_PS_ENABLED),
d6dc1a38 576 [NL80211_ATTR_CQM] = { .type = NLA_NESTED, },
d5cdfacb 577 [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG },
fd8aaaf3 578 [NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 },
98d2ff8b
JO
579 [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 },
580 [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 },
2e161f78 581 [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 },
afe0cbf8
BR
582 [NL80211_ATTR_WIPHY_ANTENNA_TX] = { .type = NLA_U32 },
583 [NL80211_ATTR_WIPHY_ANTENNA_RX] = { .type = NLA_U32 },
885a46d0 584 [NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 },
f7ca38df 585 [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG },
dbd2fd65 586 [NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
ff1b6e69 587 [NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED },
ab0d76f6
JB
588 [NL80211_ATTR_STA_PLINK_STATE] =
589 NLA_POLICY_MAX(NLA_U8, NUM_NL80211_PLINK_STATES - 1),
056e9375
JK
590 [NL80211_ATTR_MEASUREMENT_DURATION] = { .type = NLA_U16 },
591 [NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY] = { .type = NLA_FLAG },
ab0d76f6
JB
592 [NL80211_ATTR_MESH_PEER_AID] =
593 NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
bbe6ad6d 594 [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 },
e5497d76 595 [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED },
34850ab2 596 [NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED },
ab0d76f6
JB
597 [NL80211_ATTR_HIDDEN_SSID] =
598 NLA_POLICY_RANGE(NLA_U32,
599 NL80211_HIDDEN_SSID_NOT_IN_USE,
600 NL80211_HIDDEN_SSID_ZERO_CONTENTS),
3d7af878
JB
601 [NL80211_ATTR_IE_PROBE_RESP] =
602 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
603 IEEE80211_MAX_DATA_LEN),
604 [NL80211_ATTR_IE_ASSOC_RESP] =
605 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
606 IEEE80211_MAX_DATA_LEN),
f4b34b55 607 [NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG },
a1f1c21c 608 [NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED },
e9f935e3 609 [NL80211_ATTR_TX_NO_CCK_RATE] = { .type = NLA_FLAG },
109086ce
AN
610 [NL80211_ATTR_TDLS_ACTION] = { .type = NLA_U8 },
611 [NL80211_ATTR_TDLS_DIALOG_TOKEN] = { .type = NLA_U8 },
612 [NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 },
613 [NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG },
614 [NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG },
31fa97c5 615 [NL80211_ATTR_TDLS_INITIATOR] = { .type = NLA_FLAG },
e247bd90 616 [NL80211_ATTR_DONT_WAIT_FOR_ACK] = { .type = NLA_FLAG },
00f740e1
AN
617 [NL80211_ATTR_PROBE_RESP] = { .type = NLA_BINARY,
618 .len = IEEE80211_MAX_DATA_LEN },
8b60b078 619 [NL80211_ATTR_DFS_REGION] = { .type = NLA_U8 },
7e7c8926
BG
620 [NL80211_ATTR_DISABLE_HT] = { .type = NLA_FLAG },
621 [NL80211_ATTR_HT_CAPABILITY_MASK] = {
622 .len = NL80211_HT_CAPABILITY_LEN
623 },
1d9d9213 624 [NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 },
1b658f11 625 [NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 },
4486ea98 626 [NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
89a54e48 627 [NL80211_ATTR_WDEV] = { .type = NLA_U64 },
57b5ce07 628 [NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },
cb9abd48
JB
629
630 /* need to include at least Auth Transaction and Status Code */
631 [NL80211_ATTR_AUTH_DATA] = NLA_POLICY_MIN_LEN(4),
632
c7721c05 633 [NL80211_ATTR_VHT_CAPABILITY] = NLA_POLICY_EXACT_LEN_WARN(NL80211_VHT_CAPABILITY_LEN),
ed473771 634 [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
ab0d76f6
JB
635 [NL80211_ATTR_P2P_CTWINDOW] = NLA_POLICY_MAX(NLA_U8, 127),
636 [NL80211_ATTR_P2P_OPPPS] = NLA_POLICY_MAX(NLA_U8, 1),
637 [NL80211_ATTR_LOCAL_MESH_POWER_MODE] =
638 NLA_POLICY_RANGE(NLA_U32,
639 NL80211_MESH_POWER_UNKNOWN + 1,
640 NL80211_MESH_POWER_MAX),
77765eaf
VT
641 [NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 },
642 [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED },
9d62a986
JM
643 [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 },
644 [NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, },
3713b4e3 645 [NL80211_ATTR_SPLIT_WIPHY_DUMP] = { .type = NLA_FLAG, },
ee2aca34
JB
646 [NL80211_ATTR_DISABLE_VHT] = { .type = NLA_FLAG },
647 [NL80211_ATTR_VHT_CAPABILITY_MASK] = {
648 .len = NL80211_VHT_CAPABILITY_LEN,
649 },
355199e0
JM
650 [NL80211_ATTR_MDID] = { .type = NLA_U16 },
651 [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,
652 .len = IEEE80211_MAX_DATA_LEN },
0e1a1d85 653 [NL80211_ATTR_CRIT_PROT_ID] = { .type = NLA_U16 },
cb9abd48
JB
654 [NL80211_ATTR_MAX_CRIT_PROT_DURATION] =
655 NLA_POLICY_MAX(NLA_U16, NL80211_CRIT_PROTO_MAX_DURATION),
ab0d76f6
JB
656 [NL80211_ATTR_PEER_AID] =
657 NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
16ef1fe2
SW
658 [NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 },
659 [NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG },
660 [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED },
00c207ed
JC
661 [NL80211_ATTR_CNTDWN_OFFS_BEACON] = { .type = NLA_BINARY },
662 [NL80211_ATTR_CNTDWN_OFFS_PRESP] = { .type = NLA_BINARY },
cb9abd48 663 [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = NLA_POLICY_MIN_LEN(2),
c8b82802
JB
664 /*
665 * The value of the Length field of the Supported Operating
666 * Classes element is between 2 and 253.
667 */
668 [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] =
669 NLA_POLICY_RANGE(NLA_BINARY, 2, 253),
5336fa88 670 [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG },
60f4a7b1 671 [NL80211_ATTR_OPMODE_NOTIF] = { .type = NLA_U8 },
ad7e718c
JB
672 [NL80211_ATTR_VENDOR_ID] = { .type = NLA_U32 },
673 [NL80211_ATTR_VENDOR_SUBCMD] = { .type = NLA_U32 },
674 [NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY },
c8b82802
JB
675 [NL80211_ATTR_QOS_MAP] = NLA_POLICY_RANGE(NLA_BINARY,
676 IEEE80211_QOS_MAP_LEN_MIN,
677 IEEE80211_QOS_MAP_LEN_MAX),
c7721c05 678 [NL80211_ATTR_MAC_HINT] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
1df4a510 679 [NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 },
df942e7b 680 [NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 },
18e5ca65 681 [NL80211_ATTR_SOCKET_OWNER] = { .type = NLA_FLAG },
34d22ce2 682 [NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY },
bab5ab7d 683 [NL80211_ATTR_USE_RRM] = { .type = NLA_FLAG },
ab0d76f6
JB
684 [NL80211_ATTR_TSID] = NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_TIDS - 1),
685 [NL80211_ATTR_USER_PRIO] =
686 NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_UPS - 1),
960d01ac 687 [NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 },
18998c38 688 [NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 },
5cde05c6 689 [NL80211_ATTR_OPER_CLASS] = { .type = NLA_U8 },
c7721c05 690 [NL80211_ATTR_MAC_MASK] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
1bdd716c 691 [NL80211_ATTR_WIPHY_SELF_MANAGED_REG] = { .type = NLA_FLAG },
4b681c82 692 [NL80211_ATTR_NETNS_FD] = { .type = NLA_U32 },
9c748934 693 [NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 },
05050753 694 [NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG },
34d50519 695 [NL80211_ATTR_PBSS] = { .type = NLA_FLAG },
38de03d2 696 [NL80211_ATTR_BSS_SELECT] = { .type = NLA_NESTED },
ab0d76f6
JB
697 [NL80211_ATTR_STA_SUPPORT_P2P_PS] =
698 NLA_POLICY_MAX(NLA_U8, NUM_NL80211_P2P_PS_STATUS - 1),
c6e6a0c8
AE
699 [NL80211_ATTR_MU_MIMO_GROUP_DATA] = {
700 .len = VHT_MUMIMO_GROUPS_DATA_LEN
701 },
c7721c05 702 [NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
ab0d76f6 703 [NL80211_ATTR_NAN_MASTER_PREF] = NLA_POLICY_MIN(NLA_U8, 1),
8585989d 704 [NL80211_ATTR_BANDS] = { .type = NLA_U32 },
a442b761 705 [NL80211_ATTR_NAN_FUNC] = { .type = NLA_NESTED },
348bd456
JM
706 [NL80211_ATTR_FILS_KEK] = { .type = NLA_BINARY,
707 .len = FILS_MAX_KEK_LEN },
c7721c05 708 [NL80211_ATTR_FILS_NONCES] = NLA_POLICY_EXACT_LEN_WARN(2 * FILS_NONCE_LEN),
ce0ce13a 709 [NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED] = { .type = NLA_FLAG, },
c7721c05 710 [NL80211_ATTR_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
bf95ecdb 711 [NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] = { .type = NLA_S8 },
712 [NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST] = {
713 .len = sizeof(struct nl80211_bss_select_rssi_adjust)
714 },
3093ebbe 715 [NL80211_ATTR_TIMEOUT_REASON] = { .type = NLA_U32 },
a3caf744
VK
716 [NL80211_ATTR_FILS_ERP_USERNAME] = { .type = NLA_BINARY,
717 .len = FILS_ERP_MAX_USERNAME_LEN },
718 [NL80211_ATTR_FILS_ERP_REALM] = { .type = NLA_BINARY,
719 .len = FILS_ERP_MAX_REALM_LEN },
720 [NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] = { .type = NLA_U16 },
721 [NL80211_ATTR_FILS_ERP_RRK] = { .type = NLA_BINARY,
722 .len = FILS_ERP_MAX_RRK_LEN },
c7721c05 723 [NL80211_ATTR_FILS_CACHE_ID] = NLA_POLICY_EXACT_LEN_WARN(2),
a3caf744 724 [NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN },
cb9abd48 725 [NL80211_ATTR_PMKR0_NAME] = NLA_POLICY_EXACT_LEN(WLAN_PMK_NAME_LEN),
ca986ad9 726 [NL80211_ATTR_SCHED_SCAN_MULTI] = { .type = NLA_FLAG },
40cbfa90 727 [NL80211_ATTR_EXTERNAL_AUTH_SUPPORT] = { .type = NLA_FLAG },
52539ca8
THJ
728
729 [NL80211_ATTR_TXQ_LIMIT] = { .type = NLA_U32 },
730 [NL80211_ATTR_TXQ_MEMORY_LIMIT] = { .type = NLA_U32 },
731 [NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 },
c8b82802
JB
732 [NL80211_ATTR_HE_CAPABILITY] =
733 NLA_POLICY_RANGE(NLA_BINARY,
734 NL80211_HE_MIN_CAPABILITY_LEN,
735 NL80211_HE_MAX_CAPABILITY_LEN),
0e012b4e
JB
736 [NL80211_ATTR_FTM_RESPONDER] =
737 NLA_POLICY_NESTED(nl80211_ftm_responder_policy),
9bb7e0f2
JB
738 [NL80211_ATTR_TIMEOUT] = NLA_POLICY_MIN(NLA_U32, 1),
739 [NL80211_ATTR_PEER_MEASUREMENTS] =
23323289 740 NLA_POLICY_NESTED(nl80211_pmsr_attr_policy),
36647055 741 [NL80211_ATTR_AIRTIME_WEIGHT] = NLA_POLICY_MIN(NLA_U16, 1),
26f7044e
CHH
742 [NL80211_ATTR_SAE_PASSWORD] = { .type = NLA_BINARY,
743 .len = SAE_PASSWORD_MAX_LEN },
a0de1ca3 744 [NL80211_ATTR_TWT_RESPONDER] = { .type = NLA_FLAG },
796e90f4 745 [NL80211_ATTR_HE_OBSS_PD] = NLA_POLICY_NESTED(he_obss_pd_policy),
14f34e36 746 [NL80211_ATTR_VLAN_ID] = NLA_POLICY_RANGE(NLA_U16, 1, VLAN_N_VID - 2),
5c5e52d1 747 [NL80211_ATTR_HE_BSS_COLOR] = NLA_POLICY_NESTED(he_bss_color_policy),
77f576de
T
748 [NL80211_ATTR_TID_CONFIG] =
749 NLA_POLICY_NESTED_ARRAY(nl80211_tid_config_attr_policy),
5631d96a 750 [NL80211_ATTR_CONTROL_PORT_NO_PREAUTH] = { .type = NLA_FLAG },
7fc82af8
VJ
751 [NL80211_ATTR_PMK_LIFETIME] = NLA_POLICY_MIN(NLA_U32, 1),
752 [NL80211_ATTR_PMK_REAUTH_THRESHOLD] = NLA_POLICY_RANGE(NLA_U8, 1, 100),
9dba48a6 753 [NL80211_ATTR_RECEIVE_MULTICAST] = { .type = NLA_FLAG },
942ba88b 754 [NL80211_ATTR_WIPHY_FREQ_OFFSET] = NLA_POLICY_RANGE(NLA_U32, 0, 999),
2032f3b2 755 [NL80211_ATTR_SCAN_FREQ_KHZ] = { .type = NLA_NESTED },
8140860c
JB
756 [NL80211_ATTR_HE_6GHZ_CAPABILITY] =
757 NLA_POLICY_EXACT_LEN(sizeof(struct ieee80211_he_6ghz_capa)),
291c49de
AD
758 [NL80211_ATTR_FILS_DISCOVERY] =
759 NLA_POLICY_NESTED(nl80211_fils_discovery_policy),
7443dcd1
AD
760 [NL80211_ATTR_UNSOL_BCAST_PROBE_RESP] =
761 NLA_POLICY_NESTED(nl80211_unsol_bcast_probe_resp_policy),
d2b7588a
TP
762 [NL80211_ATTR_S1G_CAPABILITY] =
763 NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN),
764 [NL80211_ATTR_S1G_CAPABILITY_MASK] =
765 NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN),
9f0ffa41
RD
766 [NL80211_ATTR_SAE_PWE] =
767 NLA_POLICY_RANGE(NLA_U8, NL80211_SAE_PWE_HUNT_AND_PECK,
768 NL80211_SAE_PWE_BOTH),
3bb02143 769 [NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT },
6bdb68ce 770 [NL80211_ATTR_SAR_SPEC] = NLA_POLICY_NESTED(sar_policy),
b6db0f89 771 [NL80211_ATTR_DISABLE_HE] = { .type = NLA_FLAG },
0d2ab3ae
JC
772 [NL80211_ATTR_OBSS_COLOR_BITMAP] = { .type = NLA_U64 },
773 [NL80211_ATTR_COLOR_CHANGE_COUNT] = { .type = NLA_U8 },
774 [NL80211_ATTR_COLOR_CHANGE_COLOR] = { .type = NLA_U8 },
775 [NL80211_ATTR_COLOR_CHANGE_ELEMS] = NLA_POLICY_NESTED(nl80211_policy),
dc1e3cb8
JC
776 [NL80211_ATTR_MBSSID_CONFIG] =
777 NLA_POLICY_NESTED(nl80211_mbssid_config_policy),
778 [NL80211_ATTR_MBSSID_ELEMS] = { .type = NLA_NESTED },
55682965
JB
779};
780
e31b8213 781/* policy for the key attributes */
b54452b0 782static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = {
fffd0934 783 [NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN },
b9454e83
JB
784 [NL80211_KEY_IDX] = { .type = NLA_U8 },
785 [NL80211_KEY_CIPHER] = { .type = NLA_U32 },
81962267 786 [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
b9454e83
JB
787 [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG },
788 [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
ab0d76f6 789 [NL80211_KEY_TYPE] = NLA_POLICY_MAX(NLA_U32, NUM_NL80211_KEYTYPES - 1),
dbd2fd65 790 [NL80211_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
6cdd3979 791 [NL80211_KEY_MODE] = NLA_POLICY_RANGE(NLA_U8, 0, NL80211_KEY_SET_TX),
dbd2fd65
JB
792};
793
794/* policy for the key default flags */
795static const struct nla_policy
796nl80211_key_default_policy[NUM_NL80211_KEY_DEFAULT_TYPES] = {
797 [NL80211_KEY_DEFAULT_TYPE_UNICAST] = { .type = NLA_FLAG },
798 [NL80211_KEY_DEFAULT_TYPE_MULTICAST] = { .type = NLA_FLAG },
b9454e83
JB
799};
800
f83ace3b 801#ifdef CONFIG_PM
ff1b6e69
JB
802/* policy for WoWLAN attributes */
803static const struct nla_policy
804nl80211_wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = {
805 [NL80211_WOWLAN_TRIG_ANY] = { .type = NLA_FLAG },
806 [NL80211_WOWLAN_TRIG_DISCONNECT] = { .type = NLA_FLAG },
807 [NL80211_WOWLAN_TRIG_MAGIC_PKT] = { .type = NLA_FLAG },
808 [NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .type = NLA_NESTED },
77dbbb13
JB
809 [NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE] = { .type = NLA_FLAG },
810 [NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST] = { .type = NLA_FLAG },
811 [NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE] = { .type = NLA_FLAG },
812 [NL80211_WOWLAN_TRIG_RFKILL_RELEASE] = { .type = NLA_FLAG },
2a0e047e 813 [NL80211_WOWLAN_TRIG_TCP_CONNECTION] = { .type = NLA_NESTED },
8cd4d456 814 [NL80211_WOWLAN_TRIG_NET_DETECT] = { .type = NLA_NESTED },
2a0e047e
JB
815};
816
817static const struct nla_policy
818nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = {
819 [NL80211_WOWLAN_TCP_SRC_IPV4] = { .type = NLA_U32 },
820 [NL80211_WOWLAN_TCP_DST_IPV4] = { .type = NLA_U32 },
c7721c05 821 [NL80211_WOWLAN_TCP_DST_MAC] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
2a0e047e
JB
822 [NL80211_WOWLAN_TCP_SRC_PORT] = { .type = NLA_U16 },
823 [NL80211_WOWLAN_TCP_DST_PORT] = { .type = NLA_U16 },
bc043585 824 [NL80211_WOWLAN_TCP_DATA_PAYLOAD] = NLA_POLICY_MIN_LEN(1),
2a0e047e
JB
825 [NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ] = {
826 .len = sizeof(struct nl80211_wowlan_tcp_data_seq)
827 },
828 [NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN] = {
829 .len = sizeof(struct nl80211_wowlan_tcp_data_token)
830 },
831 [NL80211_WOWLAN_TCP_DATA_INTERVAL] = { .type = NLA_U32 },
bc043585
JB
832 [NL80211_WOWLAN_TCP_WAKE_PAYLOAD] = NLA_POLICY_MIN_LEN(1),
833 [NL80211_WOWLAN_TCP_WAKE_MASK] = NLA_POLICY_MIN_LEN(1),
ff1b6e69 834};
f83ace3b 835#endif /* CONFIG_PM */
ff1b6e69 836
be29b99a
AK
837/* policy for coalesce rule attributes */
838static const struct nla_policy
839nl80211_coalesce_policy[NUM_NL80211_ATTR_COALESCE_RULE] = {
840 [NL80211_ATTR_COALESCE_RULE_DELAY] = { .type = NLA_U32 },
ab0d76f6
JB
841 [NL80211_ATTR_COALESCE_RULE_CONDITION] =
842 NLA_POLICY_RANGE(NLA_U32,
843 NL80211_COALESCE_CONDITION_MATCH,
844 NL80211_COALESCE_CONDITION_NO_MATCH),
be29b99a
AK
845 [NL80211_ATTR_COALESCE_RULE_PKT_PATTERN] = { .type = NLA_NESTED },
846};
847
e5497d76
JB
848/* policy for GTK rekey offload attributes */
849static const struct nla_policy
850nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = {
093a48d2
NE
851 [NL80211_REKEY_DATA_KEK] = {
852 .type = NLA_BINARY,
853 .len = NL80211_KEK_EXT_LEN
854 },
855 [NL80211_REKEY_DATA_KCK] = {
856 .type = NLA_BINARY,
857 .len = NL80211_KCK_EXT_LEN
858 },
cb9abd48 859 [NL80211_REKEY_DATA_REPLAY_CTR] = NLA_POLICY_EXACT_LEN(NL80211_REPLAY_CTR_LEN),
093a48d2 860 [NL80211_REKEY_DATA_AKM] = { .type = NLA_U32 },
e5497d76
JB
861};
862
1e1b11b6 863static const struct nla_policy
864nl80211_match_band_rssi_policy[NUM_NL80211_BANDS] = {
865 [NL80211_BAND_2GHZ] = { .type = NLA_S32 },
866 [NL80211_BAND_5GHZ] = { .type = NLA_S32 },
e548a1c3 867 [NL80211_BAND_6GHZ] = { .type = NLA_S32 },
1e1b11b6 868 [NL80211_BAND_60GHZ] = { .type = NLA_S32 },
869};
870
a1f1c21c
LC
871static const struct nla_policy
872nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = {
4a4ab0d7 873 [NL80211_SCHED_SCAN_MATCH_ATTR_SSID] = { .type = NLA_BINARY,
a1f1c21c 874 .len = IEEE80211_MAX_SSID_LEN },
c7721c05 875 [NL80211_SCHED_SCAN_MATCH_ATTR_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
88e920b4 876 [NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] = { .type = NLA_U32 },
1e1b11b6 877 [NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI] =
878 NLA_POLICY_NESTED(nl80211_match_band_rssi_policy),
a1f1c21c
LC
879};
880
3b06d277
AS
881static const struct nla_policy
882nl80211_plan_policy[NL80211_SCHED_SCAN_PLAN_MAX + 1] = {
883 [NL80211_SCHED_SCAN_PLAN_INTERVAL] = { .type = NLA_U32 },
884 [NL80211_SCHED_SCAN_PLAN_ITERATIONS] = { .type = NLA_U32 },
885};
886
38de03d2
AS
887static const struct nla_policy
888nl80211_bss_select_policy[NL80211_BSS_SELECT_ATTR_MAX + 1] = {
889 [NL80211_BSS_SELECT_ATTR_RSSI] = { .type = NLA_FLAG },
890 [NL80211_BSS_SELECT_ATTR_BAND_PREF] = { .type = NLA_U32 },
891 [NL80211_BSS_SELECT_ATTR_RSSI_ADJUST] = {
892 .len = sizeof(struct nl80211_bss_select_rssi_adjust)
893 },
894};
895
a442b761
AB
896/* policy for NAN function attributes */
897static const struct nla_policy
898nl80211_nan_func_policy[NL80211_NAN_FUNC_ATTR_MAX + 1] = {
cb9abd48
JB
899 [NL80211_NAN_FUNC_TYPE] =
900 NLA_POLICY_MAX(NLA_U8, NL80211_NAN_FUNC_MAX_TYPE),
0a27844c 901 [NL80211_NAN_FUNC_SERVICE_ID] = {
a442b761
AB
902 .len = NL80211_NAN_FUNC_SERVICE_ID_LEN },
903 [NL80211_NAN_FUNC_PUBLISH_TYPE] = { .type = NLA_U8 },
904 [NL80211_NAN_FUNC_PUBLISH_BCAST] = { .type = NLA_FLAG },
905 [NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE] = { .type = NLA_FLAG },
906 [NL80211_NAN_FUNC_FOLLOW_UP_ID] = { .type = NLA_U8 },
907 [NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID] = { .type = NLA_U8 },
c7721c05 908 [NL80211_NAN_FUNC_FOLLOW_UP_DEST] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
a442b761
AB
909 [NL80211_NAN_FUNC_CLOSE_RANGE] = { .type = NLA_FLAG },
910 [NL80211_NAN_FUNC_TTL] = { .type = NLA_U32 },
911 [NL80211_NAN_FUNC_SERVICE_INFO] = { .type = NLA_BINARY,
912 .len = NL80211_NAN_FUNC_SERVICE_SPEC_INFO_MAX_LEN },
913 [NL80211_NAN_FUNC_SRF] = { .type = NLA_NESTED },
914 [NL80211_NAN_FUNC_RX_MATCH_FILTER] = { .type = NLA_NESTED },
915 [NL80211_NAN_FUNC_TX_MATCH_FILTER] = { .type = NLA_NESTED },
916 [NL80211_NAN_FUNC_INSTANCE_ID] = { .type = NLA_U8 },
917 [NL80211_NAN_FUNC_TERM_REASON] = { .type = NLA_U8 },
918};
919
920/* policy for Service Response Filter attributes */
921static const struct nla_policy
922nl80211_nan_srf_policy[NL80211_NAN_SRF_ATTR_MAX + 1] = {
923 [NL80211_NAN_SRF_INCLUDE] = { .type = NLA_FLAG },
924 [NL80211_NAN_SRF_BF] = { .type = NLA_BINARY,
925 .len = NL80211_NAN_FUNC_SRF_MAX_LEN },
926 [NL80211_NAN_SRF_BF_IDX] = { .type = NLA_U8 },
927 [NL80211_NAN_SRF_MAC_ADDRS] = { .type = NLA_NESTED },
928};
929
ad670233
PX
930/* policy for packet pattern attributes */
931static const struct nla_policy
932nl80211_packet_pattern_policy[MAX_NL80211_PKTPAT + 1] = {
933 [NL80211_PKTPAT_MASK] = { .type = NLA_BINARY, },
934 [NL80211_PKTPAT_PATTERN] = { .type = NLA_BINARY, },
935 [NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 },
936};
937
9bb7e0f2
JB
938int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
939 struct cfg80211_registered_device **rdev,
940 struct wireless_dev **wdev)
a043897a 941{
97990a06 942 int err;
a043897a 943
97990a06 944 if (!cb->args[0]) {
50508d94
JB
945 struct nlattr **attrbuf;
946
947 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf),
948 GFP_KERNEL);
949 if (!attrbuf)
950 return -ENOMEM;
951
8cb08174
JB
952 err = nlmsg_parse_deprecated(cb->nlh,
953 GENL_HDRLEN + nl80211_fam.hdrsize,
50508d94 954 attrbuf, nl80211_fam.maxattr,
8cb08174 955 nl80211_policy, NULL);
50508d94
JB
956 if (err) {
957 kfree(attrbuf);
ea90e0dc 958 return err;
50508d94 959 }
67748893 960
a05829a7
JB
961 rtnl_lock();
962 *wdev = __cfg80211_wdev_from_attrs(NULL, sock_net(cb->skb->sk),
50508d94
JB
963 attrbuf);
964 kfree(attrbuf);
a05829a7
JB
965 if (IS_ERR(*wdev)) {
966 rtnl_unlock();
ea90e0dc 967 return PTR_ERR(*wdev);
a05829a7 968 }
f26cbf40 969 *rdev = wiphy_to_rdev((*wdev)->wiphy);
a05829a7
JB
970 mutex_lock(&(*rdev)->wiphy.mtx);
971 rtnl_unlock();
c319d50b
JB
972 /* 0 is the first index - add 1 to parse only once */
973 cb->args[0] = (*rdev)->wiphy_idx + 1;
97990a06
JB
974 cb->args[1] = (*wdev)->identifier;
975 } else {
c319d50b 976 /* subtract the 1 again here */
a05829a7 977 struct wiphy *wiphy;
97990a06 978 struct wireless_dev *tmp;
67748893 979
a05829a7
JB
980 rtnl_lock();
981 wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
982 if (!wiphy) {
983 rtnl_unlock();
ea90e0dc 984 return -ENODEV;
a05829a7 985 }
f26cbf40 986 *rdev = wiphy_to_rdev(wiphy);
97990a06 987 *wdev = NULL;
67748893 988
53873f13 989 list_for_each_entry(tmp, &(*rdev)->wiphy.wdev_list, list) {
97990a06
JB
990 if (tmp->identifier == cb->args[1]) {
991 *wdev = tmp;
992 break;
993 }
994 }
67748893 995
a05829a7
JB
996 if (!*wdev) {
997 rtnl_unlock();
ea90e0dc 998 return -ENODEV;
a05829a7
JB
999 }
1000 mutex_lock(&(*rdev)->wiphy.mtx);
1001 rtnl_unlock();
67748893
JB
1002 }
1003
67748893 1004 return 0;
67748893
JB
1005}
1006
55682965 1007/* message building helper */
9bb7e0f2
JB
1008void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
1009 int flags, u8 cmd)
55682965
JB
1010{
1011 /* since there is no private header just add the generic one */
15e47304 1012 return genlmsg_put(skb, portid, seq, &nl80211_fam, flags, cmd);
55682965
JB
1013}
1014
50f32718
HD
1015static int nl80211_msg_put_wmm_rules(struct sk_buff *msg,
1016 const struct ieee80211_reg_rule *rule)
1017{
1018 int j;
1019 struct nlattr *nl_wmm_rules =
ae0be8de 1020 nla_nest_start_noflag(msg, NL80211_FREQUENCY_ATTR_WMM);
50f32718
HD
1021
1022 if (!nl_wmm_rules)
1023 goto nla_put_failure;
1024
1025 for (j = 0; j < IEEE80211_NUM_ACS; j++) {
ae0be8de 1026 struct nlattr *nl_wmm_rule = nla_nest_start_noflag(msg, j);
50f32718
HD
1027
1028 if (!nl_wmm_rule)
1029 goto nla_put_failure;
1030
1031 if (nla_put_u16(msg, NL80211_WMMR_CW_MIN,
38cb87ee 1032 rule->wmm_rule.client[j].cw_min) ||
50f32718 1033 nla_put_u16(msg, NL80211_WMMR_CW_MAX,
38cb87ee 1034 rule->wmm_rule.client[j].cw_max) ||
50f32718 1035 nla_put_u8(msg, NL80211_WMMR_AIFSN,
38cb87ee 1036 rule->wmm_rule.client[j].aifsn) ||
d3c89bbc
HD
1037 nla_put_u16(msg, NL80211_WMMR_TXOP,
1038 rule->wmm_rule.client[j].cot))
50f32718
HD
1039 goto nla_put_failure;
1040
1041 nla_nest_end(msg, nl_wmm_rule);
1042 }
1043 nla_nest_end(msg, nl_wmm_rules);
1044
1045 return 0;
1046
1047nla_put_failure:
1048 return -ENOBUFS;
1049}
1050
1051static int nl80211_msg_put_channel(struct sk_buff *msg, struct wiphy *wiphy,
cdc89b97
JB
1052 struct ieee80211_channel *chan,
1053 bool large)
5dab3b8a 1054{
ea077c1c
RL
1055 /* Some channels must be completely excluded from the
1056 * list to protect old user-space tools from breaking
1057 */
1058 if (!large && chan->flags &
1059 (IEEE80211_CHAN_NO_10MHZ | IEEE80211_CHAN_NO_20MHZ))
1060 return 0;
f8d504ca
JB
1061 if (!large && chan->freq_offset)
1062 return 0;
ea077c1c 1063
9360ffd1
DM
1064 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_FREQ,
1065 chan->center_freq))
1066 goto nla_put_failure;
5dab3b8a 1067
942ba88b
TP
1068 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_OFFSET, chan->freq_offset))
1069 goto nla_put_failure;
1070
9360ffd1
DM
1071 if ((chan->flags & IEEE80211_CHAN_DISABLED) &&
1072 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_DISABLED))
1073 goto nla_put_failure;
8fe02e16
LR
1074 if (chan->flags & IEEE80211_CHAN_NO_IR) {
1075 if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IR))
1076 goto nla_put_failure;
1077 if (nla_put_flag(msg, __NL80211_FREQUENCY_ATTR_NO_IBSS))
1078 goto nla_put_failure;
1079 }
cdc89b97
JB
1080 if (chan->flags & IEEE80211_CHAN_RADAR) {
1081 if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
1082 goto nla_put_failure;
1083 if (large) {
1084 u32 time;
1085
1086 time = elapsed_jiffies_msecs(chan->dfs_state_entered);
1087
1088 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_STATE,
1089 chan->dfs_state))
1090 goto nla_put_failure;
1091 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME,
1092 time))
1093 goto nla_put_failure;
089027e5
JD
1094 if (nla_put_u32(msg,
1095 NL80211_FREQUENCY_ATTR_DFS_CAC_TIME,
1096 chan->dfs_cac_ms))
1097 goto nla_put_failure;
cdc89b97
JB
1098 }
1099 }
5dab3b8a 1100
fe1abafd
JB
1101 if (large) {
1102 if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) &&
1103 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS))
1104 goto nla_put_failure;
1105 if ((chan->flags & IEEE80211_CHAN_NO_HT40PLUS) &&
1106 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_PLUS))
1107 goto nla_put_failure;
1108 if ((chan->flags & IEEE80211_CHAN_NO_80MHZ) &&
1109 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_80MHZ))
1110 goto nla_put_failure;
1111 if ((chan->flags & IEEE80211_CHAN_NO_160MHZ) &&
1112 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_160MHZ))
1113 goto nla_put_failure;
570dbde1
DS
1114 if ((chan->flags & IEEE80211_CHAN_INDOOR_ONLY) &&
1115 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_INDOOR_ONLY))
1116 goto nla_put_failure;
06f207fc
AN
1117 if ((chan->flags & IEEE80211_CHAN_IR_CONCURRENT) &&
1118 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_IR_CONCURRENT))
570dbde1 1119 goto nla_put_failure;
ea077c1c
RL
1120 if ((chan->flags & IEEE80211_CHAN_NO_20MHZ) &&
1121 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_20MHZ))
1122 goto nla_put_failure;
1123 if ((chan->flags & IEEE80211_CHAN_NO_10MHZ) &&
1124 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_10MHZ))
1125 goto nla_put_failure;
1e61d82c
HD
1126 if ((chan->flags & IEEE80211_CHAN_NO_HE) &&
1127 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HE))
1128 goto nla_put_failure;
d65a9770
TP
1129 if ((chan->flags & IEEE80211_CHAN_1MHZ) &&
1130 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_1MHZ))
1131 goto nla_put_failure;
1132 if ((chan->flags & IEEE80211_CHAN_2MHZ) &&
1133 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_2MHZ))
1134 goto nla_put_failure;
1135 if ((chan->flags & IEEE80211_CHAN_4MHZ) &&
1136 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_4MHZ))
1137 goto nla_put_failure;
1138 if ((chan->flags & IEEE80211_CHAN_8MHZ) &&
1139 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_8MHZ))
1140 goto nla_put_failure;
1141 if ((chan->flags & IEEE80211_CHAN_16MHZ) &&
1142 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_16MHZ))
1143 goto nla_put_failure;
fe1abafd
JB
1144 }
1145
9360ffd1
DM
1146 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
1147 DBM_TO_MBM(chan->max_power)))
1148 goto nla_put_failure;
5dab3b8a 1149
50f32718
HD
1150 if (large) {
1151 const struct ieee80211_reg_rule *rule =
b88d26d9 1152 freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq));
50f32718 1153
38cb87ee 1154 if (!IS_ERR_OR_NULL(rule) && rule->has_wmm) {
50f32718
HD
1155 if (nl80211_msg_put_wmm_rules(msg, rule))
1156 goto nla_put_failure;
1157 }
1158 }
1159
5dab3b8a
LR
1160 return 0;
1161
1162 nla_put_failure:
1163 return -ENOBUFS;
1164}
1165
52539ca8
THJ
1166static bool nl80211_put_txq_stats(struct sk_buff *msg,
1167 struct cfg80211_txq_stats *txqstats,
1168 int attrtype)
1169{
1170 struct nlattr *txqattr;
1171
1172#define PUT_TXQVAL_U32(attr, memb) do { \
1173 if (txqstats->filled & BIT(NL80211_TXQ_STATS_ ## attr) && \
1174 nla_put_u32(msg, NL80211_TXQ_STATS_ ## attr, txqstats->memb)) \
1175 return false; \
1176 } while (0)
1177
ae0be8de 1178 txqattr = nla_nest_start_noflag(msg, attrtype);
52539ca8
THJ
1179 if (!txqattr)
1180 return false;
1181
1182 PUT_TXQVAL_U32(BACKLOG_BYTES, backlog_bytes);
1183 PUT_TXQVAL_U32(BACKLOG_PACKETS, backlog_packets);
1184 PUT_TXQVAL_U32(FLOWS, flows);
1185 PUT_TXQVAL_U32(DROPS, drops);
1186 PUT_TXQVAL_U32(ECN_MARKS, ecn_marks);
1187 PUT_TXQVAL_U32(OVERLIMIT, overlimit);
1188 PUT_TXQVAL_U32(OVERMEMORY, overmemory);
1189 PUT_TXQVAL_U32(COLLISIONS, collisions);
1190 PUT_TXQVAL_U32(TX_BYTES, tx_bytes);
1191 PUT_TXQVAL_U32(TX_PACKETS, tx_packets);
1192 PUT_TXQVAL_U32(MAX_FLOWS, max_flows);
1193 nla_nest_end(msg, txqattr);
1194
1195#undef PUT_TXQVAL_U32
1196 return true;
1197}
1198
55682965
JB
1199/* netlink command implementations */
1200
b9454e83
JB
1201struct key_parse {
1202 struct key_params p;
1203 int idx;
e31b8213 1204 int type;
56be393f 1205 bool def, defmgmt, defbeacon;
dbd2fd65 1206 bool def_uni, def_multi;
b9454e83
JB
1207};
1208
768075eb
JB
1209static int nl80211_parse_key_new(struct genl_info *info, struct nlattr *key,
1210 struct key_parse *k)
b9454e83
JB
1211{
1212 struct nlattr *tb[NL80211_KEY_MAX + 1];
8cb08174
JB
1213 int err = nla_parse_nested_deprecated(tb, NL80211_KEY_MAX, key,
1214 nl80211_key_policy,
1215 info->extack);
b9454e83
JB
1216 if (err)
1217 return err;
1218
1219 k->def = !!tb[NL80211_KEY_DEFAULT];
1220 k->defmgmt = !!tb[NL80211_KEY_DEFAULT_MGMT];
56be393f 1221 k->defbeacon = !!tb[NL80211_KEY_DEFAULT_BEACON];
b9454e83 1222
dbd2fd65
JB
1223 if (k->def) {
1224 k->def_uni = true;
1225 k->def_multi = true;
1226 }
56be393f 1227 if (k->defmgmt || k->defbeacon)
dbd2fd65
JB
1228 k->def_multi = true;
1229
b9454e83
JB
1230 if (tb[NL80211_KEY_IDX])
1231 k->idx = nla_get_u8(tb[NL80211_KEY_IDX]);
1232
1233 if (tb[NL80211_KEY_DATA]) {
1234 k->p.key = nla_data(tb[NL80211_KEY_DATA]);
1235 k->p.key_len = nla_len(tb[NL80211_KEY_DATA]);
1236 }
1237
1238 if (tb[NL80211_KEY_SEQ]) {
1239 k->p.seq = nla_data(tb[NL80211_KEY_SEQ]);
1240 k->p.seq_len = nla_len(tb[NL80211_KEY_SEQ]);
1241 }
1242
1243 if (tb[NL80211_KEY_CIPHER])
1244 k->p.cipher = nla_get_u32(tb[NL80211_KEY_CIPHER]);
1245
ab0d76f6 1246 if (tb[NL80211_KEY_TYPE])
e31b8213 1247 k->type = nla_get_u32(tb[NL80211_KEY_TYPE]);
e31b8213 1248
dbd2fd65
JB
1249 if (tb[NL80211_KEY_DEFAULT_TYPES]) {
1250 struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
7a087e74 1251
8cb08174
JB
1252 err = nla_parse_nested_deprecated(kdt,
1253 NUM_NL80211_KEY_DEFAULT_TYPES - 1,
1254 tb[NL80211_KEY_DEFAULT_TYPES],
1255 nl80211_key_default_policy,
1256 info->extack);
dbd2fd65
JB
1257 if (err)
1258 return err;
1259
1260 k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST];
1261 k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
1262 }
1263
6cdd3979
AW
1264 if (tb[NL80211_KEY_MODE])
1265 k->p.mode = nla_get_u8(tb[NL80211_KEY_MODE]);
1266
b9454e83
JB
1267 return 0;
1268}
1269
1270static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k)
1271{
1272 if (info->attrs[NL80211_ATTR_KEY_DATA]) {
1273 k->p.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]);
1274 k->p.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
1275 }
1276
1277 if (info->attrs[NL80211_ATTR_KEY_SEQ]) {
1278 k->p.seq = nla_data(info->attrs[NL80211_ATTR_KEY_SEQ]);
1279 k->p.seq_len = nla_len(info->attrs[NL80211_ATTR_KEY_SEQ]);
1280 }
1281
1282 if (info->attrs[NL80211_ATTR_KEY_IDX])
1283 k->idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
1284
1285 if (info->attrs[NL80211_ATTR_KEY_CIPHER])
1286 k->p.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);
1287
1288 k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT];
1289 k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT];
1290
dbd2fd65
JB
1291 if (k->def) {
1292 k->def_uni = true;
1293 k->def_multi = true;
1294 }
1295 if (k->defmgmt)
1296 k->def_multi = true;
1297
ab0d76f6 1298 if (info->attrs[NL80211_ATTR_KEY_TYPE])
e31b8213 1299 k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
e31b8213 1300
dbd2fd65
JB
1301 if (info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES]) {
1302 struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
8cb08174
JB
1303 int err = nla_parse_nested_deprecated(kdt,
1304 NUM_NL80211_KEY_DEFAULT_TYPES - 1,
1305 info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES],
1306 nl80211_key_default_policy,
1307 info->extack);
dbd2fd65
JB
1308 if (err)
1309 return err;
1310
1311 k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST];
1312 k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
1313 }
1314
b9454e83
JB
1315 return 0;
1316}
1317
1318static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)
1319{
1320 int err;
1321
1322 memset(k, 0, sizeof(*k));
1323 k->idx = -1;
e31b8213 1324 k->type = -1;
b9454e83
JB
1325
1326 if (info->attrs[NL80211_ATTR_KEY])
768075eb 1327 err = nl80211_parse_key_new(info, info->attrs[NL80211_ATTR_KEY], k);
b9454e83
JB
1328 else
1329 err = nl80211_parse_key_old(info, k);
1330
1331 if (err)
1332 return err;
1333
56be393f
JM
1334 if ((k->def ? 1 : 0) + (k->defmgmt ? 1 : 0) +
1335 (k->defbeacon ? 1 : 0) > 1) {
1336 GENL_SET_ERR_MSG(info,
1337 "key with multiple default flags is invalid");
b9454e83 1338 return -EINVAL;
768075eb 1339 }
b9454e83 1340
56be393f 1341 if (k->defmgmt || k->defbeacon) {
768075eb 1342 if (k->def_uni || !k->def_multi) {
56be393f
JM
1343 GENL_SET_ERR_MSG(info,
1344 "defmgmt/defbeacon key must be mcast");
dbd2fd65 1345 return -EINVAL;
768075eb 1346 }
dbd2fd65
JB
1347 }
1348
b9454e83
JB
1349 if (k->idx != -1) {
1350 if (k->defmgmt) {
768075eb
JB
1351 if (k->idx < 4 || k->idx > 5) {
1352 GENL_SET_ERR_MSG(info,
1353 "defmgmt key idx not 4 or 5");
b9454e83 1354 return -EINVAL;
768075eb 1355 }
56be393f
JM
1356 } else if (k->defbeacon) {
1357 if (k->idx < 6 || k->idx > 7) {
1358 GENL_SET_ERR_MSG(info,
1359 "defbeacon key idx not 6 or 7");
1360 return -EINVAL;
1361 }
b9454e83 1362 } else if (k->def) {
768075eb
JB
1363 if (k->idx < 0 || k->idx > 3) {
1364 GENL_SET_ERR_MSG(info, "def key idx not 0-3");
b9454e83 1365 return -EINVAL;
768075eb 1366 }
b9454e83 1367 } else {
56be393f
JM
1368 if (k->idx < 0 || k->idx > 7) {
1369 GENL_SET_ERR_MSG(info, "key idx not 0-7");
b9454e83 1370 return -EINVAL;
768075eb 1371 }
b9454e83
JB
1372 }
1373 }
1374
1375 return 0;
1376}
1377
fffd0934
JB
1378static struct cfg80211_cached_keys *
1379nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
768075eb 1380 struct genl_info *info, bool *no_ht)
fffd0934 1381{
768075eb 1382 struct nlattr *keys = info->attrs[NL80211_ATTR_KEYS];
fffd0934
JB
1383 struct key_parse parse;
1384 struct nlattr *key;
1385 struct cfg80211_cached_keys *result;
1386 int rem, err, def = 0;
f1c1f17a
JB
1387 bool have_key = false;
1388
1389 nla_for_each_nested(key, keys, rem) {
1390 have_key = true;
1391 break;
1392 }
1393
1394 if (!have_key)
1395 return NULL;
fffd0934
JB
1396
1397 result = kzalloc(sizeof(*result), GFP_KERNEL);
1398 if (!result)
1399 return ERR_PTR(-ENOMEM);
1400
1401 result->def = -1;
fffd0934
JB
1402
1403 nla_for_each_nested(key, keys, rem) {
1404 memset(&parse, 0, sizeof(parse));
1405 parse.idx = -1;
1406
768075eb 1407 err = nl80211_parse_key_new(info, key, &parse);
fffd0934
JB
1408 if (err)
1409 goto error;
1410 err = -EINVAL;
1411 if (!parse.p.key)
1412 goto error;
768075eb
JB
1413 if (parse.idx < 0 || parse.idx > 3) {
1414 GENL_SET_ERR_MSG(info, "key index out of range [0-3]");
fffd0934 1415 goto error;
768075eb 1416 }
fffd0934 1417 if (parse.def) {
768075eb
JB
1418 if (def) {
1419 GENL_SET_ERR_MSG(info,
1420 "only one key can be default");
fffd0934 1421 goto error;
768075eb 1422 }
fffd0934
JB
1423 def = 1;
1424 result->def = parse.idx;
dbd2fd65
JB
1425 if (!parse.def_uni || !parse.def_multi)
1426 goto error;
fffd0934
JB
1427 } else if (parse.defmgmt)
1428 goto error;
1429 err = cfg80211_validate_key_settings(rdev, &parse.p,
e31b8213 1430 parse.idx, false, NULL);
fffd0934
JB
1431 if (err)
1432 goto error;
386b1f27
JB
1433 if (parse.p.cipher != WLAN_CIPHER_SUITE_WEP40 &&
1434 parse.p.cipher != WLAN_CIPHER_SUITE_WEP104) {
768075eb 1435 GENL_SET_ERR_MSG(info, "connect key must be WEP");
386b1f27
JB
1436 err = -EINVAL;
1437 goto error;
1438 }
fffd0934
JB
1439 result->params[parse.idx].cipher = parse.p.cipher;
1440 result->params[parse.idx].key_len = parse.p.key_len;
1441 result->params[parse.idx].key = result->data[parse.idx];
1442 memcpy(result->data[parse.idx], parse.p.key, parse.p.key_len);
de7044ee 1443
386b1f27
JB
1444 /* must be WEP key if we got here */
1445 if (no_ht)
1446 *no_ht = true;
fffd0934
JB
1447 }
1448
f1c1f17a
JB
1449 if (result->def < 0) {
1450 err = -EINVAL;
768075eb 1451 GENL_SET_ERR_MSG(info, "need a default/TX key");
f1c1f17a
JB
1452 goto error;
1453 }
1454
fffd0934
JB
1455 return result;
1456 error:
1457 kfree(result);
1458 return ERR_PTR(err);
1459}
1460
1461static int nl80211_key_allowed(struct wireless_dev *wdev)
1462{
1463 ASSERT_WDEV_LOCK(wdev);
1464
fffd0934
JB
1465 switch (wdev->iftype) {
1466 case NL80211_IFTYPE_AP:
1467 case NL80211_IFTYPE_AP_VLAN:
074ac8df 1468 case NL80211_IFTYPE_P2P_GO:
ff973af7 1469 case NL80211_IFTYPE_MESH_POINT:
fffd0934
JB
1470 break;
1471 case NL80211_IFTYPE_ADHOC:
fffd0934 1472 case NL80211_IFTYPE_STATION:
074ac8df 1473 case NL80211_IFTYPE_P2P_CLIENT:
ceca7b71 1474 if (!wdev->current_bss)
fffd0934
JB
1475 return -ENOLINK;
1476 break;
de4fcbad 1477 case NL80211_IFTYPE_UNSPECIFIED:
6e0bd6c3 1478 case NL80211_IFTYPE_OCB:
de4fcbad 1479 case NL80211_IFTYPE_MONITOR:
cb3b7d87 1480 case NL80211_IFTYPE_NAN:
de4fcbad
JB
1481 case NL80211_IFTYPE_P2P_DEVICE:
1482 case NL80211_IFTYPE_WDS:
1483 case NUM_NL80211_IFTYPES:
fffd0934
JB
1484 return -EINVAL;
1485 }
1486
1487 return 0;
1488}
1489
664834de 1490static struct ieee80211_channel *nl80211_get_valid_chan(struct wiphy *wiphy,
942ba88b 1491 u32 freq)
664834de
JM
1492{
1493 struct ieee80211_channel *chan;
1494
942ba88b 1495 chan = ieee80211_get_channel_khz(wiphy, freq);
664834de
JM
1496 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
1497 return NULL;
1498 return chan;
1499}
1500
7527a782
JB
1501static int nl80211_put_iftypes(struct sk_buff *msg, u32 attr, u16 ifmodes)
1502{
ae0be8de 1503 struct nlattr *nl_modes = nla_nest_start_noflag(msg, attr);
7527a782
JB
1504 int i;
1505
1506 if (!nl_modes)
1507 goto nla_put_failure;
1508
1509 i = 0;
1510 while (ifmodes) {
9360ffd1
DM
1511 if ((ifmodes & 1) && nla_put_flag(msg, i))
1512 goto nla_put_failure;
7527a782
JB
1513 ifmodes >>= 1;
1514 i++;
1515 }
1516
1517 nla_nest_end(msg, nl_modes);
1518 return 0;
1519
1520nla_put_failure:
1521 return -ENOBUFS;
1522}
1523
1524static int nl80211_put_iface_combinations(struct wiphy *wiphy,
cdc89b97
JB
1525 struct sk_buff *msg,
1526 bool large)
7527a782
JB
1527{
1528 struct nlattr *nl_combis;
1529 int i, j;
1530
ae0be8de
MK
1531 nl_combis = nla_nest_start_noflag(msg,
1532 NL80211_ATTR_INTERFACE_COMBINATIONS);
7527a782
JB
1533 if (!nl_combis)
1534 goto nla_put_failure;
1535
1536 for (i = 0; i < wiphy->n_iface_combinations; i++) {
1537 const struct ieee80211_iface_combination *c;
1538 struct nlattr *nl_combi, *nl_limits;
1539
1540 c = &wiphy->iface_combinations[i];
1541
ae0be8de 1542 nl_combi = nla_nest_start_noflag(msg, i + 1);
7527a782
JB
1543 if (!nl_combi)
1544 goto nla_put_failure;
1545
ae0be8de
MK
1546 nl_limits = nla_nest_start_noflag(msg,
1547 NL80211_IFACE_COMB_LIMITS);
7527a782
JB
1548 if (!nl_limits)
1549 goto nla_put_failure;
1550
1551 for (j = 0; j < c->n_limits; j++) {
1552 struct nlattr *nl_limit;
1553
ae0be8de 1554 nl_limit = nla_nest_start_noflag(msg, j + 1);
7527a782
JB
1555 if (!nl_limit)
1556 goto nla_put_failure;
9360ffd1
DM
1557 if (nla_put_u32(msg, NL80211_IFACE_LIMIT_MAX,
1558 c->limits[j].max))
1559 goto nla_put_failure;
7527a782
JB
1560 if (nl80211_put_iftypes(msg, NL80211_IFACE_LIMIT_TYPES,
1561 c->limits[j].types))
1562 goto nla_put_failure;
1563 nla_nest_end(msg, nl_limit);
1564 }
1565
1566 nla_nest_end(msg, nl_limits);
1567
9360ffd1
DM
1568 if (c->beacon_int_infra_match &&
1569 nla_put_flag(msg, NL80211_IFACE_COMB_STA_AP_BI_MATCH))
1570 goto nla_put_failure;
1571 if (nla_put_u32(msg, NL80211_IFACE_COMB_NUM_CHANNELS,
1572 c->num_different_channels) ||
1573 nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM,
1574 c->max_interfaces))
1575 goto nla_put_failure;
cdc89b97 1576 if (large &&
8c48b50a
FF
1577 (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
1578 c->radar_detect_widths) ||
1579 nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
1580 c->radar_detect_regions)))
cdc89b97 1581 goto nla_put_failure;
0c317a02
PK
1582 if (c->beacon_int_min_gcd &&
1583 nla_put_u32(msg, NL80211_IFACE_COMB_BI_MIN_GCD,
1584 c->beacon_int_min_gcd))
1585 goto nla_put_failure;
7527a782
JB
1586
1587 nla_nest_end(msg, nl_combi);
1588 }
1589
1590 nla_nest_end(msg, nl_combis);
1591
1592 return 0;
1593nla_put_failure:
1594 return -ENOBUFS;
1595}
1596
3713b4e3 1597#ifdef CONFIG_PM
b56cf720
JB
1598static int nl80211_send_wowlan_tcp_caps(struct cfg80211_registered_device *rdev,
1599 struct sk_buff *msg)
1600{
964dc9e2 1601 const struct wiphy_wowlan_tcp_support *tcp = rdev->wiphy.wowlan->tcp;
b56cf720
JB
1602 struct nlattr *nl_tcp;
1603
1604 if (!tcp)
1605 return 0;
1606
ae0be8de
MK
1607 nl_tcp = nla_nest_start_noflag(msg,
1608 NL80211_WOWLAN_TRIG_TCP_CONNECTION);
b56cf720
JB
1609 if (!nl_tcp)
1610 return -ENOBUFS;
1611
1612 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
1613 tcp->data_payload_max))
1614 return -ENOBUFS;
1615
1616 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
1617 tcp->data_payload_max))
1618 return -ENOBUFS;
1619
1620 if (tcp->seq && nla_put_flag(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ))
1621 return -ENOBUFS;
1622
1623 if (tcp->tok && nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
1624 sizeof(*tcp->tok), tcp->tok))
1625 return -ENOBUFS;
1626
1627 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
1628 tcp->data_interval_max))
1629 return -ENOBUFS;
1630
1631 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
1632 tcp->wake_payload_max))
1633 return -ENOBUFS;
1634
1635 nla_nest_end(msg, nl_tcp);
1636 return 0;
1637}
1638
3713b4e3 1639static int nl80211_send_wowlan(struct sk_buff *msg,
1b8ec87a 1640 struct cfg80211_registered_device *rdev,
b56cf720 1641 bool large)
55682965 1642{
3713b4e3 1643 struct nlattr *nl_wowlan;
55682965 1644
1b8ec87a 1645 if (!rdev->wiphy.wowlan)
3713b4e3 1646 return 0;
55682965 1647
ae0be8de
MK
1648 nl_wowlan = nla_nest_start_noflag(msg,
1649 NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED);
3713b4e3
JB
1650 if (!nl_wowlan)
1651 return -ENOBUFS;
9360ffd1 1652
1b8ec87a 1653 if (((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_ANY) &&
3713b4e3 1654 nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
1b8ec87a 1655 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_DISCONNECT) &&
3713b4e3 1656 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
1b8ec87a 1657 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT) &&
3713b4e3 1658 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
1b8ec87a 1659 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) &&
3713b4e3 1660 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED)) ||
1b8ec87a 1661 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
3713b4e3 1662 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
1b8ec87a 1663 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) &&
3713b4e3 1664 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
1b8ec87a 1665 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) &&
3713b4e3 1666 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
1b8ec87a 1667 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE) &&
3713b4e3
JB
1668 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
1669 return -ENOBUFS;
9360ffd1 1670
1b8ec87a 1671 if (rdev->wiphy.wowlan->n_patterns) {
50ac6607 1672 struct nl80211_pattern_support pat = {
1b8ec87a
ZG
1673 .max_patterns = rdev->wiphy.wowlan->n_patterns,
1674 .min_pattern_len = rdev->wiphy.wowlan->pattern_min_len,
1675 .max_pattern_len = rdev->wiphy.wowlan->pattern_max_len,
1676 .max_pkt_offset = rdev->wiphy.wowlan->max_pkt_offset,
3713b4e3 1677 };
9360ffd1 1678
3713b4e3
JB
1679 if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
1680 sizeof(pat), &pat))
1681 return -ENOBUFS;
1682 }
9360ffd1 1683
75453ccb
LC
1684 if ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_NET_DETECT) &&
1685 nla_put_u32(msg, NL80211_WOWLAN_TRIG_NET_DETECT,
1686 rdev->wiphy.wowlan->max_nd_match_sets))
1687 return -ENOBUFS;
1688
1b8ec87a 1689 if (large && nl80211_send_wowlan_tcp_caps(rdev, msg))
b56cf720
JB
1690 return -ENOBUFS;
1691
3713b4e3 1692 nla_nest_end(msg, nl_wowlan);
9360ffd1 1693
3713b4e3
JB
1694 return 0;
1695}
1696#endif
9360ffd1 1697
be29b99a 1698static int nl80211_send_coalesce(struct sk_buff *msg,
1b8ec87a 1699 struct cfg80211_registered_device *rdev)
be29b99a
AK
1700{
1701 struct nl80211_coalesce_rule_support rule;
1702
1b8ec87a 1703 if (!rdev->wiphy.coalesce)
be29b99a
AK
1704 return 0;
1705
1b8ec87a
ZG
1706 rule.max_rules = rdev->wiphy.coalesce->n_rules;
1707 rule.max_delay = rdev->wiphy.coalesce->max_delay;
1708 rule.pat.max_patterns = rdev->wiphy.coalesce->n_patterns;
1709 rule.pat.min_pattern_len = rdev->wiphy.coalesce->pattern_min_len;
1710 rule.pat.max_pattern_len = rdev->wiphy.coalesce->pattern_max_len;
1711 rule.pat.max_pkt_offset = rdev->wiphy.coalesce->max_pkt_offset;
be29b99a
AK
1712
1713 if (nla_put(msg, NL80211_ATTR_COALESCE_RULE, sizeof(rule), &rule))
1714 return -ENOBUFS;
1715
1716 return 0;
1717}
1718
c4cbaf79
LC
1719static int
1720nl80211_send_iftype_data(struct sk_buff *msg,
22395217 1721 const struct ieee80211_supported_band *sband,
c4cbaf79
LC
1722 const struct ieee80211_sband_iftype_data *iftdata)
1723{
1724 const struct ieee80211_sta_he_cap *he_cap = &iftdata->he_cap;
1725
1726 if (nl80211_put_iftypes(msg, NL80211_BAND_IFTYPE_ATTR_IFTYPES,
1727 iftdata->types_mask))
1728 return -ENOBUFS;
1729
1730 if (he_cap->has_he) {
1731 if (nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC,
1732 sizeof(he_cap->he_cap_elem.mac_cap_info),
1733 he_cap->he_cap_elem.mac_cap_info) ||
1734 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY,
1735 sizeof(he_cap->he_cap_elem.phy_cap_info),
1736 he_cap->he_cap_elem.phy_cap_info) ||
1737 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET,
1738 sizeof(he_cap->he_mcs_nss_supp),
1739 &he_cap->he_mcs_nss_supp) ||
1740 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE,
1741 sizeof(he_cap->ppe_thres), he_cap->ppe_thres))
1742 return -ENOBUFS;
1743 }
1744
22395217
JB
1745 if (sband->band == NL80211_BAND_6GHZ &&
1746 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA,
1747 sizeof(iftdata->he_6ghz_capa),
1748 &iftdata->he_6ghz_capa))
1749 return -ENOBUFS;
1750
f4f86505
JB
1751 if (iftdata->vendor_elems.data && iftdata->vendor_elems.len &&
1752 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS,
1753 iftdata->vendor_elems.len, iftdata->vendor_elems.data))
1754 return -ENOBUFS;
1755
c4cbaf79
LC
1756 return 0;
1757}
1758
3713b4e3 1759static int nl80211_send_band_rateinfo(struct sk_buff *msg,
f8d504ca
JB
1760 struct ieee80211_supported_band *sband,
1761 bool large)
3713b4e3
JB
1762{
1763 struct nlattr *nl_rates, *nl_rate;
1764 struct ieee80211_rate *rate;
1765 int i;
87bbbe22 1766
3713b4e3
JB
1767 /* add HT info */
1768 if (sband->ht_cap.ht_supported &&
1769 (nla_put(msg, NL80211_BAND_ATTR_HT_MCS_SET,
1770 sizeof(sband->ht_cap.mcs),
1771 &sband->ht_cap.mcs) ||
1772 nla_put_u16(msg, NL80211_BAND_ATTR_HT_CAPA,
1773 sband->ht_cap.cap) ||
1774 nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR,
1775 sband->ht_cap.ampdu_factor) ||
1776 nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
1777 sband->ht_cap.ampdu_density)))
1778 return -ENOBUFS;
afe0cbf8 1779
3713b4e3
JB
1780 /* add VHT info */
1781 if (sband->vht_cap.vht_supported &&
1782 (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET,
1783 sizeof(sband->vht_cap.vht_mcs),
1784 &sband->vht_cap.vht_mcs) ||
1785 nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA,
1786 sband->vht_cap.cap)))
1787 return -ENOBUFS;
f59ac048 1788
f8d504ca 1789 if (large && sband->n_iftype_data) {
c4cbaf79 1790 struct nlattr *nl_iftype_data =
ae0be8de
MK
1791 nla_nest_start_noflag(msg,
1792 NL80211_BAND_ATTR_IFTYPE_DATA);
c4cbaf79
LC
1793 int err;
1794
1795 if (!nl_iftype_data)
1796 return -ENOBUFS;
1797
1798 for (i = 0; i < sband->n_iftype_data; i++) {
1799 struct nlattr *iftdata;
1800
ae0be8de 1801 iftdata = nla_nest_start_noflag(msg, i + 1);
c4cbaf79
LC
1802 if (!iftdata)
1803 return -ENOBUFS;
1804
22395217 1805 err = nl80211_send_iftype_data(msg, sband,
c4cbaf79
LC
1806 &sband->iftype_data[i]);
1807 if (err)
1808 return err;
1809
1810 nla_nest_end(msg, iftdata);
1811 }
1812
1813 nla_nest_end(msg, nl_iftype_data);
1814 }
1815
2a38075c 1816 /* add EDMG info */
f8d504ca 1817 if (large && sband->edmg_cap.channels &&
2a38075c
AAL
1818 (nla_put_u8(msg, NL80211_BAND_ATTR_EDMG_CHANNELS,
1819 sband->edmg_cap.channels) ||
1820 nla_put_u8(msg, NL80211_BAND_ATTR_EDMG_BW_CONFIG,
1821 sband->edmg_cap.bw_config)))
1822
1823 return -ENOBUFS;
1824
3713b4e3 1825 /* add bitrates */
ae0be8de 1826 nl_rates = nla_nest_start_noflag(msg, NL80211_BAND_ATTR_RATES);
3713b4e3
JB
1827 if (!nl_rates)
1828 return -ENOBUFS;
ee688b00 1829
3713b4e3 1830 for (i = 0; i < sband->n_bitrates; i++) {
ae0be8de 1831 nl_rate = nla_nest_start_noflag(msg, i);
3713b4e3
JB
1832 if (!nl_rate)
1833 return -ENOBUFS;
ee688b00 1834
3713b4e3
JB
1835 rate = &sband->bitrates[i];
1836 if (nla_put_u32(msg, NL80211_BITRATE_ATTR_RATE,
1837 rate->bitrate))
1838 return -ENOBUFS;
1839 if ((rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) &&
1840 nla_put_flag(msg,
1841 NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE))
1842 return -ENOBUFS;
ee688b00 1843
3713b4e3
JB
1844 nla_nest_end(msg, nl_rate);
1845 }
d51626df 1846
3713b4e3 1847 nla_nest_end(msg, nl_rates);
bf0c111e 1848
3713b4e3
JB
1849 return 0;
1850}
ee688b00 1851
3713b4e3
JB
1852static int
1853nl80211_send_mgmt_stypes(struct sk_buff *msg,
1854 const struct ieee80211_txrx_stypes *mgmt_stypes)
1855{
1856 u16 stypes;
1857 struct nlattr *nl_ftypes, *nl_ifs;
1858 enum nl80211_iftype ift;
1859 int i;
ee688b00 1860
3713b4e3
JB
1861 if (!mgmt_stypes)
1862 return 0;
5dab3b8a 1863
ae0be8de 1864 nl_ifs = nla_nest_start_noflag(msg, NL80211_ATTR_TX_FRAME_TYPES);
3713b4e3
JB
1865 if (!nl_ifs)
1866 return -ENOBUFS;
e2f367f2 1867
3713b4e3 1868 for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
ae0be8de 1869 nl_ftypes = nla_nest_start_noflag(msg, ift);
3713b4e3
JB
1870 if (!nl_ftypes)
1871 return -ENOBUFS;
1872 i = 0;
1873 stypes = mgmt_stypes[ift].tx;
1874 while (stypes) {
1875 if ((stypes & 1) &&
1876 nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
1877 (i << 4) | IEEE80211_FTYPE_MGMT))
1878 return -ENOBUFS;
1879 stypes >>= 1;
1880 i++;
ee688b00 1881 }
3713b4e3
JB
1882 nla_nest_end(msg, nl_ftypes);
1883 }
ee688b00 1884
3713b4e3 1885 nla_nest_end(msg, nl_ifs);
ee688b00 1886
ae0be8de 1887 nl_ifs = nla_nest_start_noflag(msg, NL80211_ATTR_RX_FRAME_TYPES);
3713b4e3
JB
1888 if (!nl_ifs)
1889 return -ENOBUFS;
ee688b00 1890
3713b4e3 1891 for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
ae0be8de 1892 nl_ftypes = nla_nest_start_noflag(msg, ift);
3713b4e3
JB
1893 if (!nl_ftypes)
1894 return -ENOBUFS;
1895 i = 0;
1896 stypes = mgmt_stypes[ift].rx;
1897 while (stypes) {
1898 if ((stypes & 1) &&
1899 nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
1900 (i << 4) | IEEE80211_FTYPE_MGMT))
1901 return -ENOBUFS;
1902 stypes >>= 1;
1903 i++;
1904 }
1905 nla_nest_end(msg, nl_ftypes);
1906 }
1907 nla_nest_end(msg, nl_ifs);
ee688b00 1908
3713b4e3
JB
1909 return 0;
1910}
ee688b00 1911
1794899e
JB
1912#define CMD(op, n) \
1913 do { \
1914 if (rdev->ops->op) { \
1915 i++; \
1916 if (nla_put_u32(msg, i, NL80211_CMD_ ## n)) \
1917 goto nla_put_failure; \
1918 } \
1919 } while (0)
1920
1921static int nl80211_add_commands_unsplit(struct cfg80211_registered_device *rdev,
1922 struct sk_buff *msg)
1923{
1924 int i = 0;
1925
1926 /*
1927 * do *NOT* add anything into this function, new things need to be
1928 * advertised only to new versions of userspace that can deal with
1929 * the split (and they can't possibly care about new features...
1930 */
1931 CMD(add_virtual_intf, NEW_INTERFACE);
1932 CMD(change_virtual_intf, SET_INTERFACE);
1933 CMD(add_key, NEW_KEY);
1934 CMD(start_ap, START_AP);
1935 CMD(add_station, NEW_STATION);
1936 CMD(add_mpath, NEW_MPATH);
1937 CMD(update_mesh_config, SET_MESH_CONFIG);
1938 CMD(change_bss, SET_BSS);
1939 CMD(auth, AUTHENTICATE);
1940 CMD(assoc, ASSOCIATE);
1941 CMD(deauth, DEAUTHENTICATE);
1942 CMD(disassoc, DISASSOCIATE);
1943 CMD(join_ibss, JOIN_IBSS);
1944 CMD(join_mesh, JOIN_MESH);
1945 CMD(set_pmksa, SET_PMKSA);
1946 CMD(del_pmksa, DEL_PMKSA);
1947 CMD(flush_pmksa, FLUSH_PMKSA);
1948 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)
1949 CMD(remain_on_channel, REMAIN_ON_CHANNEL);
1950 CMD(set_bitrate_mask, SET_TX_BITRATE_MASK);
1951 CMD(mgmt_tx, FRAME);
1952 CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL);
1953 if (rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
1954 i++;
1955 if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS))
1956 goto nla_put_failure;
1957 }
1958 if (rdev->ops->set_monitor_channel || rdev->ops->start_ap ||
1959 rdev->ops->join_mesh) {
1960 i++;
1961 if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL))
1962 goto nla_put_failure;
1963 }
1794899e
JB
1964 if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) {
1965 CMD(tdls_mgmt, TDLS_MGMT);
1966 CMD(tdls_oper, TDLS_OPER);
1967 }
ca986ad9 1968 if (rdev->wiphy.max_sched_scan_reqs)
1794899e
JB
1969 CMD(sched_scan_start, START_SCHED_SCAN);
1970 CMD(probe_client, PROBE_CLIENT);
1971 CMD(set_noack_map, SET_NOACK_MAP);
1972 if (rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) {
1973 i++;
1974 if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS))
1975 goto nla_put_failure;
1976 }
1977 CMD(start_p2p_device, START_P2P_DEVICE);
1978 CMD(set_mcast_rate, SET_MCAST_RATE);
1979#ifdef CONFIG_NL80211_TESTMODE
1980 CMD(testmode_cmd, TESTMODE);
1981#endif
1982
1983 if (rdev->ops->connect || rdev->ops->auth) {
1984 i++;
1985 if (nla_put_u32(msg, i, NL80211_CMD_CONNECT))
1986 goto nla_put_failure;
1987 }
1988
1989 if (rdev->ops->disconnect || rdev->ops->deauth) {
1990 i++;
1991 if (nla_put_u32(msg, i, NL80211_CMD_DISCONNECT))
1992 goto nla_put_failure;
1993 }
1994
1995 return i;
1996 nla_put_failure:
1997 return -ENOBUFS;
1998}
1999
9bb7e0f2
JB
2000static int
2001nl80211_send_pmsr_ftm_capa(const struct cfg80211_pmsr_capabilities *cap,
2002 struct sk_buff *msg)
2003{
2004 struct nlattr *ftm;
2005
2006 if (!cap->ftm.supported)
2007 return 0;
2008
ae0be8de 2009 ftm = nla_nest_start_noflag(msg, NL80211_PMSR_TYPE_FTM);
9bb7e0f2
JB
2010 if (!ftm)
2011 return -ENOBUFS;
2012
2013 if (cap->ftm.asap && nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_ASAP))
2014 return -ENOBUFS;
2015 if (cap->ftm.non_asap &&
2016 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_NON_ASAP))
2017 return -ENOBUFS;
2018 if (cap->ftm.request_lci &&
2019 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_REQ_LCI))
2020 return -ENOBUFS;
2021 if (cap->ftm.request_civicloc &&
2022 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_REQ_CIVICLOC))
2023 return -ENOBUFS;
2024 if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES,
2025 cap->ftm.preambles))
2026 return -ENOBUFS;
2027 if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS,
2028 cap->ftm.bandwidths))
2029 return -ENOBUFS;
2030 if (cap->ftm.max_bursts_exponent >= 0 &&
2031 nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT,
2032 cap->ftm.max_bursts_exponent))
2033 return -ENOBUFS;
2034 if (cap->ftm.max_ftms_per_burst &&
2035 nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST,
2036 cap->ftm.max_ftms_per_burst))
2037 return -ENOBUFS;
efb5520d
AS
2038 if (cap->ftm.trigger_based &&
2039 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED))
2040 return -ENOBUFS;
2041 if (cap->ftm.non_trigger_based &&
2042 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED))
2043 return -ENOBUFS;
9bb7e0f2
JB
2044
2045 nla_nest_end(msg, ftm);
2046 return 0;
2047}
2048
2049static int nl80211_send_pmsr_capa(struct cfg80211_registered_device *rdev,
2050 struct sk_buff *msg)
2051{
2052 const struct cfg80211_pmsr_capabilities *cap = rdev->wiphy.pmsr_capa;
2053 struct nlattr *pmsr, *caps;
2054
2055 if (!cap)
2056 return 0;
2057
2058 /*
2059 * we don't need to clean up anything here since the caller
2060 * will genlmsg_cancel() if we fail
2061 */
2062
ae0be8de 2063 pmsr = nla_nest_start_noflag(msg, NL80211_ATTR_PEER_MEASUREMENTS);
9bb7e0f2
JB
2064 if (!pmsr)
2065 return -ENOBUFS;
2066
2067 if (nla_put_u32(msg, NL80211_PMSR_ATTR_MAX_PEERS, cap->max_peers))
2068 return -ENOBUFS;
2069
2070 if (cap->report_ap_tsf &&
2071 nla_put_flag(msg, NL80211_PMSR_ATTR_REPORT_AP_TSF))
2072 return -ENOBUFS;
2073
2074 if (cap->randomize_mac_addr &&
2075 nla_put_flag(msg, NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR))
2076 return -ENOBUFS;
2077
ae0be8de 2078 caps = nla_nest_start_noflag(msg, NL80211_PMSR_ATTR_TYPE_CAPA);
9bb7e0f2
JB
2079 if (!caps)
2080 return -ENOBUFS;
2081
2082 if (nl80211_send_pmsr_ftm_capa(cap, msg))
2083 return -ENOBUFS;
2084
2085 nla_nest_end(msg, caps);
2086 nla_nest_end(msg, pmsr);
2087
2088 return 0;
2089}
2090
d6039a34
VJ
2091static int
2092nl80211_put_iftype_akm_suites(struct cfg80211_registered_device *rdev,
2093 struct sk_buff *msg)
2094{
2095 int i;
2096 struct nlattr *nested, *nested_akms;
2097 const struct wiphy_iftype_akm_suites *iftype_akms;
2098
2099 if (!rdev->wiphy.num_iftype_akm_suites ||
2100 !rdev->wiphy.iftype_akm_suites)
2101 return 0;
2102
2103 nested = nla_nest_start(msg, NL80211_ATTR_IFTYPE_AKM_SUITES);
2104 if (!nested)
2105 return -ENOBUFS;
2106
2107 for (i = 0; i < rdev->wiphy.num_iftype_akm_suites; i++) {
2108 nested_akms = nla_nest_start(msg, i + 1);
2109 if (!nested_akms)
2110 return -ENOBUFS;
2111
2112 iftype_akms = &rdev->wiphy.iftype_akm_suites[i];
2113
2114 if (nl80211_put_iftypes(msg, NL80211_IFTYPE_AKM_ATTR_IFTYPES,
2115 iftype_akms->iftypes_mask))
2116 return -ENOBUFS;
2117
2118 if (nla_put(msg, NL80211_IFTYPE_AKM_ATTR_SUITES,
2119 sizeof(u32) * iftype_akms->n_akm_suites,
2120 iftype_akms->akm_suites)) {
2121 return -ENOBUFS;
2122 }
2123 nla_nest_end(msg, nested_akms);
2124 }
2125
2126 nla_nest_end(msg, nested);
2127
2128 return 0;
2129}
2130
3710a8a6
JB
2131static int
2132nl80211_put_tid_config_support(struct cfg80211_registered_device *rdev,
2133 struct sk_buff *msg)
2134{
2135 struct nlattr *supp;
2136
2137 if (!rdev->wiphy.tid_config_support.vif &&
2138 !rdev->wiphy.tid_config_support.peer)
2139 return 0;
2140
2141 supp = nla_nest_start(msg, NL80211_ATTR_TID_CONFIG);
2142 if (!supp)
2143 return -ENOSPC;
2144
2145 if (rdev->wiphy.tid_config_support.vif &&
2146 nla_put_u64_64bit(msg, NL80211_TID_CONFIG_ATTR_VIF_SUPP,
2147 rdev->wiphy.tid_config_support.vif,
2148 NL80211_TID_CONFIG_ATTR_PAD))
2149 goto fail;
2150
2151 if (rdev->wiphy.tid_config_support.peer &&
2152 nla_put_u64_64bit(msg, NL80211_TID_CONFIG_ATTR_PEER_SUPP,
2153 rdev->wiphy.tid_config_support.peer,
2154 NL80211_TID_CONFIG_ATTR_PAD))
2155 goto fail;
2156
6a21d16c
T
2157 /* for now we just use the same value ... makes more sense */
2158 if (nla_put_u8(msg, NL80211_TID_CONFIG_ATTR_RETRY_SHORT,
2159 rdev->wiphy.tid_config_support.max_retry))
2160 goto fail;
2161 if (nla_put_u8(msg, NL80211_TID_CONFIG_ATTR_RETRY_LONG,
2162 rdev->wiphy.tid_config_support.max_retry))
2163 goto fail;
2164
3710a8a6
JB
2165 nla_nest_end(msg, supp);
2166
2167 return 0;
2168fail:
2169 nla_nest_cancel(msg, supp);
2170 return -ENOBUFS;
2171}
2172
6bdb68ce
CH
2173static int
2174nl80211_put_sar_specs(struct cfg80211_registered_device *rdev,
2175 struct sk_buff *msg)
2176{
2177 struct nlattr *sar_capa, *specs, *sub_freq_range;
2178 u8 num_freq_ranges;
2179 int i;
2180
2181 if (!rdev->wiphy.sar_capa)
2182 return 0;
2183
2184 num_freq_ranges = rdev->wiphy.sar_capa->num_freq_ranges;
2185
2186 sar_capa = nla_nest_start(msg, NL80211_ATTR_SAR_SPEC);
2187 if (!sar_capa)
2188 return -ENOSPC;
2189
2190 if (nla_put_u32(msg, NL80211_SAR_ATTR_TYPE, rdev->wiphy.sar_capa->type))
2191 goto fail;
2192
2193 specs = nla_nest_start(msg, NL80211_SAR_ATTR_SPECS);
2194 if (!specs)
2195 goto fail;
2196
2197 /* report supported freq_ranges */
2198 for (i = 0; i < num_freq_ranges; i++) {
2199 sub_freq_range = nla_nest_start(msg, i + 1);
2200 if (!sub_freq_range)
2201 goto fail;
2202
2203 if (nla_put_u32(msg, NL80211_SAR_ATTR_SPECS_START_FREQ,
2204 rdev->wiphy.sar_capa->freq_ranges[i].start_freq))
2205 goto fail;
2206
2207 if (nla_put_u32(msg, NL80211_SAR_ATTR_SPECS_END_FREQ,
2208 rdev->wiphy.sar_capa->freq_ranges[i].end_freq))
2209 goto fail;
2210
2211 nla_nest_end(msg, sub_freq_range);
2212 }
2213
2214 nla_nest_end(msg, specs);
2215 nla_nest_end(msg, sar_capa);
2216
2217 return 0;
2218fail:
2219 nla_nest_cancel(msg, sar_capa);
2220 return -ENOBUFS;
2221}
2222
dc1e3cb8
JC
2223static int nl80211_put_mbssid_support(struct wiphy *wiphy, struct sk_buff *msg)
2224{
2225 struct nlattr *config;
2226
2227 if (!wiphy->mbssid_max_interfaces)
2228 return 0;
2229
2230 config = nla_nest_start(msg, NL80211_ATTR_MBSSID_CONFIG);
2231 if (!config)
2232 return -ENOBUFS;
2233
2234 if (nla_put_u8(msg, NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES,
2235 wiphy->mbssid_max_interfaces))
2236 goto fail;
2237
2238 if (wiphy->ema_max_profile_periodicity &&
2239 nla_put_u8(msg,
2240 NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY,
2241 wiphy->ema_max_profile_periodicity))
2242 goto fail;
2243
2244 nla_nest_end(msg, config);
2245 return 0;
2246
2247fail:
2248 nla_nest_cancel(msg, config);
2249 return -ENOBUFS;
2250}
2251
86e8cf98
JB
2252struct nl80211_dump_wiphy_state {
2253 s64 filter_wiphy;
2254 long start;
019ae3a9 2255 long split_start, band_start, chan_start, capa_start;
86e8cf98
JB
2256 bool split;
2257};
2258
1b8ec87a 2259static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
3bb20556 2260 enum nl80211_commands cmd,
3713b4e3 2261 struct sk_buff *msg, u32 portid, u32 seq,
86e8cf98 2262 int flags, struct nl80211_dump_wiphy_state *state)
3713b4e3
JB
2263{
2264 void *hdr;
2265 struct nlattr *nl_bands, *nl_band;
2266 struct nlattr *nl_freqs, *nl_freq;
2267 struct nlattr *nl_cmds;
57fbcce3 2268 enum nl80211_band band;
3713b4e3
JB
2269 struct ieee80211_channel *chan;
2270 int i;
2271 const struct ieee80211_txrx_stypes *mgmt_stypes =
1b8ec87a 2272 rdev->wiphy.mgmt_stypes;
fe1abafd 2273 u32 features;
ee688b00 2274
3bb20556 2275 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
3713b4e3
JB
2276 if (!hdr)
2277 return -ENOBUFS;
ee688b00 2278
86e8cf98
JB
2279 if (WARN_ON(!state))
2280 return -EINVAL;
ee688b00 2281
1b8ec87a 2282 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
3713b4e3 2283 nla_put_string(msg, NL80211_ATTR_WIPHY_NAME,
1b8ec87a 2284 wiphy_name(&rdev->wiphy)) ||
3713b4e3
JB
2285 nla_put_u32(msg, NL80211_ATTR_GENERATION,
2286 cfg80211_rdev_list_generation))
8fdc621d
JB
2287 goto nla_put_failure;
2288
3bb20556
JB
2289 if (cmd != NL80211_CMD_NEW_WIPHY)
2290 goto finish;
2291
86e8cf98 2292 switch (state->split_start) {
3713b4e3
JB
2293 case 0:
2294 if (nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT,
1b8ec87a 2295 rdev->wiphy.retry_short) ||
3713b4e3 2296 nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_LONG,
1b8ec87a 2297 rdev->wiphy.retry_long) ||
3713b4e3 2298 nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
1b8ec87a 2299 rdev->wiphy.frag_threshold) ||
3713b4e3 2300 nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD,
1b8ec87a 2301 rdev->wiphy.rts_threshold) ||
3713b4e3 2302 nla_put_u8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS,
1b8ec87a 2303 rdev->wiphy.coverage_class) ||
3713b4e3 2304 nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
1b8ec87a 2305 rdev->wiphy.max_scan_ssids) ||
3713b4e3 2306 nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
1b8ec87a 2307 rdev->wiphy.max_sched_scan_ssids) ||
3713b4e3 2308 nla_put_u16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
1b8ec87a 2309 rdev->wiphy.max_scan_ie_len) ||
3713b4e3 2310 nla_put_u16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN,
1b8ec87a 2311 rdev->wiphy.max_sched_scan_ie_len) ||
3713b4e3 2312 nla_put_u8(msg, NL80211_ATTR_MAX_MATCH_SETS,
f8d504ca 2313 rdev->wiphy.max_match_sets))
9360ffd1 2314 goto nla_put_failure;
3713b4e3 2315
1b8ec87a 2316 if ((rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) &&
3713b4e3 2317 nla_put_flag(msg, NL80211_ATTR_SUPPORT_IBSS_RSN))
aa430da4 2318 goto nla_put_failure;
1b8ec87a 2319 if ((rdev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) &&
3713b4e3
JB
2320 nla_put_flag(msg, NL80211_ATTR_SUPPORT_MESH_AUTH))
2321 goto nla_put_failure;
1b8ec87a 2322 if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) &&
3713b4e3
JB
2323 nla_put_flag(msg, NL80211_ATTR_SUPPORT_AP_UAPSD))
2324 goto nla_put_failure;
1b8ec87a 2325 if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) &&
3713b4e3
JB
2326 nla_put_flag(msg, NL80211_ATTR_ROAM_SUPPORT))
2327 goto nla_put_failure;
1b8ec87a 2328 if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
3713b4e3
JB
2329 nla_put_flag(msg, NL80211_ATTR_TDLS_SUPPORT))
2330 goto nla_put_failure;
1b8ec87a 2331 if ((rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) &&
3713b4e3 2332 nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP))
9360ffd1 2333 goto nla_put_failure;
86e8cf98
JB
2334 state->split_start++;
2335 if (state->split)
3713b4e3 2336 break;
7b506ff6 2337 fallthrough;
3713b4e3
JB
2338 case 1:
2339 if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES,
1b8ec87a
ZG
2340 sizeof(u32) * rdev->wiphy.n_cipher_suites,
2341 rdev->wiphy.cipher_suites))
3713b4e3 2342 goto nla_put_failure;
4745fc09 2343
3713b4e3 2344 if (nla_put_u8(msg, NL80211_ATTR_MAX_NUM_PMKIDS,
1b8ec87a 2345 rdev->wiphy.max_num_pmkids))
3713b4e3 2346 goto nla_put_failure;
b23aa676 2347
1b8ec87a 2348 if ((rdev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) &&
3713b4e3 2349 nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE))
9360ffd1 2350 goto nla_put_failure;
b23aa676 2351
3713b4e3 2352 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX,
1b8ec87a 2353 rdev->wiphy.available_antennas_tx) ||
3713b4e3 2354 nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX,
1b8ec87a 2355 rdev->wiphy.available_antennas_rx))
9360ffd1 2356 goto nla_put_failure;
b23aa676 2357
1b8ec87a 2358 if ((rdev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) &&
3713b4e3 2359 nla_put_u32(msg, NL80211_ATTR_PROBE_RESP_OFFLOAD,
1b8ec87a 2360 rdev->wiphy.probe_resp_offload))
3713b4e3 2361 goto nla_put_failure;
8fdc621d 2362
1b8ec87a
ZG
2363 if ((rdev->wiphy.available_antennas_tx ||
2364 rdev->wiphy.available_antennas_rx) &&
2365 rdev->ops->get_antenna) {
3713b4e3
JB
2366 u32 tx_ant = 0, rx_ant = 0;
2367 int res;
7a087e74 2368
1b8ec87a 2369 res = rdev_get_antenna(rdev, &tx_ant, &rx_ant);
3713b4e3
JB
2370 if (!res) {
2371 if (nla_put_u32(msg,
2372 NL80211_ATTR_WIPHY_ANTENNA_TX,
2373 tx_ant) ||
2374 nla_put_u32(msg,
2375 NL80211_ATTR_WIPHY_ANTENNA_RX,
2376 rx_ant))
2377 goto nla_put_failure;
2378 }
2379 }
a293911d 2380
86e8cf98
JB
2381 state->split_start++;
2382 if (state->split)
3713b4e3 2383 break;
7b506ff6 2384 fallthrough;
3713b4e3
JB
2385 case 2:
2386 if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES,
1b8ec87a 2387 rdev->wiphy.interface_modes))
3713b4e3 2388 goto nla_put_failure;
86e8cf98
JB
2389 state->split_start++;
2390 if (state->split)
3713b4e3 2391 break;
7b506ff6 2392 fallthrough;
3713b4e3 2393 case 3:
ae0be8de
MK
2394 nl_bands = nla_nest_start_noflag(msg,
2395 NL80211_ATTR_WIPHY_BANDS);
3713b4e3
JB
2396 if (!nl_bands)
2397 goto nla_put_failure;
f7ca38df 2398
86e8cf98 2399 for (band = state->band_start;
0d059964
JB
2400 band < (state->split ?
2401 NUM_NL80211_BANDS :
2402 NL80211_BAND_60GHZ + 1);
2403 band++) {
3713b4e3 2404 struct ieee80211_supported_band *sband;
2e161f78 2405
f8d504ca
JB
2406 /* omit higher bands for ancient software */
2407 if (band > NL80211_BAND_5GHZ && !state->split)
2408 break;
2409
1b8ec87a 2410 sband = rdev->wiphy.bands[band];
2e161f78 2411
3713b4e3
JB
2412 if (!sband)
2413 continue;
2414
ae0be8de 2415 nl_band = nla_nest_start_noflag(msg, band);
3713b4e3 2416 if (!nl_band)
2e161f78 2417 goto nla_put_failure;
3713b4e3 2418
86e8cf98 2419 switch (state->chan_start) {
3713b4e3 2420 case 0:
f8d504ca
JB
2421 if (nl80211_send_band_rateinfo(msg, sband,
2422 state->split))
9360ffd1 2423 goto nla_put_failure;
86e8cf98
JB
2424 state->chan_start++;
2425 if (state->split)
3713b4e3 2426 break;
7b506ff6 2427 fallthrough;
3713b4e3
JB
2428 default:
2429 /* add frequencies */
ae0be8de
MK
2430 nl_freqs = nla_nest_start_noflag(msg,
2431 NL80211_BAND_ATTR_FREQS);
3713b4e3
JB
2432 if (!nl_freqs)
2433 goto nla_put_failure;
2434
86e8cf98 2435 for (i = state->chan_start - 1;
3713b4e3
JB
2436 i < sband->n_channels;
2437 i++) {
ae0be8de
MK
2438 nl_freq = nla_nest_start_noflag(msg,
2439 i);
3713b4e3
JB
2440 if (!nl_freq)
2441 goto nla_put_failure;
2442
2443 chan = &sband->channels[i];
2444
86e8cf98 2445 if (nl80211_msg_put_channel(
50f32718 2446 msg, &rdev->wiphy, chan,
86e8cf98 2447 state->split))
3713b4e3
JB
2448 goto nla_put_failure;
2449
2450 nla_nest_end(msg, nl_freq);
86e8cf98 2451 if (state->split)
3713b4e3
JB
2452 break;
2453 }
2454 if (i < sband->n_channels)
86e8cf98 2455 state->chan_start = i + 2;
3713b4e3 2456 else
86e8cf98 2457 state->chan_start = 0;
3713b4e3
JB
2458 nla_nest_end(msg, nl_freqs);
2459 }
2460
2461 nla_nest_end(msg, nl_band);
2462
86e8cf98 2463 if (state->split) {
3713b4e3 2464 /* start again here */
86e8cf98 2465 if (state->chan_start)
3713b4e3
JB
2466 band--;
2467 break;
2e161f78 2468 }
2e161f78 2469 }
3713b4e3 2470 nla_nest_end(msg, nl_bands);
2e161f78 2471
57fbcce3 2472 if (band < NUM_NL80211_BANDS)
86e8cf98 2473 state->band_start = band + 1;
3713b4e3 2474 else
86e8cf98 2475 state->band_start = 0;
74b70a4e 2476
3713b4e3 2477 /* if bands & channels are done, continue outside */
86e8cf98
JB
2478 if (state->band_start == 0 && state->chan_start == 0)
2479 state->split_start++;
2480 if (state->split)
3713b4e3 2481 break;
7b506ff6 2482 fallthrough;
3713b4e3 2483 case 4:
ae0be8de
MK
2484 nl_cmds = nla_nest_start_noflag(msg,
2485 NL80211_ATTR_SUPPORTED_COMMANDS);
3713b4e3 2486 if (!nl_cmds)
2e161f78
JB
2487 goto nla_put_failure;
2488
1794899e
JB
2489 i = nl80211_add_commands_unsplit(rdev, msg);
2490 if (i < 0)
2491 goto nla_put_failure;
86e8cf98 2492 if (state->split) {
5de17984
AS
2493 CMD(crit_proto_start, CRIT_PROTOCOL_START);
2494 CMD(crit_proto_stop, CRIT_PROTOCOL_STOP);
1b8ec87a 2495 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)
16ef1fe2 2496 CMD(channel_switch, CHANNEL_SWITCH);
02df00eb 2497 CMD(set_qos_map, SET_QOS_MAP);
723e73ac
JB
2498 if (rdev->wiphy.features &
2499 NL80211_FEATURE_SUPPORTS_WMM_ADMISSION)
960d01ac 2500 CMD(add_tx_ts, ADD_TX_TS);
ce0ce13a 2501 CMD(set_multicast_to_unicast, SET_MULTICAST_TO_UNICAST);
088e8df8 2502 CMD(update_connect_params, UPDATE_CONNECT_PARAMS);
7010998c 2503 CMD(update_ft_ies, UPDATE_FT_IES);
6bdb68ce
CH
2504 if (rdev->wiphy.sar_capa)
2505 CMD(set_sar_specs, SET_SAR_SPECS);
5de17984 2506 }
3713b4e3 2507#undef CMD
ff1b6e69 2508
3713b4e3 2509 nla_nest_end(msg, nl_cmds);
86e8cf98
JB
2510 state->split_start++;
2511 if (state->split)
3713b4e3 2512 break;
7b506ff6 2513 fallthrough;
3713b4e3 2514 case 5:
1b8ec87a
ZG
2515 if (rdev->ops->remain_on_channel &&
2516 (rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) &&
3713b4e3
JB
2517 nla_put_u32(msg,
2518 NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION,
1b8ec87a 2519 rdev->wiphy.max_remain_on_channel_duration))
3713b4e3
JB
2520 goto nla_put_failure;
2521
1b8ec87a 2522 if ((rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX) &&
3713b4e3
JB
2523 nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK))
2524 goto nla_put_failure;
2525
86e8cf98
JB
2526 state->split_start++;
2527 if (state->split)
3713b4e3 2528 break;
7b506ff6 2529 fallthrough;
3713b4e3
JB
2530 case 6:
2531#ifdef CONFIG_PM
1b8ec87a 2532 if (nl80211_send_wowlan(msg, rdev, state->split))
3713b4e3 2533 goto nla_put_failure;
86e8cf98
JB
2534 state->split_start++;
2535 if (state->split)
3713b4e3
JB
2536 break;
2537#else
86e8cf98 2538 state->split_start++;
dfb89c56 2539#endif
7b506ff6 2540 fallthrough;
3713b4e3
JB
2541 case 7:
2542 if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES,
1b8ec87a 2543 rdev->wiphy.software_iftypes))
3713b4e3 2544 goto nla_put_failure;
ff1b6e69 2545
1b8ec87a 2546 if (nl80211_put_iface_combinations(&rdev->wiphy, msg,
86e8cf98 2547 state->split))
3713b4e3 2548 goto nla_put_failure;
7527a782 2549
86e8cf98
JB
2550 state->split_start++;
2551 if (state->split)
3713b4e3 2552 break;
7b506ff6 2553 fallthrough;
3713b4e3 2554 case 8:
1b8ec87a 2555 if ((rdev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) &&
3713b4e3 2556 nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME,
1b8ec87a 2557 rdev->wiphy.ap_sme_capa))
3713b4e3 2558 goto nla_put_failure;
7527a782 2559
1b8ec87a 2560 features = rdev->wiphy.features;
fe1abafd
JB
2561 /*
2562 * We can only add the per-channel limit information if the
2563 * dump is split, otherwise it makes it too big. Therefore
2564 * only advertise it in that case.
2565 */
86e8cf98 2566 if (state->split)
fe1abafd
JB
2567 features |= NL80211_FEATURE_ADVERTISE_CHAN_LIMITS;
2568 if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, features))
3713b4e3 2569 goto nla_put_failure;
562a7480 2570
1b8ec87a 2571 if (rdev->wiphy.ht_capa_mod_mask &&
3713b4e3 2572 nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK,
1b8ec87a
ZG
2573 sizeof(*rdev->wiphy.ht_capa_mod_mask),
2574 rdev->wiphy.ht_capa_mod_mask))
3713b4e3 2575 goto nla_put_failure;
1f074bd8 2576
1b8ec87a
ZG
2577 if (rdev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME &&
2578 rdev->wiphy.max_acl_mac_addrs &&
3713b4e3 2579 nla_put_u32(msg, NL80211_ATTR_MAC_ACL_MAX,
1b8ec87a 2580 rdev->wiphy.max_acl_mac_addrs))
3713b4e3 2581 goto nla_put_failure;
7e7c8926 2582
3713b4e3
JB
2583 /*
2584 * Any information below this point is only available to
2585 * applications that can deal with it being split. This
2586 * helps ensure that newly added capabilities don't break
2587 * older tools by overrunning their buffers.
2588 *
2589 * We still increment split_start so that in the split
2590 * case we'll continue with more data in the next round,
2591 * but break unconditionally so unsplit data stops here.
2592 */
ab10c22b
JB
2593 if (state->split)
2594 state->split_start++;
2595 else
2596 state->split_start = 0;
3713b4e3
JB
2597 break;
2598 case 9:
f8d504ca
JB
2599 if (nl80211_send_mgmt_stypes(msg, mgmt_stypes))
2600 goto nla_put_failure;
2601
2602 if (nla_put_u32(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS,
2603 rdev->wiphy.max_sched_scan_plans) ||
2604 nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL,
2605 rdev->wiphy.max_sched_scan_plan_interval) ||
2606 nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS,
2607 rdev->wiphy.max_sched_scan_plan_iterations))
2608 goto nla_put_failure;
2609
1b8ec87a 2610 if (rdev->wiphy.extended_capabilities &&
fe1abafd 2611 (nla_put(msg, NL80211_ATTR_EXT_CAPA,
1b8ec87a
ZG
2612 rdev->wiphy.extended_capabilities_len,
2613 rdev->wiphy.extended_capabilities) ||
fe1abafd 2614 nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK,
1b8ec87a
ZG
2615 rdev->wiphy.extended_capabilities_len,
2616 rdev->wiphy.extended_capabilities_mask)))
fe1abafd 2617 goto nla_put_failure;
a50df0c4 2618
1b8ec87a 2619 if (rdev->wiphy.vht_capa_mod_mask &&
ee2aca34 2620 nla_put(msg, NL80211_ATTR_VHT_CAPABILITY_MASK,
1b8ec87a
ZG
2621 sizeof(*rdev->wiphy.vht_capa_mod_mask),
2622 rdev->wiphy.vht_capa_mod_mask))
ee2aca34
JB
2623 goto nla_put_failure;
2624
ae6fa4d5
DK
2625 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
2626 rdev->wiphy.perm_addr))
2627 goto nla_put_failure;
2628
2629 if (!is_zero_ether_addr(rdev->wiphy.addr_mask) &&
2630 nla_put(msg, NL80211_ATTR_MAC_MASK, ETH_ALEN,
2631 rdev->wiphy.addr_mask))
2632 goto nla_put_failure;
2633
2634 if (rdev->wiphy.n_addresses > 1) {
2635 void *attr;
2636
2637 attr = nla_nest_start(msg, NL80211_ATTR_MAC_ADDRS);
2638 if (!attr)
2639 goto nla_put_failure;
2640
2641 for (i = 0; i < rdev->wiphy.n_addresses; i++)
2642 if (nla_put(msg, i + 1, ETH_ALEN,
2643 rdev->wiphy.addresses[i].addr))
2644 goto nla_put_failure;
2645
2646 nla_nest_end(msg, attr);
2647 }
2648
be29b99a
AK
2649 state->split_start++;
2650 break;
2651 case 10:
1b8ec87a 2652 if (nl80211_send_coalesce(msg, rdev))
be29b99a
AK
2653 goto nla_put_failure;
2654
1b8ec87a 2655 if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) &&
01e0daa4
FF
2656 (nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) ||
2657 nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ)))
2658 goto nla_put_failure;
b43504cf 2659
1b8ec87a 2660 if (rdev->wiphy.max_ap_assoc_sta &&
b43504cf 2661 nla_put_u32(msg, NL80211_ATTR_MAX_AP_ASSOC_STA,
1b8ec87a 2662 rdev->wiphy.max_ap_assoc_sta))
b43504cf
JM
2663 goto nla_put_failure;
2664
ad7e718c
JB
2665 state->split_start++;
2666 break;
2667 case 11:
1b8ec87a 2668 if (rdev->wiphy.n_vendor_commands) {
567ffc35
JB
2669 const struct nl80211_vendor_cmd_info *info;
2670 struct nlattr *nested;
2671
ae0be8de
MK
2672 nested = nla_nest_start_noflag(msg,
2673 NL80211_ATTR_VENDOR_DATA);
567ffc35
JB
2674 if (!nested)
2675 goto nla_put_failure;
2676
1b8ec87a
ZG
2677 for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) {
2678 info = &rdev->wiphy.vendor_commands[i].info;
567ffc35
JB
2679 if (nla_put(msg, i + 1, sizeof(*info), info))
2680 goto nla_put_failure;
2681 }
2682 nla_nest_end(msg, nested);
2683 }
2684
1b8ec87a 2685 if (rdev->wiphy.n_vendor_events) {
567ffc35
JB
2686 const struct nl80211_vendor_cmd_info *info;
2687 struct nlattr *nested;
ad7e718c 2688
ae0be8de
MK
2689 nested = nla_nest_start_noflag(msg,
2690 NL80211_ATTR_VENDOR_EVENTS);
567ffc35 2691 if (!nested)
ad7e718c 2692 goto nla_put_failure;
567ffc35 2693
1b8ec87a
ZG
2694 for (i = 0; i < rdev->wiphy.n_vendor_events; i++) {
2695 info = &rdev->wiphy.vendor_events[i];
567ffc35
JB
2696 if (nla_put(msg, i + 1, sizeof(*info), info))
2697 goto nla_put_failure;
2698 }
2699 nla_nest_end(msg, nested);
2700 }
9a774c78
AO
2701 state->split_start++;
2702 break;
2703 case 12:
2704 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH &&
2705 nla_put_u8(msg, NL80211_ATTR_MAX_CSA_COUNTERS,
2706 rdev->wiphy.max_num_csa_counters))
2707 goto nla_put_failure;
01e0daa4 2708
1bdd716c
AN
2709 if (rdev->wiphy.regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
2710 nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
2711 goto nla_put_failure;
2712
ca986ad9
AVS
2713 if (rdev->wiphy.max_sched_scan_reqs &&
2714 nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_MAX_REQS,
2715 rdev->wiphy.max_sched_scan_reqs))
2716 goto nla_put_failure;
2717
d75bb06b
GKS
2718 if (nla_put(msg, NL80211_ATTR_EXT_FEATURES,
2719 sizeof(rdev->wiphy.ext_features),
2720 rdev->wiphy.ext_features))
2721 goto nla_put_failure;
2722
38de03d2
AS
2723 if (rdev->wiphy.bss_select_support) {
2724 struct nlattr *nested;
2725 u32 bss_select_support = rdev->wiphy.bss_select_support;
2726
ae0be8de
MK
2727 nested = nla_nest_start_noflag(msg,
2728 NL80211_ATTR_BSS_SELECT);
38de03d2
AS
2729 if (!nested)
2730 goto nla_put_failure;
2731
2732 i = 0;
2733 while (bss_select_support) {
2734 if ((bss_select_support & 1) &&
2735 nla_put_flag(msg, i))
2736 goto nla_put_failure;
2737 i++;
2738 bss_select_support >>= 1;
2739 }
2740 nla_nest_end(msg, nested);
2741 }
2742
019ae3a9
KV
2743 state->split_start++;
2744 break;
2745 case 13:
2746 if (rdev->wiphy.num_iftype_ext_capab &&
2747 rdev->wiphy.iftype_ext_capab) {
2748 struct nlattr *nested_ext_capab, *nested;
2749
ae0be8de
MK
2750 nested = nla_nest_start_noflag(msg,
2751 NL80211_ATTR_IFTYPE_EXT_CAPA);
019ae3a9
KV
2752 if (!nested)
2753 goto nla_put_failure;
2754
2755 for (i = state->capa_start;
2756 i < rdev->wiphy.num_iftype_ext_capab; i++) {
2757 const struct wiphy_iftype_ext_capab *capab;
2758
2759 capab = &rdev->wiphy.iftype_ext_capab[i];
2760
ae0be8de
MK
2761 nested_ext_capab = nla_nest_start_noflag(msg,
2762 i);
019ae3a9
KV
2763 if (!nested_ext_capab ||
2764 nla_put_u32(msg, NL80211_ATTR_IFTYPE,
2765 capab->iftype) ||
2766 nla_put(msg, NL80211_ATTR_EXT_CAPA,
2767 capab->extended_capabilities_len,
2768 capab->extended_capabilities) ||
2769 nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK,
2770 capab->extended_capabilities_len,
2771 capab->extended_capabilities_mask))
2772 goto nla_put_failure;
2773
2774 nla_nest_end(msg, nested_ext_capab);
2775 if (state->split)
2776 break;
2777 }
2778 nla_nest_end(msg, nested);
2779 if (i < rdev->wiphy.num_iftype_ext_capab) {
2780 state->capa_start = i + 1;
2781 break;
2782 }
2783 }
2784
8585989d
LC
2785 if (nla_put_u32(msg, NL80211_ATTR_BANDS,
2786 rdev->wiphy.nan_supported_bands))
2787 goto nla_put_failure;
2788
52539ca8
THJ
2789 if (wiphy_ext_feature_isset(&rdev->wiphy,
2790 NL80211_EXT_FEATURE_TXQS)) {
2791 struct cfg80211_txq_stats txqstats = {};
2792 int res;
2793
2794 res = rdev_get_txq_stats(rdev, NULL, &txqstats);
2795 if (!res &&
2796 !nl80211_put_txq_stats(msg, &txqstats,
2797 NL80211_ATTR_TXQ_STATS))
2798 goto nla_put_failure;
2799
2800 if (nla_put_u32(msg, NL80211_ATTR_TXQ_LIMIT,
2801 rdev->wiphy.txq_limit))
2802 goto nla_put_failure;
2803 if (nla_put_u32(msg, NL80211_ATTR_TXQ_MEMORY_LIMIT,
2804 rdev->wiphy.txq_memory_limit))
2805 goto nla_put_failure;
2806 if (nla_put_u32(msg, NL80211_ATTR_TXQ_QUANTUM,
2807 rdev->wiphy.txq_quantum))
2808 goto nla_put_failure;
2809 }
2810
9bb7e0f2
JB
2811 state->split_start++;
2812 break;
2813 case 14:
2814 if (nl80211_send_pmsr_capa(rdev, msg))
2815 goto nla_put_failure;
2816
ab4dfa20
VJ
2817 state->split_start++;
2818 break;
2819 case 15:
2820 if (rdev->wiphy.akm_suites &&
2821 nla_put(msg, NL80211_ATTR_AKM_SUITES,
2822 sizeof(u32) * rdev->wiphy.n_akm_suites,
2823 rdev->wiphy.akm_suites))
2824 goto nla_put_failure;
2825
d6039a34
VJ
2826 if (nl80211_put_iftype_akm_suites(rdev, msg))
2827 goto nla_put_failure;
2828
3710a8a6
JB
2829 if (nl80211_put_tid_config_support(rdev, msg))
2830 goto nla_put_failure;
6bdb68ce
CH
2831 state->split_start++;
2832 break;
2833 case 16:
2834 if (nl80211_put_sar_specs(rdev, msg))
2835 goto nla_put_failure;
3710a8a6 2836
dc1e3cb8
JC
2837 if (nl80211_put_mbssid_support(&rdev->wiphy, msg))
2838 goto nla_put_failure;
2839
3713b4e3 2840 /* done */
86e8cf98 2841 state->split_start = 0;
3713b4e3
JB
2842 break;
2843 }
3bb20556 2844 finish:
053c095a
JB
2845 genlmsg_end(msg, hdr);
2846 return 0;
55682965
JB
2847
2848 nla_put_failure:
bc3ed28c
TG
2849 genlmsg_cancel(msg, hdr);
2850 return -EMSGSIZE;
55682965
JB
2851}
2852
86e8cf98
JB
2853static int nl80211_dump_wiphy_parse(struct sk_buff *skb,
2854 struct netlink_callback *cb,
2855 struct nl80211_dump_wiphy_state *state)
2856{
50508d94
JB
2857 struct nlattr **tb = kcalloc(NUM_NL80211_ATTR, sizeof(*tb), GFP_KERNEL);
2858 int ret;
2859
2860 if (!tb)
2861 return -ENOMEM;
2862
2863 ret = nlmsg_parse_deprecated(cb->nlh,
2864 GENL_HDRLEN + nl80211_fam.hdrsize,
2865 tb, nl80211_fam.maxattr,
2866 nl80211_policy, NULL);
86e8cf98 2867 /* ignore parse errors for backward compatibility */
50508d94
JB
2868 if (ret) {
2869 ret = 0;
2870 goto out;
2871 }
86e8cf98
JB
2872
2873 state->split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP];
2874 if (tb[NL80211_ATTR_WIPHY])
2875 state->filter_wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
2876 if (tb[NL80211_ATTR_WDEV])
2877 state->filter_wiphy = nla_get_u64(tb[NL80211_ATTR_WDEV]) >> 32;
2878 if (tb[NL80211_ATTR_IFINDEX]) {
2879 struct net_device *netdev;
2880 struct cfg80211_registered_device *rdev;
2881 int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
2882
7f2b8562 2883 netdev = __dev_get_by_index(sock_net(skb->sk), ifidx);
50508d94
JB
2884 if (!netdev) {
2885 ret = -ENODEV;
2886 goto out;
2887 }
86e8cf98 2888 if (netdev->ieee80211_ptr) {
f26cbf40 2889 rdev = wiphy_to_rdev(
86e8cf98
JB
2890 netdev->ieee80211_ptr->wiphy);
2891 state->filter_wiphy = rdev->wiphy_idx;
2892 }
86e8cf98
JB
2893 }
2894
50508d94
JB
2895 ret = 0;
2896out:
2897 kfree(tb);
2898 return ret;
86e8cf98
JB
2899}
2900
55682965
JB
2901static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
2902{
645e77de 2903 int idx = 0, ret;
86e8cf98 2904 struct nl80211_dump_wiphy_state *state = (void *)cb->args[0];
1b8ec87a 2905 struct cfg80211_registered_device *rdev;
3a5a423b 2906
5fe231e8 2907 rtnl_lock();
86e8cf98
JB
2908 if (!state) {
2909 state = kzalloc(sizeof(*state), GFP_KERNEL);
57ed5cd6
JL
2910 if (!state) {
2911 rtnl_unlock();
86e8cf98 2912 return -ENOMEM;
3713b4e3 2913 }
86e8cf98
JB
2914 state->filter_wiphy = -1;
2915 ret = nl80211_dump_wiphy_parse(skb, cb, state);
2916 if (ret) {
2917 kfree(state);
2918 rtnl_unlock();
2919 return ret;
3713b4e3 2920 }
86e8cf98 2921 cb->args[0] = (long)state;
3713b4e3
JB
2922 }
2923
1b8ec87a
ZG
2924 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
2925 if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
463d0183 2926 continue;
86e8cf98 2927 if (++idx <= state->start)
55682965 2928 continue;
86e8cf98 2929 if (state->filter_wiphy != -1 &&
1b8ec87a 2930 state->filter_wiphy != rdev->wiphy_idx)
3713b4e3
JB
2931 continue;
2932 /* attempt to fit multiple wiphy data chunks into the skb */
2933 do {
3bb20556
JB
2934 ret = nl80211_send_wiphy(rdev, NL80211_CMD_NEW_WIPHY,
2935 skb,
3713b4e3
JB
2936 NETLINK_CB(cb->skb).portid,
2937 cb->nlh->nlmsg_seq,
86e8cf98 2938 NLM_F_MULTI, state);
3713b4e3
JB
2939 if (ret < 0) {
2940 /*
2941 * If sending the wiphy data didn't fit (ENOBUFS
2942 * or EMSGSIZE returned), this SKB is still
2943 * empty (so it's not too big because another
2944 * wiphy dataset is already in the skb) and
2945 * we've not tried to adjust the dump allocation
2946 * yet ... then adjust the alloc size to be
2947 * bigger, and return 1 but with the empty skb.
2948 * This results in an empty message being RX'ed
2949 * in userspace, but that is ignored.
2950 *
2951 * We can then retry with the larger buffer.
2952 */
2953 if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
f12cb289 2954 !skb->len && !state->split &&
3713b4e3
JB
2955 cb->min_dump_alloc < 4096) {
2956 cb->min_dump_alloc = 4096;
f12cb289 2957 state->split_start = 0;
d98cae64 2958 rtnl_unlock();
3713b4e3
JB
2959 return 1;
2960 }
2961 idx--;
2962 break;
645e77de 2963 }
86e8cf98 2964 } while (state->split_start > 0);
3713b4e3 2965 break;
55682965 2966 }
5fe231e8 2967 rtnl_unlock();
55682965 2968
86e8cf98 2969 state->start = idx;
55682965
JB
2970
2971 return skb->len;
2972}
2973
86e8cf98
JB
2974static int nl80211_dump_wiphy_done(struct netlink_callback *cb)
2975{
2976 kfree((void *)cb->args[0]);
2977 return 0;
2978}
2979
55682965
JB
2980static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
2981{
2982 struct sk_buff *msg;
1b8ec87a 2983 struct cfg80211_registered_device *rdev = info->user_ptr[0];
86e8cf98 2984 struct nl80211_dump_wiphy_state state = {};
55682965 2985
645e77de 2986 msg = nlmsg_new(4096, GFP_KERNEL);
55682965 2987 if (!msg)
4c476991 2988 return -ENOMEM;
55682965 2989
3bb20556
JB
2990 if (nl80211_send_wiphy(rdev, NL80211_CMD_NEW_WIPHY, msg,
2991 info->snd_portid, info->snd_seq, 0,
86e8cf98 2992 &state) < 0) {
4c476991
JB
2993 nlmsg_free(msg);
2994 return -ENOBUFS;
2995 }
55682965 2996
134e6375 2997 return genlmsg_reply(msg, info);
55682965
JB
2998}
2999
31888487
JM
3000static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = {
3001 [NL80211_TXQ_ATTR_QUEUE] = { .type = NLA_U8 },
3002 [NL80211_TXQ_ATTR_TXOP] = { .type = NLA_U16 },
3003 [NL80211_TXQ_ATTR_CWMIN] = { .type = NLA_U16 },
3004 [NL80211_TXQ_ATTR_CWMAX] = { .type = NLA_U16 },
3005 [NL80211_TXQ_ATTR_AIFS] = { .type = NLA_U8 },
3006};
3007
3008static int parse_txq_params(struct nlattr *tb[],
3009 struct ieee80211_txq_params *txq_params)
3010{
259d8c1e
DW
3011 u8 ac;
3012
a3304b0a 3013 if (!tb[NL80211_TXQ_ATTR_AC] || !tb[NL80211_TXQ_ATTR_TXOP] ||
31888487
JM
3014 !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] ||
3015 !tb[NL80211_TXQ_ATTR_AIFS])
3016 return -EINVAL;
3017
259d8c1e 3018 ac = nla_get_u8(tb[NL80211_TXQ_ATTR_AC]);
31888487
JM
3019 txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]);
3020 txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]);
3021 txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]);
3022 txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]);
3023
259d8c1e 3024 if (ac >= NL80211_NUM_ACS)
a3304b0a 3025 return -EINVAL;
259d8c1e 3026 txq_params->ac = array_index_nospec(ac, NL80211_NUM_ACS);
31888487
JM
3027 return 0;
3028}
3029
f444de05
JB
3030static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev)
3031{
3032 /*
e7e0517c
JB
3033 * You can only set the channel explicitly for some interfaces,
3034 * most have their channel managed via their respective
cc1d2806
JB
3035 * "establish a connection" command (connect, join, ...)
3036 *
3037 * For AP/GO and mesh mode, the channel can be set with the
3038 * channel userspace API, but is only stored and passed to the
3039 * low-level driver when the AP starts or the mesh is joined.
3040 * This is for backward compatibility, userspace can also give
3041 * the channel in the start-ap or join-mesh commands instead.
f444de05
JB
3042 *
3043 * Monitors are special as they are normally slaved to
e8c9bd5b
JB
3044 * whatever else is going on, so they have their own special
3045 * operation to set the monitor channel if possible.
f444de05
JB
3046 */
3047 return !wdev ||
3048 wdev->iftype == NL80211_IFTYPE_AP ||
f444de05 3049 wdev->iftype == NL80211_IFTYPE_MESH_POINT ||
074ac8df
JB
3050 wdev->iftype == NL80211_IFTYPE_MONITOR ||
3051 wdev->iftype == NL80211_IFTYPE_P2P_GO;
f444de05
JB
3052}
3053
9bb7e0f2
JB
3054int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
3055 struct genl_info *info,
3056 struct cfg80211_chan_def *chandef)
683b6d3b 3057{
49f9cf0e
JB
3058 struct netlink_ext_ack *extack = info->extack;
3059 struct nlattr **attrs = info->attrs;
dbeca2ea 3060 u32 control_freq;
683b6d3b 3061
49f9cf0e 3062 if (!attrs[NL80211_ATTR_WIPHY_FREQ])
683b6d3b
JB
3063 return -EINVAL;
3064
942ba88b
TP
3065 control_freq = MHZ_TO_KHZ(
3066 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
3067 if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
3068 control_freq +=
3069 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
683b6d3b 3070
f43e5210 3071 memset(chandef, 0, sizeof(*chandef));
942ba88b 3072 chandef->chan = ieee80211_get_channel_khz(&rdev->wiphy, control_freq);
3d9d1d66 3073 chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
942ba88b
TP
3074 chandef->center_freq1 = KHZ_TO_MHZ(control_freq);
3075 chandef->freq1_offset = control_freq % 1000;
3d9d1d66 3076 chandef->center_freq2 = 0;
683b6d3b
JB
3077
3078 /* Primary channel not allowed */
49f9cf0e
JB
3079 if (!chandef->chan || chandef->chan->flags & IEEE80211_CHAN_DISABLED) {
3080 NL_SET_ERR_MSG_ATTR(extack, attrs[NL80211_ATTR_WIPHY_FREQ],
3081 "Channel is disabled");
683b6d3b 3082 return -EINVAL;
49f9cf0e 3083 }
683b6d3b 3084
49f9cf0e 3085 if (attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
3d9d1d66
JB
3086 enum nl80211_channel_type chantype;
3087
49f9cf0e 3088 chantype = nla_get_u32(attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
3d9d1d66
JB
3089
3090 switch (chantype) {
3091 case NL80211_CHAN_NO_HT:
3092 case NL80211_CHAN_HT20:
3093 case NL80211_CHAN_HT40PLUS:
3094 case NL80211_CHAN_HT40MINUS:
3095 cfg80211_chandef_create(chandef, chandef->chan,
3096 chantype);
ffa4629e 3097 /* user input for center_freq is incorrect */
49f9cf0e
JB
3098 if (attrs[NL80211_ATTR_CENTER_FREQ1] &&
3099 chandef->center_freq1 != nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1])) {
3100 NL_SET_ERR_MSG_ATTR(extack,
3101 attrs[NL80211_ATTR_CENTER_FREQ1],
3102 "bad center frequency 1");
ffa4629e 3103 return -EINVAL;
49f9cf0e 3104 }
ffa4629e 3105 /* center_freq2 must be zero */
49f9cf0e
JB
3106 if (attrs[NL80211_ATTR_CENTER_FREQ2] &&
3107 nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2])) {
3108 NL_SET_ERR_MSG_ATTR(extack,
3109 attrs[NL80211_ATTR_CENTER_FREQ2],
3110 "center frequency 2 can't be used");
ffa4629e 3111 return -EINVAL;
49f9cf0e 3112 }
3d9d1d66
JB
3113 break;
3114 default:
49f9cf0e
JB
3115 NL_SET_ERR_MSG_ATTR(extack,
3116 attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
3117 "invalid channel type");
3d9d1d66
JB
3118 return -EINVAL;
3119 }
49f9cf0e 3120 } else if (attrs[NL80211_ATTR_CHANNEL_WIDTH]) {
3d9d1d66 3121 chandef->width =
49f9cf0e 3122 nla_get_u32(attrs[NL80211_ATTR_CHANNEL_WIDTH]);
942ba88b 3123 if (attrs[NL80211_ATTR_CENTER_FREQ1]) {
3d9d1d66 3124 chandef->center_freq1 =
49f9cf0e 3125 nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1]);
942ba88b
TP
3126 if (attrs[NL80211_ATTR_CENTER_FREQ1_OFFSET])
3127 chandef->freq1_offset = nla_get_u32(
3128 attrs[NL80211_ATTR_CENTER_FREQ1_OFFSET]);
3129 else
3130 chandef->freq1_offset = 0;
3131 }
49f9cf0e 3132 if (attrs[NL80211_ATTR_CENTER_FREQ2])
3d9d1d66 3133 chandef->center_freq2 =
49f9cf0e 3134 nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2]);
3d9d1d66
JB
3135 }
3136
2a38075c
AAL
3137 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]) {
3138 chandef->edmg.channels =
3139 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]);
3140
3141 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG])
3142 chandef->edmg.bw_config =
3143 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]);
3144 } else {
3145 chandef->edmg.bw_config = 0;
3146 chandef->edmg.channels = 0;
3147 }
3148
49f9cf0e
JB
3149 if (!cfg80211_chandef_valid(chandef)) {
3150 NL_SET_ERR_MSG(extack, "invalid channel definition");
3d9d1d66 3151 return -EINVAL;
49f9cf0e 3152 }
3d9d1d66 3153
9f5e8f6e 3154 if (!cfg80211_chandef_usable(&rdev->wiphy, chandef,
49f9cf0e
JB
3155 IEEE80211_CHAN_DISABLED)) {
3156 NL_SET_ERR_MSG(extack, "(extension) channel is disabled");
3d9d1d66 3157 return -EINVAL;
49f9cf0e 3158 }
3d9d1d66 3159
2f301ab2
SW
3160 if ((chandef->width == NL80211_CHAN_WIDTH_5 ||
3161 chandef->width == NL80211_CHAN_WIDTH_10) &&
49f9cf0e
JB
3162 !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ)) {
3163 NL_SET_ERR_MSG(extack, "5/10 MHz not supported");
2f301ab2 3164 return -EINVAL;
49f9cf0e 3165 }
2f301ab2 3166
683b6d3b
JB
3167 return 0;
3168}
3169
f444de05 3170static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
e16821bc 3171 struct net_device *dev,
f444de05
JB
3172 struct genl_info *info)
3173{
683b6d3b 3174 struct cfg80211_chan_def chandef;
f444de05 3175 int result;
e8c9bd5b 3176 enum nl80211_iftype iftype = NL80211_IFTYPE_MONITOR;
e16821bc 3177 struct wireless_dev *wdev = NULL;
e8c9bd5b 3178
e16821bc
JM
3179 if (dev)
3180 wdev = dev->ieee80211_ptr;
f444de05
JB
3181 if (!nl80211_can_set_dev_channel(wdev))
3182 return -EOPNOTSUPP;
e16821bc
JM
3183 if (wdev)
3184 iftype = wdev->iftype;
f444de05 3185
683b6d3b
JB
3186 result = nl80211_parse_chandef(rdev, info, &chandef);
3187 if (result)
3188 return result;
f444de05 3189
e8c9bd5b 3190 switch (iftype) {
aa430da4
JB
3191 case NL80211_IFTYPE_AP:
3192 case NL80211_IFTYPE_P2P_GO:
923b352f
AN
3193 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
3194 iftype)) {
aa430da4
JB
3195 result = -EINVAL;
3196 break;
3197 }
e16821bc
JM
3198 if (wdev->beacon_interval) {
3199 if (!dev || !rdev->ops->set_ap_chanwidth ||
3200 !(rdev->wiphy.features &
3201 NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE)) {
3202 result = -EBUSY;
3203 break;
3204 }
3205
3206 /* Only allow dynamic channel width changes */
3207 if (chandef.chan != wdev->preset_chandef.chan) {
3208 result = -EBUSY;
3209 break;
3210 }
3211 result = rdev_set_ap_chanwidth(rdev, dev, &chandef);
3212 if (result)
3213 break;
3214 }
683b6d3b 3215 wdev->preset_chandef = chandef;
aa430da4
JB
3216 result = 0;
3217 break;
cc1d2806 3218 case NL80211_IFTYPE_MESH_POINT:
683b6d3b 3219 result = cfg80211_set_mesh_channel(rdev, wdev, &chandef);
cc1d2806 3220 break;
e8c9bd5b 3221 case NL80211_IFTYPE_MONITOR:
683b6d3b 3222 result = cfg80211_set_monitor_channel(rdev, &chandef);
e8c9bd5b 3223 break;
aa430da4 3224 default:
e8c9bd5b 3225 result = -EINVAL;
f444de05 3226 }
f444de05
JB
3227
3228 return result;
3229}
3230
3231static int nl80211_set_channel(struct sk_buff *skb, struct genl_info *info)
3232{
4c476991
JB
3233 struct cfg80211_registered_device *rdev = info->user_ptr[0];
3234 struct net_device *netdev = info->user_ptr[1];
f444de05 3235
e16821bc 3236 return __nl80211_set_channel(rdev, netdev, info);
f444de05
JB
3237}
3238
55682965
JB
3239static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
3240{
a05829a7 3241 struct cfg80211_registered_device *rdev = NULL;
f444de05
JB
3242 struct net_device *netdev = NULL;
3243 struct wireless_dev *wdev;
a1e567c8 3244 int result = 0, rem_txq_params = 0;
31888487 3245 struct nlattr *nl_txq_params;
b9a5f8ca
JM
3246 u32 changed;
3247 u8 retry_short = 0, retry_long = 0;
3248 u32 frag_threshold = 0, rts_threshold = 0;
81077e82 3249 u8 coverage_class = 0;
52539ca8 3250 u32 txq_limit = 0, txq_memory_limit = 0, txq_quantum = 0;
55682965 3251
a05829a7 3252 rtnl_lock();
f444de05
JB
3253 /*
3254 * Try to find the wiphy and netdev. Normally this
3255 * function shouldn't need the netdev, but this is
3256 * done for backward compatibility -- previously
3257 * setting the channel was done per wiphy, but now
3258 * it is per netdev. Previous userland like hostapd
3259 * also passed a netdev to set_wiphy, so that it is
3260 * possible to let that go to the right netdev!
3261 */
4bbf4d56 3262
f444de05
JB
3263 if (info->attrs[NL80211_ATTR_IFINDEX]) {
3264 int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
3265
7f2b8562 3266 netdev = __dev_get_by_index(genl_info_net(info), ifindex);
5fe231e8 3267 if (netdev && netdev->ieee80211_ptr)
f26cbf40 3268 rdev = wiphy_to_rdev(netdev->ieee80211_ptr->wiphy);
5fe231e8 3269 else
f444de05 3270 netdev = NULL;
4bbf4d56
JB
3271 }
3272
f444de05 3273 if (!netdev) {
878d9ec7
JB
3274 rdev = __cfg80211_rdev_from_attrs(genl_info_net(info),
3275 info->attrs);
a05829a7
JB
3276 if (IS_ERR(rdev)) {
3277 rtnl_unlock();
4c476991 3278 return PTR_ERR(rdev);
a05829a7 3279 }
f444de05
JB
3280 wdev = NULL;
3281 netdev = NULL;
3282 result = 0;
71fe96bf 3283 } else
f444de05 3284 wdev = netdev->ieee80211_ptr;
f444de05 3285
a05829a7 3286 wiphy_lock(&rdev->wiphy);
a05829a7 3287
f444de05
JB
3288 /*
3289 * end workaround code, by now the rdev is available
3290 * and locked, and wdev may or may not be NULL.
3291 */
4bbf4d56
JB
3292
3293 if (info->attrs[NL80211_ATTR_WIPHY_NAME])
31888487
JM
3294 result = cfg80211_dev_rename(
3295 rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
0391a45c 3296 rtnl_unlock();
4bbf4d56 3297
4bbf4d56 3298 if (result)
a05829a7 3299 goto out;
31888487
JM
3300
3301 if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) {
3302 struct ieee80211_txq_params txq_params;
3303 struct nlattr *tb[NL80211_TXQ_ATTR_MAX + 1];
3304
a05829a7
JB
3305 if (!rdev->ops->set_txq_params) {
3306 result = -EOPNOTSUPP;
3307 goto out;
3308 }
31888487 3309
a05829a7
JB
3310 if (!netdev) {
3311 result = -EINVAL;
3312 goto out;
3313 }
f70f01c2 3314
133a3ff2 3315 if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
a05829a7
JB
3316 netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
3317 result = -EINVAL;
3318 goto out;
3319 }
133a3ff2 3320
a05829a7
JB
3321 if (!netif_running(netdev)) {
3322 result = -ENETDOWN;
3323 goto out;
3324 }
2b5f8b0b 3325
31888487
JM
3326 nla_for_each_nested(nl_txq_params,
3327 info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
3328 rem_txq_params) {
8cb08174
JB
3329 result = nla_parse_nested_deprecated(tb,
3330 NL80211_TXQ_ATTR_MAX,
3331 nl_txq_params,
3332 txq_params_policy,
3333 info->extack);
ae811e21 3334 if (result)
a05829a7 3335 goto out;
31888487
JM
3336 result = parse_txq_params(tb, &txq_params);
3337 if (result)
a05829a7 3338 goto out;
31888487 3339
e35e4d28
HG
3340 result = rdev_set_txq_params(rdev, netdev,
3341 &txq_params);
31888487 3342 if (result)
a05829a7 3343 goto out;
31888487
JM
3344 }
3345 }
55682965 3346
72bdcf34 3347 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
e16821bc
JM
3348 result = __nl80211_set_channel(
3349 rdev,
3350 nl80211_can_set_dev_channel(wdev) ? netdev : NULL,
3351 info);
72bdcf34 3352 if (result)
a05829a7 3353 goto out;
72bdcf34
JM
3354 }
3355
98d2ff8b 3356 if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) {
c8442118 3357 struct wireless_dev *txp_wdev = wdev;
98d2ff8b
JO
3358 enum nl80211_tx_power_setting type;
3359 int idx, mbm = 0;
3360
c8442118
JB
3361 if (!(rdev->wiphy.features & NL80211_FEATURE_VIF_TXPOWER))
3362 txp_wdev = NULL;
3363
a05829a7
JB
3364 if (!rdev->ops->set_tx_power) {
3365 result = -EOPNOTSUPP;
3366 goto out;
3367 }
98d2ff8b
JO
3368
3369 idx = NL80211_ATTR_WIPHY_TX_POWER_SETTING;
3370 type = nla_get_u32(info->attrs[idx]);
3371
3372 if (!info->attrs[NL80211_ATTR_WIPHY_TX_POWER_LEVEL] &&
a05829a7
JB
3373 (type != NL80211_TX_POWER_AUTOMATIC)) {
3374 result = -EINVAL;
3375 goto out;
3376 }
98d2ff8b
JO
3377
3378 if (type != NL80211_TX_POWER_AUTOMATIC) {
3379 idx = NL80211_ATTR_WIPHY_TX_POWER_LEVEL;
3380 mbm = nla_get_u32(info->attrs[idx]);
3381 }
3382
c8442118 3383 result = rdev_set_tx_power(rdev, txp_wdev, type, mbm);
98d2ff8b 3384 if (result)
a05829a7 3385 goto out;
98d2ff8b
JO
3386 }
3387
afe0cbf8
BR
3388 if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
3389 info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {
3390 u32 tx_ant, rx_ant;
7a087e74 3391
7f531e03
BR
3392 if ((!rdev->wiphy.available_antennas_tx &&
3393 !rdev->wiphy.available_antennas_rx) ||
a05829a7
JB
3394 !rdev->ops->set_antenna) {
3395 result = -EOPNOTSUPP;
3396 goto out;
3397 }
afe0cbf8
BR
3398
3399 tx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]);
3400 rx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]);
3401
a7ffac95 3402 /* reject antenna configurations which don't match the
7f531e03
BR
3403 * available antenna masks, except for the "all" mask */
3404 if ((~tx_ant && (tx_ant & ~rdev->wiphy.available_antennas_tx)) ||
a05829a7
JB
3405 (~rx_ant && (rx_ant & ~rdev->wiphy.available_antennas_rx))) {
3406 result = -EINVAL;
3407 goto out;
3408 }
a7ffac95 3409
7f531e03
BR
3410 tx_ant = tx_ant & rdev->wiphy.available_antennas_tx;
3411 rx_ant = rx_ant & rdev->wiphy.available_antennas_rx;
a7ffac95 3412
e35e4d28 3413 result = rdev_set_antenna(rdev, tx_ant, rx_ant);
afe0cbf8 3414 if (result)
a05829a7 3415 goto out;
afe0cbf8
BR
3416 }
3417
b9a5f8ca
JM
3418 changed = 0;
3419
3420 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {
3421 retry_short = nla_get_u8(
3422 info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]);
7f2b8562 3423
b9a5f8ca
JM
3424 changed |= WIPHY_PARAM_RETRY_SHORT;
3425 }
3426
3427 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]) {
3428 retry_long = nla_get_u8(
3429 info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]);
7f2b8562 3430
b9a5f8ca
JM
3431 changed |= WIPHY_PARAM_RETRY_LONG;
3432 }
3433
3434 if (info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) {
3435 frag_threshold = nla_get_u32(
3436 info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]);
a05829a7
JB
3437 if (frag_threshold < 256) {
3438 result = -EINVAL;
3439 goto out;
3440 }
7f2b8562 3441
b9a5f8ca
JM
3442 if (frag_threshold != (u32) -1) {
3443 /*
3444 * Fragments (apart from the last one) are required to
3445 * have even length. Make the fragmentation code
3446 * simpler by stripping LSB should someone try to use
3447 * odd threshold value.
3448 */
3449 frag_threshold &= ~0x1;
3450 }
3451 changed |= WIPHY_PARAM_FRAG_THRESHOLD;
3452 }
3453
3454 if (info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]) {
3455 rts_threshold = nla_get_u32(
3456 info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]);
3457 changed |= WIPHY_PARAM_RTS_THRESHOLD;
3458 }
3459
81077e82 3460 if (info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) {
a05829a7
JB
3461 if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) {
3462 result = -EINVAL;
3463 goto out;
3464 }
3057dbfd 3465
81077e82
LT
3466 coverage_class = nla_get_u8(
3467 info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]);
3468 changed |= WIPHY_PARAM_COVERAGE_CLASS;
3469 }
3470
3057dbfd 3471 if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) {
a05829a7
JB
3472 if (!(rdev->wiphy.features & NL80211_FEATURE_ACKTO_ESTIMATION)) {
3473 result = -EOPNOTSUPP;
3474 goto out;
3475 }
3057dbfd
LB
3476
3477 changed |= WIPHY_PARAM_DYN_ACK;
81077e82
LT
3478 }
3479
52539ca8
THJ
3480 if (info->attrs[NL80211_ATTR_TXQ_LIMIT]) {
3481 if (!wiphy_ext_feature_isset(&rdev->wiphy,
a05829a7
JB
3482 NL80211_EXT_FEATURE_TXQS)) {
3483 result = -EOPNOTSUPP;
3484 goto out;
3485 }
52539ca8
THJ
3486 txq_limit = nla_get_u32(
3487 info->attrs[NL80211_ATTR_TXQ_LIMIT]);
3488 changed |= WIPHY_PARAM_TXQ_LIMIT;
3489 }
3490
3491 if (info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]) {
3492 if (!wiphy_ext_feature_isset(&rdev->wiphy,
a05829a7
JB
3493 NL80211_EXT_FEATURE_TXQS)) {
3494 result = -EOPNOTSUPP;
3495 goto out;
3496 }
52539ca8
THJ
3497 txq_memory_limit = nla_get_u32(
3498 info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]);
3499 changed |= WIPHY_PARAM_TXQ_MEMORY_LIMIT;
3500 }
3501
3502 if (info->attrs[NL80211_ATTR_TXQ_QUANTUM]) {
3503 if (!wiphy_ext_feature_isset(&rdev->wiphy,
a05829a7
JB
3504 NL80211_EXT_FEATURE_TXQS)) {
3505 result = -EOPNOTSUPP;
3506 goto out;
3507 }
52539ca8
THJ
3508 txq_quantum = nla_get_u32(
3509 info->attrs[NL80211_ATTR_TXQ_QUANTUM]);
3510 changed |= WIPHY_PARAM_TXQ_QUANTUM;
3511 }
3512
b9a5f8ca
JM
3513 if (changed) {
3514 u8 old_retry_short, old_retry_long;
3515 u32 old_frag_threshold, old_rts_threshold;
81077e82 3516 u8 old_coverage_class;
52539ca8 3517 u32 old_txq_limit, old_txq_memory_limit, old_txq_quantum;
b9a5f8ca 3518
a05829a7
JB
3519 if (!rdev->ops->set_wiphy_params) {
3520 result = -EOPNOTSUPP;
3521 goto out;
3522 }
b9a5f8ca
JM
3523
3524 old_retry_short = rdev->wiphy.retry_short;
3525 old_retry_long = rdev->wiphy.retry_long;
3526 old_frag_threshold = rdev->wiphy.frag_threshold;
3527 old_rts_threshold = rdev->wiphy.rts_threshold;
81077e82 3528 old_coverage_class = rdev->wiphy.coverage_class;
52539ca8
THJ
3529 old_txq_limit = rdev->wiphy.txq_limit;
3530 old_txq_memory_limit = rdev->wiphy.txq_memory_limit;
3531 old_txq_quantum = rdev->wiphy.txq_quantum;
b9a5f8ca
JM
3532
3533 if (changed & WIPHY_PARAM_RETRY_SHORT)
3534 rdev->wiphy.retry_short = retry_short;
3535 if (changed & WIPHY_PARAM_RETRY_LONG)
3536 rdev->wiphy.retry_long = retry_long;
3537 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
3538 rdev->wiphy.frag_threshold = frag_threshold;
3539 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
3540 rdev->wiphy.rts_threshold = rts_threshold;
81077e82
LT
3541 if (changed & WIPHY_PARAM_COVERAGE_CLASS)
3542 rdev->wiphy.coverage_class = coverage_class;
52539ca8
THJ
3543 if (changed & WIPHY_PARAM_TXQ_LIMIT)
3544 rdev->wiphy.txq_limit = txq_limit;
3545 if (changed & WIPHY_PARAM_TXQ_MEMORY_LIMIT)
3546 rdev->wiphy.txq_memory_limit = txq_memory_limit;
3547 if (changed & WIPHY_PARAM_TXQ_QUANTUM)
3548 rdev->wiphy.txq_quantum = txq_quantum;
b9a5f8ca 3549
e35e4d28 3550 result = rdev_set_wiphy_params(rdev, changed);
b9a5f8ca
JM
3551 if (result) {
3552 rdev->wiphy.retry_short = old_retry_short;
3553 rdev->wiphy.retry_long = old_retry_long;
3554 rdev->wiphy.frag_threshold = old_frag_threshold;
3555 rdev->wiphy.rts_threshold = old_rts_threshold;
81077e82 3556 rdev->wiphy.coverage_class = old_coverage_class;
52539ca8
THJ
3557 rdev->wiphy.txq_limit = old_txq_limit;
3558 rdev->wiphy.txq_memory_limit = old_txq_memory_limit;
3559 rdev->wiphy.txq_quantum = old_txq_quantum;
a05829a7 3560 goto out;
b9a5f8ca
JM
3561 }
3562 }
a05829a7
JB
3563
3564 result = 0;
3565
3566out:
3567 wiphy_unlock(&rdev->wiphy);
3568 return result;
55682965
JB
3569}
3570
683b6d3b 3571static int nl80211_send_chandef(struct sk_buff *msg,
d2859df5 3572 const struct cfg80211_chan_def *chandef)
683b6d3b 3573{
601555cd
JB
3574 if (WARN_ON(!cfg80211_chandef_valid(chandef)))
3575 return -EINVAL;
3d9d1d66 3576
683b6d3b
JB
3577 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
3578 chandef->chan->center_freq))
3579 return -ENOBUFS;
942ba88b
TP
3580 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
3581 chandef->chan->freq_offset))
3582 return -ENOBUFS;
3d9d1d66
JB
3583 switch (chandef->width) {
3584 case NL80211_CHAN_WIDTH_20_NOHT:
3585 case NL80211_CHAN_WIDTH_20:
3586 case NL80211_CHAN_WIDTH_40:
3587 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
3588 cfg80211_get_chandef_type(chandef)))
3589 return -ENOBUFS;
3590 break;
3591 default:
3592 break;
3593 }
3594 if (nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, chandef->width))
3595 return -ENOBUFS;
3596 if (nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ1, chandef->center_freq1))
3597 return -ENOBUFS;
3598 if (chandef->center_freq2 &&
3599 nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2, chandef->center_freq2))
683b6d3b
JB
3600 return -ENOBUFS;
3601 return 0;
3602}
3603
15e47304 3604static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags,
d726405a 3605 struct cfg80211_registered_device *rdev,
3d1a5bbf
AZ
3606 struct wireless_dev *wdev,
3607 enum nl80211_commands cmd)
55682965 3608{
72fb2abc 3609 struct net_device *dev = wdev->netdev;
55682965
JB
3610 void *hdr;
3611
3d1a5bbf
AZ
3612 WARN_ON(cmd != NL80211_CMD_NEW_INTERFACE &&
3613 cmd != NL80211_CMD_DEL_INTERFACE &&
3614 cmd != NL80211_CMD_SET_INTERFACE);
8f894be2
TB
3615
3616 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
55682965
JB
3617 if (!hdr)
3618 return -1;
3619
72fb2abc
JB
3620 if (dev &&
3621 (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
98104fde 3622 nla_put_string(msg, NL80211_ATTR_IFNAME, dev->name)))
72fb2abc
JB
3623 goto nla_put_failure;
3624
3625 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
3626 nla_put_u32(msg, NL80211_ATTR_IFTYPE, wdev->iftype) ||
2dad624e
ND
3627 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
3628 NL80211_ATTR_PAD) ||
98104fde 3629 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, wdev_address(wdev)) ||
9360ffd1
DM
3630 nla_put_u32(msg, NL80211_ATTR_GENERATION,
3631 rdev->devlist_generation ^
446faa15
AQ
3632 (cfg80211_rdev_list_generation << 2)) ||
3633 nla_put_u8(msg, NL80211_ATTR_4ADDR, wdev->use_4addr))
9360ffd1 3634 goto nla_put_failure;
f5ea9120 3635
5b7ccaf3 3636 if (rdev->ops->get_channel) {
683b6d3b 3637 int ret;
f43e5210 3638 struct cfg80211_chan_def chandef = {};
683b6d3b
JB
3639
3640 ret = rdev_get_channel(rdev, wdev, &chandef);
3641 if (ret == 0) {
3642 if (nl80211_send_chandef(msg, &chandef))
3643 goto nla_put_failure;
3644 }
d91df0e3
PF
3645 }
3646
d55d0d59
RM
3647 if (rdev->ops->get_tx_power) {
3648 int dbm, ret;
3649
3650 ret = rdev_get_tx_power(rdev, wdev, &dbm);
3651 if (ret == 0 &&
3652 nla_put_u32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL,
3653 DBM_TO_MBM(dbm)))
3654 goto nla_put_failure;
3655 }
3656
44905265
JB
3657 wdev_lock(wdev);
3658 switch (wdev->iftype) {
3659 case NL80211_IFTYPE_AP:
3660 if (wdev->ssid_len &&
3661 nla_put(msg, NL80211_ATTR_SSID, wdev->ssid_len, wdev->ssid))
4564b187 3662 goto nla_put_failure_locked;
44905265
JB
3663 break;
3664 case NL80211_IFTYPE_STATION:
3665 case NL80211_IFTYPE_P2P_CLIENT:
3666 case NL80211_IFTYPE_ADHOC: {
3667 const u8 *ssid_ie;
3668 if (!wdev->current_bss)
3669 break;
7a94b8c2 3670 rcu_read_lock();
44905265
JB
3671 ssid_ie = ieee80211_bss_get_ie(&wdev->current_bss->pub,
3672 WLAN_EID_SSID);
7a94b8c2
DB
3673 if (ssid_ie &&
3674 nla_put(msg, NL80211_ATTR_SSID, ssid_ie[1], ssid_ie + 2))
3675 goto nla_put_failure_rcu_locked;
3676 rcu_read_unlock();
44905265
JB
3677 break;
3678 }
3679 default:
3680 /* nothing */
3681 break;
b84e7a05 3682 }
44905265 3683 wdev_unlock(wdev);
b84e7a05 3684
52539ca8
THJ
3685 if (rdev->ops->get_txq_stats) {
3686 struct cfg80211_txq_stats txqstats = {};
3687 int ret = rdev_get_txq_stats(rdev, wdev, &txqstats);
3688
3689 if (ret == 0 &&
3690 !nl80211_put_txq_stats(msg, &txqstats,
3691 NL80211_ATTR_TXQ_STATS))
3692 goto nla_put_failure;
3693 }
3694
053c095a
JB
3695 genlmsg_end(msg, hdr);
3696 return 0;
55682965 3697
7a94b8c2
DB
3698 nla_put_failure_rcu_locked:
3699 rcu_read_unlock();
4564b187
JB
3700 nla_put_failure_locked:
3701 wdev_unlock(wdev);
55682965 3702 nla_put_failure:
bc3ed28c
TG
3703 genlmsg_cancel(msg, hdr);
3704 return -EMSGSIZE;
55682965
JB
3705}
3706
3707static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
3708{
3709 int wp_idx = 0;
3710 int if_idx = 0;
3711 int wp_start = cb->args[0];
3712 int if_start = cb->args[1];
b7fb44da 3713 int filter_wiphy = -1;
f5ea9120 3714 struct cfg80211_registered_device *rdev;
55682965 3715 struct wireless_dev *wdev;
ea90e0dc 3716 int ret;
55682965 3717
5fe231e8 3718 rtnl_lock();
b7fb44da
DK
3719 if (!cb->args[2]) {
3720 struct nl80211_dump_wiphy_state state = {
3721 .filter_wiphy = -1,
3722 };
b7fb44da
DK
3723
3724 ret = nl80211_dump_wiphy_parse(skb, cb, &state);
3725 if (ret)
ea90e0dc 3726 goto out_unlock;
b7fb44da
DK
3727
3728 filter_wiphy = state.filter_wiphy;
3729
3730 /*
3731 * if filtering, set cb->args[2] to +1 since 0 is the default
3732 * value needed to determine that parsing is necessary.
3733 */
3734 if (filter_wiphy >= 0)
3735 cb->args[2] = filter_wiphy + 1;
3736 else
3737 cb->args[2] = -1;
3738 } else if (cb->args[2] > 0) {
3739 filter_wiphy = cb->args[2] - 1;
3740 }
3741
f5ea9120
JB
3742 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
3743 if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
463d0183 3744 continue;
bba95fef
JB
3745 if (wp_idx < wp_start) {
3746 wp_idx++;
55682965 3747 continue;
bba95fef 3748 }
b7fb44da
DK
3749
3750 if (filter_wiphy >= 0 && filter_wiphy != rdev->wiphy_idx)
3751 continue;
3752
55682965
JB
3753 if_idx = 0;
3754
53873f13 3755 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
bba95fef
JB
3756 if (if_idx < if_start) {
3757 if_idx++;
55682965 3758 continue;
bba95fef 3759 }
15e47304 3760 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid,
55682965 3761 cb->nlh->nlmsg_seq, NLM_F_MULTI,
3d1a5bbf
AZ
3762 rdev, wdev,
3763 NL80211_CMD_NEW_INTERFACE) < 0) {
bba95fef
JB
3764 goto out;
3765 }
3766 if_idx++;
55682965 3767 }
bba95fef
JB
3768
3769 wp_idx++;
55682965 3770 }
bba95fef 3771 out:
55682965
JB
3772 cb->args[0] = wp_idx;
3773 cb->args[1] = if_idx;
3774
ea90e0dc
JB
3775 ret = skb->len;
3776 out_unlock:
3777 rtnl_unlock();
3778
3779 return ret;
55682965
JB
3780}
3781
3782static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
3783{
3784 struct sk_buff *msg;
1b8ec87a 3785 struct cfg80211_registered_device *rdev = info->user_ptr[0];
72fb2abc 3786 struct wireless_dev *wdev = info->user_ptr[1];
55682965 3787
fd2120ca 3788 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
55682965 3789 if (!msg)
4c476991 3790 return -ENOMEM;
55682965 3791
15e47304 3792 if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0,
3d1a5bbf 3793 rdev, wdev, NL80211_CMD_NEW_INTERFACE) < 0) {
4c476991
JB
3794 nlmsg_free(msg);
3795 return -ENOBUFS;
3796 }
55682965 3797
134e6375 3798 return genlmsg_reply(msg, info);
55682965
JB
3799}
3800
66f7ac50
MW
3801static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = {
3802 [NL80211_MNTR_FLAG_FCSFAIL] = { .type = NLA_FLAG },
3803 [NL80211_MNTR_FLAG_PLCPFAIL] = { .type = NLA_FLAG },
3804 [NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG },
3805 [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG },
3806 [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG },
e057d3c3 3807 [NL80211_MNTR_FLAG_ACTIVE] = { .type = NLA_FLAG },
66f7ac50
MW
3808};
3809
3810static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
3811{
3812 struct nlattr *flags[NL80211_MNTR_FLAG_MAX + 1];
3813 int flag;
3814
3815 *mntrflags = 0;
3816
3817 if (!nla)
3818 return -EINVAL;
3819
8cb08174 3820 if (nla_parse_nested_deprecated(flags, NL80211_MNTR_FLAG_MAX, nla, mntr_flags_policy, NULL))
66f7ac50
MW
3821 return -EINVAL;
3822
3823 for (flag = 1; flag <= NL80211_MNTR_FLAG_MAX; flag++)
3824 if (flags[flag])
3825 *mntrflags |= (1<<flag);
3826
818a986e
JB
3827 *mntrflags |= MONITOR_FLAG_CHANGED;
3828
66f7ac50
MW
3829 return 0;
3830}
3831
1db77596
JB
3832static int nl80211_parse_mon_options(struct cfg80211_registered_device *rdev,
3833 enum nl80211_iftype type,
3834 struct genl_info *info,
3835 struct vif_params *params)
3836{
3837 bool change = false;
3838 int err;
3839
3840 if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
3841 if (type != NL80211_IFTYPE_MONITOR)
3842 return -EINVAL;
3843
3844 err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS],
3845 &params->flags);
3846 if (err)
3847 return err;
3848
3849 change = true;
3850 }
3851
3852 if (params->flags & MONITOR_FLAG_ACTIVE &&
3853 !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR))
3854 return -EOPNOTSUPP;
3855
3856 if (info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]) {
3857 const u8 *mumimo_groups;
3858 u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
3859
3860 if (type != NL80211_IFTYPE_MONITOR)
3861 return -EINVAL;
3862
3863 if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
3864 return -EOPNOTSUPP;
3865
3866 mumimo_groups =
3867 nla_data(info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]);
3868
3869 /* bits 0 and 63 are reserved and must be zero */
4954601f
JB
3870 if ((mumimo_groups[0] & BIT(0)) ||
3871 (mumimo_groups[VHT_MUMIMO_GROUPS_DATA_LEN - 1] & BIT(7)))
1db77596
JB
3872 return -EINVAL;
3873
3874 params->vht_mumimo_groups = mumimo_groups;
3875 change = true;
3876 }
3877
3878 if (info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]) {
3879 u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
3880
3881 if (type != NL80211_IFTYPE_MONITOR)
3882 return -EINVAL;
3883
3884 if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
3885 return -EOPNOTSUPP;
3886
3887 params->vht_mumimo_follow_addr =
3888 nla_data(info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]);
3889 change = true;
3890 }
3891
3892 return change ? 1 : 0;
3893}
3894
9bc383de 3895static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev,
ad4bb6f8
JB
3896 struct net_device *netdev, u8 use_4addr,
3897 enum nl80211_iftype iftype)
9bc383de 3898{
ad4bb6f8 3899 if (!use_4addr) {
2e92a2d0 3900 if (netdev && netif_is_bridge_port(netdev))
ad4bb6f8 3901 return -EBUSY;
9bc383de 3902 return 0;
ad4bb6f8 3903 }
9bc383de
JB
3904
3905 switch (iftype) {
3906 case NL80211_IFTYPE_AP_VLAN:
3907 if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP)
3908 return 0;
3909 break;
3910 case NL80211_IFTYPE_STATION:
3911 if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_STATION)
3912 return 0;
3913 break;
3914 default:
3915 break;
3916 }
3917
3918 return -EOPNOTSUPP;
3919}
3920
55682965
JB
3921static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
3922{
4c476991 3923 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2ec600d6 3924 struct vif_params params;
e36d56b6 3925 int err;
04a773ad 3926 enum nl80211_iftype otype, ntype;
4c476991 3927 struct net_device *dev = info->user_ptr[1];
ac7f9cfa 3928 bool change = false;
55682965 3929
2ec600d6
LCC
3930 memset(&params, 0, sizeof(params));
3931
04a773ad 3932 otype = ntype = dev->ieee80211_ptr->iftype;
55682965 3933
723b038d 3934 if (info->attrs[NL80211_ATTR_IFTYPE]) {
ac7f9cfa 3935 ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
04a773ad 3936 if (otype != ntype)
ac7f9cfa 3937 change = true;
723b038d
JB
3938 }
3939
92ffe055 3940 if (info->attrs[NL80211_ATTR_MESH_ID]) {
29cbe68c
JB
3941 struct wireless_dev *wdev = dev->ieee80211_ptr;
3942
4c476991
JB
3943 if (ntype != NL80211_IFTYPE_MESH_POINT)
3944 return -EINVAL;
29cbe68c
JB
3945 if (netif_running(dev))
3946 return -EBUSY;
3947
3948 wdev_lock(wdev);
3949 BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN !=
3950 IEEE80211_MAX_MESH_ID_LEN);
3951 wdev->mesh_id_up_len =
3952 nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
3953 memcpy(wdev->ssid, nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
3954 wdev->mesh_id_up_len);
3955 wdev_unlock(wdev);
2ec600d6
LCC
3956 }
3957
8b787643
FF
3958 if (info->attrs[NL80211_ATTR_4ADDR]) {
3959 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
3960 change = true;
ad4bb6f8 3961 err = nl80211_valid_4addr(rdev, dev, params.use_4addr, ntype);
9bc383de 3962 if (err)
4c476991 3963 return err;
8b787643
FF
3964 } else {
3965 params.use_4addr = -1;
3966 }
3967
1db77596
JB
3968 err = nl80211_parse_mon_options(rdev, ntype, info, &params);
3969 if (err < 0)
3970 return err;
3971 if (err > 0)
c6e6a0c8 3972 change = true;
e057d3c3 3973
ac7f9cfa 3974 if (change)
818a986e 3975 err = cfg80211_change_iface(rdev, dev, ntype, &params);
ac7f9cfa
JB
3976 else
3977 err = 0;
60719ffd 3978
9bc383de
JB
3979 if (!err && params.use_4addr != -1)
3980 dev->ieee80211_ptr->use_4addr = params.use_4addr;
3981
3d1a5bbf
AZ
3982 if (change && !err) {
3983 struct wireless_dev *wdev = dev->ieee80211_ptr;
3984
3985 nl80211_notify_iface(rdev, wdev, NL80211_CMD_SET_INTERFACE);
3986 }
3987
55682965
JB
3988 return err;
3989}
3990
ea6b2098 3991static int _nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
55682965 3992{
4c476991 3993 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2ec600d6 3994 struct vif_params params;
84efbb84 3995 struct wireless_dev *wdev;
896ff063 3996 struct sk_buff *msg;
55682965
JB
3997 int err;
3998 enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
3999
2ec600d6
LCC
4000 memset(&params, 0, sizeof(params));
4001
55682965
JB
4002 if (!info->attrs[NL80211_ATTR_IFNAME])
4003 return -EINVAL;
4004
ab0d76f6 4005 if (info->attrs[NL80211_ATTR_IFTYPE])
55682965 4006 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
55682965 4007
33d915d9 4008 if (!rdev->ops->add_virtual_intf)
4c476991 4009 return -EOPNOTSUPP;
55682965 4010
cb3b7d87 4011 if ((type == NL80211_IFTYPE_P2P_DEVICE || type == NL80211_IFTYPE_NAN ||
e8f479b1
BG
4012 rdev->wiphy.features & NL80211_FEATURE_MAC_ON_CREATE) &&
4013 info->attrs[NL80211_ATTR_MAC]) {
1c18f145
AS
4014 nla_memcpy(params.macaddr, info->attrs[NL80211_ATTR_MAC],
4015 ETH_ALEN);
4016 if (!is_valid_ether_addr(params.macaddr))
4017 return -EADDRNOTAVAIL;
4018 }
4019
9bc383de 4020 if (info->attrs[NL80211_ATTR_4ADDR]) {
8b787643 4021 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
ad4bb6f8 4022 err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type);
9bc383de 4023 if (err)
4c476991 4024 return err;
9bc383de 4025 }
8b787643 4026
e6f40511 4027 if (!cfg80211_iftype_allowed(&rdev->wiphy, type, params.use_4addr, 0))
33d915d9
MP
4028 return -EOPNOTSUPP;
4029
1db77596
JB
4030 err = nl80211_parse_mon_options(rdev, type, info, &params);
4031 if (err < 0)
4032 return err;
e057d3c3 4033
a18c7192
JB
4034 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4035 if (!msg)
4036 return -ENOMEM;
4037
e35e4d28
HG
4038 wdev = rdev_add_virtual_intf(rdev,
4039 nla_data(info->attrs[NL80211_ATTR_IFNAME]),
818a986e 4040 NET_NAME_USER, type, &params);
d687cbb7
RM
4041 if (WARN_ON(!wdev)) {
4042 nlmsg_free(msg);
4043 return -EPROTO;
4044 } else if (IS_ERR(wdev)) {
1c90f9d4 4045 nlmsg_free(msg);
84efbb84 4046 return PTR_ERR(wdev);
1c90f9d4 4047 }
2ec600d6 4048
18e5ca65 4049 if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
78f22b6a
JB
4050 wdev->owner_nlportid = info->snd_portid;
4051
98104fde
JB
4052 switch (type) {
4053 case NL80211_IFTYPE_MESH_POINT:
4054 if (!info->attrs[NL80211_ATTR_MESH_ID])
4055 break;
29cbe68c
JB
4056 wdev_lock(wdev);
4057 BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN !=
4058 IEEE80211_MAX_MESH_ID_LEN);
4059 wdev->mesh_id_up_len =
4060 nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
4061 memcpy(wdev->ssid, nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
4062 wdev->mesh_id_up_len);
4063 wdev_unlock(wdev);
98104fde 4064 break;
cb3b7d87 4065 case NL80211_IFTYPE_NAN:
98104fde
JB
4066 case NL80211_IFTYPE_P2P_DEVICE:
4067 /*
cb3b7d87 4068 * P2P Device and NAN do not have a netdev, so don't go
98104fde
JB
4069 * through the netdev notifier and must be added here
4070 */
9bdaf3b9
JB
4071 cfg80211_init_wdev(wdev);
4072 cfg80211_register_wdev(rdev, wdev);
98104fde
JB
4073 break;
4074 default:
4075 break;
29cbe68c
JB
4076 }
4077
15e47304 4078 if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0,
3d1a5bbf 4079 rdev, wdev, NL80211_CMD_NEW_INTERFACE) < 0) {
1c90f9d4
JB
4080 nlmsg_free(msg);
4081 return -ENOBUFS;
4082 }
4083
4084 return genlmsg_reply(msg, info);
55682965
JB
4085}
4086
ea6b2098
JB
4087static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
4088{
4089 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4090 int ret;
4091
4092 /* to avoid failing a new interface creation due to pending removal */
4093 cfg80211_destroy_ifaces(rdev);
4094
4095 wiphy_lock(&rdev->wiphy);
4096 ret = _nl80211_new_interface(skb, info);
4097 wiphy_unlock(&rdev->wiphy);
4098
4099 return ret;
4100}
4101
55682965
JB
4102static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
4103{
4c476991 4104 struct cfg80211_registered_device *rdev = info->user_ptr[0];
84efbb84 4105 struct wireless_dev *wdev = info->user_ptr[1];
55682965 4106
4c476991
JB
4107 if (!rdev->ops->del_virtual_intf)
4108 return -EOPNOTSUPP;
55682965 4109
a05829a7
JB
4110 /*
4111 * We hold RTNL, so this is safe, without RTNL opencount cannot
4112 * reach 0, and thus the rdev cannot be deleted.
4113 *
4114 * We need to do it for the dev_close(), since that will call
4115 * the netdev notifiers, and we need to acquire the mutex there
4116 * but don't know if we get there from here or from some other
4117 * place (e.g. "ip link set ... down").
4118 */
4119 mutex_unlock(&rdev->wiphy.mtx);
4120
84efbb84
JB
4121 /*
4122 * If we remove a wireless device without a netdev then clear
4123 * user_ptr[1] so that nl80211_post_doit won't dereference it
4124 * to check if it needs to do dev_put(). Otherwise it crashes
4125 * since the wdev has been freed, unlike with a netdev where
4126 * we need the dev_put() for the netdev to really be freed.
4127 */
4128 if (!wdev->netdev)
4129 info->user_ptr[1] = NULL;
a05829a7
JB
4130 else
4131 dev_close(wdev->netdev);
4132
4133 mutex_lock(&rdev->wiphy.mtx);
84efbb84 4134
7f8ed01e 4135 return rdev_del_virtual_intf(rdev, wdev);
55682965
JB
4136}
4137
1d9d9213
SW
4138static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info)
4139{
4140 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4141 struct net_device *dev = info->user_ptr[1];
4142 u16 noack_map;
4143
4144 if (!info->attrs[NL80211_ATTR_NOACK_MAP])
4145 return -EINVAL;
4146
4147 if (!rdev->ops->set_noack_map)
4148 return -EOPNOTSUPP;
4149
4150 noack_map = nla_get_u16(info->attrs[NL80211_ATTR_NOACK_MAP]);
4151
e35e4d28 4152 return rdev_set_noack_map(rdev, dev, noack_map);
1d9d9213
SW
4153}
4154
41ade00f
JB
4155struct get_key_cookie {
4156 struct sk_buff *msg;
4157 int error;
b9454e83 4158 int idx;
41ade00f
JB
4159};
4160
4161static void get_key_callback(void *c, struct key_params *params)
4162{
b9454e83 4163 struct nlattr *key;
41ade00f
JB
4164 struct get_key_cookie *cookie = c;
4165
9360ffd1
DM
4166 if ((params->key &&
4167 nla_put(cookie->msg, NL80211_ATTR_KEY_DATA,
4168 params->key_len, params->key)) ||
4169 (params->seq &&
4170 nla_put(cookie->msg, NL80211_ATTR_KEY_SEQ,
4171 params->seq_len, params->seq)) ||
4172 (params->cipher &&
4173 nla_put_u32(cookie->msg, NL80211_ATTR_KEY_CIPHER,
4174 params->cipher)))
4175 goto nla_put_failure;
41ade00f 4176
ae0be8de 4177 key = nla_nest_start_noflag(cookie->msg, NL80211_ATTR_KEY);
b9454e83
JB
4178 if (!key)
4179 goto nla_put_failure;
4180
9360ffd1
DM
4181 if ((params->key &&
4182 nla_put(cookie->msg, NL80211_KEY_DATA,
4183 params->key_len, params->key)) ||
4184 (params->seq &&
4185 nla_put(cookie->msg, NL80211_KEY_SEQ,
4186 params->seq_len, params->seq)) ||
4187 (params->cipher &&
4188 nla_put_u32(cookie->msg, NL80211_KEY_CIPHER,
4189 params->cipher)))
4190 goto nla_put_failure;
b9454e83 4191
efdfce72 4192 if (nla_put_u8(cookie->msg, NL80211_KEY_IDX, cookie->idx))
9360ffd1 4193 goto nla_put_failure;
b9454e83
JB
4194
4195 nla_nest_end(cookie->msg, key);
4196
41ade00f
JB
4197 return;
4198 nla_put_failure:
4199 cookie->error = 1;
4200}
4201
4202static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
4203{
4c476991 4204 struct cfg80211_registered_device *rdev = info->user_ptr[0];
41ade00f 4205 int err;
4c476991 4206 struct net_device *dev = info->user_ptr[1];
41ade00f 4207 u8 key_idx = 0;
e31b8213
JB
4208 const u8 *mac_addr = NULL;
4209 bool pairwise;
41ade00f
JB
4210 struct get_key_cookie cookie = {
4211 .error = 0,
4212 };
4213 void *hdr;
4214 struct sk_buff *msg;
155d7c73
JB
4215 bool bigtk_support = false;
4216
4217 if (wiphy_ext_feature_isset(&rdev->wiphy,
4218 NL80211_EXT_FEATURE_BEACON_PROTECTION))
4219 bigtk_support = true;
4220
4221 if ((dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION ||
4222 dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
4223 wiphy_ext_feature_isset(&rdev->wiphy,
4224 NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT))
4225 bigtk_support = true;
41ade00f 4226
56be393f 4227 if (info->attrs[NL80211_ATTR_KEY_IDX]) {
41ade00f 4228 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
155d7c73
JB
4229
4230 if (key_idx >= 6 && key_idx <= 7 && !bigtk_support) {
4231 GENL_SET_ERR_MSG(info, "BIGTK not supported");
56be393f 4232 return -EINVAL;
155d7c73 4233 }
56be393f 4234 }
41ade00f 4235
41ade00f
JB
4236 if (info->attrs[NL80211_ATTR_MAC])
4237 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4238
e31b8213
JB
4239 pairwise = !!mac_addr;
4240 if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
4241 u32 kt = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
7a087e74 4242
e31b8213
JB
4243 if (kt != NL80211_KEYTYPE_GROUP &&
4244 kt != NL80211_KEYTYPE_PAIRWISE)
4245 return -EINVAL;
4246 pairwise = kt == NL80211_KEYTYPE_PAIRWISE;
4247 }
4248
4c476991
JB
4249 if (!rdev->ops->get_key)
4250 return -EOPNOTSUPP;
41ade00f 4251
0fa7b391
JB
4252 if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
4253 return -ENOENT;
4254
fd2120ca 4255 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
4256 if (!msg)
4257 return -ENOMEM;
41ade00f 4258
15e47304 4259 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
41ade00f 4260 NL80211_CMD_NEW_KEY);
cb35fba3 4261 if (!hdr)
9fe271af 4262 goto nla_put_failure;
41ade00f
JB
4263
4264 cookie.msg = msg;
b9454e83 4265 cookie.idx = key_idx;
41ade00f 4266
9360ffd1
DM
4267 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
4268 nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx))
4269 goto nla_put_failure;
4270 if (mac_addr &&
4271 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr))
4272 goto nla_put_failure;
41ade00f 4273
e35e4d28
HG
4274 err = rdev_get_key(rdev, dev, key_idx, pairwise, mac_addr, &cookie,
4275 get_key_callback);
41ade00f
JB
4276
4277 if (err)
6c95e2a2 4278 goto free_msg;
41ade00f
JB
4279
4280 if (cookie.error)
4281 goto nla_put_failure;
4282
4283 genlmsg_end(msg, hdr);
4c476991 4284 return genlmsg_reply(msg, info);
41ade00f
JB
4285
4286 nla_put_failure:
4287 err = -ENOBUFS;
6c95e2a2 4288 free_msg:
41ade00f 4289 nlmsg_free(msg);
41ade00f
JB
4290 return err;
4291}
4292
4293static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
4294{
4c476991 4295 struct cfg80211_registered_device *rdev = info->user_ptr[0];
b9454e83 4296 struct key_parse key;
41ade00f 4297 int err;
4c476991 4298 struct net_device *dev = info->user_ptr[1];
41ade00f 4299
b9454e83
JB
4300 err = nl80211_parse_key(info, &key);
4301 if (err)
4302 return err;
41ade00f 4303
b9454e83 4304 if (key.idx < 0)
41ade00f
JB
4305 return -EINVAL;
4306
6cdd3979
AW
4307 /* Only support setting default key and
4308 * Extended Key ID action NL80211_KEY_SET_TX.
4309 */
56be393f 4310 if (!key.def && !key.defmgmt && !key.defbeacon &&
6cdd3979 4311 !(key.p.mode == NL80211_KEY_SET_TX))
41ade00f
JB
4312 return -EINVAL;
4313
dbd2fd65 4314 wdev_lock(dev->ieee80211_ptr);
3cfcf6ac 4315
dbd2fd65
JB
4316 if (key.def) {
4317 if (!rdev->ops->set_default_key) {
4318 err = -EOPNOTSUPP;
4319 goto out;
4320 }
41ade00f 4321
dbd2fd65
JB
4322 err = nl80211_key_allowed(dev->ieee80211_ptr);
4323 if (err)
4324 goto out;
4325
e35e4d28 4326 err = rdev_set_default_key(rdev, dev, key.idx,
dbd2fd65
JB
4327 key.def_uni, key.def_multi);
4328
4329 if (err)
4330 goto out;
fffd0934 4331
3d23e349 4332#ifdef CONFIG_CFG80211_WEXT
dbd2fd65
JB
4333 dev->ieee80211_ptr->wext.default_key = key.idx;
4334#endif
6cdd3979 4335 } else if (key.defmgmt) {
dbd2fd65
JB
4336 if (key.def_uni || !key.def_multi) {
4337 err = -EINVAL;
4338 goto out;
4339 }
4340
4341 if (!rdev->ops->set_default_mgmt_key) {
4342 err = -EOPNOTSUPP;
4343 goto out;
4344 }
4345
4346 err = nl80211_key_allowed(dev->ieee80211_ptr);
4347 if (err)
4348 goto out;
4349
e35e4d28 4350 err = rdev_set_default_mgmt_key(rdev, dev, key.idx);
dbd2fd65
JB
4351 if (err)
4352 goto out;
4353
4354#ifdef CONFIG_CFG80211_WEXT
4355 dev->ieee80211_ptr->wext.default_mgmt_key = key.idx;
08645126 4356#endif
56be393f
JM
4357 } else if (key.defbeacon) {
4358 if (key.def_uni || !key.def_multi) {
4359 err = -EINVAL;
4360 goto out;
4361 }
4362
4363 if (!rdev->ops->set_default_beacon_key) {
4364 err = -EOPNOTSUPP;
4365 goto out;
4366 }
4367
4368 err = nl80211_key_allowed(dev->ieee80211_ptr);
4369 if (err)
4370 goto out;
4371
4372 err = rdev_set_default_beacon_key(rdev, dev, key.idx);
4373 if (err)
4374 goto out;
6cdd3979
AW
4375 } else if (key.p.mode == NL80211_KEY_SET_TX &&
4376 wiphy_ext_feature_isset(&rdev->wiphy,
4377 NL80211_EXT_FEATURE_EXT_KEY_ID)) {
4378 u8 *mac_addr = NULL;
4379
4380 if (info->attrs[NL80211_ATTR_MAC])
4381 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4382
4383 if (!mac_addr || key.idx < 0 || key.idx > 1) {
4384 err = -EINVAL;
4385 goto out;
4386 }
dbd2fd65 4387
6cdd3979
AW
4388 err = rdev_add_key(rdev, dev, key.idx,
4389 NL80211_KEYTYPE_PAIRWISE,
4390 mac_addr, &key.p);
4391 } else {
4392 err = -EINVAL;
4393 }
dbd2fd65 4394 out:
fffd0934 4395 wdev_unlock(dev->ieee80211_ptr);
41ade00f 4396
41ade00f
JB
4397 return err;
4398}
4399
4400static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
4401{
4c476991 4402 struct cfg80211_registered_device *rdev = info->user_ptr[0];
fffd0934 4403 int err;
4c476991 4404 struct net_device *dev = info->user_ptr[1];
b9454e83 4405 struct key_parse key;
e31b8213 4406 const u8 *mac_addr = NULL;
41ade00f 4407
b9454e83
JB
4408 err = nl80211_parse_key(info, &key);
4409 if (err)
4410 return err;
41ade00f 4411
f8af764b
JM
4412 if (!key.p.key) {
4413 GENL_SET_ERR_MSG(info, "no key");
41ade00f 4414 return -EINVAL;
f8af764b 4415 }
41ade00f 4416
41ade00f
JB
4417 if (info->attrs[NL80211_ATTR_MAC])
4418 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4419
e31b8213
JB
4420 if (key.type == -1) {
4421 if (mac_addr)
4422 key.type = NL80211_KEYTYPE_PAIRWISE;
4423 else
4424 key.type = NL80211_KEYTYPE_GROUP;
4425 }
4426
4427 /* for now */
4428 if (key.type != NL80211_KEYTYPE_PAIRWISE &&
f8af764b
JM
4429 key.type != NL80211_KEYTYPE_GROUP) {
4430 GENL_SET_ERR_MSG(info, "key type not pairwise or group");
e31b8213 4431 return -EINVAL;
f8af764b 4432 }
e31b8213 4433
14f34e36
GG
4434 if (key.type == NL80211_KEYTYPE_GROUP &&
4435 info->attrs[NL80211_ATTR_VLAN_ID])
4436 key.p.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
4437
4c476991
JB
4438 if (!rdev->ops->add_key)
4439 return -EOPNOTSUPP;
25e47c18 4440
e31b8213
JB
4441 if (cfg80211_validate_key_settings(rdev, &key.p, key.idx,
4442 key.type == NL80211_KEYTYPE_PAIRWISE,
f8af764b
JM
4443 mac_addr)) {
4444 GENL_SET_ERR_MSG(info, "key setting validation failed");
4c476991 4445 return -EINVAL;
f8af764b 4446 }
41ade00f 4447
fffd0934
JB
4448 wdev_lock(dev->ieee80211_ptr);
4449 err = nl80211_key_allowed(dev->ieee80211_ptr);
f8af764b
JM
4450 if (err)
4451 GENL_SET_ERR_MSG(info, "key not allowed");
4452 if (!err) {
e35e4d28
HG
4453 err = rdev_add_key(rdev, dev, key.idx,
4454 key.type == NL80211_KEYTYPE_PAIRWISE,
4455 mac_addr, &key.p);
f8af764b
JM
4456 if (err)
4457 GENL_SET_ERR_MSG(info, "key addition failed");
4458 }
fffd0934 4459 wdev_unlock(dev->ieee80211_ptr);
41ade00f 4460
41ade00f
JB
4461 return err;
4462}
4463
4464static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
4465{
4c476991 4466 struct cfg80211_registered_device *rdev = info->user_ptr[0];
41ade00f 4467 int err;
4c476991 4468 struct net_device *dev = info->user_ptr[1];
41ade00f 4469 u8 *mac_addr = NULL;
b9454e83 4470 struct key_parse key;
41ade00f 4471
b9454e83
JB
4472 err = nl80211_parse_key(info, &key);
4473 if (err)
4474 return err;
41ade00f
JB
4475
4476 if (info->attrs[NL80211_ATTR_MAC])
4477 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4478
e31b8213
JB
4479 if (key.type == -1) {
4480 if (mac_addr)
4481 key.type = NL80211_KEYTYPE_PAIRWISE;
4482 else
4483 key.type = NL80211_KEYTYPE_GROUP;
4484 }
4485
4486 /* for now */
4487 if (key.type != NL80211_KEYTYPE_PAIRWISE &&
4488 key.type != NL80211_KEYTYPE_GROUP)
4489 return -EINVAL;
4490
2d946308
AT
4491 if (!cfg80211_valid_key_idx(rdev, key.idx,
4492 key.type == NL80211_KEYTYPE_PAIRWISE))
4493 return -EINVAL;
4494
4c476991
JB
4495 if (!rdev->ops->del_key)
4496 return -EOPNOTSUPP;
41ade00f 4497
fffd0934
JB
4498 wdev_lock(dev->ieee80211_ptr);
4499 err = nl80211_key_allowed(dev->ieee80211_ptr);
e31b8213 4500
0fa7b391 4501 if (key.type == NL80211_KEYTYPE_GROUP && mac_addr &&
e31b8213
JB
4502 !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
4503 err = -ENOENT;
4504
fffd0934 4505 if (!err)
e35e4d28
HG
4506 err = rdev_del_key(rdev, dev, key.idx,
4507 key.type == NL80211_KEYTYPE_PAIRWISE,
4508 mac_addr);
41ade00f 4509
3d23e349 4510#ifdef CONFIG_CFG80211_WEXT
08645126 4511 if (!err) {
b9454e83 4512 if (key.idx == dev->ieee80211_ptr->wext.default_key)
08645126 4513 dev->ieee80211_ptr->wext.default_key = -1;
b9454e83 4514 else if (key.idx == dev->ieee80211_ptr->wext.default_mgmt_key)
08645126
JB
4515 dev->ieee80211_ptr->wext.default_mgmt_key = -1;
4516 }
4517#endif
fffd0934 4518 wdev_unlock(dev->ieee80211_ptr);
08645126 4519
41ade00f
JB
4520 return err;
4521}
4522
77765eaf
VT
4523/* This function returns an error or the number of nested attributes */
4524static int validate_acl_mac_addrs(struct nlattr *nl_attr)
4525{
4526 struct nlattr *attr;
4527 int n_entries = 0, tmp;
4528
4529 nla_for_each_nested(attr, nl_attr, tmp) {
4530 if (nla_len(attr) != ETH_ALEN)
4531 return -EINVAL;
4532
4533 n_entries++;
4534 }
4535
4536 return n_entries;
4537}
4538
4539/*
4540 * This function parses ACL information and allocates memory for ACL data.
4541 * On successful return, the calling function is responsible to free the
4542 * ACL buffer returned by this function.
4543 */
4544static struct cfg80211_acl_data *parse_acl_data(struct wiphy *wiphy,
4545 struct genl_info *info)
4546{
4547 enum nl80211_acl_policy acl_policy;
4548 struct nlattr *attr;
4549 struct cfg80211_acl_data *acl;
4550 int i = 0, n_entries, tmp;
4551
4552 if (!wiphy->max_acl_mac_addrs)
4553 return ERR_PTR(-EOPNOTSUPP);
4554
4555 if (!info->attrs[NL80211_ATTR_ACL_POLICY])
4556 return ERR_PTR(-EINVAL);
4557
4558 acl_policy = nla_get_u32(info->attrs[NL80211_ATTR_ACL_POLICY]);
4559 if (acl_policy != NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED &&
4560 acl_policy != NL80211_ACL_POLICY_DENY_UNLESS_LISTED)
4561 return ERR_PTR(-EINVAL);
4562
4563 if (!info->attrs[NL80211_ATTR_MAC_ADDRS])
4564 return ERR_PTR(-EINVAL);
4565
4566 n_entries = validate_acl_mac_addrs(info->attrs[NL80211_ATTR_MAC_ADDRS]);
4567 if (n_entries < 0)
4568 return ERR_PTR(n_entries);
4569
4570 if (n_entries > wiphy->max_acl_mac_addrs)
4571 return ERR_PTR(-ENOTSUPP);
4572
391d132c 4573 acl = kzalloc(struct_size(acl, mac_addrs, n_entries), GFP_KERNEL);
77765eaf
VT
4574 if (!acl)
4575 return ERR_PTR(-ENOMEM);
4576
4577 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_MAC_ADDRS], tmp) {
4578 memcpy(acl->mac_addrs[i].addr, nla_data(attr), ETH_ALEN);
4579 i++;
4580 }
4581
4582 acl->n_acl_entries = n_entries;
4583 acl->acl_policy = acl_policy;
4584
4585 return acl;
4586}
4587
4588static int nl80211_set_mac_acl(struct sk_buff *skb, struct genl_info *info)
4589{
4590 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4591 struct net_device *dev = info->user_ptr[1];
4592 struct cfg80211_acl_data *acl;
4593 int err;
4594
4595 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
4596 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
4597 return -EOPNOTSUPP;
4598
4599 if (!dev->ieee80211_ptr->beacon_interval)
4600 return -EINVAL;
4601
4602 acl = parse_acl_data(&rdev->wiphy, info);
4603 if (IS_ERR(acl))
4604 return PTR_ERR(acl);
4605
4606 err = rdev_set_mac_acl(rdev, dev, acl);
4607
4608 kfree(acl);
4609
4610 return err;
4611}
4612
a7c7fbff
PK
4613static u32 rateset_to_mask(struct ieee80211_supported_band *sband,
4614 u8 *rates, u8 rates_len)
4615{
4616 u8 i;
4617 u32 mask = 0;
4618
4619 for (i = 0; i < rates_len; i++) {
4620 int rate = (rates[i] & 0x7f) * 5;
4621 int ridx;
4622
4623 for (ridx = 0; ridx < sband->n_bitrates; ridx++) {
4624 struct ieee80211_rate *srate =
4625 &sband->bitrates[ridx];
4626 if (rate == srate->bitrate) {
4627 mask |= 1 << ridx;
4628 break;
4629 }
4630 }
4631 if (ridx == sband->n_bitrates)
4632 return 0; /* rate not found */
4633 }
4634
4635 return mask;
4636}
4637
4638static bool ht_rateset_to_mask(struct ieee80211_supported_band *sband,
4639 u8 *rates, u8 rates_len,
4640 u8 mcs[IEEE80211_HT_MCS_MASK_LEN])
4641{
4642 u8 i;
4643
4644 memset(mcs, 0, IEEE80211_HT_MCS_MASK_LEN);
4645
4646 for (i = 0; i < rates_len; i++) {
4647 int ridx, rbit;
4648
4649 ridx = rates[i] / 8;
4650 rbit = BIT(rates[i] % 8);
4651
4652 /* check validity */
4653 if ((ridx < 0) || (ridx >= IEEE80211_HT_MCS_MASK_LEN))
4654 return false;
4655
4656 /* check availability */
30fe6d50 4657 ridx = array_index_nospec(ridx, IEEE80211_HT_MCS_MASK_LEN);
a7c7fbff
PK
4658 if (sband->ht_cap.mcs.rx_mask[ridx] & rbit)
4659 mcs[ridx] |= rbit;
4660 else
4661 return false;
4662 }
4663
4664 return true;
4665}
4666
4667static u16 vht_mcs_map_to_mcs_mask(u8 vht_mcs_map)
4668{
4669 u16 mcs_mask = 0;
4670
4671 switch (vht_mcs_map) {
4672 case IEEE80211_VHT_MCS_NOT_SUPPORTED:
4673 break;
4674 case IEEE80211_VHT_MCS_SUPPORT_0_7:
4675 mcs_mask = 0x00FF;
4676 break;
4677 case IEEE80211_VHT_MCS_SUPPORT_0_8:
4678 mcs_mask = 0x01FF;
4679 break;
4680 case IEEE80211_VHT_MCS_SUPPORT_0_9:
4681 mcs_mask = 0x03FF;
4682 break;
4683 default:
4684 break;
4685 }
4686
4687 return mcs_mask;
4688}
4689
4690static void vht_build_mcs_mask(u16 vht_mcs_map,
4691 u16 vht_mcs_mask[NL80211_VHT_NSS_MAX])
4692{
4693 u8 nss;
4694
4695 for (nss = 0; nss < NL80211_VHT_NSS_MAX; nss++) {
4696 vht_mcs_mask[nss] = vht_mcs_map_to_mcs_mask(vht_mcs_map & 0x03);
4697 vht_mcs_map >>= 2;
4698 }
4699}
4700
4701static bool vht_set_mcs_mask(struct ieee80211_supported_band *sband,
4702 struct nl80211_txrate_vht *txrate,
4703 u16 mcs[NL80211_VHT_NSS_MAX])
4704{
4705 u16 tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
4706 u16 tx_mcs_mask[NL80211_VHT_NSS_MAX] = {};
4707 u8 i;
4708
4709 if (!sband->vht_cap.vht_supported)
4710 return false;
4711
4712 memset(mcs, 0, sizeof(u16) * NL80211_VHT_NSS_MAX);
4713
4714 /* Build vht_mcs_mask from VHT capabilities */
4715 vht_build_mcs_mask(tx_mcs_map, tx_mcs_mask);
4716
4717 for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
4718 if ((tx_mcs_mask[i] & txrate->mcs[i]) == txrate->mcs[i])
4719 mcs[i] = txrate->mcs[i];
4720 else
4721 return false;
4722 }
4723
4724 return true;
4725}
4726
eb89a6a6
MH
4727static u16 he_mcs_map_to_mcs_mask(u8 he_mcs_map)
4728{
4729 switch (he_mcs_map) {
4730 case IEEE80211_HE_MCS_NOT_SUPPORTED:
4731 return 0;
4732 case IEEE80211_HE_MCS_SUPPORT_0_7:
4733 return 0x00FF;
4734 case IEEE80211_HE_MCS_SUPPORT_0_9:
4735 return 0x03FF;
4736 case IEEE80211_HE_MCS_SUPPORT_0_11:
4737 return 0xFFF;
4738 default:
4739 break;
4740 }
4741 return 0;
4742}
4743
4744static void he_build_mcs_mask(u16 he_mcs_map,
4745 u16 he_mcs_mask[NL80211_HE_NSS_MAX])
4746{
4747 u8 nss;
4748
4749 for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++) {
4750 he_mcs_mask[nss] = he_mcs_map_to_mcs_mask(he_mcs_map & 0x03);
4751 he_mcs_map >>= 2;
4752 }
4753}
4754
4755static u16 he_get_txmcsmap(struct genl_info *info,
4756 const struct ieee80211_sta_he_cap *he_cap)
4757{
4758 struct net_device *dev = info->user_ptr[1];
4759 struct wireless_dev *wdev = dev->ieee80211_ptr;
4760 __le16 tx_mcs;
4761
4762 switch (wdev->chandef.width) {
4763 case NL80211_CHAN_WIDTH_80P80:
4764 tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_80p80;
4765 break;
4766 case NL80211_CHAN_WIDTH_160:
4767 tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_160;
4768 break;
4769 default:
4770 tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_80;
4771 break;
4772 }
4773 return le16_to_cpu(tx_mcs);
4774}
4775
4776static bool he_set_mcs_mask(struct genl_info *info,
4777 struct wireless_dev *wdev,
4778 struct ieee80211_supported_band *sband,
4779 struct nl80211_txrate_he *txrate,
4780 u16 mcs[NL80211_HE_NSS_MAX])
4781{
4782 const struct ieee80211_sta_he_cap *he_cap;
4783 u16 tx_mcs_mask[NL80211_HE_NSS_MAX] = {};
4784 u16 tx_mcs_map = 0;
4785 u8 i;
4786
4787 he_cap = ieee80211_get_he_iftype_cap(sband, wdev->iftype);
4788 if (!he_cap)
4789 return false;
4790
4791 memset(mcs, 0, sizeof(u16) * NL80211_HE_NSS_MAX);
4792
4793 tx_mcs_map = he_get_txmcsmap(info, he_cap);
4794
4795 /* Build he_mcs_mask from HE capabilities */
4796 he_build_mcs_mask(tx_mcs_map, tx_mcs_mask);
4797
4798 for (i = 0; i < NL80211_HE_NSS_MAX; i++) {
4799 if ((tx_mcs_mask[i] & txrate->mcs[i]) == txrate->mcs[i])
4800 mcs[i] = txrate->mcs[i];
4801 else
4802 return false;
4803 }
4804
4805 return true;
4806}
4807
a7c7fbff 4808static int nl80211_parse_tx_bitrate_mask(struct genl_info *info,
9a5f6488
TC
4809 struct nlattr *attrs[],
4810 enum nl80211_attrs attr,
eb89a6a6 4811 struct cfg80211_bitrate_mask *mask,
857b34c4
RM
4812 struct net_device *dev,
4813 bool default_all_enabled)
a7c7fbff
PK
4814{
4815 struct nlattr *tb[NL80211_TXRATE_MAX + 1];
4816 struct cfg80211_registered_device *rdev = info->user_ptr[0];
eb89a6a6 4817 struct wireless_dev *wdev = dev->ieee80211_ptr;
a7c7fbff
PK
4818 int rem, i;
4819 struct nlattr *tx_rates;
4820 struct ieee80211_supported_band *sband;
eb89a6a6 4821 u16 vht_tx_mcs_map, he_tx_mcs_map;
a7c7fbff
PK
4822
4823 memset(mask, 0, sizeof(*mask));
4824 /* Default to all rates enabled */
4825 for (i = 0; i < NUM_NL80211_BANDS; i++) {
eb89a6a6
MH
4826 const struct ieee80211_sta_he_cap *he_cap;
4827
857b34c4
RM
4828 if (!default_all_enabled)
4829 break;
4830
a7c7fbff
PK
4831 sband = rdev->wiphy.bands[i];
4832
4833 if (!sband)
4834 continue;
4835
4836 mask->control[i].legacy = (1 << sband->n_bitrates) - 1;
4837 memcpy(mask->control[i].ht_mcs,
4838 sband->ht_cap.mcs.rx_mask,
4839 sizeof(mask->control[i].ht_mcs));
4840
9df66d5b
PKS
4841 if (sband->vht_cap.vht_supported) {
4842 vht_tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
4843 vht_build_mcs_mask(vht_tx_mcs_map, mask->control[i].vht_mcs);
4844 }
eb89a6a6
MH
4845
4846 he_cap = ieee80211_get_he_iftype_cap(sband, wdev->iftype);
4847 if (!he_cap)
4848 continue;
4849
4850 he_tx_mcs_map = he_get_txmcsmap(info, he_cap);
4851 he_build_mcs_mask(he_tx_mcs_map, mask->control[i].he_mcs);
4852
4853 mask->control[i].he_gi = 0xFF;
4854 mask->control[i].he_ltf = 0xFF;
a7c7fbff
PK
4855 }
4856
4857 /* if no rates are given set it back to the defaults */
9a5f6488 4858 if (!attrs[attr])
a7c7fbff
PK
4859 goto out;
4860
4861 /* The nested attribute uses enum nl80211_band as the index. This maps
4862 * directly to the enum nl80211_band values used in cfg80211.
4863 */
4864 BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8);
9a5f6488 4865 nla_for_each_nested(tx_rates, attrs[attr], rem) {
a7c7fbff
PK
4866 enum nl80211_band band = nla_type(tx_rates);
4867 int err;
4868
4869 if (band < 0 || band >= NUM_NL80211_BANDS)
4870 return -EINVAL;
4871 sband = rdev->wiphy.bands[band];
4872 if (sband == NULL)
4873 return -EINVAL;
8cb08174
JB
4874 err = nla_parse_nested_deprecated(tb, NL80211_TXRATE_MAX,
4875 tx_rates,
4876 nl80211_txattr_policy,
4877 info->extack);
a7c7fbff
PK
4878 if (err)
4879 return err;
4880 if (tb[NL80211_TXRATE_LEGACY]) {
4881 mask->control[band].legacy = rateset_to_mask(
4882 sband,
4883 nla_data(tb[NL80211_TXRATE_LEGACY]),
4884 nla_len(tb[NL80211_TXRATE_LEGACY]));
4885 if ((mask->control[band].legacy == 0) &&
4886 nla_len(tb[NL80211_TXRATE_LEGACY]))
4887 return -EINVAL;
4888 }
4889 if (tb[NL80211_TXRATE_HT]) {
4890 if (!ht_rateset_to_mask(
4891 sband,
4892 nla_data(tb[NL80211_TXRATE_HT]),
4893 nla_len(tb[NL80211_TXRATE_HT]),
4894 mask->control[band].ht_mcs))
4895 return -EINVAL;
4896 }
c4a30446 4897
a7c7fbff
PK
4898 if (tb[NL80211_TXRATE_VHT]) {
4899 if (!vht_set_mcs_mask(
4900 sband,
4901 nla_data(tb[NL80211_TXRATE_VHT]),
4902 mask->control[band].vht_mcs))
4903 return -EINVAL;
4904 }
c4a30446 4905
a7c7fbff
PK
4906 if (tb[NL80211_TXRATE_GI]) {
4907 mask->control[band].gi =
4908 nla_get_u8(tb[NL80211_TXRATE_GI]);
4909 if (mask->control[band].gi > NL80211_TXRATE_FORCE_LGI)
4910 return -EINVAL;
4911 }
eb89a6a6
MH
4912 if (tb[NL80211_TXRATE_HE] &&
4913 !he_set_mcs_mask(info, wdev, sband,
4914 nla_data(tb[NL80211_TXRATE_HE]),
4915 mask->control[band].he_mcs))
4916 return -EINVAL;
c4a30446 4917
eb89a6a6
MH
4918 if (tb[NL80211_TXRATE_HE_GI])
4919 mask->control[band].he_gi =
4920 nla_get_u8(tb[NL80211_TXRATE_HE_GI]);
4921 if (tb[NL80211_TXRATE_HE_LTF])
4922 mask->control[band].he_ltf =
4923 nla_get_u8(tb[NL80211_TXRATE_HE_LTF]);
a7c7fbff
PK
4924
4925 if (mask->control[band].legacy == 0) {
eb89a6a6 4926 /* don't allow empty legacy rates if HT, VHT or HE
a7c7fbff
PK
4927 * are not even supported.
4928 */
4929 if (!(rdev->wiphy.bands[band]->ht_cap.ht_supported ||
eb89a6a6
MH
4930 rdev->wiphy.bands[band]->vht_cap.vht_supported ||
4931 ieee80211_get_he_iftype_cap(sband, wdev->iftype)))
a7c7fbff
PK
4932 return -EINVAL;
4933
4934 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
4935 if (mask->control[band].ht_mcs[i])
4936 goto out;
4937
4938 for (i = 0; i < NL80211_VHT_NSS_MAX; i++)
4939 if (mask->control[band].vht_mcs[i])
4940 goto out;
4941
eb89a6a6
MH
4942 for (i = 0; i < NL80211_HE_NSS_MAX; i++)
4943 if (mask->control[band].he_mcs[i])
4944 goto out;
4945
a7c7fbff
PK
4946 /* legacy and mcs rates may not be both empty */
4947 return -EINVAL;
4948 }
4949 }
4950
4951out:
4952 return 0;
4953}
4954
8564e382
JB
4955static int validate_beacon_tx_rate(struct cfg80211_registered_device *rdev,
4956 enum nl80211_band band,
4957 struct cfg80211_bitrate_mask *beacon_rate)
a7c7fbff 4958{
c4a30446 4959 u32 count_ht, count_vht, count_he, i;
8564e382 4960 u32 rate = beacon_rate->control[band].legacy;
a7c7fbff
PK
4961
4962 /* Allow only one rate */
4963 if (hweight32(rate) > 1)
4964 return -EINVAL;
4965
4966 count_ht = 0;
4967 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
8564e382 4968 if (hweight8(beacon_rate->control[band].ht_mcs[i]) > 1) {
a7c7fbff 4969 return -EINVAL;
8564e382 4970 } else if (beacon_rate->control[band].ht_mcs[i]) {
a7c7fbff
PK
4971 count_ht++;
4972 if (count_ht > 1)
4973 return -EINVAL;
4974 }
4975 if (count_ht && rate)
4976 return -EINVAL;
4977 }
4978
4979 count_vht = 0;
4980 for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
8564e382 4981 if (hweight16(beacon_rate->control[band].vht_mcs[i]) > 1) {
a7c7fbff 4982 return -EINVAL;
8564e382 4983 } else if (beacon_rate->control[band].vht_mcs[i]) {
a7c7fbff
PK
4984 count_vht++;
4985 if (count_vht > 1)
4986 return -EINVAL;
4987 }
4988 if (count_vht && rate)
4989 return -EINVAL;
4990 }
4991
c4a30446
RM
4992 count_he = 0;
4993 for (i = 0; i < NL80211_HE_NSS_MAX; i++) {
4994 if (hweight16(beacon_rate->control[band].he_mcs[i]) > 1) {
4995 return -EINVAL;
4996 } else if (beacon_rate->control[band].he_mcs[i]) {
4997 count_he++;
4998 if (count_he > 1)
4999 return -EINVAL;
5000 }
5001 if (count_he && rate)
5002 return -EINVAL;
5003 }
5004
5005 if ((count_ht && count_vht && count_he) ||
5006 (!rate && !count_ht && !count_vht && !count_he))
a7c7fbff
PK
5007 return -EINVAL;
5008
8564e382
JB
5009 if (rate &&
5010 !wiphy_ext_feature_isset(&rdev->wiphy,
5011 NL80211_EXT_FEATURE_BEACON_RATE_LEGACY))
5012 return -EINVAL;
5013 if (count_ht &&
5014 !wiphy_ext_feature_isset(&rdev->wiphy,
5015 NL80211_EXT_FEATURE_BEACON_RATE_HT))
5016 return -EINVAL;
5017 if (count_vht &&
5018 !wiphy_ext_feature_isset(&rdev->wiphy,
5019 NL80211_EXT_FEATURE_BEACON_RATE_VHT))
5020 return -EINVAL;
c4a30446
RM
5021 if (count_he &&
5022 !wiphy_ext_feature_isset(&rdev->wiphy,
5023 NL80211_EXT_FEATURE_BEACON_RATE_HE))
5024 return -EINVAL;
8564e382 5025
a7c7fbff
PK
5026 return 0;
5027}
5028
dc1e3cb8
JC
5029static int nl80211_parse_mbssid_config(struct wiphy *wiphy,
5030 struct net_device *dev,
5031 struct nlattr *attrs,
5032 struct cfg80211_mbssid_config *config,
5033 u8 num_elems)
5034{
5035 struct nlattr *tb[NL80211_MBSSID_CONFIG_ATTR_MAX + 1];
5036
5037 if (!wiphy->mbssid_max_interfaces)
5038 return -EOPNOTSUPP;
5039
5040 if (nla_parse_nested(tb, NL80211_MBSSID_CONFIG_ATTR_MAX, attrs, NULL,
5041 NULL) ||
5042 !tb[NL80211_MBSSID_CONFIG_ATTR_INDEX])
5043 return -EINVAL;
5044
5045 config->ema = nla_get_flag(tb[NL80211_MBSSID_CONFIG_ATTR_EMA]);
5046 if (config->ema) {
5047 if (!wiphy->ema_max_profile_periodicity)
5048 return -EOPNOTSUPP;
5049
5050 if (num_elems > wiphy->ema_max_profile_periodicity)
5051 return -EINVAL;
5052 }
5053
5054 config->index = nla_get_u8(tb[NL80211_MBSSID_CONFIG_ATTR_INDEX]);
5055 if (config->index >= wiphy->mbssid_max_interfaces ||
5056 (!config->index && !num_elems))
5057 return -EINVAL;
5058
5059 if (tb[NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX]) {
5060 u32 tx_ifindex =
5061 nla_get_u32(tb[NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX]);
5062
5063 if ((!config->index && tx_ifindex != dev->ifindex) ||
5064 (config->index && tx_ifindex == dev->ifindex))
5065 return -EINVAL;
5066
5067 if (tx_ifindex != dev->ifindex) {
5068 struct net_device *tx_netdev =
5069 dev_get_by_index(wiphy_net(wiphy), tx_ifindex);
5070
5071 if (!tx_netdev || !tx_netdev->ieee80211_ptr ||
5072 tx_netdev->ieee80211_ptr->wiphy != wiphy ||
5073 tx_netdev->ieee80211_ptr->iftype !=
5074 NL80211_IFTYPE_AP) {
5075 dev_put(tx_netdev);
5076 return -EINVAL;
5077 }
5078
5079 config->tx_wdev = tx_netdev->ieee80211_ptr;
5080 } else {
5081 config->tx_wdev = dev->ieee80211_ptr;
5082 }
5083 } else if (!config->index) {
5084 config->tx_wdev = dev->ieee80211_ptr;
5085 } else {
5086 return -EINVAL;
5087 }
5088
5089 return 0;
5090}
5091
5092static struct cfg80211_mbssid_elems *
5093nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs)
5094{
5095 struct nlattr *nl_elems;
5096 struct cfg80211_mbssid_elems *elems;
5097 int rem_elems;
5098 u8 i = 0, num_elems = 0;
5099
5100 if (!wiphy->mbssid_max_interfaces)
5101 return ERR_PTR(-EINVAL);
5102
5103 nla_for_each_nested(nl_elems, attrs, rem_elems)
5104 num_elems++;
5105
5106 elems = kzalloc(struct_size(elems, elem, num_elems), GFP_KERNEL);
5107 if (!elems)
5108 return ERR_PTR(-ENOMEM);
5109
5110 nla_for_each_nested(nl_elems, attrs, rem_elems) {
5111 elems->elem[i].data = nla_data(nl_elems);
5112 elems->elem[i].len = nla_len(nl_elems);
5113 i++;
5114 }
5115 elems->cnt = num_elems;
5116 return elems;
5117}
5118
81e54d08
PKC
5119static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
5120 struct nlattr *attrs[],
8860020e 5121 struct cfg80211_beacon_data *bcn)
ed1b6cc7 5122{
8860020e 5123 bool haveinfo = false;
81e54d08 5124 int err;
ed1b6cc7 5125
8860020e 5126 memset(bcn, 0, sizeof(*bcn));
ed1b6cc7 5127
a1193be8
SW
5128 if (attrs[NL80211_ATTR_BEACON_HEAD]) {
5129 bcn->head = nla_data(attrs[NL80211_ATTR_BEACON_HEAD]);
5130 bcn->head_len = nla_len(attrs[NL80211_ATTR_BEACON_HEAD]);
8860020e
JB
5131 if (!bcn->head_len)
5132 return -EINVAL;
5133 haveinfo = true;
ed1b6cc7
JB
5134 }
5135
a1193be8
SW
5136 if (attrs[NL80211_ATTR_BEACON_TAIL]) {
5137 bcn->tail = nla_data(attrs[NL80211_ATTR_BEACON_TAIL]);
5138 bcn->tail_len = nla_len(attrs[NL80211_ATTR_BEACON_TAIL]);
8860020e 5139 haveinfo = true;
ed1b6cc7
JB
5140 }
5141
4c476991
JB
5142 if (!haveinfo)
5143 return -EINVAL;
3b85875a 5144
a1193be8
SW
5145 if (attrs[NL80211_ATTR_IE]) {
5146 bcn->beacon_ies = nla_data(attrs[NL80211_ATTR_IE]);
5147 bcn->beacon_ies_len = nla_len(attrs[NL80211_ATTR_IE]);
9946ecfb
JM
5148 }
5149
a1193be8 5150 if (attrs[NL80211_ATTR_IE_PROBE_RESP]) {
8860020e 5151 bcn->proberesp_ies =
a1193be8 5152 nla_data(attrs[NL80211_ATTR_IE_PROBE_RESP]);
8860020e 5153 bcn->proberesp_ies_len =
a1193be8 5154 nla_len(attrs[NL80211_ATTR_IE_PROBE_RESP]);
9946ecfb
JM
5155 }
5156
a1193be8 5157 if (attrs[NL80211_ATTR_IE_ASSOC_RESP]) {
8860020e 5158 bcn->assocresp_ies =
a1193be8 5159 nla_data(attrs[NL80211_ATTR_IE_ASSOC_RESP]);
8860020e 5160 bcn->assocresp_ies_len =
a1193be8 5161 nla_len(attrs[NL80211_ATTR_IE_ASSOC_RESP]);
9946ecfb
JM
5162 }
5163
a1193be8
SW
5164 if (attrs[NL80211_ATTR_PROBE_RESP]) {
5165 bcn->probe_resp = nla_data(attrs[NL80211_ATTR_PROBE_RESP]);
5166 bcn->probe_resp_len = nla_len(attrs[NL80211_ATTR_PROBE_RESP]);
00f740e1
AN
5167 }
5168
81e54d08
PKC
5169 if (attrs[NL80211_ATTR_FTM_RESPONDER]) {
5170 struct nlattr *tb[NL80211_FTM_RESP_ATTR_MAX + 1];
5171
8cb08174
JB
5172 err = nla_parse_nested_deprecated(tb,
5173 NL80211_FTM_RESP_ATTR_MAX,
5174 attrs[NL80211_ATTR_FTM_RESPONDER],
5175 NULL, NULL);
81e54d08
PKC
5176 if (err)
5177 return err;
5178
5179 if (tb[NL80211_FTM_RESP_ATTR_ENABLED] &&
5180 wiphy_ext_feature_isset(&rdev->wiphy,
5181 NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER))
5182 bcn->ftm_responder = 1;
5183 else
5184 return -EOPNOTSUPP;
5185
5186 if (tb[NL80211_FTM_RESP_ATTR_LCI]) {
5187 bcn->lci = nla_data(tb[NL80211_FTM_RESP_ATTR_LCI]);
5188 bcn->lci_len = nla_len(tb[NL80211_FTM_RESP_ATTR_LCI]);
5189 }
5190
5191 if (tb[NL80211_FTM_RESP_ATTR_CIVICLOC]) {
5192 bcn->civicloc = nla_data(tb[NL80211_FTM_RESP_ATTR_CIVICLOC]);
5193 bcn->civicloc_len = nla_len(tb[NL80211_FTM_RESP_ATTR_CIVICLOC]);
5194 }
5195 } else {
5196 bcn->ftm_responder = -1;
5197 }
5198
dc1e3cb8
JC
5199 if (attrs[NL80211_ATTR_MBSSID_ELEMS]) {
5200 struct cfg80211_mbssid_elems *mbssid =
5201 nl80211_parse_mbssid_elems(&rdev->wiphy,
5202 attrs[NL80211_ATTR_MBSSID_ELEMS]);
5203
5204 if (IS_ERR(mbssid))
5205 return PTR_ERR(mbssid);
5206
5207 bcn->mbssid_ies = mbssid;
5208 }
5209
8860020e
JB
5210 return 0;
5211}
5212
796e90f4
JC
5213static int nl80211_parse_he_obss_pd(struct nlattr *attrs,
5214 struct ieee80211_he_obss_pd *he_obss_pd)
5215{
5216 struct nlattr *tb[NL80211_HE_OBSS_PD_ATTR_MAX + 1];
5217 int err;
5218
5219 err = nla_parse_nested(tb, NL80211_HE_OBSS_PD_ATTR_MAX, attrs,
5220 he_obss_pd_policy, NULL);
5221 if (err)
5222 return err;
5223
f5bec330
RM
5224 if (!tb[NL80211_HE_OBSS_PD_ATTR_SR_CTRL])
5225 return -EINVAL;
5226
5227 he_obss_pd->sr_ctrl = nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_SR_CTRL]);
5228
6c8b6e4a
RM
5229 if (tb[NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET])
5230 he_obss_pd->min_offset =
5231 nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET]);
5232 if (tb[NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET])
5233 he_obss_pd->max_offset =
5234 nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET]);
f5bec330
RM
5235 if (tb[NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET])
5236 he_obss_pd->non_srg_max_offset =
5237 nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET]);
6c8b6e4a
RM
5238
5239 if (he_obss_pd->min_offset > he_obss_pd->max_offset)
796e90f4
JC
5240 return -EINVAL;
5241
f5bec330
RM
5242 if (tb[NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP])
5243 memcpy(he_obss_pd->bss_color_bitmap,
5244 nla_data(tb[NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP]),
5245 sizeof(he_obss_pd->bss_color_bitmap));
5246
5247 if (tb[NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP])
5248 memcpy(he_obss_pd->partial_bssid_bitmap,
5249 nla_data(tb[NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP]),
5250 sizeof(he_obss_pd->partial_bssid_bitmap));
5251
796e90f4
JC
5252 he_obss_pd->enable = true;
5253
5254 return 0;
5255}
5256
5c5e52d1
JC
5257static int nl80211_parse_he_bss_color(struct nlattr *attrs,
5258 struct cfg80211_he_bss_color *he_bss_color)
5259{
5260 struct nlattr *tb[NL80211_HE_BSS_COLOR_ATTR_MAX + 1];
5261 int err;
5262
5263 err = nla_parse_nested(tb, NL80211_HE_BSS_COLOR_ATTR_MAX, attrs,
5264 he_bss_color_policy, NULL);
5265 if (err)
5266 return err;
5267
5268 if (!tb[NL80211_HE_BSS_COLOR_ATTR_COLOR])
5269 return -EINVAL;
5270
5271 he_bss_color->color =
5272 nla_get_u8(tb[NL80211_HE_BSS_COLOR_ATTR_COLOR]);
75e6b594
JB
5273 he_bss_color->enabled =
5274 !nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_DISABLED]);
5c5e52d1
JC
5275 he_bss_color->partial =
5276 nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_PARTIAL]);
5277
5278 return 0;
5279}
5280
291c49de
AD
5281static int nl80211_parse_fils_discovery(struct cfg80211_registered_device *rdev,
5282 struct nlattr *attrs,
5283 struct cfg80211_ap_settings *params)
5284{
5285 struct nlattr *tb[NL80211_FILS_DISCOVERY_ATTR_MAX + 1];
5286 int ret;
5287 struct cfg80211_fils_discovery *fd = &params->fils_discovery;
5288
5289 if (!wiphy_ext_feature_isset(&rdev->wiphy,
5290 NL80211_EXT_FEATURE_FILS_DISCOVERY))
5291 return -EINVAL;
5292
5293 ret = nla_parse_nested(tb, NL80211_FILS_DISCOVERY_ATTR_MAX, attrs,
5294 NULL, NULL);
5295 if (ret)
5296 return ret;
5297
5298 if (!tb[NL80211_FILS_DISCOVERY_ATTR_INT_MIN] ||
5299 !tb[NL80211_FILS_DISCOVERY_ATTR_INT_MAX] ||
5300 !tb[NL80211_FILS_DISCOVERY_ATTR_TMPL])
5301 return -EINVAL;
5302
5303 fd->tmpl_len = nla_len(tb[NL80211_FILS_DISCOVERY_ATTR_TMPL]);
5304 fd->tmpl = nla_data(tb[NL80211_FILS_DISCOVERY_ATTR_TMPL]);
5305 fd->min_interval = nla_get_u32(tb[NL80211_FILS_DISCOVERY_ATTR_INT_MIN]);
5306 fd->max_interval = nla_get_u32(tb[NL80211_FILS_DISCOVERY_ATTR_INT_MAX]);
5307
5308 return 0;
5309}
5310
7443dcd1
AD
5311static int
5312nl80211_parse_unsol_bcast_probe_resp(struct cfg80211_registered_device *rdev,
5313 struct nlattr *attrs,
5314 struct cfg80211_ap_settings *params)
5315{
5316 struct nlattr *tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX + 1];
5317 int ret;
5318 struct cfg80211_unsol_bcast_probe_resp *presp =
5319 &params->unsol_bcast_probe_resp;
5320
5321 if (!wiphy_ext_feature_isset(&rdev->wiphy,
5322 NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP))
5323 return -EINVAL;
5324
5325 ret = nla_parse_nested(tb, NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX,
5326 attrs, NULL, NULL);
5327 if (ret)
5328 return ret;
5329
5330 if (!tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT] ||
5331 !tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL])
5332 return -EINVAL;
5333
5334 presp->tmpl = nla_data(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL]);
5335 presp->tmpl_len = nla_len(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL]);
5336 presp->interval = nla_get_u32(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT]);
5337 return 0;
5338}
5339
66cd794e 5340static void nl80211_check_ap_rate_selectors(struct cfg80211_ap_settings *params,
153e2a11 5341 const struct element *rates)
66cd794e
JB
5342{
5343 int i;
5344
5345 if (!rates)
5346 return;
5347
153e2a11
JB
5348 for (i = 0; i < rates->datalen; i++) {
5349 if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_HT_PHY)
66cd794e 5350 params->ht_required = true;
153e2a11 5351 if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_VHT_PHY)
66cd794e 5352 params->vht_required = true;
153e2a11 5353 if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_HE_PHY)
2a392596 5354 params->he_required = true;
153e2a11 5355 if (rates->data[i] == BSS_MEMBERSHIP_SELECTOR_SAE_H2E)
d6587602 5356 params->sae_h2e_required = true;
66cd794e
JB
5357 }
5358}
5359
5360/*
5361 * Since the nl80211 API didn't include, from the beginning, attributes about
5362 * HT/VHT requirements/capabilities, we parse them out of the IEs for the
5363 * benefit of drivers that rebuild IEs in the firmware.
5364 */
5365static void nl80211_calculate_ap_params(struct cfg80211_ap_settings *params)
5366{
5367 const struct cfg80211_beacon_data *bcn = &params->beacon;
ba83bfb1
IM
5368 size_t ies_len = bcn->tail_len;
5369 const u8 *ies = bcn->tail;
153e2a11
JB
5370 const struct element *rates;
5371 const struct element *cap;
66cd794e 5372
153e2a11 5373 rates = cfg80211_find_elem(WLAN_EID_SUPP_RATES, ies, ies_len);
66cd794e
JB
5374 nl80211_check_ap_rate_selectors(params, rates);
5375
153e2a11 5376 rates = cfg80211_find_elem(WLAN_EID_EXT_SUPP_RATES, ies, ies_len);
66cd794e
JB
5377 nl80211_check_ap_rate_selectors(params, rates);
5378
153e2a11
JB
5379 cap = cfg80211_find_elem(WLAN_EID_HT_CAPABILITY, ies, ies_len);
5380 if (cap && cap->datalen >= sizeof(*params->ht_cap))
5381 params->ht_cap = (void *)cap->data;
5382 cap = cfg80211_find_elem(WLAN_EID_VHT_CAPABILITY, ies, ies_len);
5383 if (cap && cap->datalen >= sizeof(*params->vht_cap))
5384 params->vht_cap = (void *)cap->data;
5385 cap = cfg80211_find_ext_elem(WLAN_EID_EXT_HE_CAPABILITY, ies, ies_len);
5386 if (cap && cap->datalen >= sizeof(*params->he_cap) + 1)
5387 params->he_cap = (void *)(cap->data + 1);
5388 cap = cfg80211_find_ext_elem(WLAN_EID_EXT_HE_OPERATION, ies, ies_len);
5389 if (cap && cap->datalen >= sizeof(*params->he_oper) + 1)
5390 params->he_oper = (void *)(cap->data + 1);
66cd794e
JB
5391}
5392
46c1dd0c
FF
5393static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
5394 struct cfg80211_ap_settings *params)
5395{
5396 struct wireless_dev *wdev;
5397 bool ret = false;
5398
53873f13 5399 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
46c1dd0c
FF
5400 if (wdev->iftype != NL80211_IFTYPE_AP &&
5401 wdev->iftype != NL80211_IFTYPE_P2P_GO)
5402 continue;
5403
683b6d3b 5404 if (!wdev->preset_chandef.chan)
46c1dd0c
FF
5405 continue;
5406
683b6d3b 5407 params->chandef = wdev->preset_chandef;
46c1dd0c
FF
5408 ret = true;
5409 break;
5410 }
5411
46c1dd0c
FF
5412 return ret;
5413}
5414
e39e5b5e
JM
5415static bool nl80211_valid_auth_type(struct cfg80211_registered_device *rdev,
5416 enum nl80211_auth_type auth_type,
5417 enum nl80211_commands cmd)
5418{
5419 if (auth_type > NL80211_AUTHTYPE_MAX)
5420 return false;
5421
5422 switch (cmd) {
5423 case NL80211_CMD_AUTHENTICATE:
5424 if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) &&
5425 auth_type == NL80211_AUTHTYPE_SAE)
5426 return false;
63181060
JM
5427 if (!wiphy_ext_feature_isset(&rdev->wiphy,
5428 NL80211_EXT_FEATURE_FILS_STA) &&
5429 (auth_type == NL80211_AUTHTYPE_FILS_SK ||
5430 auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
5431 auth_type == NL80211_AUTHTYPE_FILS_PK))
5432 return false;
e39e5b5e
JM
5433 return true;
5434 case NL80211_CMD_CONNECT:
10773a7c 5435 if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) &&
26f7044e
CHH
5436 !wiphy_ext_feature_isset(&rdev->wiphy,
5437 NL80211_EXT_FEATURE_SAE_OFFLOAD) &&
10773a7c 5438 auth_type == NL80211_AUTHTYPE_SAE)
a3caf744 5439 return false;
10773a7c 5440
a3caf744
VK
5441 /* FILS with SK PFS or PK not supported yet */
5442 if (auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
5443 auth_type == NL80211_AUTHTYPE_FILS_PK)
5444 return false;
5445 if (!wiphy_ext_feature_isset(
5446 &rdev->wiphy,
5447 NL80211_EXT_FEATURE_FILS_SK_OFFLOAD) &&
5448 auth_type == NL80211_AUTHTYPE_FILS_SK)
5449 return false;
5450 return true;
e39e5b5e 5451 case NL80211_CMD_START_AP:
2831a631
CHH
5452 if (!wiphy_ext_feature_isset(&rdev->wiphy,
5453 NL80211_EXT_FEATURE_SAE_OFFLOAD_AP) &&
5454 auth_type == NL80211_AUTHTYPE_SAE)
e39e5b5e 5455 return false;
63181060
JM
5456 /* FILS not supported yet */
5457 if (auth_type == NL80211_AUTHTYPE_FILS_SK ||
5458 auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
5459 auth_type == NL80211_AUTHTYPE_FILS_PK)
5460 return false;
e39e5b5e
JM
5461 return true;
5462 default:
5463 return false;
5464 }
5465}
5466
8860020e
JB
5467static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
5468{
5469 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5470 struct net_device *dev = info->user_ptr[1];
5471 struct wireless_dev *wdev = dev->ieee80211_ptr;
9e263e19 5472 struct cfg80211_ap_settings *params;
8860020e
JB
5473 int err;
5474
5475 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
5476 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
5477 return -EOPNOTSUPP;
5478
5479 if (!rdev->ops->start_ap)
5480 return -EOPNOTSUPP;
5481
5482 if (wdev->beacon_interval)
5483 return -EALREADY;
5484
8860020e
JB
5485 /* these are required for START_AP */
5486 if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
5487 !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
5488 !info->attrs[NL80211_ATTR_BEACON_HEAD])
5489 return -EINVAL;
5490
9e263e19
JB
5491 params = kzalloc(sizeof(*params), GFP_KERNEL);
5492 if (!params)
5493 return -ENOMEM;
5494
5495 err = nl80211_parse_beacon(rdev, info->attrs, &params->beacon);
8860020e 5496 if (err)
9e263e19 5497 goto out;
8860020e 5498
9e263e19 5499 params->beacon_interval =
8860020e 5500 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
9e263e19 5501 params->dtim_period =
8860020e
JB
5502 nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
5503
0c317a02 5504 err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype,
9e263e19 5505 params->beacon_interval);
8860020e 5506 if (err)
9e263e19 5507 goto out;
8860020e
JB
5508
5509 /*
5510 * In theory, some of these attributes should be required here
5511 * but since they were not used when the command was originally
5512 * added, keep them optional for old user space programs to let
5513 * them continue to work with drivers that do not need the
5514 * additional information -- drivers must check!
5515 */
5516 if (info->attrs[NL80211_ATTR_SSID]) {
9e263e19
JB
5517 params->ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
5518 params->ssid_len =
8860020e 5519 nla_len(info->attrs[NL80211_ATTR_SSID]);
9e263e19
JB
5520 if (params->ssid_len == 0) {
5521 err = -EINVAL;
5522 goto out;
5523 }
8860020e
JB
5524 }
5525
ab0d76f6 5526 if (info->attrs[NL80211_ATTR_HIDDEN_SSID])
9e263e19 5527 params->hidden_ssid = nla_get_u32(
8860020e 5528 info->attrs[NL80211_ATTR_HIDDEN_SSID]);
8860020e 5529
9e263e19 5530 params->privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
8860020e
JB
5531
5532 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
9e263e19 5533 params->auth_type = nla_get_u32(
8860020e 5534 info->attrs[NL80211_ATTR_AUTH_TYPE]);
9e263e19
JB
5535 if (!nl80211_valid_auth_type(rdev, params->auth_type,
5536 NL80211_CMD_START_AP)) {
5537 err = -EINVAL;
5538 goto out;
5539 }
8860020e 5540 } else
9e263e19 5541 params->auth_type = NL80211_AUTHTYPE_AUTOMATIC;
8860020e 5542
9e263e19 5543 err = nl80211_crypto_settings(rdev, info, &params->crypto,
8860020e
JB
5544 NL80211_MAX_NR_CIPHER_SUITES);
5545 if (err)
9e263e19 5546 goto out;
8860020e 5547
1b658f11 5548 if (info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]) {
9e263e19
JB
5549 if (!(rdev->wiphy.features & NL80211_FEATURE_INACTIVITY_TIMER)) {
5550 err = -EOPNOTSUPP;
5551 goto out;
5552 }
5553 params->inactivity_timeout = nla_get_u16(
1b658f11
VT
5554 info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
5555 }
5556
53cabad7 5557 if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
9e263e19
JB
5558 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
5559 err = -EINVAL;
5560 goto out;
5561 }
5562 params->p2p_ctwindow =
53cabad7 5563 nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
9e263e19
JB
5564 if (params->p2p_ctwindow != 0 &&
5565 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN)) {
5566 err = -EINVAL;
5567 goto out;
5568 }
53cabad7
JB
5569 }
5570
5571 if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
5572 u8 tmp;
5573
9e263e19
JB
5574 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
5575 err = -EINVAL;
5576 goto out;
5577 }
53cabad7 5578 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
9e263e19
JB
5579 params->p2p_opp_ps = tmp;
5580 if (params->p2p_opp_ps != 0 &&
5581 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS)) {
5582 err = -EINVAL;
5583 goto out;
5584 }
53cabad7
JB
5585 }
5586
aa430da4 5587 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
9e263e19 5588 err = nl80211_parse_chandef(rdev, info, &params->chandef);
683b6d3b 5589 if (err)
9e263e19 5590 goto out;
683b6d3b 5591 } else if (wdev->preset_chandef.chan) {
9e263e19
JB
5592 params->chandef = wdev->preset_chandef;
5593 } else if (!nl80211_get_ap_channel(rdev, params)) {
5594 err = -EINVAL;
5595 goto out;
5596 }
aa430da4 5597
9e263e19
JB
5598 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params->chandef,
5599 wdev->iftype)) {
5600 err = -EINVAL;
5601 goto out;
5602 }
aa430da4 5603
a7c7fbff 5604 if (info->attrs[NL80211_ATTR_TX_RATES]) {
9a5f6488
TC
5605 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
5606 NL80211_ATTR_TX_RATES,
9e263e19 5607 &params->beacon_rate,
857b34c4 5608 dev, false);
a7c7fbff 5609 if (err)
9e263e19 5610 goto out;
a7c7fbff 5611
9e263e19
JB
5612 err = validate_beacon_tx_rate(rdev, params->chandef.chan->band,
5613 &params->beacon_rate);
a7c7fbff 5614 if (err)
9e263e19 5615 goto out;
a7c7fbff
PK
5616 }
5617
18998c38 5618 if (info->attrs[NL80211_ATTR_SMPS_MODE]) {
9e263e19 5619 params->smps_mode =
18998c38 5620 nla_get_u8(info->attrs[NL80211_ATTR_SMPS_MODE]);
9e263e19 5621 switch (params->smps_mode) {
18998c38
EP
5622 case NL80211_SMPS_OFF:
5623 break;
5624 case NL80211_SMPS_STATIC:
5625 if (!(rdev->wiphy.features &
9e263e19
JB
5626 NL80211_FEATURE_STATIC_SMPS)) {
5627 err = -EINVAL;
5628 goto out;
5629 }
18998c38
EP
5630 break;
5631 case NL80211_SMPS_DYNAMIC:
5632 if (!(rdev->wiphy.features &
9e263e19
JB
5633 NL80211_FEATURE_DYNAMIC_SMPS)) {
5634 err = -EINVAL;
5635 goto out;
5636 }
18998c38
EP
5637 break;
5638 default:
9e263e19
JB
5639 err = -EINVAL;
5640 goto out;
18998c38
EP
5641 }
5642 } else {
9e263e19 5643 params->smps_mode = NL80211_SMPS_OFF;
18998c38
EP
5644 }
5645
9e263e19
JB
5646 params->pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
5647 if (params->pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) {
5648 err = -EOPNOTSUPP;
5649 goto out;
5650 }
6e8ef842 5651
4baf6bea 5652 if (info->attrs[NL80211_ATTR_ACL_POLICY]) {
9e263e19
JB
5653 params->acl = parse_acl_data(&rdev->wiphy, info);
5654 if (IS_ERR(params->acl)) {
5655 err = PTR_ERR(params->acl);
05075fe7 5656 params->acl = NULL;
9e263e19
JB
5657 goto out;
5658 }
4baf6bea
OO
5659 }
5660
9e263e19 5661 params->twt_responder =
a0de1ca3
JC
5662 nla_get_flag(info->attrs[NL80211_ATTR_TWT_RESPONDER]);
5663
796e90f4
JC
5664 if (info->attrs[NL80211_ATTR_HE_OBSS_PD]) {
5665 err = nl80211_parse_he_obss_pd(
5666 info->attrs[NL80211_ATTR_HE_OBSS_PD],
9e263e19 5667 &params->he_obss_pd);
bc7a39b4
LC
5668 if (err)
5669 goto out;
796e90f4
JC
5670 }
5671
5c5e52d1
JC
5672 if (info->attrs[NL80211_ATTR_HE_BSS_COLOR]) {
5673 err = nl80211_parse_he_bss_color(
5674 info->attrs[NL80211_ATTR_HE_BSS_COLOR],
9e263e19 5675 &params->he_bss_color);
5c5e52d1 5676 if (err)
60a0121f 5677 goto out;
5c5e52d1
JC
5678 }
5679
291c49de
AD
5680 if (info->attrs[NL80211_ATTR_FILS_DISCOVERY]) {
5681 err = nl80211_parse_fils_discovery(rdev,
5682 info->attrs[NL80211_ATTR_FILS_DISCOVERY],
9e263e19 5683 params);
291c49de
AD
5684 if (err)
5685 goto out;
5686 }
5687
7443dcd1
AD
5688 if (info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP]) {
5689 err = nl80211_parse_unsol_bcast_probe_resp(
5690 rdev, info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP],
9e263e19 5691 params);
7443dcd1 5692 if (err)
abaf94ec 5693 goto out;
7443dcd1
AD
5694 }
5695
dc1e3cb8
JC
5696 if (info->attrs[NL80211_ATTR_MBSSID_CONFIG]) {
5697 err = nl80211_parse_mbssid_config(&rdev->wiphy, dev,
5698 info->attrs[NL80211_ATTR_MBSSID_CONFIG],
5699 &params->mbssid_config,
5700 params->beacon.mbssid_ies ?
5701 params->beacon.mbssid_ies->cnt :
5702 0);
5703 if (err)
5704 goto out;
5705 }
5706
9e263e19 5707 nl80211_calculate_ap_params(params);
66cd794e 5708
fe494370 5709 if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
9e263e19 5710 params->flags |= AP_SETTINGS_EXTERNAL_AUTH_SUPPORT;
fe494370 5711
c56589ed 5712 wdev_lock(wdev);
9e263e19 5713 err = rdev_start_ap(rdev, dev, params);
46c1dd0c 5714 if (!err) {
9e263e19
JB
5715 wdev->preset_chandef = params->chandef;
5716 wdev->beacon_interval = params->beacon_interval;
5717 wdev->chandef = params->chandef;
5718 wdev->ssid_len = params->ssid_len;
5719 memcpy(wdev->ssid, params->ssid, wdev->ssid_len);
466a3061
DK
5720
5721 if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
5722 wdev->conn_owner_nlportid = info->snd_portid;
46c1dd0c 5723 }
c56589ed 5724 wdev_unlock(wdev);
77765eaf 5725
9951ebfc 5726out:
9e263e19 5727 kfree(params->acl);
dc1e3cb8
JC
5728 kfree(params->beacon.mbssid_ies);
5729 if (params->mbssid_config.tx_wdev &&
5730 params->mbssid_config.tx_wdev->netdev &&
5731 params->mbssid_config.tx_wdev->netdev != dev)
5732 dev_put(params->mbssid_config.tx_wdev->netdev);
9e263e19 5733 kfree(params);
77765eaf 5734
56d1893d 5735 return err;
ed1b6cc7
JB
5736}
5737
8860020e
JB
5738static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info)
5739{
5740 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5741 struct net_device *dev = info->user_ptr[1];
5742 struct wireless_dev *wdev = dev->ieee80211_ptr;
5743 struct cfg80211_beacon_data params;
5744 int err;
5745
5746 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
5747 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
5748 return -EOPNOTSUPP;
5749
5750 if (!rdev->ops->change_beacon)
5751 return -EOPNOTSUPP;
5752
5753 if (!wdev->beacon_interval)
5754 return -EINVAL;
5755
81e54d08 5756 err = nl80211_parse_beacon(rdev, info->attrs, &params);
8860020e 5757 if (err)
dc1e3cb8 5758 goto out;
8860020e 5759
c56589ed
SW
5760 wdev_lock(wdev);
5761 err = rdev_change_beacon(rdev, dev, &params);
5762 wdev_unlock(wdev);
5763
dc1e3cb8
JC
5764out:
5765 kfree(params.mbssid_ies);
c56589ed 5766 return err;
8860020e
JB
5767}
5768
5769static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info)
ed1b6cc7 5770{
4c476991
JB
5771 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5772 struct net_device *dev = info->user_ptr[1];
ed1b6cc7 5773
7c8d5e03 5774 return cfg80211_stop_ap(rdev, dev, false);
ed1b6cc7
JB
5775}
5776
5727ef1b
JB
5777static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
5778 [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG },
5779 [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG },
5780 [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG },
0e46724a 5781 [NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG },
b39c48fa 5782 [NL80211_STA_FLAG_AUTHENTICATED] = { .type = NLA_FLAG },
d83023da 5783 [NL80211_STA_FLAG_TDLS_PEER] = { .type = NLA_FLAG },
5727ef1b
JB
5784};
5785
eccb8e8f 5786static int parse_station_flags(struct genl_info *info,
bdd3ae3d 5787 enum nl80211_iftype iftype,
eccb8e8f 5788 struct station_parameters *params)
5727ef1b
JB
5789{
5790 struct nlattr *flags[NL80211_STA_FLAG_MAX + 1];
eccb8e8f 5791 struct nlattr *nla;
5727ef1b
JB
5792 int flag;
5793
eccb8e8f
JB
5794 /*
5795 * Try parsing the new attribute first so userspace
5796 * can specify both for older kernels.
5797 */
5798 nla = info->attrs[NL80211_ATTR_STA_FLAGS2];
5799 if (nla) {
5800 struct nl80211_sta_flag_update *sta_flags;
5801
5802 sta_flags = nla_data(nla);
5803 params->sta_flags_mask = sta_flags->mask;
5804 params->sta_flags_set = sta_flags->set;
77ee7c89 5805 params->sta_flags_set &= params->sta_flags_mask;
eccb8e8f
JB
5806 if ((params->sta_flags_mask |
5807 params->sta_flags_set) & BIT(__NL80211_STA_FLAG_INVALID))
5808 return -EINVAL;
5809 return 0;
5810 }
5811
5812 /* if present, parse the old attribute */
5727ef1b 5813
eccb8e8f 5814 nla = info->attrs[NL80211_ATTR_STA_FLAGS];
5727ef1b
JB
5815 if (!nla)
5816 return 0;
5817
8cb08174 5818 if (nla_parse_nested_deprecated(flags, NL80211_STA_FLAG_MAX, nla, sta_flags_policy, info->extack))
5727ef1b
JB
5819 return -EINVAL;
5820
bdd3ae3d
JB
5821 /*
5822 * Only allow certain flags for interface types so that
5823 * other attributes are silently ignored. Remember that
5824 * this is backward compatibility code with old userspace
5825 * and shouldn't be hit in other cases anyway.
5826 */
5827 switch (iftype) {
5828 case NL80211_IFTYPE_AP:
5829 case NL80211_IFTYPE_AP_VLAN:
5830 case NL80211_IFTYPE_P2P_GO:
5831 params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
5832 BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
5833 BIT(NL80211_STA_FLAG_WME) |
5834 BIT(NL80211_STA_FLAG_MFP);
5835 break;
5836 case NL80211_IFTYPE_P2P_CLIENT:
5837 case NL80211_IFTYPE_STATION:
5838 params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
5839 BIT(NL80211_STA_FLAG_TDLS_PEER);
5840 break;
5841 case NL80211_IFTYPE_MESH_POINT:
5842 params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHENTICATED) |
5843 BIT(NL80211_STA_FLAG_MFP) |
5844 BIT(NL80211_STA_FLAG_AUTHORIZED);
5cf3006c 5845 break;
bdd3ae3d
JB
5846 default:
5847 return -EINVAL;
5848 }
5727ef1b 5849
3383b5a6
JB
5850 for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++) {
5851 if (flags[flag]) {
eccb8e8f 5852 params->sta_flags_set |= (1<<flag);
5727ef1b 5853
3383b5a6
JB
5854 /* no longer support new API additions in old API */
5855 if (flag > NL80211_STA_FLAG_MAX_OLD_API)
5856 return -EINVAL;
5857 }
5858 }
5859
5727ef1b
JB
5860 return 0;
5861}
5862
9bb7e0f2 5863bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr)
c8dcfd8a
FF
5864{
5865 struct nlattr *rate;
8eb41c8d
VK
5866 u32 bitrate;
5867 u16 bitrate_compat;
bbf67e45 5868 enum nl80211_rate_info rate_flg;
c8dcfd8a 5869
ae0be8de 5870 rate = nla_nest_start_noflag(msg, attr);
c8dcfd8a 5871 if (!rate)
db9c64cf 5872 return false;
c8dcfd8a
FF
5873
5874 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
5875 bitrate = cfg80211_calculate_bitrate(info);
8eb41c8d
VK
5876 /* report 16-bit bitrate only if we can */
5877 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
db9c64cf
JB
5878 if (bitrate > 0 &&
5879 nla_put_u32(msg, NL80211_RATE_INFO_BITRATE32, bitrate))
5880 return false;
5881 if (bitrate_compat > 0 &&
5882 nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat))
5883 return false;
5884
b51f3bee
JB
5885 switch (info->bw) {
5886 case RATE_INFO_BW_5:
5887 rate_flg = NL80211_RATE_INFO_5_MHZ_WIDTH;
5888 break;
5889 case RATE_INFO_BW_10:
5890 rate_flg = NL80211_RATE_INFO_10_MHZ_WIDTH;
5891 break;
5892 default:
5893 WARN_ON(1);
7b506ff6 5894 fallthrough;
b51f3bee
JB
5895 case RATE_INFO_BW_20:
5896 rate_flg = 0;
5897 break;
5898 case RATE_INFO_BW_40:
5899 rate_flg = NL80211_RATE_INFO_40_MHZ_WIDTH;
5900 break;
5901 case RATE_INFO_BW_80:
5902 rate_flg = NL80211_RATE_INFO_80_MHZ_WIDTH;
5903 break;
5904 case RATE_INFO_BW_160:
5905 rate_flg = NL80211_RATE_INFO_160_MHZ_WIDTH;
5906 break;
c4cbaf79
LC
5907 case RATE_INFO_BW_HE_RU:
5908 rate_flg = 0;
5909 WARN_ON(!(info->flags & RATE_INFO_FLAGS_HE_MCS));
b51f3bee
JB
5910 }
5911
5912 if (rate_flg && nla_put_flag(msg, rate_flg))
5913 return false;
5914
db9c64cf
JB
5915 if (info->flags & RATE_INFO_FLAGS_MCS) {
5916 if (nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs))
5917 return false;
db9c64cf
JB
5918 if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
5919 nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
5920 return false;
5921 } else if (info->flags & RATE_INFO_FLAGS_VHT_MCS) {
5922 if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_MCS, info->mcs))
5923 return false;
5924 if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_NSS, info->nss))
5925 return false;
db9c64cf
JB
5926 if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
5927 nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
5928 return false;
c4cbaf79
LC
5929 } else if (info->flags & RATE_INFO_FLAGS_HE_MCS) {
5930 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_MCS, info->mcs))
5931 return false;
5932 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_NSS, info->nss))
5933 return false;
5934 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_GI, info->he_gi))
5935 return false;
5936 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_DCM, info->he_dcm))
5937 return false;
5938 if (info->bw == RATE_INFO_BW_HE_RU &&
5939 nla_put_u8(msg, NL80211_RATE_INFO_HE_RU_ALLOC,
5940 info->he_ru_alloc))
5941 return false;
db9c64cf 5942 }
c8dcfd8a
FF
5943
5944 nla_nest_end(msg, rate);
5945 return true;
c8dcfd8a
FF
5946}
5947
119363c7
FF
5948static bool nl80211_put_signal(struct sk_buff *msg, u8 mask, s8 *signal,
5949 int id)
5950{
5951 void *attr;
5952 int i = 0;
5953
5954 if (!mask)
5955 return true;
5956
ae0be8de 5957 attr = nla_nest_start_noflag(msg, id);
119363c7
FF
5958 if (!attr)
5959 return false;
5960
5961 for (i = 0; i < IEEE80211_MAX_CHAINS; i++) {
5962 if (!(mask & BIT(i)))
5963 continue;
5964
5965 if (nla_put_u8(msg, i, signal[i]))
5966 return false;
5967 }
5968
5969 nla_nest_end(msg, attr);
5970
5971 return true;
5972}
5973
cf5ead82
JB
5974static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
5975 u32 seq, int flags,
66266b3a
JL
5976 struct cfg80211_registered_device *rdev,
5977 struct net_device *dev,
98b62183 5978 const u8 *mac_addr, struct station_info *sinfo)
fd5b74dc
JB
5979{
5980 void *hdr;
f4263c98 5981 struct nlattr *sinfoattr, *bss_param;
fd5b74dc 5982
cf5ead82 5983 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
f77bf486
AS
5984 if (!hdr) {
5985 cfg80211_sinfo_release_content(sinfo);
fd5b74dc 5986 return -1;
f77bf486 5987 }
fd5b74dc 5988
9360ffd1
DM
5989 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
5990 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) ||
5991 nla_put_u32(msg, NL80211_ATTR_GENERATION, sinfo->generation))
5992 goto nla_put_failure;
f5ea9120 5993
ae0be8de 5994 sinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_STA_INFO);
2ec600d6 5995 if (!sinfoattr)
fd5b74dc 5996 goto nla_put_failure;
319090bf
JB
5997
5998#define PUT_SINFO(attr, memb, type) do { \
d686b920 5999 BUILD_BUG_ON(sizeof(type) == sizeof(u64)); \
397c657a 6000 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
319090bf
JB
6001 nla_put_ ## type(msg, NL80211_STA_INFO_ ## attr, \
6002 sinfo->memb)) \
6003 goto nla_put_failure; \
6004 } while (0)
d686b920 6005#define PUT_SINFO_U64(attr, memb) do { \
397c657a 6006 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
d686b920
JB
6007 nla_put_u64_64bit(msg, NL80211_STA_INFO_ ## attr, \
6008 sinfo->memb, NL80211_STA_INFO_PAD)) \
6009 goto nla_put_failure; \
6010 } while (0)
319090bf
JB
6011
6012 PUT_SINFO(CONNECTED_TIME, connected_time, u32);
6013 PUT_SINFO(INACTIVE_TIME, inactive_time, u32);
6c7a0033 6014 PUT_SINFO_U64(ASSOC_AT_BOOTTIME, assoc_at);
319090bf 6015
397c657a
OE
6016 if (sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES) |
6017 BIT_ULL(NL80211_STA_INFO_RX_BYTES64)) &&
9360ffd1 6018 nla_put_u32(msg, NL80211_STA_INFO_RX_BYTES,
42745e03 6019 (u32)sinfo->rx_bytes))
9360ffd1 6020 goto nla_put_failure;
319090bf 6021
397c657a
OE
6022 if (sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES) |
6023 BIT_ULL(NL80211_STA_INFO_TX_BYTES64)) &&
9360ffd1 6024 nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES,
42745e03
VK
6025 (u32)sinfo->tx_bytes))
6026 goto nla_put_failure;
319090bf 6027
d686b920
JB
6028 PUT_SINFO_U64(RX_BYTES64, rx_bytes);
6029 PUT_SINFO_U64(TX_BYTES64, tx_bytes);
319090bf
JB
6030 PUT_SINFO(LLID, llid, u16);
6031 PUT_SINFO(PLID, plid, u16);
6032 PUT_SINFO(PLINK_STATE, plink_state, u8);
d686b920 6033 PUT_SINFO_U64(RX_DURATION, rx_duration);
36647055
THJ
6034 PUT_SINFO_U64(TX_DURATION, tx_duration);
6035
6036 if (wiphy_ext_feature_isset(&rdev->wiphy,
6037 NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
6038 PUT_SINFO(AIRTIME_WEIGHT, airtime_weight, u16);
319090bf 6039
66266b3a
JL
6040 switch (rdev->wiphy.signal_type) {
6041 case CFG80211_SIGNAL_TYPE_MBM:
319090bf
JB
6042 PUT_SINFO(SIGNAL, signal, u8);
6043 PUT_SINFO(SIGNAL_AVG, signal_avg, u8);
66266b3a
JL
6044 break;
6045 default:
6046 break;
6047 }
397c657a 6048 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) {
119363c7
FF
6049 if (!nl80211_put_signal(msg, sinfo->chains,
6050 sinfo->chain_signal,
6051 NL80211_STA_INFO_CHAIN_SIGNAL))
6052 goto nla_put_failure;
6053 }
397c657a 6054 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) {
119363c7
FF
6055 if (!nl80211_put_signal(msg, sinfo->chains,
6056 sinfo->chain_signal_avg,
6057 NL80211_STA_INFO_CHAIN_SIGNAL_AVG))
6058 goto nla_put_failure;
6059 }
397c657a 6060 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) {
c8dcfd8a
FF
6061 if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
6062 NL80211_STA_INFO_TX_BITRATE))
6063 goto nla_put_failure;
6064 }
397c657a 6065 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) {
c8dcfd8a
FF
6066 if (!nl80211_put_sta_rate(msg, &sinfo->rxrate,
6067 NL80211_STA_INFO_RX_BITRATE))
420e7fab 6068 goto nla_put_failure;
420e7fab 6069 }
319090bf
JB
6070
6071 PUT_SINFO(RX_PACKETS, rx_packets, u32);
6072 PUT_SINFO(TX_PACKETS, tx_packets, u32);
6073 PUT_SINFO(TX_RETRIES, tx_retries, u32);
6074 PUT_SINFO(TX_FAILED, tx_failed, u32);
6075 PUT_SINFO(EXPECTED_THROUGHPUT, expected_throughput, u32);
ab60633c 6076 PUT_SINFO(AIRTIME_LINK_METRIC, airtime_link_metric, u32);
319090bf
JB
6077 PUT_SINFO(BEACON_LOSS, beacon_loss_count, u32);
6078 PUT_SINFO(LOCAL_PM, local_pm, u32);
6079 PUT_SINFO(PEER_PM, peer_pm, u32);
6080 PUT_SINFO(NONPEER_PM, nonpeer_pm, u32);
dbdaee7a 6081 PUT_SINFO(CONNECTED_TO_GATE, connected_to_gate, u8);
1303a51c 6082 PUT_SINFO(CONNECTED_TO_AS, connected_to_as, u8);
319090bf 6083
397c657a 6084 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_BSS_PARAM)) {
ae0be8de
MK
6085 bss_param = nla_nest_start_noflag(msg,
6086 NL80211_STA_INFO_BSS_PARAM);
f4263c98
PS
6087 if (!bss_param)
6088 goto nla_put_failure;
6089
9360ffd1
DM
6090 if (((sinfo->bss_param.flags & BSS_PARAM_FLAGS_CTS_PROT) &&
6091 nla_put_flag(msg, NL80211_STA_BSS_PARAM_CTS_PROT)) ||
6092 ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_PREAMBLE) &&
6093 nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_PREAMBLE)) ||
6094 ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_SLOT_TIME) &&
6095 nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME)) ||
6096 nla_put_u8(msg, NL80211_STA_BSS_PARAM_DTIM_PERIOD,
6097 sinfo->bss_param.dtim_period) ||
6098 nla_put_u16(msg, NL80211_STA_BSS_PARAM_BEACON_INTERVAL,
6099 sinfo->bss_param.beacon_interval))
6100 goto nla_put_failure;
f4263c98
PS
6101
6102 nla_nest_end(msg, bss_param);
6103 }
397c657a 6104 if ((sinfo->filled & BIT_ULL(NL80211_STA_INFO_STA_FLAGS)) &&
9360ffd1
DM
6105 nla_put(msg, NL80211_STA_INFO_STA_FLAGS,
6106 sizeof(struct nl80211_sta_flag_update),
6107 &sinfo->sta_flags))
6108 goto nla_put_failure;
319090bf 6109
d686b920
JB
6110 PUT_SINFO_U64(T_OFFSET, t_offset);
6111 PUT_SINFO_U64(RX_DROP_MISC, rx_dropped_misc);
6112 PUT_SINFO_U64(BEACON_RX, rx_beacon);
a76b1942 6113 PUT_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8);
0d4e14a3
AB
6114 PUT_SINFO(RX_MPDUS, rx_mpdu_count, u32);
6115 PUT_SINFO(FCS_ERROR_COUNT, fcs_err_count, u32);
81d5439d 6116 if (wiphy_ext_feature_isset(&rdev->wiphy,
9c06602b
BP
6117 NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT)) {
6118 PUT_SINFO(ACK_SIGNAL, ack_signal, u8);
6119 PUT_SINFO(ACK_SIGNAL_AVG, avg_ack_signal, s8);
6120 }
319090bf
JB
6121
6122#undef PUT_SINFO
d686b920 6123#undef PUT_SINFO_U64
6de39808 6124
8689c051 6125 if (sinfo->pertid) {
6de39808
JB
6126 struct nlattr *tidsattr;
6127 int tid;
6128
ae0be8de
MK
6129 tidsattr = nla_nest_start_noflag(msg,
6130 NL80211_STA_INFO_TID_STATS);
6de39808
JB
6131 if (!tidsattr)
6132 goto nla_put_failure;
6133
6134 for (tid = 0; tid < IEEE80211_NUM_TIDS + 1; tid++) {
6135 struct cfg80211_tid_stats *tidstats;
6136 struct nlattr *tidattr;
6137
6138 tidstats = &sinfo->pertid[tid];
6139
6140 if (!tidstats->filled)
6141 continue;
6142
ae0be8de 6143 tidattr = nla_nest_start_noflag(msg, tid + 1);
6de39808
JB
6144 if (!tidattr)
6145 goto nla_put_failure;
6146
d686b920 6147#define PUT_TIDVAL_U64(attr, memb) do { \
6de39808 6148 if (tidstats->filled & BIT(NL80211_TID_STATS_ ## attr) && \
d686b920
JB
6149 nla_put_u64_64bit(msg, NL80211_TID_STATS_ ## attr, \
6150 tidstats->memb, NL80211_TID_STATS_PAD)) \
6de39808
JB
6151 goto nla_put_failure; \
6152 } while (0)
6153
d686b920
JB
6154 PUT_TIDVAL_U64(RX_MSDU, rx_msdu);
6155 PUT_TIDVAL_U64(TX_MSDU, tx_msdu);
6156 PUT_TIDVAL_U64(TX_MSDU_RETRIES, tx_msdu_retries);
6157 PUT_TIDVAL_U64(TX_MSDU_FAILED, tx_msdu_failed);
6de39808 6158
d686b920 6159#undef PUT_TIDVAL_U64
52539ca8
THJ
6160 if ((tidstats->filled &
6161 BIT(NL80211_TID_STATS_TXQ_STATS)) &&
6162 !nl80211_put_txq_stats(msg, &tidstats->txq_stats,
6163 NL80211_TID_STATS_TXQ_STATS))
6164 goto nla_put_failure;
6165
6de39808
JB
6166 nla_nest_end(msg, tidattr);
6167 }
6168
6169 nla_nest_end(msg, tidsattr);
6170 }
6171
2ec600d6 6172 nla_nest_end(msg, sinfoattr);
fd5b74dc 6173
319090bf 6174 if (sinfo->assoc_req_ies_len &&
9360ffd1
DM
6175 nla_put(msg, NL80211_ATTR_IE, sinfo->assoc_req_ies_len,
6176 sinfo->assoc_req_ies))
6177 goto nla_put_failure;
50d3dfb7 6178
7ea3e110 6179 cfg80211_sinfo_release_content(sinfo);
053c095a
JB
6180 genlmsg_end(msg, hdr);
6181 return 0;
fd5b74dc
JB
6182
6183 nla_put_failure:
7ea3e110 6184 cfg80211_sinfo_release_content(sinfo);
bc3ed28c
TG
6185 genlmsg_cancel(msg, hdr);
6186 return -EMSGSIZE;
fd5b74dc
JB
6187}
6188
2ec600d6 6189static int nl80211_dump_station(struct sk_buff *skb,
bba95fef 6190 struct netlink_callback *cb)
2ec600d6 6191{
73887fd9 6192 struct station_info sinfo;
1b8ec87a 6193 struct cfg80211_registered_device *rdev;
97990a06 6194 struct wireless_dev *wdev;
2ec600d6 6195 u8 mac_addr[ETH_ALEN];
97990a06 6196 int sta_idx = cb->args[2];
2ec600d6 6197 int err;
2ec600d6 6198
5297c65c 6199 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
67748893 6200 if (err)
a05829a7
JB
6201 return err;
6202 /* nl80211_prepare_wdev_dump acquired it in the successful case */
6203 __acquire(&rdev->wiphy.mtx);
bba95fef 6204
97990a06
JB
6205 if (!wdev->netdev) {
6206 err = -EINVAL;
6207 goto out_err;
6208 }
6209
1b8ec87a 6210 if (!rdev->ops->dump_station) {
eec60b03 6211 err = -EOPNOTSUPP;
bba95fef
JB
6212 goto out_err;
6213 }
6214
bba95fef 6215 while (1) {
73887fd9 6216 memset(&sinfo, 0, sizeof(sinfo));
1b8ec87a 6217 err = rdev_dump_station(rdev, wdev->netdev, sta_idx,
73887fd9 6218 mac_addr, &sinfo);
bba95fef
JB
6219 if (err == -ENOENT)
6220 break;
6221 if (err)
3b85875a 6222 goto out_err;
bba95fef 6223
cf5ead82 6224 if (nl80211_send_station(skb, NL80211_CMD_NEW_STATION,
15e47304 6225 NETLINK_CB(cb->skb).portid,
bba95fef 6226 cb->nlh->nlmsg_seq, NLM_F_MULTI,
1b8ec87a 6227 rdev, wdev->netdev, mac_addr,
73887fd9 6228 &sinfo) < 0)
bba95fef
JB
6229 goto out;
6230
6231 sta_idx++;
6232 }
6233
bba95fef 6234 out:
97990a06 6235 cb->args[2] = sta_idx;
bba95fef 6236 err = skb->len;
bba95fef 6237 out_err:
a05829a7 6238 wiphy_unlock(&rdev->wiphy);
bba95fef
JB
6239
6240 return err;
2ec600d6 6241}
fd5b74dc 6242
5727ef1b
JB
6243static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
6244{
4c476991
JB
6245 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6246 struct net_device *dev = info->user_ptr[1];
73887fd9 6247 struct station_info sinfo;
fd5b74dc
JB
6248 struct sk_buff *msg;
6249 u8 *mac_addr = NULL;
4c476991 6250 int err;
fd5b74dc 6251
73887fd9 6252 memset(&sinfo, 0, sizeof(sinfo));
fd5b74dc 6253
73887fd9
JB
6254 if (!info->attrs[NL80211_ATTR_MAC])
6255 return -EINVAL;
fd5b74dc
JB
6256
6257 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
6258
73887fd9
JB
6259 if (!rdev->ops->get_station)
6260 return -EOPNOTSUPP;
3b85875a 6261
73887fd9 6262 err = rdev_get_station(rdev, dev, mac_addr, &sinfo);
fd5b74dc 6263 if (err)
73887fd9 6264 return err;
2ec600d6 6265
fd2120ca 6266 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7ea3e110 6267 if (!msg) {
ba8f566a 6268 cfg80211_sinfo_release_content(&sinfo);
73887fd9 6269 return -ENOMEM;
7ea3e110 6270 }
fd5b74dc 6271
cf5ead82
JB
6272 if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION,
6273 info->snd_portid, info->snd_seq, 0,
73887fd9 6274 rdev, dev, mac_addr, &sinfo) < 0) {
4c476991 6275 nlmsg_free(msg);
73887fd9 6276 return -ENOBUFS;
4c476991 6277 }
3b85875a 6278
73887fd9 6279 return genlmsg_reply(msg, info);
5727ef1b
JB
6280}
6281
77ee7c89
JB
6282int cfg80211_check_station_change(struct wiphy *wiphy,
6283 struct station_parameters *params,
6284 enum cfg80211_station_type statype)
6285{
e4208427
AB
6286 if (params->listen_interval != -1 &&
6287 statype != CFG80211_STA_AP_CLIENT_UNASSOC)
77ee7c89 6288 return -EINVAL;
e4208427 6289
17b94247
AB
6290 if (params->support_p2p_ps != -1 &&
6291 statype != CFG80211_STA_AP_CLIENT_UNASSOC)
6292 return -EINVAL;
6293
c72e1140 6294 if (params->aid &&
e4208427
AB
6295 !(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
6296 statype != CFG80211_STA_AP_CLIENT_UNASSOC)
77ee7c89
JB
6297 return -EINVAL;
6298
6299 /* When you run into this, adjust the code below for the new flag */
6300 BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7);
6301
6302 switch (statype) {
eef941e6
TP
6303 case CFG80211_STA_MESH_PEER_KERNEL:
6304 case CFG80211_STA_MESH_PEER_USER:
77ee7c89
JB
6305 /*
6306 * No ignoring the TDLS flag here -- the userspace mesh
6307 * code doesn't have the bug of including TDLS in the
6308 * mask everywhere.
6309 */
6310 if (params->sta_flags_mask &
6311 ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) |
6312 BIT(NL80211_STA_FLAG_MFP) |
6313 BIT(NL80211_STA_FLAG_AUTHORIZED)))
6314 return -EINVAL;
6315 break;
6316 case CFG80211_STA_TDLS_PEER_SETUP:
6317 case CFG80211_STA_TDLS_PEER_ACTIVE:
6318 if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
6319 return -EINVAL;
6320 /* ignore since it can't change */
6321 params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
6322 break;
6323 default:
6324 /* disallow mesh-specific things */
6325 if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION)
6326 return -EINVAL;
6327 if (params->local_pm)
6328 return -EINVAL;
6329 if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)
6330 return -EINVAL;
6331 }
6332
6333 if (statype != CFG80211_STA_TDLS_PEER_SETUP &&
6334 statype != CFG80211_STA_TDLS_PEER_ACTIVE) {
6335 /* TDLS can't be set, ... */
6336 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
6337 return -EINVAL;
6338 /*
6339 * ... but don't bother the driver with it. This works around
6340 * a hostapd/wpa_supplicant issue -- it always includes the
6341 * TLDS_PEER flag in the mask even for AP mode.
6342 */
6343 params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
6344 }
6345
47edb11b
AB
6346 if (statype != CFG80211_STA_TDLS_PEER_SETUP &&
6347 statype != CFG80211_STA_AP_CLIENT_UNASSOC) {
77ee7c89
JB
6348 /* reject other things that can't change */
6349 if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD)
6350 return -EINVAL;
6351 if (params->sta_modify_mask & STATION_PARAM_APPLY_CAPABILITY)
6352 return -EINVAL;
6353 if (params->supported_rates)
6354 return -EINVAL;
c4cbaf79
LC
6355 if (params->ext_capab || params->ht_capa || params->vht_capa ||
6356 params->he_capa)
77ee7c89
JB
6357 return -EINVAL;
6358 }
6359
47edb11b
AB
6360 if (statype != CFG80211_STA_AP_CLIENT &&
6361 statype != CFG80211_STA_AP_CLIENT_UNASSOC) {
77ee7c89
JB
6362 if (params->vlan)
6363 return -EINVAL;
6364 }
6365
6366 switch (statype) {
6367 case CFG80211_STA_AP_MLME_CLIENT:
6368 /* Use this only for authorizing/unauthorizing a station */
6369 if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))
6370 return -EOPNOTSUPP;
6371 break;
6372 case CFG80211_STA_AP_CLIENT:
47edb11b 6373 case CFG80211_STA_AP_CLIENT_UNASSOC:
77ee7c89
JB
6374 /* accept only the listed bits */
6375 if (params->sta_flags_mask &
6376 ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
6377 BIT(NL80211_STA_FLAG_AUTHENTICATED) |
6378 BIT(NL80211_STA_FLAG_ASSOCIATED) |
6379 BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
6380 BIT(NL80211_STA_FLAG_WME) |
6381 BIT(NL80211_STA_FLAG_MFP)))
6382 return -EINVAL;
6383
6384 /* but authenticated/associated only if driver handles it */
6385 if (!(wiphy->features & NL80211_FEATURE_FULL_AP_CLIENT_STATE) &&
6386 params->sta_flags_mask &
6387 (BIT(NL80211_STA_FLAG_AUTHENTICATED) |
6388 BIT(NL80211_STA_FLAG_ASSOCIATED)))
6389 return -EINVAL;
6390 break;
6391 case CFG80211_STA_IBSS:
6392 case CFG80211_STA_AP_STA:
6393 /* reject any changes other than AUTHORIZED */
6394 if (params->sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED))
6395 return -EINVAL;
6396 break;
6397 case CFG80211_STA_TDLS_PEER_SETUP:
6398 /* reject any changes other than AUTHORIZED or WME */
6399 if (params->sta_flags_mask & ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
6400 BIT(NL80211_STA_FLAG_WME)))
6401 return -EINVAL;
6402 /* force (at least) rates when authorizing */
6403 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED) &&
6404 !params->supported_rates)
6405 return -EINVAL;
6406 break;
6407 case CFG80211_STA_TDLS_PEER_ACTIVE:
6408 /* reject any changes */
6409 return -EINVAL;
eef941e6 6410 case CFG80211_STA_MESH_PEER_KERNEL:
77ee7c89
JB
6411 if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)
6412 return -EINVAL;
6413 break;
eef941e6 6414 case CFG80211_STA_MESH_PEER_USER:
42925040
CYY
6415 if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION &&
6416 params->plink_action != NL80211_PLINK_ACTION_BLOCK)
77ee7c89
JB
6417 return -EINVAL;
6418 break;
6419 }
6420
06f7c88c
BL
6421 /*
6422 * Older kernel versions ignored this attribute entirely, so don't
6423 * reject attempts to update it but mark it as unused instead so the
6424 * driver won't look at the data.
6425 */
6426 if (statype != CFG80211_STA_AP_CLIENT_UNASSOC &&
6427 statype != CFG80211_STA_TDLS_PEER_SETUP)
6428 params->opmode_notif_used = false;
6429
77ee7c89
JB
6430 return 0;
6431}
6432EXPORT_SYMBOL(cfg80211_check_station_change);
6433
5727ef1b 6434/*
c258d2de 6435 * Get vlan interface making sure it is running and on the right wiphy.
5727ef1b 6436 */
80b99899
JB
6437static struct net_device *get_vlan(struct genl_info *info,
6438 struct cfg80211_registered_device *rdev)
5727ef1b 6439{
463d0183 6440 struct nlattr *vlanattr = info->attrs[NL80211_ATTR_STA_VLAN];
80b99899
JB
6441 struct net_device *v;
6442 int ret;
6443
6444 if (!vlanattr)
6445 return NULL;
6446
6447 v = dev_get_by_index(genl_info_net(info), nla_get_u32(vlanattr));
6448 if (!v)
6449 return ERR_PTR(-ENODEV);
6450
6451 if (!v->ieee80211_ptr || v->ieee80211_ptr->wiphy != &rdev->wiphy) {
6452 ret = -EINVAL;
6453 goto error;
5727ef1b 6454 }
80b99899 6455
77ee7c89
JB
6456 if (v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
6457 v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
6458 v->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
6459 ret = -EINVAL;
6460 goto error;
6461 }
6462
80b99899
JB
6463 if (!netif_running(v)) {
6464 ret = -ENETDOWN;
6465 goto error;
6466 }
6467
6468 return v;
6469 error:
6470 dev_put(v);
6471 return ERR_PTR(ret);
5727ef1b
JB
6472}
6473
94e860f1
JB
6474static const struct nla_policy
6475nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] = {
df881293
JM
6476 [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 },
6477 [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 },
6478};
6479
ff276691
JB
6480static int nl80211_parse_sta_wme(struct genl_info *info,
6481 struct station_parameters *params)
df881293 6482{
df881293
JM
6483 struct nlattr *tb[NL80211_STA_WME_MAX + 1];
6484 struct nlattr *nla;
6485 int err;
6486
df881293
JM
6487 /* parse WME attributes if present */
6488 if (!info->attrs[NL80211_ATTR_STA_WME])
6489 return 0;
6490
6491 nla = info->attrs[NL80211_ATTR_STA_WME];
8cb08174
JB
6492 err = nla_parse_nested_deprecated(tb, NL80211_STA_WME_MAX, nla,
6493 nl80211_sta_wme_policy,
6494 info->extack);
df881293
JM
6495 if (err)
6496 return err;
6497
6498 if (tb[NL80211_STA_WME_UAPSD_QUEUES])
6499 params->uapsd_queues = nla_get_u8(
6500 tb[NL80211_STA_WME_UAPSD_QUEUES]);
6501 if (params->uapsd_queues & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
6502 return -EINVAL;
6503
6504 if (tb[NL80211_STA_WME_MAX_SP])
6505 params->max_sp = nla_get_u8(tb[NL80211_STA_WME_MAX_SP]);
6506
6507 if (params->max_sp & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
6508 return -EINVAL;
6509
6510 params->sta_modify_mask |= STATION_PARAM_APPLY_UAPSD;
6511
6512 return 0;
6513}
6514
c01fc9ad
SD
6515static int nl80211_parse_sta_channel_info(struct genl_info *info,
6516 struct station_parameters *params)
6517{
6518 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]) {
6519 params->supported_channels =
6520 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
6521 params->supported_channels_len =
6522 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
6523 /*
6524 * Need to include at least one (first channel, number of
cb9abd48
JB
6525 * channels) tuple for each subband (checked in policy),
6526 * and must have proper tuples for the rest of the data as well.
c01fc9ad 6527 */
c01fc9ad
SD
6528 if (params->supported_channels_len % 2)
6529 return -EINVAL;
6530 }
6531
6532 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]) {
6533 params->supported_oper_classes =
6534 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
6535 params->supported_oper_classes_len =
6536 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
c01fc9ad
SD
6537 }
6538 return 0;
6539}
6540
ff276691
JB
6541static int nl80211_set_station_tdls(struct genl_info *info,
6542 struct station_parameters *params)
6543{
c01fc9ad 6544 int err;
ff276691 6545 /* Dummy STA entry gets updated once the peer capabilities are known */
5e4b6f56
JM
6546 if (info->attrs[NL80211_ATTR_PEER_AID])
6547 params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
ff276691
JB
6548 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
6549 params->ht_capa =
6550 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
6551 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
6552 params->vht_capa =
6553 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
c4cbaf79
LC
6554 if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
6555 params->he_capa =
6556 nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
6557 params->he_capa_len =
6558 nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
c4cbaf79 6559 }
ff276691 6560
c01fc9ad
SD
6561 err = nl80211_parse_sta_channel_info(info, params);
6562 if (err)
6563 return err;
6564
ff276691
JB
6565 return nl80211_parse_sta_wme(info, params);
6566}
6567
e96d1cd2
ARN
6568static int nl80211_parse_sta_txpower_setting(struct genl_info *info,
6569 struct station_parameters *params)
6570{
6571 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6572 int idx;
6573
6574 if (info->attrs[NL80211_ATTR_STA_TX_POWER_SETTING]) {
6575 if (!rdev->ops->set_tx_power ||
6576 !wiphy_ext_feature_isset(&rdev->wiphy,
6577 NL80211_EXT_FEATURE_STA_TX_PWR))
6578 return -EOPNOTSUPP;
6579
6580 idx = NL80211_ATTR_STA_TX_POWER_SETTING;
6581 params->txpwr.type = nla_get_u8(info->attrs[idx]);
6582
6583 if (params->txpwr.type == NL80211_TX_POWER_LIMITED) {
6584 idx = NL80211_ATTR_STA_TX_POWER;
6585
6586 if (info->attrs[idx])
6587 params->txpwr.power =
6588 nla_get_s16(info->attrs[idx]);
6589 else
6590 return -EINVAL;
6591 }
6592 params->sta_modify_mask |= STATION_PARAM_APPLY_STA_TXPOWER;
6593 }
6594
6595 return 0;
6596}
6597
5727ef1b
JB
6598static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
6599{
4c476991 6600 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 6601 struct net_device *dev = info->user_ptr[1];
5727ef1b 6602 struct station_parameters params;
77ee7c89
JB
6603 u8 *mac_addr;
6604 int err;
5727ef1b
JB
6605
6606 memset(&params, 0, sizeof(params));
6607
77ee7c89
JB
6608 if (!rdev->ops->change_station)
6609 return -EOPNOTSUPP;
6610
e4208427
AB
6611 /*
6612 * AID and listen_interval properties can be set only for unassociated
6613 * station. Include these parameters here and will check them in
6614 * cfg80211_check_station_change().
6615 */
a9bc31e4
AB
6616 if (info->attrs[NL80211_ATTR_STA_AID])
6617 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
e4208427 6618
14f34e36
GG
6619 if (info->attrs[NL80211_ATTR_VLAN_ID])
6620 params.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
6621
e4208427
AB
6622 if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
6623 params.listen_interval =
6624 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
6625 else
6626 params.listen_interval = -1;
5727ef1b 6627
ab0d76f6
JB
6628 if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS])
6629 params.support_p2p_ps =
6630 nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
6631 else
17b94247 6632 params.support_p2p_ps = -1;
17b94247 6633
5727ef1b
JB
6634 if (!info->attrs[NL80211_ATTR_MAC])
6635 return -EINVAL;
6636
6637 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
6638
6639 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
6640 params.supported_rates =
6641 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
6642 params.supported_rates_len =
6643 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
6644 }
6645
9d62a986
JM
6646 if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
6647 params.capability =
6648 nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]);
6649 params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY;
6650 }
6651
6652 if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) {
6653 params.ext_capab =
6654 nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
6655 params.ext_capab_len =
6656 nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
6657 }
6658
bdd3ae3d 6659 if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
5727ef1b
JB
6660 return -EINVAL;
6661
ab0d76f6 6662 if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
2ec600d6 6663 params.plink_action =
f8bacc21 6664 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
2ec600d6 6665
f8bacc21 6666 if (info->attrs[NL80211_ATTR_STA_PLINK_STATE]) {
9c3990aa 6667 params.plink_state =
f8bacc21 6668 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]);
ab0d76f6 6669 if (info->attrs[NL80211_ATTR_MESH_PEER_AID])
7d27a0ba
MH
6670 params.peer_aid = nla_get_u16(
6671 info->attrs[NL80211_ATTR_MESH_PEER_AID]);
f8bacc21
JB
6672 params.sta_modify_mask |= STATION_PARAM_APPLY_PLINK_STATE;
6673 }
9c3990aa 6674
ab0d76f6
JB
6675 if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE])
6676 params.local_pm = nla_get_u32(
3b1c5a53
MP
6677 info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]);
6678
06f7c88c
BL
6679 if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
6680 params.opmode_notif_used = true;
6681 params.opmode_notif =
6682 nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
6683 }
6684
43e64bf3
RM
6685 if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
6686 params.he_6ghz_capa =
fce2ff72 6687 nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
43e64bf3 6688
36647055
THJ
6689 if (info->attrs[NL80211_ATTR_AIRTIME_WEIGHT])
6690 params.airtime_weight =
6691 nla_get_u16(info->attrs[NL80211_ATTR_AIRTIME_WEIGHT]);
6692
6693 if (params.airtime_weight &&
6694 !wiphy_ext_feature_isset(&rdev->wiphy,
6695 NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
6696 return -EOPNOTSUPP;
6697
e96d1cd2
ARN
6698 err = nl80211_parse_sta_txpower_setting(info, &params);
6699 if (err)
6700 return err;
6701
77ee7c89
JB
6702 /* Include parameters for TDLS peer (will check later) */
6703 err = nl80211_set_station_tdls(info, &params);
6704 if (err)
6705 return err;
6706
6707 params.vlan = get_vlan(info, rdev);
6708 if (IS_ERR(params.vlan))
6709 return PTR_ERR(params.vlan);
6710
a97f4424
JB
6711 switch (dev->ieee80211_ptr->iftype) {
6712 case NL80211_IFTYPE_AP:
6713 case NL80211_IFTYPE_AP_VLAN:
074ac8df 6714 case NL80211_IFTYPE_P2P_GO:
074ac8df 6715 case NL80211_IFTYPE_P2P_CLIENT:
a97f4424 6716 case NL80211_IFTYPE_STATION:
267335d6 6717 case NL80211_IFTYPE_ADHOC:
a97f4424 6718 case NL80211_IFTYPE_MESH_POINT:
a97f4424
JB
6719 break;
6720 default:
77ee7c89
JB
6721 err = -EOPNOTSUPP;
6722 goto out_put_vlan;
034d655e
JB
6723 }
6724
77ee7c89 6725 /* driver will call cfg80211_check_station_change() */
e35e4d28 6726 err = rdev_change_station(rdev, dev, mac_addr, &params);
5727ef1b 6727
77ee7c89 6728 out_put_vlan:
1160dfa1 6729 dev_put(params.vlan);
3b85875a 6730
5727ef1b
JB
6731 return err;
6732}
6733
6734static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
6735{
4c476991 6736 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5727ef1b 6737 int err;
4c476991 6738 struct net_device *dev = info->user_ptr[1];
5727ef1b
JB
6739 struct station_parameters params;
6740 u8 *mac_addr = NULL;
bda95eb1
JB
6741 u32 auth_assoc = BIT(NL80211_STA_FLAG_AUTHENTICATED) |
6742 BIT(NL80211_STA_FLAG_ASSOCIATED);
5727ef1b
JB
6743
6744 memset(&params, 0, sizeof(params));
6745
984c311b
JB
6746 if (!rdev->ops->add_station)
6747 return -EOPNOTSUPP;
6748
5727ef1b
JB
6749 if (!info->attrs[NL80211_ATTR_MAC])
6750 return -EINVAL;
6751
5727ef1b
JB
6752 if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
6753 return -EINVAL;
6754
6755 if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
6756 return -EINVAL;
6757
5e4b6f56
JM
6758 if (!info->attrs[NL80211_ATTR_STA_AID] &&
6759 !info->attrs[NL80211_ATTR_PEER_AID])
0e956c13
TLSC
6760 return -EINVAL;
6761
5727ef1b
JB
6762 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
6763 params.supported_rates =
6764 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
6765 params.supported_rates_len =
6766 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
6767 params.listen_interval =
6768 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
51b50fbe 6769
14f34e36
GG
6770 if (info->attrs[NL80211_ATTR_VLAN_ID])
6771 params.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
6772
17b94247 6773 if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) {
ab0d76f6
JB
6774 params.support_p2p_ps =
6775 nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
17b94247
AB
6776 } else {
6777 /*
6778 * if not specified, assume it's supported for P2P GO interface,
6779 * and is NOT supported for AP interface
6780 */
6781 params.support_p2p_ps =
6782 dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO;
6783 }
6784
3d124ea2 6785 if (info->attrs[NL80211_ATTR_PEER_AID])
5e4b6f56 6786 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
3d124ea2
JM
6787 else
6788 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
51b50fbe 6789
9d62a986
JM
6790 if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
6791 params.capability =
6792 nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]);
6793 params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY;
6794 }
6795
6796 if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) {
6797 params.ext_capab =
6798 nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
6799 params.ext_capab_len =
6800 nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
6801 }
6802
36aedc90
JM
6803 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
6804 params.ht_capa =
6805 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
5727ef1b 6806
f461be3e
MP
6807 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
6808 params.vht_capa =
6809 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
6810
c4cbaf79
LC
6811 if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
6812 params.he_capa =
6813 nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
6814 params.he_capa_len =
6815 nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
c4cbaf79
LC
6816 }
6817
43e64bf3
RM
6818 if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
6819 params.he_6ghz_capa =
6820 nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
6821
60f4a7b1
MK
6822 if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
6823 params.opmode_notif_used = true;
6824 params.opmode_notif =
6825 nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
6826 }
6827
ab0d76f6 6828 if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
96b78dff 6829 params.plink_action =
f8bacc21 6830 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
96b78dff 6831
36647055
THJ
6832 if (info->attrs[NL80211_ATTR_AIRTIME_WEIGHT])
6833 params.airtime_weight =
6834 nla_get_u16(info->attrs[NL80211_ATTR_AIRTIME_WEIGHT]);
6835
6836 if (params.airtime_weight &&
6837 !wiphy_ext_feature_isset(&rdev->wiphy,
6838 NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
6839 return -EOPNOTSUPP;
6840
e96d1cd2
ARN
6841 err = nl80211_parse_sta_txpower_setting(info, &params);
6842 if (err)
6843 return err;
6844
c01fc9ad
SD
6845 err = nl80211_parse_sta_channel_info(info, &params);
6846 if (err)
6847 return err;
6848
ff276691
JB
6849 err = nl80211_parse_sta_wme(info, &params);
6850 if (err)
6851 return err;
bdd90d5e 6852
bdd3ae3d 6853 if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
5727ef1b
JB
6854 return -EINVAL;
6855
496fcc29
JB
6856 /* HT/VHT requires QoS, but if we don't have that just ignore HT/VHT
6857 * as userspace might just pass through the capabilities from the IEs
6858 * directly, rather than enforcing this restriction and returning an
6859 * error in this case.
6860 */
6861 if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME))) {
6862 params.ht_capa = NULL;
6863 params.vht_capa = NULL;
c4cbaf79
LC
6864
6865 /* HE requires WME */
43e64bf3 6866 if (params.he_capa_len || params.he_6ghz_capa)
c4cbaf79 6867 return -EINVAL;
496fcc29
JB
6868 }
6869
43e64bf3
RM
6870 /* Ensure that HT/VHT capabilities are not set for 6 GHz HE STA */
6871 if (params.he_6ghz_capa && (params.ht_capa || params.vht_capa))
6872 return -EINVAL;
6873
77ee7c89
JB
6874 /* When you run into this, adjust the code below for the new flag */
6875 BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7);
6876
bdd90d5e
JB
6877 switch (dev->ieee80211_ptr->iftype) {
6878 case NL80211_IFTYPE_AP:
6879 case NL80211_IFTYPE_AP_VLAN:
6880 case NL80211_IFTYPE_P2P_GO:
984c311b
JB
6881 /* ignore WME attributes if iface/sta is not capable */
6882 if (!(rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) ||
6883 !(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)))
6884 params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
c75786c9 6885
bdd90d5e 6886 /* TDLS peers cannot be added */
3d124ea2
JM
6887 if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ||
6888 info->attrs[NL80211_ATTR_PEER_AID])
4319e193 6889 return -EINVAL;
bdd90d5e
JB
6890 /* but don't bother the driver with it */
6891 params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
3b9ce80c 6892
d582cffb
JB
6893 /* allow authenticated/associated only if driver handles it */
6894 if (!(rdev->wiphy.features &
6895 NL80211_FEATURE_FULL_AP_CLIENT_STATE) &&
bda95eb1 6896 params.sta_flags_mask & auth_assoc)
d582cffb
JB
6897 return -EINVAL;
6898
bda95eb1
JB
6899 /* Older userspace, or userspace wanting to be compatible with
6900 * !NL80211_FEATURE_FULL_AP_CLIENT_STATE, will not set the auth
6901 * and assoc flags in the mask, but assumes the station will be
6902 * added as associated anyway since this was the required driver
6903 * behaviour before NL80211_FEATURE_FULL_AP_CLIENT_STATE was
6904 * introduced.
6905 * In order to not bother drivers with this quirk in the API
6906 * set the flags in both the mask and set for new stations in
6907 * this case.
6908 */
6909 if (!(params.sta_flags_mask & auth_assoc)) {
6910 params.sta_flags_mask |= auth_assoc;
6911 params.sta_flags_set |= auth_assoc;
6912 }
6913
bdd90d5e
JB
6914 /* must be last in here for error handling */
6915 params.vlan = get_vlan(info, rdev);
6916 if (IS_ERR(params.vlan))
6917 return PTR_ERR(params.vlan);
6918 break;
6919 case NL80211_IFTYPE_MESH_POINT:
984c311b
JB
6920 /* ignore uAPSD data */
6921 params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
6922
d582cffb
JB
6923 /* associated is disallowed */
6924 if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED))
6925 return -EINVAL;
bdd90d5e 6926 /* TDLS peers cannot be added */
3d124ea2
JM
6927 if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ||
6928 info->attrs[NL80211_ATTR_PEER_AID])
bdd90d5e
JB
6929 return -EINVAL;
6930 break;
6931 case NL80211_IFTYPE_STATION:
93d08f0b 6932 case NL80211_IFTYPE_P2P_CLIENT:
984c311b
JB
6933 /* ignore uAPSD data */
6934 params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
6935
77ee7c89
JB
6936 /* these are disallowed */
6937 if (params.sta_flags_mask &
6938 (BIT(NL80211_STA_FLAG_ASSOCIATED) |
6939 BIT(NL80211_STA_FLAG_AUTHENTICATED)))
d582cffb 6940 return -EINVAL;
bdd90d5e
JB
6941 /* Only TDLS peers can be added */
6942 if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
6943 return -EINVAL;
6944 /* Can only add if TDLS ... */
6945 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS))
6946 return -EOPNOTSUPP;
6947 /* ... with external setup is supported */
6948 if (!(rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP))
6949 return -EOPNOTSUPP;
77ee7c89
JB
6950 /*
6951 * Older wpa_supplicant versions always mark the TDLS peer
6952 * as authorized, but it shouldn't yet be.
6953 */
6954 params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_AUTHORIZED);
bdd90d5e
JB
6955 break;
6956 default:
6957 return -EOPNOTSUPP;
c75786c9
EP
6958 }
6959
bdd90d5e 6960 /* be aware of params.vlan when changing code here */
5727ef1b 6961
e35e4d28 6962 err = rdev_add_station(rdev, dev, mac_addr, &params);
5727ef1b 6963
1160dfa1 6964 dev_put(params.vlan);
5727ef1b
JB
6965 return err;
6966}
6967
6968static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
6969{
4c476991
JB
6970 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6971 struct net_device *dev = info->user_ptr[1];
89c771e5
JM
6972 struct station_del_parameters params;
6973
6974 memset(&params, 0, sizeof(params));
5727ef1b
JB
6975
6976 if (info->attrs[NL80211_ATTR_MAC])
89c771e5 6977 params.mac = nla_data(info->attrs[NL80211_ATTR_MAC]);
5727ef1b 6978
306b79ea
JB
6979 switch (dev->ieee80211_ptr->iftype) {
6980 case NL80211_IFTYPE_AP:
6981 case NL80211_IFTYPE_AP_VLAN:
6982 case NL80211_IFTYPE_MESH_POINT:
6983 case NL80211_IFTYPE_P2P_GO:
6984 /* always accept these */
6985 break;
6986 case NL80211_IFTYPE_ADHOC:
6987 /* conditionally accept */
6988 if (wiphy_ext_feature_isset(&rdev->wiphy,
6989 NL80211_EXT_FEATURE_DEL_IBSS_STA))
6990 break;
edafcf42 6991 return -EINVAL;
306b79ea 6992 default:
4c476991 6993 return -EINVAL;
306b79ea 6994 }
5727ef1b 6995
4c476991
JB
6996 if (!rdev->ops->del_station)
6997 return -EOPNOTSUPP;
3b85875a 6998
98856866
JM
6999 if (info->attrs[NL80211_ATTR_MGMT_SUBTYPE]) {
7000 params.subtype =
7001 nla_get_u8(info->attrs[NL80211_ATTR_MGMT_SUBTYPE]);
7002 if (params.subtype != IEEE80211_STYPE_DISASSOC >> 4 &&
7003 params.subtype != IEEE80211_STYPE_DEAUTH >> 4)
7004 return -EINVAL;
7005 } else {
7006 /* Default to Deauthentication frame */
7007 params.subtype = IEEE80211_STYPE_DEAUTH >> 4;
7008 }
7009
7010 if (info->attrs[NL80211_ATTR_REASON_CODE]) {
7011 params.reason_code =
7012 nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
7013 if (params.reason_code == 0)
7014 return -EINVAL; /* 0 is reserved */
7015 } else {
7016 /* Default to reason code 2 */
7017 params.reason_code = WLAN_REASON_PREV_AUTH_NOT_VALID;
7018 }
7019
89c771e5 7020 return rdev_del_station(rdev, dev, &params);
5727ef1b
JB
7021}
7022
15e47304 7023static int nl80211_send_mpath(struct sk_buff *msg, u32 portid, u32 seq,
2ec600d6
LCC
7024 int flags, struct net_device *dev,
7025 u8 *dst, u8 *next_hop,
7026 struct mpath_info *pinfo)
7027{
7028 void *hdr;
7029 struct nlattr *pinfoattr;
7030
1ef4c850 7031 hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_MPATH);
2ec600d6
LCC
7032 if (!hdr)
7033 return -1;
7034
9360ffd1
DM
7035 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
7036 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, dst) ||
7037 nla_put(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop) ||
7038 nla_put_u32(msg, NL80211_ATTR_GENERATION, pinfo->generation))
7039 goto nla_put_failure;
f5ea9120 7040
ae0be8de 7041 pinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_MPATH_INFO);
2ec600d6
LCC
7042 if (!pinfoattr)
7043 goto nla_put_failure;
9360ffd1
DM
7044 if ((pinfo->filled & MPATH_INFO_FRAME_QLEN) &&
7045 nla_put_u32(msg, NL80211_MPATH_INFO_FRAME_QLEN,
7046 pinfo->frame_qlen))
7047 goto nla_put_failure;
7048 if (((pinfo->filled & MPATH_INFO_SN) &&
7049 nla_put_u32(msg, NL80211_MPATH_INFO_SN, pinfo->sn)) ||
7050 ((pinfo->filled & MPATH_INFO_METRIC) &&
7051 nla_put_u32(msg, NL80211_MPATH_INFO_METRIC,
7052 pinfo->metric)) ||
7053 ((pinfo->filled & MPATH_INFO_EXPTIME) &&
7054 nla_put_u32(msg, NL80211_MPATH_INFO_EXPTIME,
7055 pinfo->exptime)) ||
7056 ((pinfo->filled & MPATH_INFO_FLAGS) &&
7057 nla_put_u8(msg, NL80211_MPATH_INFO_FLAGS,
7058 pinfo->flags)) ||
7059 ((pinfo->filled & MPATH_INFO_DISCOVERY_TIMEOUT) &&
7060 nla_put_u32(msg, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT,
7061 pinfo->discovery_timeout)) ||
7062 ((pinfo->filled & MPATH_INFO_DISCOVERY_RETRIES) &&
7063 nla_put_u8(msg, NL80211_MPATH_INFO_DISCOVERY_RETRIES,
cc241636
JH
7064 pinfo->discovery_retries)) ||
7065 ((pinfo->filled & MPATH_INFO_HOP_COUNT) &&
7066 nla_put_u8(msg, NL80211_MPATH_INFO_HOP_COUNT,
540bbcb9
JH
7067 pinfo->hop_count)) ||
7068 ((pinfo->filled & MPATH_INFO_PATH_CHANGE) &&
7069 nla_put_u32(msg, NL80211_MPATH_INFO_PATH_CHANGE,
7070 pinfo->path_change_count)))
9360ffd1 7071 goto nla_put_failure;
2ec600d6
LCC
7072
7073 nla_nest_end(msg, pinfoattr);
7074
053c095a
JB
7075 genlmsg_end(msg, hdr);
7076 return 0;
2ec600d6
LCC
7077
7078 nla_put_failure:
bc3ed28c
TG
7079 genlmsg_cancel(msg, hdr);
7080 return -EMSGSIZE;
2ec600d6
LCC
7081}
7082
7083static int nl80211_dump_mpath(struct sk_buff *skb,
bba95fef 7084 struct netlink_callback *cb)
2ec600d6 7085{
2ec600d6 7086 struct mpath_info pinfo;
1b8ec87a 7087 struct cfg80211_registered_device *rdev;
97990a06 7088 struct wireless_dev *wdev;
2ec600d6
LCC
7089 u8 dst[ETH_ALEN];
7090 u8 next_hop[ETH_ALEN];
97990a06 7091 int path_idx = cb->args[2];
2ec600d6 7092 int err;
2ec600d6 7093
5297c65c 7094 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
67748893 7095 if (err)
a05829a7
JB
7096 return err;
7097 /* nl80211_prepare_wdev_dump acquired it in the successful case */
7098 __acquire(&rdev->wiphy.mtx);
bba95fef 7099
1b8ec87a 7100 if (!rdev->ops->dump_mpath) {
eec60b03 7101 err = -EOPNOTSUPP;
bba95fef
JB
7102 goto out_err;
7103 }
7104
97990a06 7105 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
eec60b03 7106 err = -EOPNOTSUPP;
0448b5fc 7107 goto out_err;
eec60b03
JM
7108 }
7109
bba95fef 7110 while (1) {
1b8ec87a 7111 err = rdev_dump_mpath(rdev, wdev->netdev, path_idx, dst,
97990a06 7112 next_hop, &pinfo);
bba95fef 7113 if (err == -ENOENT)
2ec600d6 7114 break;
bba95fef 7115 if (err)
3b85875a 7116 goto out_err;
2ec600d6 7117
15e47304 7118 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid,
bba95fef 7119 cb->nlh->nlmsg_seq, NLM_F_MULTI,
97990a06 7120 wdev->netdev, dst, next_hop,
bba95fef
JB
7121 &pinfo) < 0)
7122 goto out;
2ec600d6 7123
bba95fef 7124 path_idx++;
2ec600d6 7125 }
2ec600d6 7126
bba95fef 7127 out:
97990a06 7128 cb->args[2] = path_idx;
bba95fef 7129 err = skb->len;
bba95fef 7130 out_err:
a05829a7 7131 wiphy_unlock(&rdev->wiphy);
bba95fef 7132 return err;
2ec600d6
LCC
7133}
7134
7135static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
7136{
4c476991 7137 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2ec600d6 7138 int err;
4c476991 7139 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
7140 struct mpath_info pinfo;
7141 struct sk_buff *msg;
7142 u8 *dst = NULL;
7143 u8 next_hop[ETH_ALEN];
7144
7145 memset(&pinfo, 0, sizeof(pinfo));
7146
7147 if (!info->attrs[NL80211_ATTR_MAC])
7148 return -EINVAL;
7149
7150 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
7151
4c476991
JB
7152 if (!rdev->ops->get_mpath)
7153 return -EOPNOTSUPP;
2ec600d6 7154
4c476991
JB
7155 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
7156 return -EOPNOTSUPP;
eec60b03 7157
e35e4d28 7158 err = rdev_get_mpath(rdev, dev, dst, next_hop, &pinfo);
2ec600d6 7159 if (err)
4c476991 7160 return err;
2ec600d6 7161
fd2120ca 7162 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2ec600d6 7163 if (!msg)
4c476991 7164 return -ENOMEM;
2ec600d6 7165
15e47304 7166 if (nl80211_send_mpath(msg, info->snd_portid, info->snd_seq, 0,
4c476991
JB
7167 dev, dst, next_hop, &pinfo) < 0) {
7168 nlmsg_free(msg);
7169 return -ENOBUFS;
7170 }
3b85875a 7171
4c476991 7172 return genlmsg_reply(msg, info);
2ec600d6
LCC
7173}
7174
7175static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
7176{
4c476991
JB
7177 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7178 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
7179 u8 *dst = NULL;
7180 u8 *next_hop = NULL;
7181
7182 if (!info->attrs[NL80211_ATTR_MAC])
7183 return -EINVAL;
7184
7185 if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
7186 return -EINVAL;
7187
7188 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
7189 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
7190
4c476991
JB
7191 if (!rdev->ops->change_mpath)
7192 return -EOPNOTSUPP;
35a8efe1 7193
4c476991
JB
7194 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
7195 return -EOPNOTSUPP;
2ec600d6 7196
e35e4d28 7197 return rdev_change_mpath(rdev, dev, dst, next_hop);
2ec600d6 7198}
4c476991 7199
2ec600d6
LCC
7200static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
7201{
4c476991
JB
7202 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7203 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
7204 u8 *dst = NULL;
7205 u8 *next_hop = NULL;
7206
7207 if (!info->attrs[NL80211_ATTR_MAC])
7208 return -EINVAL;
7209
7210 if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
7211 return -EINVAL;
7212
7213 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
7214 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
7215
4c476991
JB
7216 if (!rdev->ops->add_mpath)
7217 return -EOPNOTSUPP;
35a8efe1 7218
4c476991
JB
7219 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
7220 return -EOPNOTSUPP;
2ec600d6 7221
e35e4d28 7222 return rdev_add_mpath(rdev, dev, dst, next_hop);
2ec600d6
LCC
7223}
7224
7225static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
7226{
4c476991
JB
7227 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7228 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
7229 u8 *dst = NULL;
7230
7231 if (info->attrs[NL80211_ATTR_MAC])
7232 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
7233
4c476991
JB
7234 if (!rdev->ops->del_mpath)
7235 return -EOPNOTSUPP;
3b85875a 7236
b501426c
MP
7237 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
7238 return -EOPNOTSUPP;
7239
e35e4d28 7240 return rdev_del_mpath(rdev, dev, dst);
2ec600d6
LCC
7241}
7242
66be7d2b
HR
7243static int nl80211_get_mpp(struct sk_buff *skb, struct genl_info *info)
7244{
7245 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7246 int err;
7247 struct net_device *dev = info->user_ptr[1];
7248 struct mpath_info pinfo;
7249 struct sk_buff *msg;
7250 u8 *dst = NULL;
7251 u8 mpp[ETH_ALEN];
7252
7253 memset(&pinfo, 0, sizeof(pinfo));
7254
7255 if (!info->attrs[NL80211_ATTR_MAC])
7256 return -EINVAL;
7257
7258 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
7259
7260 if (!rdev->ops->get_mpp)
7261 return -EOPNOTSUPP;
7262
7263 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
7264 return -EOPNOTSUPP;
7265
7266 err = rdev_get_mpp(rdev, dev, dst, mpp, &pinfo);
7267 if (err)
7268 return err;
7269
7270 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7271 if (!msg)
7272 return -ENOMEM;
7273
7274 if (nl80211_send_mpath(msg, info->snd_portid, info->snd_seq, 0,
7275 dev, dst, mpp, &pinfo) < 0) {
7276 nlmsg_free(msg);
7277 return -ENOBUFS;
7278 }
7279
7280 return genlmsg_reply(msg, info);
7281}
7282
7283static int nl80211_dump_mpp(struct sk_buff *skb,
7284 struct netlink_callback *cb)
7285{
7286 struct mpath_info pinfo;
7287 struct cfg80211_registered_device *rdev;
7288 struct wireless_dev *wdev;
7289 u8 dst[ETH_ALEN];
7290 u8 mpp[ETH_ALEN];
7291 int path_idx = cb->args[2];
7292 int err;
7293
5297c65c 7294 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
66be7d2b 7295 if (err)
a05829a7
JB
7296 return err;
7297 /* nl80211_prepare_wdev_dump acquired it in the successful case */
7298 __acquire(&rdev->wiphy.mtx);
66be7d2b
HR
7299
7300 if (!rdev->ops->dump_mpp) {
7301 err = -EOPNOTSUPP;
7302 goto out_err;
7303 }
7304
7305 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
7306 err = -EOPNOTSUPP;
7307 goto out_err;
7308 }
7309
7310 while (1) {
7311 err = rdev_dump_mpp(rdev, wdev->netdev, path_idx, dst,
7312 mpp, &pinfo);
7313 if (err == -ENOENT)
7314 break;
7315 if (err)
7316 goto out_err;
7317
7318 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid,
7319 cb->nlh->nlmsg_seq, NLM_F_MULTI,
7320 wdev->netdev, dst, mpp,
7321 &pinfo) < 0)
7322 goto out;
7323
7324 path_idx++;
7325 }
7326
7327 out:
7328 cb->args[2] = path_idx;
7329 err = skb->len;
7330 out_err:
a05829a7 7331 wiphy_unlock(&rdev->wiphy);
66be7d2b
HR
7332 return err;
7333}
7334
9f1ba906
JM
7335static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
7336{
4c476991
JB
7337 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7338 struct net_device *dev = info->user_ptr[1];
c56589ed 7339 struct wireless_dev *wdev = dev->ieee80211_ptr;
9f1ba906 7340 struct bss_parameters params;
c56589ed 7341 int err;
9f1ba906
JM
7342
7343 memset(&params, 0, sizeof(params));
7344 /* default to not changing parameters */
7345 params.use_cts_prot = -1;
7346 params.use_short_preamble = -1;
7347 params.use_short_slot_time = -1;
fd8aaaf3 7348 params.ap_isolate = -1;
50b12f59 7349 params.ht_opmode = -1;
53cabad7
JB
7350 params.p2p_ctwindow = -1;
7351 params.p2p_opp_ps = -1;
9f1ba906
JM
7352
7353 if (info->attrs[NL80211_ATTR_BSS_CTS_PROT])
7354 params.use_cts_prot =
7355 nla_get_u8(info->attrs[NL80211_ATTR_BSS_CTS_PROT]);
7356 if (info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE])
7357 params.use_short_preamble =
7358 nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]);
7359 if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME])
7360 params.use_short_slot_time =
7361 nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]);
90c97a04
JM
7362 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
7363 params.basic_rates =
7364 nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
7365 params.basic_rates_len =
7366 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
7367 }
fd8aaaf3
FF
7368 if (info->attrs[NL80211_ATTR_AP_ISOLATE])
7369 params.ap_isolate = !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]);
50b12f59
HS
7370 if (info->attrs[NL80211_ATTR_BSS_HT_OPMODE])
7371 params.ht_opmode =
7372 nla_get_u16(info->attrs[NL80211_ATTR_BSS_HT_OPMODE]);
9f1ba906 7373
53cabad7
JB
7374 if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
7375 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
7376 return -EINVAL;
7377 params.p2p_ctwindow =
ab0d76f6 7378 nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
53cabad7
JB
7379 if (params.p2p_ctwindow != 0 &&
7380 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
7381 return -EINVAL;
7382 }
7383
7384 if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
7385 u8 tmp;
7386
7387 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
7388 return -EINVAL;
7389 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
53cabad7
JB
7390 params.p2p_opp_ps = tmp;
7391 if (params.p2p_opp_ps &&
7392 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
7393 return -EINVAL;
7394 }
7395
4c476991
JB
7396 if (!rdev->ops->change_bss)
7397 return -EOPNOTSUPP;
9f1ba906 7398
074ac8df 7399 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
4c476991
JB
7400 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
7401 return -EOPNOTSUPP;
3b85875a 7402
c56589ed
SW
7403 wdev_lock(wdev);
7404 err = rdev_change_bss(rdev, dev, &params);
7405 wdev_unlock(wdev);
7406
7407 return err;
9f1ba906
JM
7408}
7409
b2e1b302
LR
7410static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
7411{
b2e1b302 7412 char *data = NULL;
05050753 7413 bool is_indoor;
57b5ce07 7414 enum nl80211_user_reg_hint_type user_reg_hint_type;
05050753
I
7415 u32 owner_nlportid;
7416
80778f18
LR
7417 /*
7418 * You should only get this when cfg80211 hasn't yet initialized
7419 * completely when built-in to the kernel right between the time
7420 * window between nl80211_init() and regulatory_init(), if that is
7421 * even possible.
7422 */
458f4f9e 7423 if (unlikely(!rcu_access_pointer(cfg80211_regdomain)))
fe33eb39 7424 return -EINPROGRESS;
80778f18 7425
57b5ce07
LR
7426 if (info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE])
7427 user_reg_hint_type =
7428 nla_get_u32(info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE]);
7429 else
7430 user_reg_hint_type = NL80211_USER_REG_HINT_USER;
7431
7432 switch (user_reg_hint_type) {
7433 case NL80211_USER_REG_HINT_USER:
7434 case NL80211_USER_REG_HINT_CELL_BASE:
52616f2b
IP
7435 if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
7436 return -EINVAL;
7437
7438 data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
7439 return regulatory_hint_user(data, user_reg_hint_type);
7440 case NL80211_USER_REG_HINT_INDOOR:
05050753
I
7441 if (info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
7442 owner_nlportid = info->snd_portid;
7443 is_indoor = !!info->attrs[NL80211_ATTR_REG_INDOOR];
7444 } else {
7445 owner_nlportid = 0;
7446 is_indoor = true;
7447 }
7448
7449 return regulatory_hint_indoor(is_indoor, owner_nlportid);
57b5ce07
LR
7450 default:
7451 return -EINVAL;
7452 }
b2e1b302
LR
7453}
7454
1ea4ff3e
JB
7455static int nl80211_reload_regdb(struct sk_buff *skb, struct genl_info *info)
7456{
7457 return reg_reload_regdb();
7458}
7459
24bdd9f4 7460static int nl80211_get_mesh_config(struct sk_buff *skb,
29cbe68c 7461 struct genl_info *info)
93da9cc1 7462{
4c476991 7463 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 7464 struct net_device *dev = info->user_ptr[1];
29cbe68c
JB
7465 struct wireless_dev *wdev = dev->ieee80211_ptr;
7466 struct mesh_config cur_params;
7467 int err = 0;
93da9cc1 7468 void *hdr;
7469 struct nlattr *pinfoattr;
7470 struct sk_buff *msg;
7471
29cbe68c
JB
7472 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
7473 return -EOPNOTSUPP;
7474
24bdd9f4 7475 if (!rdev->ops->get_mesh_config)
4c476991 7476 return -EOPNOTSUPP;
f3f92586 7477
29cbe68c
JB
7478 wdev_lock(wdev);
7479 /* If not connected, get default parameters */
7480 if (!wdev->mesh_id_len)
7481 memcpy(&cur_params, &default_mesh_config, sizeof(cur_params));
7482 else
e35e4d28 7483 err = rdev_get_mesh_config(rdev, dev, &cur_params);
29cbe68c
JB
7484 wdev_unlock(wdev);
7485
93da9cc1 7486 if (err)
4c476991 7487 return err;
93da9cc1 7488
7489 /* Draw up a netlink message to send back */
fd2120ca 7490 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
7491 if (!msg)
7492 return -ENOMEM;
15e47304 7493 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
24bdd9f4 7494 NL80211_CMD_GET_MESH_CONFIG);
93da9cc1 7495 if (!hdr)
efe1cf0c 7496 goto out;
ae0be8de 7497 pinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_MESH_CONFIG);
93da9cc1 7498 if (!pinfoattr)
7499 goto nla_put_failure;
9360ffd1
DM
7500 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
7501 nla_put_u16(msg, NL80211_MESHCONF_RETRY_TIMEOUT,
7502 cur_params.dot11MeshRetryTimeout) ||
7503 nla_put_u16(msg, NL80211_MESHCONF_CONFIRM_TIMEOUT,
7504 cur_params.dot11MeshConfirmTimeout) ||
7505 nla_put_u16(msg, NL80211_MESHCONF_HOLDING_TIMEOUT,
7506 cur_params.dot11MeshHoldingTimeout) ||
7507 nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS,
7508 cur_params.dot11MeshMaxPeerLinks) ||
7509 nla_put_u8(msg, NL80211_MESHCONF_MAX_RETRIES,
7510 cur_params.dot11MeshMaxRetries) ||
7511 nla_put_u8(msg, NL80211_MESHCONF_TTL,
7512 cur_params.dot11MeshTTL) ||
7513 nla_put_u8(msg, NL80211_MESHCONF_ELEMENT_TTL,
7514 cur_params.element_ttl) ||
7515 nla_put_u8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
7516 cur_params.auto_open_plinks) ||
7eab0f64
JL
7517 nla_put_u32(msg, NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
7518 cur_params.dot11MeshNbrOffsetMaxNeighbor) ||
9360ffd1
DM
7519 nla_put_u8(msg, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
7520 cur_params.dot11MeshHWMPmaxPREQretries) ||
7521 nla_put_u32(msg, NL80211_MESHCONF_PATH_REFRESH_TIME,
7522 cur_params.path_refresh_time) ||
7523 nla_put_u16(msg, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
7524 cur_params.min_discovery_timeout) ||
7525 nla_put_u32(msg, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
7526 cur_params.dot11MeshHWMPactivePathTimeout) ||
7527 nla_put_u16(msg, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
7528 cur_params.dot11MeshHWMPpreqMinInterval) ||
7529 nla_put_u16(msg, NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
7530 cur_params.dot11MeshHWMPperrMinInterval) ||
7531 nla_put_u16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
7532 cur_params.dot11MeshHWMPnetDiameterTraversalTime) ||
7533 nla_put_u8(msg, NL80211_MESHCONF_HWMP_ROOTMODE,
7534 cur_params.dot11MeshHWMPRootMode) ||
7535 nla_put_u16(msg, NL80211_MESHCONF_HWMP_RANN_INTERVAL,
7536 cur_params.dot11MeshHWMPRannInterval) ||
7537 nla_put_u8(msg, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
7538 cur_params.dot11MeshGateAnnouncementProtocol) ||
7539 nla_put_u8(msg, NL80211_MESHCONF_FORWARDING,
7540 cur_params.dot11MeshForwarding) ||
335d5349 7541 nla_put_s32(msg, NL80211_MESHCONF_RSSI_THRESHOLD,
70c33eaa
AN
7542 cur_params.rssi_threshold) ||
7543 nla_put_u32(msg, NL80211_MESHCONF_HT_OPMODE,
ac1073a6
CYY
7544 cur_params.ht_opmode) ||
7545 nla_put_u32(msg, NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
7546 cur_params.dot11MeshHWMPactivePathToRootTimeout) ||
7547 nla_put_u16(msg, NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
728b19e5
CYY
7548 cur_params.dot11MeshHWMProotInterval) ||
7549 nla_put_u16(msg, NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
3b1c5a53
MP
7550 cur_params.dot11MeshHWMPconfirmationInterval) ||
7551 nla_put_u32(msg, NL80211_MESHCONF_POWER_MODE,
7552 cur_params.power_mode) ||
7553 nla_put_u16(msg, NL80211_MESHCONF_AWAKE_WINDOW,
8e7c0538
CT
7554 cur_params.dot11MeshAwakeWindowDuration) ||
7555 nla_put_u32(msg, NL80211_MESHCONF_PLINK_TIMEOUT,
01d66fbd
BC
7556 cur_params.plink_timeout) ||
7557 nla_put_u8(msg, NL80211_MESHCONF_CONNECTED_TO_GATE,
e3718a61
LL
7558 cur_params.dot11MeshConnectedToMeshGate) ||
7559 nla_put_u8(msg, NL80211_MESHCONF_NOLEARN,
184eebe6
MT
7560 cur_params.dot11MeshNolearn) ||
7561 nla_put_u8(msg, NL80211_MESHCONF_CONNECTED_TO_AS,
7562 cur_params.dot11MeshConnectedToAuthServer))
9360ffd1 7563 goto nla_put_failure;
93da9cc1 7564 nla_nest_end(msg, pinfoattr);
7565 genlmsg_end(msg, hdr);
4c476991 7566 return genlmsg_reply(msg, info);
93da9cc1 7567
3b85875a 7568 nla_put_failure:
efe1cf0c 7569 out:
d080e275 7570 nlmsg_free(msg);
4c476991 7571 return -ENOBUFS;
93da9cc1 7572}
7573
ab0d76f6
JB
7574static const struct nla_policy
7575nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] = {
7576 [NL80211_MESHCONF_RETRY_TIMEOUT] =
7577 NLA_POLICY_RANGE(NLA_U16, 1, 255),
7578 [NL80211_MESHCONF_CONFIRM_TIMEOUT] =
7579 NLA_POLICY_RANGE(NLA_U16, 1, 255),
7580 [NL80211_MESHCONF_HOLDING_TIMEOUT] =
7581 NLA_POLICY_RANGE(NLA_U16, 1, 255),
7582 [NL80211_MESHCONF_MAX_PEER_LINKS] =
7583 NLA_POLICY_RANGE(NLA_U16, 0, 255),
7584 [NL80211_MESHCONF_MAX_RETRIES] = NLA_POLICY_MAX(NLA_U8, 16),
7585 [NL80211_MESHCONF_TTL] = NLA_POLICY_MIN(NLA_U8, 1),
7586 [NL80211_MESHCONF_ELEMENT_TTL] = NLA_POLICY_MIN(NLA_U8, 1),
7587 [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = NLA_POLICY_MAX(NLA_U8, 1),
7588 [NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR] =
7589 NLA_POLICY_RANGE(NLA_U32, 1, 255),
93da9cc1 7590 [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 },
7591 [NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 },
ab0d76f6 7592 [NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = NLA_POLICY_MIN(NLA_U16, 1),
93da9cc1 7593 [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 },
ab0d76f6
JB
7594 [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] =
7595 NLA_POLICY_MIN(NLA_U16, 1),
7596 [NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL] =
7597 NLA_POLICY_MIN(NLA_U16, 1),
7598 [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] =
7599 NLA_POLICY_MIN(NLA_U16, 1),
7600 [NL80211_MESHCONF_HWMP_ROOTMODE] = NLA_POLICY_MAX(NLA_U8, 4),
7601 [NL80211_MESHCONF_HWMP_RANN_INTERVAL] =
7602 NLA_POLICY_MIN(NLA_U16, 1),
7603 [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = NLA_POLICY_MAX(NLA_U8, 1),
7604 [NL80211_MESHCONF_FORWARDING] = NLA_POLICY_MAX(NLA_U8, 1),
7605 [NL80211_MESHCONF_RSSI_THRESHOLD] =
7606 NLA_POLICY_RANGE(NLA_S32, -255, 0),
a4f606ea 7607 [NL80211_MESHCONF_HT_OPMODE] = { .type = NLA_U16 },
ac1073a6 7608 [NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT] = { .type = NLA_U32 },
ab0d76f6
JB
7609 [NL80211_MESHCONF_HWMP_ROOT_INTERVAL] =
7610 NLA_POLICY_MIN(NLA_U16, 1),
7611 [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] =
7612 NLA_POLICY_MIN(NLA_U16, 1),
7613 [NL80211_MESHCONF_POWER_MODE] =
7614 NLA_POLICY_RANGE(NLA_U32,
7615 NL80211_MESH_POWER_ACTIVE,
7616 NL80211_MESH_POWER_MAX),
3b1c5a53 7617 [NL80211_MESHCONF_AWAKE_WINDOW] = { .type = NLA_U16 },
8e7c0538 7618 [NL80211_MESHCONF_PLINK_TIMEOUT] = { .type = NLA_U32 },
01d66fbd 7619 [NL80211_MESHCONF_CONNECTED_TO_GATE] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
e3718a61 7620 [NL80211_MESHCONF_NOLEARN] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
184eebe6 7621 [NL80211_MESHCONF_CONNECTED_TO_AS] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
93da9cc1 7622};
7623
c80d545d
JC
7624static const struct nla_policy
7625 nl80211_mesh_setup_params_policy[NL80211_MESH_SETUP_ATTR_MAX+1] = {
d299a1f2 7626 [NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC] = { .type = NLA_U8 },
c80d545d
JC
7627 [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 },
7628 [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 },
15d5dda6 7629 [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG },
6e16d90b 7630 [NL80211_MESH_SETUP_AUTH_PROTOCOL] = { .type = NLA_U8 },
bb2798d4 7631 [NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG },
3d7af878
JB
7632 [NL80211_MESH_SETUP_IE] =
7633 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
7634 IEEE80211_MAX_DATA_LEN),
b130e5ce 7635 [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG },
c80d545d
JC
7636};
7637
24bdd9f4 7638static int nl80211_parse_mesh_config(struct genl_info *info,
bd90fdcc
JB
7639 struct mesh_config *cfg,
7640 u32 *mask_out)
93da9cc1 7641{
93da9cc1 7642 struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1];
bd90fdcc 7643 u32 mask = 0;
9757235f 7644 u16 ht_opmode;
93da9cc1 7645
ab0d76f6
JB
7646#define FILL_IN_MESH_PARAM_IF_SET(tb, cfg, param, mask, attr, fn) \
7647do { \
7648 if (tb[attr]) { \
7649 cfg->param = fn(tb[attr]); \
7650 mask |= BIT((attr) - 1); \
7651 } \
ea54fba2 7652} while (0)
bd90fdcc 7653
24bdd9f4 7654 if (!info->attrs[NL80211_ATTR_MESH_CONFIG])
93da9cc1 7655 return -EINVAL;
8cb08174 7656 if (nla_parse_nested_deprecated(tb, NL80211_MESHCONF_ATTR_MAX, info->attrs[NL80211_ATTR_MESH_CONFIG], nl80211_meshconf_params_policy, info->extack))
93da9cc1 7657 return -EINVAL;
7658
93da9cc1 7659 /* This makes sure that there aren't more than 32 mesh config
7660 * parameters (otherwise our bitfield scheme would not work.) */
7661 BUILD_BUG_ON(NL80211_MESHCONF_ATTR_MAX > 32);
7662
7663 /* Fill in the params struct */
ab0d76f6
JB
7664 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, mask,
7665 NL80211_MESHCONF_RETRY_TIMEOUT, nla_get_u16);
7666 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, mask,
7667 NL80211_MESHCONF_CONFIRM_TIMEOUT,
7668 nla_get_u16);
7669 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, mask,
7670 NL80211_MESHCONF_HOLDING_TIMEOUT,
7671 nla_get_u16);
7672 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, mask,
7673 NL80211_MESHCONF_MAX_PEER_LINKS,
7674 nla_get_u16);
7675 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, mask,
7676 NL80211_MESHCONF_MAX_RETRIES, nla_get_u8);
7677 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, mask,
7678 NL80211_MESHCONF_TTL, nla_get_u8);
7679 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, mask,
7680 NL80211_MESHCONF_ELEMENT_TTL, nla_get_u8);
7681 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, mask,
7682 NL80211_MESHCONF_AUTO_OPEN_PLINKS,
7683 nla_get_u8);
ea54fba2 7684 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor,
ab0d76f6 7685 mask,
a4f606ea 7686 NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
ab0d76f6
JB
7687 nla_get_u32);
7688 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, mask,
7689 NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
7690 nla_get_u8);
7691 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, mask,
7692 NL80211_MESHCONF_PATH_REFRESH_TIME,
7693 nla_get_u32);
7694 if (mask & BIT(NL80211_MESHCONF_PATH_REFRESH_TIME) &&
7695 (cfg->path_refresh_time < 1 || cfg->path_refresh_time > 65535))
7696 return -EINVAL;
7697 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, mask,
7698 NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
7699 nla_get_u16);
ea54fba2 7700 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout,
ab0d76f6 7701 mask,
a4f606ea 7702 NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
ab0d76f6
JB
7703 nla_get_u32);
7704 if (mask & BIT(NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT) &&
7705 (cfg->dot11MeshHWMPactivePathTimeout < 1 ||
7706 cfg->dot11MeshHWMPactivePathTimeout > 65535))
7707 return -EINVAL;
7708 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval, mask,
ea54fba2 7709 NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
ab0d76f6
JB
7710 nla_get_u16);
7711 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval, mask,
ea54fba2 7712 NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
ab0d76f6 7713 nla_get_u16);
93da9cc1 7714 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
ab0d76f6 7715 dot11MeshHWMPnetDiameterTraversalTime, mask,
a4f606ea 7716 NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
ab0d76f6
JB
7717 nla_get_u16);
7718 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, mask,
7719 NL80211_MESHCONF_HWMP_ROOTMODE, nla_get_u8);
7720 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, mask,
7721 NL80211_MESHCONF_HWMP_RANN_INTERVAL,
7722 nla_get_u16);
7723 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshGateAnnouncementProtocol,
ea54fba2 7724 mask, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
ab0d76f6
JB
7725 nla_get_u8);
7726 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, mask,
7727 NL80211_MESHCONF_FORWARDING, nla_get_u8);
7728 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, mask,
7729 NL80211_MESHCONF_RSSI_THRESHOLD,
7730 nla_get_s32);
01d66fbd
BC
7731 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConnectedToMeshGate, mask,
7732 NL80211_MESHCONF_CONNECTED_TO_GATE,
7733 nla_get_u8);
184eebe6
MT
7734 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConnectedToAuthServer, mask,
7735 NL80211_MESHCONF_CONNECTED_TO_AS,
7736 nla_get_u8);
9757235f
MH
7737 /*
7738 * Check HT operation mode based on
188f60ab 7739 * IEEE 802.11-2016 9.4.2.57 HT Operation element.
9757235f
MH
7740 */
7741 if (tb[NL80211_MESHCONF_HT_OPMODE]) {
7742 ht_opmode = nla_get_u16(tb[NL80211_MESHCONF_HT_OPMODE]);
7743
7744 if (ht_opmode & ~(IEEE80211_HT_OP_MODE_PROTECTION |
7745 IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT |
7746 IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT))
7747 return -EINVAL;
7748
188f60ab
BC
7749 /* NON_HT_STA bit is reserved, but some programs set it */
7750 ht_opmode &= ~IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT;
9757235f 7751
9757235f 7752 cfg->ht_opmode = ht_opmode;
fd551bac 7753 mask |= (1 << (NL80211_MESHCONF_HT_OPMODE - 1));
9757235f 7754 }
728b19e5 7755 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
ab0d76f6
JB
7756 dot11MeshHWMPactivePathToRootTimeout, mask,
7757 NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
7758 nla_get_u32);
7759 if (mask & BIT(NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT) &&
7760 (cfg->dot11MeshHWMPactivePathToRootTimeout < 1 ||
7761 cfg->dot11MeshHWMPactivePathToRootTimeout > 65535))
7762 return -EINVAL;
7763 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMProotInterval, mask,
7764 NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
7765 nla_get_u16);
7766 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPconfirmationInterval,
7767 mask,
728b19e5 7768 NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
ab0d76f6
JB
7769 nla_get_u16);
7770 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode, mask,
7771 NL80211_MESHCONF_POWER_MODE, nla_get_u32);
7772 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration, mask,
7773 NL80211_MESHCONF_AWAKE_WINDOW, nla_get_u16);
7774 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, mask,
7775 NL80211_MESHCONF_PLINK_TIMEOUT, nla_get_u32);
e3718a61
LL
7776 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNolearn, mask,
7777 NL80211_MESHCONF_NOLEARN, nla_get_u8);
bd90fdcc
JB
7778 if (mask_out)
7779 *mask_out = mask;
c80d545d 7780
bd90fdcc
JB
7781 return 0;
7782
7783#undef FILL_IN_MESH_PARAM_IF_SET
7784}
7785
c80d545d
JC
7786static int nl80211_parse_mesh_setup(struct genl_info *info,
7787 struct mesh_setup *setup)
7788{
bb2798d4 7789 struct cfg80211_registered_device *rdev = info->user_ptr[0];
c80d545d
JC
7790 struct nlattr *tb[NL80211_MESH_SETUP_ATTR_MAX + 1];
7791
7792 if (!info->attrs[NL80211_ATTR_MESH_SETUP])
7793 return -EINVAL;
8cb08174 7794 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
7795 return -EINVAL;
7796
d299a1f2
JC
7797 if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC])
7798 setup->sync_method =
7799 (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC])) ?
7800 IEEE80211_SYNC_METHOD_VENDOR :
7801 IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET;
7802
c80d545d
JC
7803 if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])
7804 setup->path_sel_proto =
7805 (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])) ?
7806 IEEE80211_PATH_PROTOCOL_VENDOR :
7807 IEEE80211_PATH_PROTOCOL_HWMP;
7808
7809 if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC])
7810 setup->path_metric =
7811 (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC])) ?
7812 IEEE80211_PATH_METRIC_VENDOR :
7813 IEEE80211_PATH_METRIC_AIRTIME;
7814
581a8b0f 7815 if (tb[NL80211_MESH_SETUP_IE]) {
c80d545d 7816 struct nlattr *ieattr =
581a8b0f 7817 tb[NL80211_MESH_SETUP_IE];
581a8b0f
JC
7818 setup->ie = nla_data(ieattr);
7819 setup->ie_len = nla_len(ieattr);
c80d545d 7820 }
bb2798d4
TP
7821 if (tb[NL80211_MESH_SETUP_USERSPACE_MPM] &&
7822 !(rdev->wiphy.features & NL80211_FEATURE_USERSPACE_MPM))
7823 return -EINVAL;
7824 setup->user_mpm = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_MPM]);
b130e5ce
JC
7825 setup->is_authenticated = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]);
7826 setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AMPE]);
bb2798d4
TP
7827 if (setup->is_secure)
7828 setup->user_mpm = true;
c80d545d 7829
6e16d90b
CT
7830 if (tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]) {
7831 if (!setup->user_mpm)
7832 return -EINVAL;
7833 setup->auth_id =
7834 nla_get_u8(tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]);
7835 }
7836
c80d545d
JC
7837 return 0;
7838}
7839
24bdd9f4 7840static int nl80211_update_mesh_config(struct sk_buff *skb,
29cbe68c 7841 struct genl_info *info)
bd90fdcc
JB
7842{
7843 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7844 struct net_device *dev = info->user_ptr[1];
29cbe68c 7845 struct wireless_dev *wdev = dev->ieee80211_ptr;
bd90fdcc
JB
7846 struct mesh_config cfg;
7847 u32 mask;
7848 int err;
7849
29cbe68c
JB
7850 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
7851 return -EOPNOTSUPP;
7852
24bdd9f4 7853 if (!rdev->ops->update_mesh_config)
bd90fdcc
JB
7854 return -EOPNOTSUPP;
7855
24bdd9f4 7856 err = nl80211_parse_mesh_config(info, &cfg, &mask);
bd90fdcc
JB
7857 if (err)
7858 return err;
7859
29cbe68c
JB
7860 wdev_lock(wdev);
7861 if (!wdev->mesh_id_len)
7862 err = -ENOLINK;
7863
7864 if (!err)
e35e4d28 7865 err = rdev_update_mesh_config(rdev, dev, mask, &cfg);
29cbe68c
JB
7866
7867 wdev_unlock(wdev);
7868
7869 return err;
93da9cc1 7870}
7871
ad30ca2c
AN
7872static int nl80211_put_regdom(const struct ieee80211_regdomain *regdom,
7873 struct sk_buff *msg)
f130347c 7874{
f130347c
LR
7875 struct nlattr *nl_reg_rules;
7876 unsigned int i;
f130347c 7877
458f4f9e
JB
7878 if (nla_put_string(msg, NL80211_ATTR_REG_ALPHA2, regdom->alpha2) ||
7879 (regdom->dfs_region &&
7880 nla_put_u8(msg, NL80211_ATTR_DFS_REGION, regdom->dfs_region)))
ad30ca2c 7881 goto nla_put_failure;
458f4f9e 7882
ae0be8de 7883 nl_reg_rules = nla_nest_start_noflag(msg, NL80211_ATTR_REG_RULES);
f130347c 7884 if (!nl_reg_rules)
ad30ca2c 7885 goto nla_put_failure;
f130347c 7886
458f4f9e 7887 for (i = 0; i < regdom->n_reg_rules; i++) {
f130347c
LR
7888 struct nlattr *nl_reg_rule;
7889 const struct ieee80211_reg_rule *reg_rule;
7890 const struct ieee80211_freq_range *freq_range;
7891 const struct ieee80211_power_rule *power_rule;
97524820 7892 unsigned int max_bandwidth_khz;
f130347c 7893
458f4f9e 7894 reg_rule = &regdom->reg_rules[i];
f130347c
LR
7895 freq_range = &reg_rule->freq_range;
7896 power_rule = &reg_rule->power_rule;
7897
ae0be8de 7898 nl_reg_rule = nla_nest_start_noflag(msg, i);
f130347c 7899 if (!nl_reg_rule)
ad30ca2c 7900 goto nla_put_failure;
f130347c 7901
97524820
JD
7902 max_bandwidth_khz = freq_range->max_bandwidth_khz;
7903 if (!max_bandwidth_khz)
7904 max_bandwidth_khz = reg_get_max_bandwidth(regdom,
7905 reg_rule);
7906
9360ffd1
DM
7907 if (nla_put_u32(msg, NL80211_ATTR_REG_RULE_FLAGS,
7908 reg_rule->flags) ||
7909 nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_START,
7910 freq_range->start_freq_khz) ||
7911 nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_END,
7912 freq_range->end_freq_khz) ||
7913 nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW,
97524820 7914 max_bandwidth_khz) ||
9360ffd1
DM
7915 nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
7916 power_rule->max_antenna_gain) ||
7917 nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP,
089027e5
JD
7918 power_rule->max_eirp) ||
7919 nla_put_u32(msg, NL80211_ATTR_DFS_CAC_TIME,
7920 reg_rule->dfs_cac_ms))
ad30ca2c 7921 goto nla_put_failure;
f130347c
LR
7922
7923 nla_nest_end(msg, nl_reg_rule);
7924 }
7925
7926 nla_nest_end(msg, nl_reg_rules);
ad30ca2c
AN
7927 return 0;
7928
7929nla_put_failure:
7930 return -EMSGSIZE;
7931}
7932
7933static int nl80211_get_reg_do(struct sk_buff *skb, struct genl_info *info)
7934{
7935 const struct ieee80211_regdomain *regdom = NULL;
7936 struct cfg80211_registered_device *rdev;
7937 struct wiphy *wiphy = NULL;
7938 struct sk_buff *msg;
7939 void *hdr;
7940
7941 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7942 if (!msg)
7943 return -ENOBUFS;
7944
7945 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
7946 NL80211_CMD_GET_REG);
7947 if (!hdr)
7948 goto put_failure;
7949
a05829a7
JB
7950 rtnl_lock();
7951
ad30ca2c 7952 if (info->attrs[NL80211_ATTR_WIPHY]) {
1bdd716c
AN
7953 bool self_managed;
7954
ad30ca2c
AN
7955 rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
7956 if (IS_ERR(rdev)) {
7957 nlmsg_free(msg);
a05829a7 7958 rtnl_unlock();
ad30ca2c
AN
7959 return PTR_ERR(rdev);
7960 }
7961
7962 wiphy = &rdev->wiphy;
1bdd716c
AN
7963 self_managed = wiphy->regulatory_flags &
7964 REGULATORY_WIPHY_SELF_MANAGED;
ad30ca2c
AN
7965 regdom = get_wiphy_regdom(wiphy);
7966
1bdd716c
AN
7967 /* a self-managed-reg device must have a private regdom */
7968 if (WARN_ON(!regdom && self_managed)) {
7969 nlmsg_free(msg);
a05829a7 7970 rtnl_unlock();
1bdd716c
AN
7971 return -EINVAL;
7972 }
7973
ad30ca2c
AN
7974 if (regdom &&
7975 nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
7976 goto nla_put_failure;
7977 }
7978
7979 if (!wiphy && reg_last_request_cell_base() &&
7980 nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
7981 NL80211_USER_REG_HINT_CELL_BASE))
7982 goto nla_put_failure;
7983
7984 rcu_read_lock();
7985
7986 if (!regdom)
7987 regdom = rcu_dereference(cfg80211_regdomain);
7988
7989 if (nl80211_put_regdom(regdom, msg))
7990 goto nla_put_failure_rcu;
7991
7992 rcu_read_unlock();
f130347c
LR
7993
7994 genlmsg_end(msg, hdr);
a05829a7 7995 rtnl_unlock();
5fe231e8 7996 return genlmsg_reply(msg, info);
f130347c 7997
458f4f9e
JB
7998nla_put_failure_rcu:
7999 rcu_read_unlock();
f130347c 8000nla_put_failure:
a05829a7 8001 rtnl_unlock();
efe1cf0c 8002put_failure:
d080e275 8003 nlmsg_free(msg);
5fe231e8 8004 return -EMSGSIZE;
f130347c
LR
8005}
8006
ad30ca2c
AN
8007static int nl80211_send_regdom(struct sk_buff *msg, struct netlink_callback *cb,
8008 u32 seq, int flags, struct wiphy *wiphy,
8009 const struct ieee80211_regdomain *regdom)
8010{
8011 void *hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).portid, seq, flags,
8012 NL80211_CMD_GET_REG);
8013
8014 if (!hdr)
8015 return -1;
8016
0a833c29 8017 genl_dump_check_consistent(cb, hdr);
ad30ca2c
AN
8018
8019 if (nl80211_put_regdom(regdom, msg))
8020 goto nla_put_failure;
8021
8022 if (!wiphy && reg_last_request_cell_base() &&
8023 nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
8024 NL80211_USER_REG_HINT_CELL_BASE))
8025 goto nla_put_failure;
8026
8027 if (wiphy &&
8028 nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
8029 goto nla_put_failure;
8030
1bdd716c
AN
8031 if (wiphy && wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
8032 nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
8033 goto nla_put_failure;
8034
053c095a
JB
8035 genlmsg_end(msg, hdr);
8036 return 0;
ad30ca2c
AN
8037
8038nla_put_failure:
8039 genlmsg_cancel(msg, hdr);
8040 return -EMSGSIZE;
8041}
8042
8043static int nl80211_get_reg_dump(struct sk_buff *skb,
8044 struct netlink_callback *cb)
8045{
8046 const struct ieee80211_regdomain *regdom = NULL;
8047 struct cfg80211_registered_device *rdev;
8048 int err, reg_idx, start = cb->args[2];
8049
8050 rtnl_lock();
8051
8052 if (cfg80211_regdomain && start == 0) {
8053 err = nl80211_send_regdom(skb, cb, cb->nlh->nlmsg_seq,
8054 NLM_F_MULTI, NULL,
8055 rtnl_dereference(cfg80211_regdomain));
8056 if (err < 0)
8057 goto out_err;
8058 }
8059
8060 /* the global regdom is idx 0 */
8061 reg_idx = 1;
8062 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
8063 regdom = get_wiphy_regdom(&rdev->wiphy);
8064 if (!regdom)
8065 continue;
8066
8067 if (++reg_idx <= start)
8068 continue;
8069
8070 err = nl80211_send_regdom(skb, cb, cb->nlh->nlmsg_seq,
8071 NLM_F_MULTI, &rdev->wiphy, regdom);
8072 if (err < 0) {
8073 reg_idx--;
8074 break;
8075 }
8076 }
8077
8078 cb->args[2] = reg_idx;
8079 err = skb->len;
8080out_err:
8081 rtnl_unlock();
8082 return err;
8083}
8084
b6863036
JB
8085#ifdef CONFIG_CFG80211_CRDA_SUPPORT
8086static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = {
8087 [NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 },
8088 [NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 },
8089 [NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 },
8090 [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 },
8091 [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 },
8092 [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 },
8093 [NL80211_ATTR_DFS_CAC_TIME] = { .type = NLA_U32 },
8094};
8095
8096static int parse_reg_rule(struct nlattr *tb[],
8097 struct ieee80211_reg_rule *reg_rule)
8098{
8099 struct ieee80211_freq_range *freq_range = &reg_rule->freq_range;
8100 struct ieee80211_power_rule *power_rule = &reg_rule->power_rule;
8101
8102 if (!tb[NL80211_ATTR_REG_RULE_FLAGS])
8103 return -EINVAL;
8104 if (!tb[NL80211_ATTR_FREQ_RANGE_START])
8105 return -EINVAL;
8106 if (!tb[NL80211_ATTR_FREQ_RANGE_END])
8107 return -EINVAL;
8108 if (!tb[NL80211_ATTR_FREQ_RANGE_MAX_BW])
8109 return -EINVAL;
8110 if (!tb[NL80211_ATTR_POWER_RULE_MAX_EIRP])
8111 return -EINVAL;
8112
8113 reg_rule->flags = nla_get_u32(tb[NL80211_ATTR_REG_RULE_FLAGS]);
8114
8115 freq_range->start_freq_khz =
8116 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]);
8117 freq_range->end_freq_khz =
8118 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]);
8119 freq_range->max_bandwidth_khz =
8120 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]);
8121
8122 power_rule->max_eirp =
8123 nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]);
8124
8125 if (tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN])
8126 power_rule->max_antenna_gain =
8127 nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]);
8128
8129 if (tb[NL80211_ATTR_DFS_CAC_TIME])
8130 reg_rule->dfs_cac_ms =
8131 nla_get_u32(tb[NL80211_ATTR_DFS_CAC_TIME]);
8132
8133 return 0;
8134}
8135
b2e1b302
LR
8136static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
8137{
8138 struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1];
8139 struct nlattr *nl_reg_rule;
ea372c54
JB
8140 char *alpha2;
8141 int rem_reg_rules, r;
391d132c 8142 u32 num_rules = 0, rule_idx = 0;
4c7d3982 8143 enum nl80211_dfs_regions dfs_region = NL80211_DFS_UNSET;
ea372c54 8144 struct ieee80211_regdomain *rd;
b2e1b302
LR
8145
8146 if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
8147 return -EINVAL;
8148
8149 if (!info->attrs[NL80211_ATTR_REG_RULES])
8150 return -EINVAL;
8151
8152 alpha2 = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
8153
8b60b078
LR
8154 if (info->attrs[NL80211_ATTR_DFS_REGION])
8155 dfs_region = nla_get_u8(info->attrs[NL80211_ATTR_DFS_REGION]);
8156
b2e1b302 8157 nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
1a919318 8158 rem_reg_rules) {
b2e1b302
LR
8159 num_rules++;
8160 if (num_rules > NL80211_MAX_SUPP_REG_RULES)
4776c6e7 8161 return -EINVAL;
b2e1b302
LR
8162 }
8163
a05829a7
JB
8164 rtnl_lock();
8165 if (!reg_is_valid_request(alpha2)) {
8166 r = -EINVAL;
8167 goto out;
8168 }
e438768f 8169
391d132c 8170 rd = kzalloc(struct_size(rd, reg_rules, num_rules), GFP_KERNEL);
a05829a7
JB
8171 if (!rd) {
8172 r = -ENOMEM;
8173 goto out;
8174 }
b2e1b302
LR
8175
8176 rd->n_reg_rules = num_rules;
8177 rd->alpha2[0] = alpha2[0];
8178 rd->alpha2[1] = alpha2[1];
8179
8b60b078
LR
8180 /*
8181 * Disable DFS master mode if the DFS region was
8182 * not supported or known on this kernel.
8183 */
8184 if (reg_supported_dfs_region(dfs_region))
8185 rd->dfs_region = dfs_region;
8186
b2e1b302 8187 nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
1a919318 8188 rem_reg_rules) {
8cb08174
JB
8189 r = nla_parse_nested_deprecated(tb, NL80211_REG_RULE_ATTR_MAX,
8190 nl_reg_rule, reg_rule_policy,
8191 info->extack);
ae811e21
JB
8192 if (r)
8193 goto bad_reg;
b2e1b302
LR
8194 r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]);
8195 if (r)
8196 goto bad_reg;
8197
8198 rule_idx++;
8199
d0e18f83
LR
8200 if (rule_idx > NL80211_MAX_SUPP_REG_RULES) {
8201 r = -EINVAL;
b2e1b302 8202 goto bad_reg;
d0e18f83 8203 }
b2e1b302
LR
8204 }
8205
a05829a7 8206 r = set_regdom(rd, REGD_SOURCE_CRDA);
06627990 8207 /* set_regdom takes ownership of rd */
a05829a7 8208 rd = NULL;
d2372b31 8209 bad_reg:
b2e1b302 8210 kfree(rd);
a05829a7
JB
8211 out:
8212 rtnl_unlock();
d0e18f83 8213 return r;
b2e1b302 8214}
b6863036 8215#endif /* CONFIG_CFG80211_CRDA_SUPPORT */
b2e1b302 8216
83f5e2cf
JB
8217static int validate_scan_freqs(struct nlattr *freqs)
8218{
8219 struct nlattr *attr1, *attr2;
8220 int n_channels = 0, tmp1, tmp2;
8221
d7f13f74
SD
8222 nla_for_each_nested(attr1, freqs, tmp1)
8223 if (nla_len(attr1) != sizeof(u32))
8224 return 0;
8225
83f5e2cf
JB
8226 nla_for_each_nested(attr1, freqs, tmp1) {
8227 n_channels++;
8228 /*
8229 * Some hardware has a limited channel list for
8230 * scanning, and it is pretty much nonsensical
8231 * to scan for a channel twice, so disallow that
8232 * and don't require drivers to check that the
8233 * channel list they get isn't longer than what
8234 * they can scan, as long as they can scan all
8235 * the channels they registered at once.
8236 */
8237 nla_for_each_nested(attr2, freqs, tmp2)
8238 if (attr1 != attr2 &&
8239 nla_get_u32(attr1) == nla_get_u32(attr2))
8240 return 0;
8241 }
8242
8243 return n_channels;
8244}
8245
57fbcce3 8246static bool is_band_valid(struct wiphy *wiphy, enum nl80211_band b)
38de03d2 8247{
57fbcce3 8248 return b < NUM_NL80211_BANDS && wiphy->bands[b];
38de03d2
AS
8249}
8250
8251static int parse_bss_select(struct nlattr *nla, struct wiphy *wiphy,
8252 struct cfg80211_bss_selection *bss_select)
8253{
8254 struct nlattr *attr[NL80211_BSS_SELECT_ATTR_MAX + 1];
8255 struct nlattr *nest;
8256 int err;
8257 bool found = false;
8258 int i;
8259
8260 /* only process one nested attribute */
8261 nest = nla_data(nla);
8262 if (!nla_ok(nest, nla_len(nest)))
8263 return -EINVAL;
8264
8cb08174
JB
8265 err = nla_parse_nested_deprecated(attr, NL80211_BSS_SELECT_ATTR_MAX,
8266 nest, nl80211_bss_select_policy,
8267 NULL);
38de03d2
AS
8268 if (err)
8269 return err;
8270
8271 /* only one attribute may be given */
8272 for (i = 0; i <= NL80211_BSS_SELECT_ATTR_MAX; i++) {
8273 if (attr[i]) {
8274 if (found)
8275 return -EINVAL;
8276 found = true;
8277 }
8278 }
8279
8280 bss_select->behaviour = __NL80211_BSS_SELECT_ATTR_INVALID;
8281
8282 if (attr[NL80211_BSS_SELECT_ATTR_RSSI])
8283 bss_select->behaviour = NL80211_BSS_SELECT_ATTR_RSSI;
8284
8285 if (attr[NL80211_BSS_SELECT_ATTR_BAND_PREF]) {
8286 bss_select->behaviour = NL80211_BSS_SELECT_ATTR_BAND_PREF;
8287 bss_select->param.band_pref =
8288 nla_get_u32(attr[NL80211_BSS_SELECT_ATTR_BAND_PREF]);
8289 if (!is_band_valid(wiphy, bss_select->param.band_pref))
8290 return -EINVAL;
8291 }
8292
8293 if (attr[NL80211_BSS_SELECT_ATTR_RSSI_ADJUST]) {
8294 struct nl80211_bss_select_rssi_adjust *adj_param;
8295
8296 adj_param = nla_data(attr[NL80211_BSS_SELECT_ATTR_RSSI_ADJUST]);
8297 bss_select->behaviour = NL80211_BSS_SELECT_ATTR_RSSI_ADJUST;
8298 bss_select->param.adjust.band = adj_param->band;
8299 bss_select->param.adjust.delta = adj_param->delta;
8300 if (!is_band_valid(wiphy, bss_select->param.adjust.band))
8301 return -EINVAL;
8302 }
8303
8304 /* user-space did not provide behaviour attribute */
8305 if (bss_select->behaviour == __NL80211_BSS_SELECT_ATTR_INVALID)
8306 return -EINVAL;
8307
8308 if (!(wiphy->bss_select_support & BIT(bss_select->behaviour)))
8309 return -EINVAL;
8310
8311 return 0;
8312}
8313
9bb7e0f2
JB
8314int nl80211_parse_random_mac(struct nlattr **attrs,
8315 u8 *mac_addr, u8 *mac_addr_mask)
ad2b26ab
JB
8316{
8317 int i;
8318
8319 if (!attrs[NL80211_ATTR_MAC] && !attrs[NL80211_ATTR_MAC_MASK]) {
d2beae10
JP
8320 eth_zero_addr(mac_addr);
8321 eth_zero_addr(mac_addr_mask);
ad2b26ab
JB
8322 mac_addr[0] = 0x2;
8323 mac_addr_mask[0] = 0x3;
8324
8325 return 0;
8326 }
8327
8328 /* need both or none */
8329 if (!attrs[NL80211_ATTR_MAC] || !attrs[NL80211_ATTR_MAC_MASK])
8330 return -EINVAL;
8331
8332 memcpy(mac_addr, nla_data(attrs[NL80211_ATTR_MAC]), ETH_ALEN);
8333 memcpy(mac_addr_mask, nla_data(attrs[NL80211_ATTR_MAC_MASK]), ETH_ALEN);
8334
8335 /* don't allow or configure an mcast address */
8336 if (!is_multicast_ether_addr(mac_addr_mask) ||
8337 is_multicast_ether_addr(mac_addr))
8338 return -EINVAL;
8339
8340 /*
8341 * allow users to pass a MAC address that has bits set outside
8342 * of the mask, but don't bother drivers with having to deal
8343 * with such bits
8344 */
8345 for (i = 0; i < ETH_ALEN; i++)
8346 mac_addr[i] &= mac_addr_mask[i];
8347
8348 return 0;
8349}
8350
34373d12
VT
8351static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev)
8352{
8353 ASSERT_WDEV_LOCK(wdev);
8354
8355 if (!cfg80211_beaconing_iface_active(wdev))
8356 return true;
8357
8358 if (!(wdev->chandef.chan->flags & IEEE80211_CHAN_RADAR))
8359 return true;
8360
8361 return regulatory_pre_cac_allowed(wdev->wiphy);
8362}
8363
db0a4ad8
JB
8364static bool nl80211_check_scan_feat(struct wiphy *wiphy, u32 flags, u32 flag,
8365 enum nl80211_ext_feature_index feat)
8366{
8367 if (!(flags & flag))
8368 return true;
8369 if (wiphy_ext_feature_isset(wiphy, feat))
8370 return true;
8371 return false;
8372}
8373
2d23d073
RZ
8374static int
8375nl80211_check_scan_flags(struct wiphy *wiphy, struct wireless_dev *wdev,
8376 void *request, struct nlattr **attrs,
8377 bool is_sched_scan)
8378{
8379 u8 *mac_addr, *mac_addr_mask;
8380 u32 *flags;
8381 enum nl80211_feature_flags randomness_flag;
8382
8383 if (!attrs[NL80211_ATTR_SCAN_FLAGS])
8384 return 0;
8385
8386 if (is_sched_scan) {
8387 struct cfg80211_sched_scan_request *req = request;
8388
8389 randomness_flag = wdev ?
8390 NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR :
8391 NL80211_FEATURE_ND_RANDOM_MAC_ADDR;
8392 flags = &req->flags;
8393 mac_addr = req->mac_addr;
8394 mac_addr_mask = req->mac_addr_mask;
8395 } else {
8396 struct cfg80211_scan_request *req = request;
8397
8398 randomness_flag = NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
8399 flags = &req->flags;
8400 mac_addr = req->mac_addr;
8401 mac_addr_mask = req->mac_addr_mask;
8402 }
8403
8404 *flags = nla_get_u32(attrs[NL80211_ATTR_SCAN_FLAGS]);
8405
5037a009
SD
8406 if (((*flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
8407 !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) ||
db0a4ad8
JB
8408 !nl80211_check_scan_feat(wiphy, *flags,
8409 NL80211_SCAN_FLAG_LOW_SPAN,
8410 NL80211_EXT_FEATURE_LOW_SPAN_SCAN) ||
8411 !nl80211_check_scan_feat(wiphy, *flags,
8412 NL80211_SCAN_FLAG_LOW_POWER,
8413 NL80211_EXT_FEATURE_LOW_POWER_SCAN) ||
8414 !nl80211_check_scan_feat(wiphy, *flags,
8415 NL80211_SCAN_FLAG_HIGH_ACCURACY,
8416 NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN) ||
8417 !nl80211_check_scan_feat(wiphy, *flags,
8418 NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME,
8419 NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME) ||
8420 !nl80211_check_scan_feat(wiphy, *flags,
8421 NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP,
8422 NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP) ||
8423 !nl80211_check_scan_feat(wiphy, *flags,
8424 NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION,
8425 NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION) ||
8426 !nl80211_check_scan_feat(wiphy, *flags,
8427 NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE,
2e076f19
JB
8428 NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE) ||
8429 !nl80211_check_scan_feat(wiphy, *flags,
8430 NL80211_SCAN_FLAG_RANDOM_SN,
8431 NL80211_EXT_FEATURE_SCAN_RANDOM_SN) ||
8432 !nl80211_check_scan_feat(wiphy, *flags,
8433 NL80211_SCAN_FLAG_MIN_PREQ_CONTENT,
8434 NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT))
2d23d073
RZ
8435 return -EOPNOTSUPP;
8436
8437 if (*flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
8438 int err;
8439
8440 if (!(wiphy->features & randomness_flag) ||
8441 (wdev && wdev->current_bss))
8442 return -EOPNOTSUPP;
8443
8444 err = nl80211_parse_random_mac(attrs, mac_addr, mac_addr_mask);
8445 if (err)
8446 return err;
8447 }
8448
2d23d073
RZ
8449 return 0;
8450}
8451
2a519311
JB
8452static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
8453{
4c476991 8454 struct cfg80211_registered_device *rdev = info->user_ptr[0];
fd014284 8455 struct wireless_dev *wdev = info->user_ptr[1];
2a519311 8456 struct cfg80211_scan_request *request;
2032f3b2
TP
8457 struct nlattr *scan_freqs = NULL;
8458 bool scan_freqs_khz = false;
2a519311
JB
8459 struct nlattr *attr;
8460 struct wiphy *wiphy;
83f5e2cf 8461 int err, tmp, n_ssids = 0, n_channels, i;
70692ad2 8462 size_t ie_len;
2a519311 8463
79c97e97 8464 wiphy = &rdev->wiphy;
2a519311 8465
cb3b7d87
AB
8466 if (wdev->iftype == NL80211_IFTYPE_NAN)
8467 return -EOPNOTSUPP;
8468
4c476991
JB
8469 if (!rdev->ops->scan)
8470 return -EOPNOTSUPP;
2a519311 8471
83286856
CJ
8472 if (rdev->scan_req || rdev->scan_msg)
8473 return -EBUSY;
2a519311 8474
2032f3b2
TP
8475 if (info->attrs[NL80211_ATTR_SCAN_FREQ_KHZ]) {
8476 if (!wiphy_ext_feature_isset(wiphy,
8477 NL80211_EXT_FEATURE_SCAN_FREQ_KHZ))
8478 return -EOPNOTSUPP;
8479 scan_freqs = info->attrs[NL80211_ATTR_SCAN_FREQ_KHZ];
8480 scan_freqs_khz = true;
8481 } else if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES])
8482 scan_freqs = info->attrs[NL80211_ATTR_SCAN_FREQUENCIES];
8483
8484 if (scan_freqs) {
8485 n_channels = validate_scan_freqs(scan_freqs);
83286856
CJ
8486 if (!n_channels)
8487 return -EINVAL;
2a519311 8488 } else {
bdfbec2d 8489 n_channels = ieee80211_get_num_supported_channels(wiphy);
2a519311
JB
8490 }
8491
8492 if (info->attrs[NL80211_ATTR_SCAN_SSIDS])
8493 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp)
8494 n_ssids++;
8495
83286856
CJ
8496 if (n_ssids > wiphy->max_scan_ssids)
8497 return -EINVAL;
2a519311 8498
70692ad2
JM
8499 if (info->attrs[NL80211_ATTR_IE])
8500 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
8501 else
8502 ie_len = 0;
8503
83286856
CJ
8504 if (ie_len > wiphy->max_scan_ie_len)
8505 return -EINVAL;
18a83659 8506
2a519311 8507 request = kzalloc(sizeof(*request)
a2cd43c5
LC
8508 + sizeof(*request->ssids) * n_ssids
8509 + sizeof(*request->channels) * n_channels
70692ad2 8510 + ie_len, GFP_KERNEL);
83286856
CJ
8511 if (!request)
8512 return -ENOMEM;
2a519311 8513
2a519311 8514 if (n_ssids)
5ba63533 8515 request->ssids = (void *)&request->channels[n_channels];
2a519311 8516 request->n_ssids = n_ssids;
70692ad2 8517 if (ie_len) {
13874e4b 8518 if (n_ssids)
70692ad2
JM
8519 request->ie = (void *)(request->ssids + n_ssids);
8520 else
8521 request->ie = (void *)(request->channels + n_channels);
8522 }
2a519311 8523
584991dc 8524 i = 0;
2032f3b2 8525 if (scan_freqs) {
2a519311 8526 /* user specified, bail out if channel not found */
2032f3b2 8527 nla_for_each_nested(attr, scan_freqs, tmp) {
584991dc 8528 struct ieee80211_channel *chan;
2032f3b2 8529 int freq = nla_get_u32(attr);
584991dc 8530
2032f3b2
TP
8531 if (!scan_freqs_khz)
8532 freq = MHZ_TO_KHZ(freq);
584991dc 8533
2032f3b2 8534 chan = ieee80211_get_channel_khz(wiphy, freq);
584991dc 8535 if (!chan) {
2a519311
JB
8536 err = -EINVAL;
8537 goto out_free;
8538 }
584991dc
JB
8539
8540 /* ignore disabled channels */
8541 if (chan->flags & IEEE80211_CHAN_DISABLED)
8542 continue;
8543
8544 request->channels[i] = chan;
2a519311
JB
8545 i++;
8546 }
8547 } else {
57fbcce3 8548 enum nl80211_band band;
34850ab2 8549
2a519311 8550 /* all channels */
57fbcce3 8551 for (band = 0; band < NUM_NL80211_BANDS; band++) {
2a519311 8552 int j;
7a087e74 8553
2a519311
JB
8554 if (!wiphy->bands[band])
8555 continue;
8556 for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
584991dc
JB
8557 struct ieee80211_channel *chan;
8558
8559 chan = &wiphy->bands[band]->channels[j];
8560
8561 if (chan->flags & IEEE80211_CHAN_DISABLED)
8562 continue;
8563
8564 request->channels[i] = chan;
2a519311
JB
8565 i++;
8566 }
8567 }
8568 }
8569
584991dc
JB
8570 if (!i) {
8571 err = -EINVAL;
8572 goto out_free;
8573 }
8574
8575 request->n_channels = i;
8576
34373d12
VT
8577 wdev_lock(wdev);
8578 if (!cfg80211_off_channel_oper_allowed(wdev)) {
8579 struct ieee80211_channel *chan;
8580
8581 if (request->n_channels != 1) {
8582 wdev_unlock(wdev);
8583 err = -EBUSY;
8584 goto out_free;
8585 }
8586
8587 chan = request->channels[0];
8588 if (chan->center_freq != wdev->chandef.chan->center_freq) {
8589 wdev_unlock(wdev);
8590 err = -EBUSY;
8591 goto out_free;
8592 }
8593 }
8594 wdev_unlock(wdev);
8595
2a519311 8596 i = 0;
13874e4b 8597 if (n_ssids) {
2a519311 8598 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) {
57a27e1d 8599 if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) {
2a519311
JB
8600 err = -EINVAL;
8601 goto out_free;
8602 }
57a27e1d 8603 request->ssids[i].ssid_len = nla_len(attr);
2a519311 8604 memcpy(request->ssids[i].ssid, nla_data(attr), nla_len(attr));
2a519311
JB
8605 i++;
8606 }
8607 }
8608
70692ad2
JM
8609 if (info->attrs[NL80211_ATTR_IE]) {
8610 request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
de95a54b
JB
8611 memcpy((void *)request->ie,
8612 nla_data(info->attrs[NL80211_ATTR_IE]),
70692ad2
JM
8613 request->ie_len);
8614 }
8615
57fbcce3 8616 for (i = 0; i < NUM_NL80211_BANDS; i++)
a401d2bb
JB
8617 if (wiphy->bands[i])
8618 request->rates[i] =
8619 (1 << wiphy->bands[i]->n_bitrates) - 1;
34850ab2
JB
8620
8621 if (info->attrs[NL80211_ATTR_SCAN_SUPP_RATES]) {
8622 nla_for_each_nested(attr,
8623 info->attrs[NL80211_ATTR_SCAN_SUPP_RATES],
8624 tmp) {
57fbcce3 8625 enum nl80211_band band = nla_type(attr);
34850ab2 8626
57fbcce3 8627 if (band < 0 || band >= NUM_NL80211_BANDS) {
34850ab2
JB
8628 err = -EINVAL;
8629 goto out_free;
8630 }
1b09cd82
FF
8631
8632 if (!wiphy->bands[band])
8633 continue;
8634
34850ab2
JB
8635 err = ieee80211_get_ratemask(wiphy->bands[band],
8636 nla_data(attr),
8637 nla_len(attr),
8638 &request->rates[band]);
8639 if (err)
8640 goto out_free;
8641 }
8642 }
8643
1d76250b 8644 if (info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]) {
1d76250b
AS
8645 request->duration =
8646 nla_get_u16(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]);
8647 request->duration_mandatory =
8648 nla_get_flag(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY]);
8649 }
8650
2d23d073
RZ
8651 err = nl80211_check_scan_flags(wiphy, wdev, request, info->attrs,
8652 false);
8653 if (err)
8654 goto out_free;
ed473771 8655
e9f935e3
RM
8656 request->no_cck =
8657 nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
8658
2fa436b3
VK
8659 /* Initial implementation used NL80211_ATTR_MAC to set the specific
8660 * BSSID to scan for. This was problematic because that same attribute
8661 * was already used for another purpose (local random MAC address). The
8662 * NL80211_ATTR_BSSID attribute was added to fix this. For backwards
8663 * compatibility with older userspace components, also use the
8664 * NL80211_ATTR_MAC value here if it can be determined to be used for
8665 * the specific BSSID use case instead of the random MAC address
8666 * (NL80211_ATTR_SCAN_FLAGS is used to enable random MAC address use).
8667 */
8668 if (info->attrs[NL80211_ATTR_BSSID])
8669 memcpy(request->bssid,
8670 nla_data(info->attrs[NL80211_ATTR_BSSID]), ETH_ALEN);
8671 else if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) &&
8672 info->attrs[NL80211_ATTR_MAC])
818965d3
JM
8673 memcpy(request->bssid, nla_data(info->attrs[NL80211_ATTR_MAC]),
8674 ETH_ALEN);
8675 else
8676 eth_broadcast_addr(request->bssid);
8677
fd014284 8678 request->wdev = wdev;
79c97e97 8679 request->wiphy = &rdev->wiphy;
15d6030b 8680 request->scan_start = jiffies;
2a519311 8681
79c97e97 8682 rdev->scan_req = request;
c8cb5b85 8683 err = cfg80211_scan(rdev);
2a519311 8684
504776be
CJ
8685 if (err)
8686 goto out_free;
8687
8688 nl80211_send_scan_start(rdev, wdev);
1160dfa1 8689 dev_hold(wdev->netdev);
504776be
CJ
8690
8691 return 0;
8692
2a519311 8693 out_free:
504776be
CJ
8694 rdev->scan_req = NULL;
8695 kfree(request);
3b85875a 8696
2a519311
JB
8697 return err;
8698}
8699
91d3ab46
VK
8700static int nl80211_abort_scan(struct sk_buff *skb, struct genl_info *info)
8701{
8702 struct cfg80211_registered_device *rdev = info->user_ptr[0];
8703 struct wireless_dev *wdev = info->user_ptr[1];
8704
8705 if (!rdev->ops->abort_scan)
8706 return -EOPNOTSUPP;
8707
8708 if (rdev->scan_msg)
8709 return 0;
8710
8711 if (!rdev->scan_req)
8712 return -ENOENT;
8713
8714 rdev_abort_scan(rdev, wdev);
8715 return 0;
8716}
8717
3b06d277
AS
8718static int
8719nl80211_parse_sched_scan_plans(struct wiphy *wiphy, int n_plans,
8720 struct cfg80211_sched_scan_request *request,
8721 struct nlattr **attrs)
8722{
8723 int tmp, err, i = 0;
8724 struct nlattr *attr;
8725
8726 if (!attrs[NL80211_ATTR_SCHED_SCAN_PLANS]) {
8727 u32 interval;
8728
8729 /*
8730 * If scan plans are not specified,
5a88de53 8731 * %NL80211_ATTR_SCHED_SCAN_INTERVAL will be specified. In this
3b06d277
AS
8732 * case one scan plan will be set with the specified scan
8733 * interval and infinite number of iterations.
8734 */
3b06d277
AS
8735 interval = nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]);
8736 if (!interval)
8737 return -EINVAL;
8738
8739 request->scan_plans[0].interval =
8740 DIV_ROUND_UP(interval, MSEC_PER_SEC);
8741 if (!request->scan_plans[0].interval)
8742 return -EINVAL;
8743
8744 if (request->scan_plans[0].interval >
8745 wiphy->max_sched_scan_plan_interval)
8746 request->scan_plans[0].interval =
8747 wiphy->max_sched_scan_plan_interval;
8748
8749 return 0;
8750 }
8751
8752 nla_for_each_nested(attr, attrs[NL80211_ATTR_SCHED_SCAN_PLANS], tmp) {
8753 struct nlattr *plan[NL80211_SCHED_SCAN_PLAN_MAX + 1];
8754
8755 if (WARN_ON(i >= n_plans))
8756 return -EINVAL;
8757
8cb08174
JB
8758 err = nla_parse_nested_deprecated(plan,
8759 NL80211_SCHED_SCAN_PLAN_MAX,
8760 attr, nl80211_plan_policy,
8761 NULL);
3b06d277
AS
8762 if (err)
8763 return err;
8764
8765 if (!plan[NL80211_SCHED_SCAN_PLAN_INTERVAL])
8766 return -EINVAL;
8767
8768 request->scan_plans[i].interval =
8769 nla_get_u32(plan[NL80211_SCHED_SCAN_PLAN_INTERVAL]);
8770 if (!request->scan_plans[i].interval ||
8771 request->scan_plans[i].interval >
8772 wiphy->max_sched_scan_plan_interval)
8773 return -EINVAL;
8774
8775 if (plan[NL80211_SCHED_SCAN_PLAN_ITERATIONS]) {
8776 request->scan_plans[i].iterations =
8777 nla_get_u32(plan[NL80211_SCHED_SCAN_PLAN_ITERATIONS]);
8778 if (!request->scan_plans[i].iterations ||
8779 (request->scan_plans[i].iterations >
8780 wiphy->max_sched_scan_plan_iterations))
8781 return -EINVAL;
8782 } else if (i < n_plans - 1) {
8783 /*
8784 * All scan plans but the last one must specify
8785 * a finite number of iterations
8786 */
8787 return -EINVAL;
8788 }
8789
8790 i++;
8791 }
8792
8793 /*
8794 * The last scan plan must not specify the number of
8795 * iterations, it is supposed to run infinitely
8796 */
8797 if (request->scan_plans[n_plans - 1].iterations)
8798 return -EINVAL;
8799
8800 return 0;
8801}
8802
1e1b11b6 8803static int
8804nl80211_parse_sched_scan_per_band_rssi(struct wiphy *wiphy,
8805 struct cfg80211_match_set *match_sets,
8806 struct nlattr *tb_band_rssi,
8807 s32 rssi_thold)
8808{
8809 struct nlattr *attr;
8810 int i, tmp, ret = 0;
8811
8812 if (!wiphy_ext_feature_isset(wiphy,
8813 NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD)) {
8814 if (tb_band_rssi)
8815 ret = -EOPNOTSUPP;
8816 else
8817 for (i = 0; i < NUM_NL80211_BANDS; i++)
8818 match_sets->per_band_rssi_thold[i] =
8819 NL80211_SCAN_RSSI_THOLD_OFF;
8820 return ret;
8821 }
8822
8823 for (i = 0; i < NUM_NL80211_BANDS; i++)
8824 match_sets->per_band_rssi_thold[i] = rssi_thold;
8825
8826 nla_for_each_nested(attr, tb_band_rssi, tmp) {
8827 enum nl80211_band band = nla_type(attr);
8828
8829 if (band < 0 || band >= NUM_NL80211_BANDS)
8830 return -EINVAL;
8831
8832 match_sets->per_band_rssi_thold[band] = nla_get_s32(attr);
8833 }
8834
8835 return 0;
8836}
8837
256da02d 8838static struct cfg80211_sched_scan_request *
ad2b26ab 8839nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
aad1e812 8840 struct nlattr **attrs, int max_match_sets)
807f8a8c
LC
8841{
8842 struct cfg80211_sched_scan_request *request;
807f8a8c 8843 struct nlattr *attr;
3b06d277 8844 int err, tmp, n_ssids = 0, n_match_sets = 0, n_channels, i, n_plans = 0;
57fbcce3 8845 enum nl80211_band band;
807f8a8c 8846 size_t ie_len;
a1f1c21c 8847 struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
ea73cbce 8848 s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
807f8a8c 8849
256da02d 8850 if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
807f8a8c 8851 n_channels = validate_scan_freqs(
256da02d 8852 attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
807f8a8c 8853 if (!n_channels)
256da02d 8854 return ERR_PTR(-EINVAL);
807f8a8c 8855 } else {
bdfbec2d 8856 n_channels = ieee80211_get_num_supported_channels(wiphy);
807f8a8c
LC
8857 }
8858
256da02d
LC
8859 if (attrs[NL80211_ATTR_SCAN_SSIDS])
8860 nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
807f8a8c
LC
8861 tmp)
8862 n_ssids++;
8863
93b6aa69 8864 if (n_ssids > wiphy->max_sched_scan_ssids)
256da02d 8865 return ERR_PTR(-EINVAL);
807f8a8c 8866
ea73cbce
JB
8867 /*
8868 * First, count the number of 'real' matchsets. Due to an issue with
8869 * the old implementation, matchsets containing only the RSSI attribute
8870 * (NL80211_SCHED_SCAN_MATCH_ATTR_RSSI) are considered as the 'default'
8871 * RSSI for all matchsets, rather than their own matchset for reporting
8872 * all APs with a strong RSSI. This is needed to be compatible with
8873 * older userspace that treated a matchset with only the RSSI as the
8874 * global RSSI for all other matchsets - if there are other matchsets.
8875 */
256da02d 8876 if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
a1f1c21c 8877 nla_for_each_nested(attr,
256da02d 8878 attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
ea73cbce
JB
8879 tmp) {
8880 struct nlattr *rssi;
8881
8cb08174
JB
8882 err = nla_parse_nested_deprecated(tb,
8883 NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
8884 attr,
8885 nl80211_match_policy,
8886 NULL);
ea73cbce 8887 if (err)
256da02d 8888 return ERR_PTR(err);
3007e352
AVS
8889
8890 /* SSID and BSSID are mutually exclusive */
8891 if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID] &&
8892 tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID])
8893 return ERR_PTR(-EINVAL);
8894
ea73cbce 8895 /* add other standalone attributes here */
3007e352
AVS
8896 if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID] ||
8897 tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID]) {
ea73cbce
JB
8898 n_match_sets++;
8899 continue;
8900 }
8901 rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
8902 if (rssi)
8903 default_match_rssi = nla_get_s32(rssi);
8904 }
8905 }
8906
8907 /* However, if there's no other matchset, add the RSSI one */
8908 if (!n_match_sets && default_match_rssi != NL80211_SCAN_RSSI_THOLD_OFF)
8909 n_match_sets = 1;
a1f1c21c 8910
aad1e812 8911 if (n_match_sets > max_match_sets)
256da02d 8912 return ERR_PTR(-EINVAL);
a1f1c21c 8913
256da02d
LC
8914 if (attrs[NL80211_ATTR_IE])
8915 ie_len = nla_len(attrs[NL80211_ATTR_IE]);
807f8a8c
LC
8916 else
8917 ie_len = 0;
8918
5a865bad 8919 if (ie_len > wiphy->max_sched_scan_ie_len)
256da02d 8920 return ERR_PTR(-EINVAL);
c10841ca 8921
3b06d277
AS
8922 if (attrs[NL80211_ATTR_SCHED_SCAN_PLANS]) {
8923 /*
8924 * NL80211_ATTR_SCHED_SCAN_INTERVAL must not be specified since
8925 * each scan plan already specifies its own interval
8926 */
8927 if (attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
8928 return ERR_PTR(-EINVAL);
8929
8930 nla_for_each_nested(attr,
8931 attrs[NL80211_ATTR_SCHED_SCAN_PLANS], tmp)
8932 n_plans++;
8933 } else {
8934 /*
8935 * The scan interval attribute is kept for backward
8936 * compatibility. If no scan plans are specified and sched scan
8937 * interval is specified, one scan plan will be set with this
8938 * scan interval and infinite number of iterations.
8939 */
8940 if (!attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
8941 return ERR_PTR(-EINVAL);
8942
8943 n_plans = 1;
8944 }
8945
8946 if (!n_plans || n_plans > wiphy->max_sched_scan_plans)
8947 return ERR_PTR(-EINVAL);
8948
bf95ecdb 8949 if (!wiphy_ext_feature_isset(
8950 wiphy, NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI) &&
8951 (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] ||
8952 attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]))
8953 return ERR_PTR(-EINVAL);
8954
807f8a8c 8955 request = kzalloc(sizeof(*request)
a2cd43c5 8956 + sizeof(*request->ssids) * n_ssids
a1f1c21c 8957 + sizeof(*request->match_sets) * n_match_sets
3b06d277 8958 + sizeof(*request->scan_plans) * n_plans
a2cd43c5 8959 + sizeof(*request->channels) * n_channels
807f8a8c 8960 + ie_len, GFP_KERNEL);
256da02d
LC
8961 if (!request)
8962 return ERR_PTR(-ENOMEM);
807f8a8c
LC
8963
8964 if (n_ssids)
8965 request->ssids = (void *)&request->channels[n_channels];
8966 request->n_ssids = n_ssids;
8967 if (ie_len) {
13874e4b 8968 if (n_ssids)
807f8a8c
LC
8969 request->ie = (void *)(request->ssids + n_ssids);
8970 else
8971 request->ie = (void *)(request->channels + n_channels);
8972 }
8973
a1f1c21c
LC
8974 if (n_match_sets) {
8975 if (request->ie)
8976 request->match_sets = (void *)(request->ie + ie_len);
13874e4b 8977 else if (n_ssids)
a1f1c21c
LC
8978 request->match_sets =
8979 (void *)(request->ssids + n_ssids);
8980 else
8981 request->match_sets =
8982 (void *)(request->channels + n_channels);
8983 }
8984 request->n_match_sets = n_match_sets;
8985
3b06d277
AS
8986 if (n_match_sets)
8987 request->scan_plans = (void *)(request->match_sets +
8988 n_match_sets);
8989 else if (request->ie)
8990 request->scan_plans = (void *)(request->ie + ie_len);
8991 else if (n_ssids)
8992 request->scan_plans = (void *)(request->ssids + n_ssids);
8993 else
8994 request->scan_plans = (void *)(request->channels + n_channels);
8995
8996 request->n_scan_plans = n_plans;
8997
807f8a8c 8998 i = 0;
256da02d 8999 if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
807f8a8c
LC
9000 /* user specified, bail out if channel not found */
9001 nla_for_each_nested(attr,
256da02d 9002 attrs[NL80211_ATTR_SCAN_FREQUENCIES],
807f8a8c
LC
9003 tmp) {
9004 struct ieee80211_channel *chan;
9005
9006 chan = ieee80211_get_channel(wiphy, nla_get_u32(attr));
9007
9008 if (!chan) {
9009 err = -EINVAL;
9010 goto out_free;
9011 }
9012
9013 /* ignore disabled channels */
9014 if (chan->flags & IEEE80211_CHAN_DISABLED)
9015 continue;
9016
9017 request->channels[i] = chan;
9018 i++;
9019 }
9020 } else {
9021 /* all channels */
57fbcce3 9022 for (band = 0; band < NUM_NL80211_BANDS; band++) {
807f8a8c 9023 int j;
7a087e74 9024
807f8a8c
LC
9025 if (!wiphy->bands[band])
9026 continue;
9027 for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
9028 struct ieee80211_channel *chan;
9029
9030 chan = &wiphy->bands[band]->channels[j];
9031
9032 if (chan->flags & IEEE80211_CHAN_DISABLED)
9033 continue;
9034
9035 request->channels[i] = chan;
9036 i++;
9037 }
9038 }
9039 }
9040
9041 if (!i) {
9042 err = -EINVAL;
9043 goto out_free;
9044 }
9045
9046 request->n_channels = i;
9047
9048 i = 0;
13874e4b 9049 if (n_ssids) {
256da02d 9050 nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
807f8a8c 9051 tmp) {
57a27e1d 9052 if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) {
807f8a8c
LC
9053 err = -EINVAL;
9054 goto out_free;
9055 }
57a27e1d 9056 request->ssids[i].ssid_len = nla_len(attr);
807f8a8c
LC
9057 memcpy(request->ssids[i].ssid, nla_data(attr),
9058 nla_len(attr));
807f8a8c
LC
9059 i++;
9060 }
9061 }
9062
a1f1c21c 9063 i = 0;
256da02d 9064 if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
a1f1c21c 9065 nla_for_each_nested(attr,
256da02d 9066 attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
a1f1c21c 9067 tmp) {
3007e352 9068 struct nlattr *ssid, *bssid, *rssi;
a1f1c21c 9069
8cb08174
JB
9070 err = nla_parse_nested_deprecated(tb,
9071 NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
9072 attr,
9073 nl80211_match_policy,
9074 NULL);
ae811e21
JB
9075 if (err)
9076 goto out_free;
4a4ab0d7 9077 ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID];
3007e352 9078 bssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID];
d39f3b4f
JB
9079
9080 if (!ssid && !bssid) {
9081 i++;
9082 continue;
9083 }
9084
9085 if (WARN_ON(i >= n_match_sets)) {
9086 /* this indicates a programming error,
9087 * the loop above should have verified
9088 * things properly
9089 */
9090 err = -EINVAL;
9091 goto out_free;
9092 }
9093
9094 if (ssid) {
d39f3b4f
JB
9095 memcpy(request->match_sets[i].ssid.ssid,
9096 nla_data(ssid), nla_len(ssid));
9097 request->match_sets[i].ssid.ssid_len =
9098 nla_len(ssid);
9099 }
cb9abd48 9100 if (bssid)
d39f3b4f
JB
9101 memcpy(request->match_sets[i].bssid,
9102 nla_data(bssid), ETH_ALEN);
3007e352 9103
d39f3b4f
JB
9104 /* special attribute - old implementation w/a */
9105 request->match_sets[i].rssi_thold = default_match_rssi;
9106 rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
9107 if (rssi)
ea73cbce 9108 request->match_sets[i].rssi_thold =
d39f3b4f 9109 nla_get_s32(rssi);
1e1b11b6 9110
9111 /* Parse per band RSSI attribute */
9112 err = nl80211_parse_sched_scan_per_band_rssi(wiphy,
9113 &request->match_sets[i],
9114 tb[NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI],
9115 request->match_sets[i].rssi_thold);
9116 if (err)
9117 goto out_free;
9118
a1f1c21c
LC
9119 i++;
9120 }
ea73cbce
JB
9121
9122 /* there was no other matchset, so the RSSI one is alone */
f89f46cf 9123 if (i == 0 && n_match_sets)
ea73cbce
JB
9124 request->match_sets[0].rssi_thold = default_match_rssi;
9125
9126 request->min_rssi_thold = INT_MAX;
9127 for (i = 0; i < n_match_sets; i++)
9128 request->min_rssi_thold =
9129 min(request->match_sets[i].rssi_thold,
9130 request->min_rssi_thold);
9131 } else {
9132 request->min_rssi_thold = NL80211_SCAN_RSSI_THOLD_OFF;
a1f1c21c
LC
9133 }
9134
9900e484
JB
9135 if (ie_len) {
9136 request->ie_len = ie_len;
807f8a8c 9137 memcpy((void *)request->ie,
256da02d 9138 nla_data(attrs[NL80211_ATTR_IE]),
807f8a8c
LC
9139 request->ie_len);
9140 }
9141
2d23d073
RZ
9142 err = nl80211_check_scan_flags(wiphy, wdev, request, attrs, true);
9143 if (err)
9144 goto out_free;
ed473771 9145
9c748934
LC
9146 if (attrs[NL80211_ATTR_SCHED_SCAN_DELAY])
9147 request->delay =
9148 nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_DELAY]);
9149
bf95ecdb 9150 if (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI]) {
9151 request->relative_rssi = nla_get_s8(
9152 attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI]);
9153 request->relative_rssi_set = true;
9154 }
9155
9156 if (request->relative_rssi_set &&
9157 attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]) {
9158 struct nl80211_bss_select_rssi_adjust *rssi_adjust;
9159
9160 rssi_adjust = nla_data(
9161 attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]);
9162 request->rssi_adjust.band = rssi_adjust->band;
9163 request->rssi_adjust.delta = rssi_adjust->delta;
9164 if (!is_band_valid(wiphy, request->rssi_adjust.band)) {
9165 err = -EINVAL;
9166 goto out_free;
9167 }
9168 }
9169
3b06d277
AS
9170 err = nl80211_parse_sched_scan_plans(wiphy, n_plans, request, attrs);
9171 if (err)
9172 goto out_free;
9173
15d6030b 9174 request->scan_start = jiffies;
807f8a8c 9175
256da02d 9176 return request;
807f8a8c
LC
9177
9178out_free:
9179 kfree(request);
256da02d
LC
9180 return ERR_PTR(err);
9181}
9182
9183static int nl80211_start_sched_scan(struct sk_buff *skb,
9184 struct genl_info *info)
9185{
9186 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9187 struct net_device *dev = info->user_ptr[1];
ad2b26ab 9188 struct wireless_dev *wdev = dev->ieee80211_ptr;
31a60ed1 9189 struct cfg80211_sched_scan_request *sched_scan_req;
ca986ad9 9190 bool want_multi;
256da02d
LC
9191 int err;
9192
ca986ad9 9193 if (!rdev->wiphy.max_sched_scan_reqs || !rdev->ops->sched_scan_start)
256da02d
LC
9194 return -EOPNOTSUPP;
9195
ca986ad9
AVS
9196 want_multi = info->attrs[NL80211_ATTR_SCHED_SCAN_MULTI];
9197 err = cfg80211_sched_scan_req_possible(rdev, want_multi);
9198 if (err)
9199 return err;
256da02d 9200
31a60ed1 9201 sched_scan_req = nl80211_parse_sched_scan(&rdev->wiphy, wdev,
aad1e812
AVS
9202 info->attrs,
9203 rdev->wiphy.max_match_sets);
31a60ed1
JR
9204
9205 err = PTR_ERR_OR_ZERO(sched_scan_req);
256da02d
LC
9206 if (err)
9207 goto out_err;
9208
ca986ad9
AVS
9209 /* leave request id zero for legacy request
9210 * or if driver does not support multi-scheduled scan
9211 */
2fd351a8
DK
9212 if (want_multi && rdev->wiphy.max_sched_scan_reqs > 1)
9213 sched_scan_req->reqid = cfg80211_assign_cookie(rdev);
ca986ad9 9214
31a60ed1 9215 err = rdev_sched_scan_start(rdev, dev, sched_scan_req);
256da02d
LC
9216 if (err)
9217 goto out_free;
9218
31a60ed1
JR
9219 sched_scan_req->dev = dev;
9220 sched_scan_req->wiphy = &rdev->wiphy;
9221
93a1e86c
JR
9222 if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
9223 sched_scan_req->owner_nlportid = info->snd_portid;
9224
ca986ad9 9225 cfg80211_add_sched_scan_req(rdev, sched_scan_req);
256da02d 9226
96b08fd6 9227 nl80211_send_sched_scan(sched_scan_req, NL80211_CMD_START_SCHED_SCAN);
256da02d
LC
9228 return 0;
9229
9230out_free:
31a60ed1 9231 kfree(sched_scan_req);
256da02d 9232out_err:
807f8a8c
LC
9233 return err;
9234}
9235
9236static int nl80211_stop_sched_scan(struct sk_buff *skb,
9237 struct genl_info *info)
9238{
ca986ad9 9239 struct cfg80211_sched_scan_request *req;
807f8a8c 9240 struct cfg80211_registered_device *rdev = info->user_ptr[0];
ca986ad9 9241 u64 cookie;
807f8a8c 9242
ca986ad9 9243 if (!rdev->wiphy.max_sched_scan_reqs || !rdev->ops->sched_scan_stop)
807f8a8c
LC
9244 return -EOPNOTSUPP;
9245
ca986ad9
AVS
9246 if (info->attrs[NL80211_ATTR_COOKIE]) {
9247 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
9248 return __cfg80211_stop_sched_scan(rdev, cookie, false);
9249 }
9250
9251 req = list_first_or_null_rcu(&rdev->sched_scan_req_list,
9252 struct cfg80211_sched_scan_request,
9253 list);
9254 if (!req || req->reqid ||
9255 (req->owner_nlportid &&
9256 req->owner_nlportid != info->snd_portid))
9257 return -ENOENT;
9258
9259 return cfg80211_stop_sched_scan_req(rdev, req, false);
807f8a8c
LC
9260}
9261
04f39047
SW
9262static int nl80211_start_radar_detection(struct sk_buff *skb,
9263 struct genl_info *info)
9264{
9265 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9266 struct net_device *dev = info->user_ptr[1];
9267 struct wireless_dev *wdev = dev->ieee80211_ptr;
13cf6dec 9268 struct wiphy *wiphy = wdev->wiphy;
04f39047 9269 struct cfg80211_chan_def chandef;
55f7435c 9270 enum nl80211_dfs_regions dfs_region;
31559f35 9271 unsigned int cac_time_ms;
04f39047
SW
9272 int err;
9273
13cf6dec 9274 dfs_region = reg_get_dfs_region(wiphy);
55f7435c
LR
9275 if (dfs_region == NL80211_DFS_UNSET)
9276 return -EINVAL;
9277
04f39047
SW
9278 err = nl80211_parse_chandef(rdev, info, &chandef);
9279 if (err)
9280 return err;
9281
ff311bc1
SW
9282 if (netif_carrier_ok(dev))
9283 return -EBUSY;
9284
04f39047
SW
9285 if (wdev->cac_started)
9286 return -EBUSY;
9287
13cf6dec 9288 err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype);
04f39047
SW
9289 if (err < 0)
9290 return err;
9291
9292 if (err == 0)
9293 return -EINVAL;
9294
13cf6dec 9295 if (!cfg80211_chandef_dfs_usable(wiphy, &chandef))
04f39047
SW
9296 return -EINVAL;
9297
13cf6dec
DL
9298 /* CAC start is offloaded to HW and can't be started manually */
9299 if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD))
9300 return -EOPNOTSUPP;
9301
04f39047
SW
9302 if (!rdev->ops->start_radar_detection)
9303 return -EOPNOTSUPP;
9304
31559f35
JD
9305 cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef);
9306 if (WARN_ON(!cac_time_ms))
9307 cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
9308
a1056b1b 9309 err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms);
04f39047 9310 if (!err) {
9e0e2961 9311 wdev->chandef = chandef;
04f39047
SW
9312 wdev->cac_started = true;
9313 wdev->cac_start_time = jiffies;
31559f35 9314 wdev->cac_time_ms = cac_time_ms;
04f39047 9315 }
04f39047
SW
9316 return err;
9317}
9318
30c63115
S
9319static int nl80211_notify_radar_detection(struct sk_buff *skb,
9320 struct genl_info *info)
9321{
9322 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9323 struct net_device *dev = info->user_ptr[1];
9324 struct wireless_dev *wdev = dev->ieee80211_ptr;
9325 struct wiphy *wiphy = wdev->wiphy;
9326 struct cfg80211_chan_def chandef;
9327 enum nl80211_dfs_regions dfs_region;
9328 int err;
9329
9330 dfs_region = reg_get_dfs_region(wiphy);
9331 if (dfs_region == NL80211_DFS_UNSET) {
9332 GENL_SET_ERR_MSG(info,
9333 "DFS Region is not set. Unexpected Radar indication");
9334 return -EINVAL;
9335 }
9336
9337 err = nl80211_parse_chandef(rdev, info, &chandef);
9338 if (err) {
9339 GENL_SET_ERR_MSG(info, "Unable to extract chandef info");
9340 return err;
9341 }
9342
9343 err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype);
9344 if (err < 0) {
9345 GENL_SET_ERR_MSG(info, "chandef is invalid");
9346 return err;
9347 }
9348
9349 if (err == 0) {
9350 GENL_SET_ERR_MSG(info,
9351 "Unexpected Radar indication for chandef/iftype");
9352 return -EINVAL;
9353 }
9354
9355 /* Do not process this notification if radar is already detected
9356 * by kernel on this channel, and return success.
9357 */
9358 if (chandef.chan->dfs_state == NL80211_DFS_UNAVAILABLE)
9359 return 0;
9360
9361 cfg80211_set_dfs_state(wiphy, &chandef, NL80211_DFS_UNAVAILABLE);
9362
9363 cfg80211_sched_dfs_chan_update(rdev);
9364
a680fe46 9365 rdev->radar_chandef = chandef;
30c63115
S
9366
9367 /* Propagate this notification to other radios as well */
9368 queue_work(cfg80211_wq, &rdev->propagate_radar_detect_wk);
9369
9370 return 0;
9371}
9372
16ef1fe2
SW
9373static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
9374{
9375 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9376 struct net_device *dev = info->user_ptr[1];
9377 struct wireless_dev *wdev = dev->ieee80211_ptr;
9378 struct cfg80211_csa_settings params;
a05829a7 9379 struct nlattr **csa_attrs = NULL;
16ef1fe2 9380 int err;
ee4bc9e7 9381 bool need_new_beacon = false;
8d9de16f 9382 bool need_handle_dfs_flag = true;
9a774c78 9383 int len, i;
252e07ca 9384 u32 cs_count;
16ef1fe2
SW
9385
9386 if (!rdev->ops->channel_switch ||
9387 !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
9388 return -EOPNOTSUPP;
9389
ee4bc9e7
SW
9390 switch (dev->ieee80211_ptr->iftype) {
9391 case NL80211_IFTYPE_AP:
9392 case NL80211_IFTYPE_P2P_GO:
9393 need_new_beacon = true;
8d9de16f
BB
9394 /* For all modes except AP the handle_dfs flag needs to be
9395 * supplied to tell the kernel that userspace will handle radar
9396 * events when they happen. Otherwise a switch to a channel
9397 * requiring DFS will be rejected.
9398 */
9399 need_handle_dfs_flag = false;
ee4bc9e7
SW
9400
9401 /* useless if AP is not running */
9402 if (!wdev->beacon_interval)
1ff79dfa 9403 return -ENOTCONN;
ee4bc9e7
SW
9404 break;
9405 case NL80211_IFTYPE_ADHOC:
1ff79dfa
JB
9406 if (!wdev->ssid_len)
9407 return -ENOTCONN;
9408 break;
c6da674a 9409 case NL80211_IFTYPE_MESH_POINT:
1ff79dfa
JB
9410 if (!wdev->mesh_id_len)
9411 return -ENOTCONN;
ee4bc9e7
SW
9412 break;
9413 default:
16ef1fe2 9414 return -EOPNOTSUPP;
ee4bc9e7 9415 }
16ef1fe2
SW
9416
9417 memset(&params, 0, sizeof(params));
c177db2d 9418 params.beacon_csa.ftm_responder = -1;
16ef1fe2
SW
9419
9420 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
9421 !info->attrs[NL80211_ATTR_CH_SWITCH_COUNT])
9422 return -EINVAL;
9423
9424 /* only important for AP, IBSS and mesh create IEs internally */
d0a361a5 9425 if (need_new_beacon && !info->attrs[NL80211_ATTR_CSA_IES])
16ef1fe2
SW
9426 return -EINVAL;
9427
252e07ca
LC
9428 /* Even though the attribute is u32, the specification says
9429 * u8, so let's make sure we don't overflow.
9430 */
9431 cs_count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
9432 if (cs_count > 255)
9433 return -EINVAL;
9434
9435 params.count = cs_count;
16ef1fe2 9436
ee4bc9e7
SW
9437 if (!need_new_beacon)
9438 goto skip_beacons;
9439
81e54d08 9440 err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon_after);
16ef1fe2 9441 if (err)
dc1e3cb8 9442 goto free;
16ef1fe2 9443
a05829a7
JB
9444 csa_attrs = kcalloc(NL80211_ATTR_MAX + 1, sizeof(*csa_attrs),
9445 GFP_KERNEL);
dc1e3cb8
JC
9446 if (!csa_attrs) {
9447 err = -ENOMEM;
9448 goto free;
9449 }
a05829a7 9450
8cb08174
JB
9451 err = nla_parse_nested_deprecated(csa_attrs, NL80211_ATTR_MAX,
9452 info->attrs[NL80211_ATTR_CSA_IES],
9453 nl80211_policy, info->extack);
16ef1fe2 9454 if (err)
a05829a7 9455 goto free;
16ef1fe2 9456
81e54d08 9457 err = nl80211_parse_beacon(rdev, csa_attrs, &params.beacon_csa);
16ef1fe2 9458 if (err)
a05829a7 9459 goto free;
16ef1fe2 9460
a05829a7
JB
9461 if (!csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]) {
9462 err = -EINVAL;
9463 goto free;
9464 }
16ef1fe2 9465
00c207ed 9466 len = nla_len(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
a05829a7
JB
9467 if (!len || (len % sizeof(u16))) {
9468 err = -EINVAL;
9469 goto free;
9470 }
16ef1fe2 9471
9a774c78
AO
9472 params.n_counter_offsets_beacon = len / sizeof(u16);
9473 if (rdev->wiphy.max_num_csa_counters &&
9474 (params.n_counter_offsets_beacon >
a05829a7
JB
9475 rdev->wiphy.max_num_csa_counters)) {
9476 err = -EINVAL;
9477 goto free;
9478 }
16ef1fe2 9479
9a774c78 9480 params.counter_offsets_beacon =
00c207ed 9481 nla_data(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
9a774c78
AO
9482
9483 /* sanity checks - counters should fit and be the same */
9484 for (i = 0; i < params.n_counter_offsets_beacon; i++) {
9485 u16 offset = params.counter_offsets_beacon[i];
9486
a05829a7
JB
9487 if (offset >= params.beacon_csa.tail_len) {
9488 err = -EINVAL;
9489 goto free;
9490 }
9a774c78 9491
a05829a7
JB
9492 if (params.beacon_csa.tail[offset] != params.count) {
9493 err = -EINVAL;
9494 goto free;
9495 }
9a774c78
AO
9496 }
9497
00c207ed
JC
9498 if (csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]) {
9499 len = nla_len(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
a05829a7
JB
9500 if (!len || (len % sizeof(u16))) {
9501 err = -EINVAL;
9502 goto free;
9503 }
16ef1fe2 9504
9a774c78
AO
9505 params.n_counter_offsets_presp = len / sizeof(u16);
9506 if (rdev->wiphy.max_num_csa_counters &&
ad5987b4 9507 (params.n_counter_offsets_presp >
a05829a7
JB
9508 rdev->wiphy.max_num_csa_counters)) {
9509 err = -EINVAL;
9510 goto free;
9511 }
9a774c78
AO
9512
9513 params.counter_offsets_presp =
00c207ed 9514 nla_data(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
9a774c78
AO
9515
9516 /* sanity checks - counters should fit and be the same */
9517 for (i = 0; i < params.n_counter_offsets_presp; i++) {
9518 u16 offset = params.counter_offsets_presp[i];
9519
a05829a7
JB
9520 if (offset >= params.beacon_csa.probe_resp_len) {
9521 err = -EINVAL;
9522 goto free;
9523 }
9a774c78
AO
9524
9525 if (params.beacon_csa.probe_resp[offset] !=
a05829a7
JB
9526 params.count) {
9527 err = -EINVAL;
9528 goto free;
9529 }
9a774c78 9530 }
16ef1fe2
SW
9531 }
9532
ee4bc9e7 9533skip_beacons:
16ef1fe2
SW
9534 err = nl80211_parse_chandef(rdev, info, &params.chandef);
9535 if (err)
a05829a7 9536 goto free;
16ef1fe2 9537
923b352f 9538 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params.chandef,
a05829a7
JB
9539 wdev->iftype)) {
9540 err = -EINVAL;
9541 goto free;
9542 }
16ef1fe2 9543
2beb6dab
LC
9544 err = cfg80211_chandef_dfs_required(wdev->wiphy,
9545 &params.chandef,
9546 wdev->iftype);
9547 if (err < 0)
a05829a7 9548 goto free;
2beb6dab 9549
8d9de16f 9550 if (err > 0) {
2beb6dab 9551 params.radar_required = true;
8d9de16f
BB
9552 if (need_handle_dfs_flag &&
9553 !nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS])) {
a05829a7
JB
9554 err = -EINVAL;
9555 goto free;
8d9de16f
BB
9556 }
9557 }
16ef1fe2 9558
16ef1fe2
SW
9559 if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
9560 params.block_tx = true;
9561
c56589ed
SW
9562 wdev_lock(wdev);
9563 err = rdev_channel_switch(rdev, dev, &params);
9564 wdev_unlock(wdev);
9565
a05829a7 9566free:
dc1e3cb8
JC
9567 kfree(params.beacon_after.mbssid_ies);
9568 kfree(params.beacon_csa.mbssid_ies);
a05829a7 9569 kfree(csa_attrs);
c56589ed 9570 return err;
16ef1fe2
SW
9571}
9572
9720bb3a
JB
9573static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
9574 u32 seq, int flags,
2a519311 9575 struct cfg80211_registered_device *rdev,
48ab905d
JB
9576 struct wireless_dev *wdev,
9577 struct cfg80211_internal_bss *intbss)
2a519311 9578{
48ab905d 9579 struct cfg80211_bss *res = &intbss->pub;
9caf0364 9580 const struct cfg80211_bss_ies *ies;
2a519311
JB
9581 void *hdr;
9582 struct nlattr *bss;
48ab905d
JB
9583
9584 ASSERT_WDEV_LOCK(wdev);
2a519311 9585
15e47304 9586 hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).portid, seq, flags,
2a519311
JB
9587 NL80211_CMD_NEW_SCAN_RESULTS);
9588 if (!hdr)
9589 return -1;
9590
0a833c29 9591 genl_dump_check_consistent(cb, hdr);
9720bb3a 9592
97990a06
JB
9593 if (nla_put_u32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation))
9594 goto nla_put_failure;
9595 if (wdev->netdev &&
9360ffd1
DM
9596 nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex))
9597 goto nla_put_failure;
2dad624e
ND
9598 if (nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
9599 NL80211_ATTR_PAD))
97990a06 9600 goto nla_put_failure;
2a519311 9601
ae0be8de 9602 bss = nla_nest_start_noflag(msg, NL80211_ATTR_BSS);
2a519311
JB
9603 if (!bss)
9604 goto nla_put_failure;
9360ffd1 9605 if ((!is_zero_ether_addr(res->bssid) &&
9caf0364 9606 nla_put(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid)))
9360ffd1 9607 goto nla_put_failure;
9caf0364
JB
9608
9609 rcu_read_lock();
0e227084
JB
9610 /* indicate whether we have probe response data or not */
9611 if (rcu_access_pointer(res->proberesp_ies) &&
9612 nla_put_flag(msg, NL80211_BSS_PRESP_DATA))
9613 goto fail_unlock_rcu;
9614
9615 /* this pointer prefers to be pointed to probe response data
9616 * but is always valid
9617 */
9caf0364 9618 ies = rcu_dereference(res->ies);
8cef2c9d 9619 if (ies) {
2dad624e
ND
9620 if (nla_put_u64_64bit(msg, NL80211_BSS_TSF, ies->tsf,
9621 NL80211_BSS_PAD))
8cef2c9d 9622 goto fail_unlock_rcu;
8cef2c9d
JB
9623 if (ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS,
9624 ies->len, ies->data))
9625 goto fail_unlock_rcu;
9caf0364 9626 }
0e227084
JB
9627
9628 /* and this pointer is always (unless driver didn't know) beacon data */
9caf0364 9629 ies = rcu_dereference(res->beacon_ies);
0e227084 9630 if (ies && ies->from_beacon) {
2dad624e
ND
9631 if (nla_put_u64_64bit(msg, NL80211_BSS_BEACON_TSF, ies->tsf,
9632 NL80211_BSS_PAD))
8cef2c9d
JB
9633 goto fail_unlock_rcu;
9634 if (ies->len && nla_put(msg, NL80211_BSS_BEACON_IES,
9635 ies->len, ies->data))
9636 goto fail_unlock_rcu;
9caf0364
JB
9637 }
9638 rcu_read_unlock();
9639
9360ffd1
DM
9640 if (res->beacon_interval &&
9641 nla_put_u16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval))
9642 goto nla_put_failure;
9643 if (nla_put_u16(msg, NL80211_BSS_CAPABILITY, res->capability) ||
9644 nla_put_u32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq) ||
942ba88b
TP
9645 nla_put_u32(msg, NL80211_BSS_FREQUENCY_OFFSET,
9646 res->channel->freq_offset) ||
dcd6eac1 9647 nla_put_u32(msg, NL80211_BSS_CHAN_WIDTH, res->scan_width) ||
9360ffd1
DM
9648 nla_put_u32(msg, NL80211_BSS_SEEN_MS_AGO,
9649 jiffies_to_msecs(jiffies - intbss->ts)))
9650 goto nla_put_failure;
2a519311 9651
1d76250b
AS
9652 if (intbss->parent_tsf &&
9653 (nla_put_u64_64bit(msg, NL80211_BSS_PARENT_TSF,
9654 intbss->parent_tsf, NL80211_BSS_PAD) ||
9655 nla_put(msg, NL80211_BSS_PARENT_BSSID, ETH_ALEN,
9656 intbss->parent_bssid)))
9657 goto nla_put_failure;
9658
6e19bc4b 9659 if (intbss->ts_boottime &&
2dad624e
ND
9660 nla_put_u64_64bit(msg, NL80211_BSS_LAST_SEEN_BOOTTIME,
9661 intbss->ts_boottime, NL80211_BSS_PAD))
6e19bc4b
DS
9662 goto nla_put_failure;
9663
983dafaa
SD
9664 if (!nl80211_put_signal(msg, intbss->pub.chains,
9665 intbss->pub.chain_signal,
9666 NL80211_BSS_CHAIN_SIGNAL))
9667 goto nla_put_failure;
9668
77965c97 9669 switch (rdev->wiphy.signal_type) {
2a519311 9670 case CFG80211_SIGNAL_TYPE_MBM:
9360ffd1
DM
9671 if (nla_put_u32(msg, NL80211_BSS_SIGNAL_MBM, res->signal))
9672 goto nla_put_failure;
2a519311
JB
9673 break;
9674 case CFG80211_SIGNAL_TYPE_UNSPEC:
9360ffd1
DM
9675 if (nla_put_u8(msg, NL80211_BSS_SIGNAL_UNSPEC, res->signal))
9676 goto nla_put_failure;
2a519311
JB
9677 break;
9678 default:
9679 break;
9680 }
9681
48ab905d 9682 switch (wdev->iftype) {
074ac8df 9683 case NL80211_IFTYPE_P2P_CLIENT:
48ab905d 9684 case NL80211_IFTYPE_STATION:
9360ffd1
DM
9685 if (intbss == wdev->current_bss &&
9686 nla_put_u32(msg, NL80211_BSS_STATUS,
9687 NL80211_BSS_STATUS_ASSOCIATED))
9688 goto nla_put_failure;
48ab905d
JB
9689 break;
9690 case NL80211_IFTYPE_ADHOC:
9360ffd1
DM
9691 if (intbss == wdev->current_bss &&
9692 nla_put_u32(msg, NL80211_BSS_STATUS,
9693 NL80211_BSS_STATUS_IBSS_JOINED))
9694 goto nla_put_failure;
48ab905d
JB
9695 break;
9696 default:
9697 break;
9698 }
9699
2a519311
JB
9700 nla_nest_end(msg, bss);
9701
053c095a
JB
9702 genlmsg_end(msg, hdr);
9703 return 0;
2a519311 9704
8cef2c9d
JB
9705 fail_unlock_rcu:
9706 rcu_read_unlock();
2a519311
JB
9707 nla_put_failure:
9708 genlmsg_cancel(msg, hdr);
9709 return -EMSGSIZE;
9710}
9711
97990a06 9712static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb)
2a519311 9713{
48ab905d 9714 struct cfg80211_registered_device *rdev;
2a519311 9715 struct cfg80211_internal_bss *scan;
48ab905d 9716 struct wireless_dev *wdev;
97990a06 9717 int start = cb->args[2], idx = 0;
2a519311
JB
9718 int err;
9719
5297c65c 9720 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
a05829a7 9721 if (err)
67748893 9722 return err;
a05829a7
JB
9723 /* nl80211_prepare_wdev_dump acquired it in the successful case */
9724 __acquire(&rdev->wiphy.mtx);
2a519311 9725
48ab905d
JB
9726 wdev_lock(wdev);
9727 spin_lock_bh(&rdev->bss_lock);
d1e23c94
DK
9728
9729 /*
9730 * dump_scan will be called multiple times to break up the scan results
9731 * into multiple messages. It is unlikely that any more bss-es will be
9732 * expired after the first call, so only call only call this on the
9733 * first dump_scan invocation.
9734 */
9735 if (start == 0)
9736 cfg80211_bss_expire(rdev);
48ab905d 9737
9720bb3a
JB
9738 cb->seq = rdev->bss_generation;
9739
48ab905d 9740 list_for_each_entry(scan, &rdev->bss_list, list) {
2a519311
JB
9741 if (++idx <= start)
9742 continue;
9720bb3a 9743 if (nl80211_send_bss(skb, cb,
2a519311 9744 cb->nlh->nlmsg_seq, NLM_F_MULTI,
48ab905d 9745 rdev, wdev, scan) < 0) {
2a519311 9746 idx--;
67748893 9747 break;
2a519311
JB
9748 }
9749 }
9750
48ab905d
JB
9751 spin_unlock_bh(&rdev->bss_lock);
9752 wdev_unlock(wdev);
2a519311 9753
97990a06 9754 cb->args[2] = idx;
a05829a7 9755 wiphy_unlock(&rdev->wiphy);
2a519311 9756
67748893 9757 return skb->len;
2a519311
JB
9758}
9759
15e47304 9760static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq,
11f78ac3
JB
9761 int flags, struct net_device *dev,
9762 bool allow_radio_stats,
9763 struct survey_info *survey)
61fa713c
HS
9764{
9765 void *hdr;
9766 struct nlattr *infoattr;
9767
11f78ac3
JB
9768 /* skip radio stats if userspace didn't request them */
9769 if (!survey->channel && !allow_radio_stats)
9770 return 0;
9771
15e47304 9772 hdr = nl80211hdr_put(msg, portid, seq, flags,
61fa713c
HS
9773 NL80211_CMD_NEW_SURVEY_RESULTS);
9774 if (!hdr)
9775 return -ENOMEM;
9776
9360ffd1
DM
9777 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
9778 goto nla_put_failure;
61fa713c 9779
ae0be8de 9780 infoattr = nla_nest_start_noflag(msg, NL80211_ATTR_SURVEY_INFO);
61fa713c
HS
9781 if (!infoattr)
9782 goto nla_put_failure;
9783
11f78ac3
JB
9784 if (survey->channel &&
9785 nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY,
9360ffd1
DM
9786 survey->channel->center_freq))
9787 goto nla_put_failure;
58ef7c1b
TP
9788
9789 if (survey->channel && survey->channel->freq_offset &&
9790 nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY_OFFSET,
9791 survey->channel->freq_offset))
9792 goto nla_put_failure;
9360ffd1
DM
9793
9794 if ((survey->filled & SURVEY_INFO_NOISE_DBM) &&
9795 nla_put_u8(msg, NL80211_SURVEY_INFO_NOISE, survey->noise))
9796 goto nla_put_failure;
9797 if ((survey->filled & SURVEY_INFO_IN_USE) &&
9798 nla_put_flag(msg, NL80211_SURVEY_INFO_IN_USE))
9799 goto nla_put_failure;
4ed20beb 9800 if ((survey->filled & SURVEY_INFO_TIME) &&
2dad624e
ND
9801 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME,
9802 survey->time, NL80211_SURVEY_INFO_PAD))
9360ffd1 9803 goto nla_put_failure;
4ed20beb 9804 if ((survey->filled & SURVEY_INFO_TIME_BUSY) &&
2dad624e
ND
9805 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_BUSY,
9806 survey->time_busy, NL80211_SURVEY_INFO_PAD))
9360ffd1 9807 goto nla_put_failure;
4ed20beb 9808 if ((survey->filled & SURVEY_INFO_TIME_EXT_BUSY) &&
2dad624e
ND
9809 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_EXT_BUSY,
9810 survey->time_ext_busy, NL80211_SURVEY_INFO_PAD))
9360ffd1 9811 goto nla_put_failure;
4ed20beb 9812 if ((survey->filled & SURVEY_INFO_TIME_RX) &&
2dad624e
ND
9813 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_RX,
9814 survey->time_rx, NL80211_SURVEY_INFO_PAD))
9360ffd1 9815 goto nla_put_failure;
4ed20beb 9816 if ((survey->filled & SURVEY_INFO_TIME_TX) &&
2dad624e
ND
9817 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_TX,
9818 survey->time_tx, NL80211_SURVEY_INFO_PAD))
9360ffd1 9819 goto nla_put_failure;
052536ab 9820 if ((survey->filled & SURVEY_INFO_TIME_SCAN) &&
2dad624e
ND
9821 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_SCAN,
9822 survey->time_scan, NL80211_SURVEY_INFO_PAD))
052536ab 9823 goto nla_put_failure;
c8cd6e7f
FF
9824 if ((survey->filled & SURVEY_INFO_TIME_BSS_RX) &&
9825 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_BSS_RX,
9826 survey->time_bss_rx, NL80211_SURVEY_INFO_PAD))
9827 goto nla_put_failure;
61fa713c
HS
9828
9829 nla_nest_end(msg, infoattr);
9830
053c095a
JB
9831 genlmsg_end(msg, hdr);
9832 return 0;
61fa713c
HS
9833
9834 nla_put_failure:
9835 genlmsg_cancel(msg, hdr);
9836 return -EMSGSIZE;
9837}
9838
11f78ac3 9839static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
61fa713c 9840{
50508d94 9841 struct nlattr **attrbuf;
61fa713c 9842 struct survey_info survey;
1b8ec87a 9843 struct cfg80211_registered_device *rdev;
97990a06
JB
9844 struct wireless_dev *wdev;
9845 int survey_idx = cb->args[2];
61fa713c 9846 int res;
11f78ac3 9847 bool radio_stats;
61fa713c 9848
50508d94
JB
9849 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), GFP_KERNEL);
9850 if (!attrbuf)
9851 return -ENOMEM;
9852
5297c65c 9853 res = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
a05829a7
JB
9854 if (res) {
9855 kfree(attrbuf);
9856 return res;
9857 }
9858 /* nl80211_prepare_wdev_dump acquired it in the successful case */
9859 __acquire(&rdev->wiphy.mtx);
61fa713c 9860
11f78ac3 9861 /* prepare_wdev_dump parsed the attributes */
c90c39da 9862 radio_stats = attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS];
11f78ac3 9863
97990a06
JB
9864 if (!wdev->netdev) {
9865 res = -EINVAL;
9866 goto out_err;
9867 }
9868
1b8ec87a 9869 if (!rdev->ops->dump_survey) {
61fa713c
HS
9870 res = -EOPNOTSUPP;
9871 goto out_err;
9872 }
9873
9874 while (1) {
1b8ec87a 9875 res = rdev_dump_survey(rdev, wdev->netdev, survey_idx, &survey);
61fa713c
HS
9876 if (res == -ENOENT)
9877 break;
9878 if (res)
9879 goto out_err;
9880
11f78ac3
JB
9881 /* don't send disabled channels, but do send non-channel data */
9882 if (survey.channel &&
9883 survey.channel->flags & IEEE80211_CHAN_DISABLED) {
180cdc79
LR
9884 survey_idx++;
9885 continue;
9886 }
9887
61fa713c 9888 if (nl80211_send_survey(skb,
15e47304 9889 NETLINK_CB(cb->skb).portid,
61fa713c 9890 cb->nlh->nlmsg_seq, NLM_F_MULTI,
11f78ac3 9891 wdev->netdev, radio_stats, &survey) < 0)
61fa713c
HS
9892 goto out;
9893 survey_idx++;
9894 }
9895
9896 out:
97990a06 9897 cb->args[2] = survey_idx;
61fa713c
HS
9898 res = skb->len;
9899 out_err:
50508d94 9900 kfree(attrbuf);
a05829a7 9901 wiphy_unlock(&rdev->wiphy);
61fa713c
HS
9902 return res;
9903}
9904
b23aa676
SO
9905static bool nl80211_valid_wpa_versions(u32 wpa_versions)
9906{
9907 return !(wpa_versions & ~(NL80211_WPA_VERSION_1 |
cc3e14c2
CHH
9908 NL80211_WPA_VERSION_2 |
9909 NL80211_WPA_VERSION_3));
b23aa676
SO
9910}
9911
636a5d36
JM
9912static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
9913{
4c476991
JB
9914 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9915 struct net_device *dev = info->user_ptr[1];
19957bb3 9916 struct ieee80211_channel *chan;
11b6b5a4
JM
9917 const u8 *bssid, *ssid, *ie = NULL, *auth_data = NULL;
9918 int err, ssid_len, ie_len = 0, auth_data_len = 0;
19957bb3 9919 enum nl80211_auth_type auth_type;
fffd0934 9920 struct key_parse key;
d5cdfacb 9921 bool local_state_change;
942ba88b 9922 u32 freq;
636a5d36 9923
f4a11bb0
JB
9924 if (!info->attrs[NL80211_ATTR_MAC])
9925 return -EINVAL;
9926
1778092e
JM
9927 if (!info->attrs[NL80211_ATTR_AUTH_TYPE])
9928 return -EINVAL;
9929
19957bb3
JB
9930 if (!info->attrs[NL80211_ATTR_SSID])
9931 return -EINVAL;
9932
9933 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
9934 return -EINVAL;
9935
fffd0934
JB
9936 err = nl80211_parse_key(info, &key);
9937 if (err)
9938 return err;
9939
9940 if (key.idx >= 0) {
e31b8213
JB
9941 if (key.type != -1 && key.type != NL80211_KEYTYPE_GROUP)
9942 return -EINVAL;
fffd0934
JB
9943 if (!key.p.key || !key.p.key_len)
9944 return -EINVAL;
9945 if ((key.p.cipher != WLAN_CIPHER_SUITE_WEP40 ||
9946 key.p.key_len != WLAN_KEY_LEN_WEP40) &&
9947 (key.p.cipher != WLAN_CIPHER_SUITE_WEP104 ||
9948 key.p.key_len != WLAN_KEY_LEN_WEP104))
9949 return -EINVAL;
b6b5555b 9950 if (key.idx > 3)
fffd0934
JB
9951 return -EINVAL;
9952 } else {
9953 key.p.key_len = 0;
9954 key.p.key = NULL;
9955 }
9956
afea0b7a
JB
9957 if (key.idx >= 0) {
9958 int i;
9959 bool ok = false;
7a087e74 9960
afea0b7a
JB
9961 for (i = 0; i < rdev->wiphy.n_cipher_suites; i++) {
9962 if (key.p.cipher == rdev->wiphy.cipher_suites[i]) {
9963 ok = true;
9964 break;
9965 }
9966 }
4c476991
JB
9967 if (!ok)
9968 return -EINVAL;
afea0b7a
JB
9969 }
9970
4c476991
JB
9971 if (!rdev->ops->auth)
9972 return -EOPNOTSUPP;
636a5d36 9973
074ac8df 9974 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
9975 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
9976 return -EOPNOTSUPP;
eec60b03 9977
19957bb3 9978 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
942ba88b
TP
9979 freq = MHZ_TO_KHZ(nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
9980 if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
9981 freq +=
9982 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
9983
9984 chan = nl80211_get_valid_chan(&rdev->wiphy, freq);
664834de 9985 if (!chan)
4c476991 9986 return -EINVAL;
636a5d36 9987
19957bb3
JB
9988 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
9989 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
636a5d36
JM
9990
9991 if (info->attrs[NL80211_ATTR_IE]) {
19957bb3
JB
9992 ie = nla_data(info->attrs[NL80211_ATTR_IE]);
9993 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
9994 }
9995
19957bb3 9996 auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
e39e5b5e 9997 if (!nl80211_valid_auth_type(rdev, auth_type, NL80211_CMD_AUTHENTICATE))
4c476991 9998 return -EINVAL;
636a5d36 9999
63181060
JM
10000 if ((auth_type == NL80211_AUTHTYPE_SAE ||
10001 auth_type == NL80211_AUTHTYPE_FILS_SK ||
10002 auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
10003 auth_type == NL80211_AUTHTYPE_FILS_PK) &&
11b6b5a4 10004 !info->attrs[NL80211_ATTR_AUTH_DATA])
e39e5b5e
JM
10005 return -EINVAL;
10006
11b6b5a4 10007 if (info->attrs[NL80211_ATTR_AUTH_DATA]) {
63181060
JM
10008 if (auth_type != NL80211_AUTHTYPE_SAE &&
10009 auth_type != NL80211_AUTHTYPE_FILS_SK &&
10010 auth_type != NL80211_AUTHTYPE_FILS_SK_PFS &&
10011 auth_type != NL80211_AUTHTYPE_FILS_PK)
e39e5b5e 10012 return -EINVAL;
11b6b5a4
JM
10013 auth_data = nla_data(info->attrs[NL80211_ATTR_AUTH_DATA]);
10014 auth_data_len = nla_len(info->attrs[NL80211_ATTR_AUTH_DATA]);
e39e5b5e
JM
10015 }
10016
d5cdfacb
JM
10017 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
10018
95de817b
JB
10019 /*
10020 * Since we no longer track auth state, ignore
10021 * requests to only change local state.
10022 */
10023 if (local_state_change)
10024 return 0;
10025
91bf9b26
JB
10026 wdev_lock(dev->ieee80211_ptr);
10027 err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
10028 ssid, ssid_len, ie, ie_len,
10029 key.p.key, key.p.key_len, key.idx,
11b6b5a4 10030 auth_data, auth_data_len);
91bf9b26
JB
10031 wdev_unlock(dev->ieee80211_ptr);
10032 return err;
636a5d36
JM
10033}
10034
64bf3d4b
DK
10035static int validate_pae_over_nl80211(struct cfg80211_registered_device *rdev,
10036 struct genl_info *info)
10037{
10038 if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
10039 GENL_SET_ERR_MSG(info, "SOCKET_OWNER not set");
10040 return -EINVAL;
10041 }
10042
10043 if (!rdev->ops->tx_control_port ||
10044 !wiphy_ext_feature_isset(&rdev->wiphy,
10045 NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211))
10046 return -EOPNOTSUPP;
10047
10048 return 0;
10049}
10050
c0692b8f
JB
10051static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
10052 struct genl_info *info,
3dc27d25
JB
10053 struct cfg80211_crypto_settings *settings,
10054 int cipher_limit)
b23aa676 10055{
c0b2bbd8
JB
10056 memset(settings, 0, sizeof(*settings));
10057
b23aa676
SO
10058 settings->control_port = info->attrs[NL80211_ATTR_CONTROL_PORT];
10059
c0692b8f
JB
10060 if (info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) {
10061 u16 proto;
7a087e74 10062
c0692b8f
JB
10063 proto = nla_get_u16(
10064 info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]);
10065 settings->control_port_ethertype = cpu_to_be16(proto);
10066 if (!(rdev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) &&
10067 proto != ETH_P_PAE)
10068 return -EINVAL;
10069 if (info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT])
10070 settings->control_port_no_encrypt = true;
10071 } else
10072 settings->control_port_ethertype = cpu_to_be16(ETH_P_PAE);
10073
64bf3d4b
DK
10074 if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) {
10075 int r = validate_pae_over_nl80211(rdev, info);
10076
10077 if (r < 0)
10078 return r;
10079
10080 settings->control_port_over_nl80211 = true;
7f3f96ce
MT
10081
10082 if (info->attrs[NL80211_ATTR_CONTROL_PORT_NO_PREAUTH])
10083 settings->control_port_no_preauth = true;
64bf3d4b
DK
10084 }
10085
b23aa676
SO
10086 if (info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]) {
10087 void *data;
10088 int len, i;
10089
10090 data = nla_data(info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]);
10091 len = nla_len(info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]);
10092 settings->n_ciphers_pairwise = len / sizeof(u32);
10093
10094 if (len % sizeof(u32))
10095 return -EINVAL;
10096
3dc27d25 10097 if (settings->n_ciphers_pairwise > cipher_limit)
b23aa676
SO
10098 return -EINVAL;
10099
10100 memcpy(settings->ciphers_pairwise, data, len);
10101
10102 for (i = 0; i < settings->n_ciphers_pairwise; i++)
38ba3c57
JM
10103 if (!cfg80211_supported_cipher_suite(
10104 &rdev->wiphy,
b23aa676
SO
10105 settings->ciphers_pairwise[i]))
10106 return -EINVAL;
10107 }
10108
10109 if (info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]) {
10110 settings->cipher_group =
10111 nla_get_u32(info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]);
38ba3c57
JM
10112 if (!cfg80211_supported_cipher_suite(&rdev->wiphy,
10113 settings->cipher_group))
b23aa676
SO
10114 return -EINVAL;
10115 }
10116
10117 if (info->attrs[NL80211_ATTR_WPA_VERSIONS]) {
10118 settings->wpa_versions =
10119 nla_get_u32(info->attrs[NL80211_ATTR_WPA_VERSIONS]);
10120 if (!nl80211_valid_wpa_versions(settings->wpa_versions))
10121 return -EINVAL;
10122 }
10123
10124 if (info->attrs[NL80211_ATTR_AKM_SUITES]) {
10125 void *data;
6d30240e 10126 int len;
b23aa676
SO
10127
10128 data = nla_data(info->attrs[NL80211_ATTR_AKM_SUITES]);
10129 len = nla_len(info->attrs[NL80211_ATTR_AKM_SUITES]);
10130 settings->n_akm_suites = len / sizeof(u32);
10131
10132 if (len % sizeof(u32))
10133 return -EINVAL;
10134
1b9ca027
JM
10135 if (settings->n_akm_suites > NL80211_MAX_NR_AKM_SUITES)
10136 return -EINVAL;
10137
b23aa676 10138 memcpy(settings->akm_suites, data, len);
b23aa676
SO
10139 }
10140
91b5ab62
EP
10141 if (info->attrs[NL80211_ATTR_PMK]) {
10142 if (nla_len(info->attrs[NL80211_ATTR_PMK]) != WLAN_PMK_LEN)
10143 return -EINVAL;
10144 if (!wiphy_ext_feature_isset(&rdev->wiphy,
f9662274
CHH
10145 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK) &&
10146 !wiphy_ext_feature_isset(&rdev->wiphy,
10147 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK))
91b5ab62
EP
10148 return -EINVAL;
10149 settings->psk = nla_data(info->attrs[NL80211_ATTR_PMK]);
10150 }
10151
26f7044e
CHH
10152 if (info->attrs[NL80211_ATTR_SAE_PASSWORD]) {
10153 if (!wiphy_ext_feature_isset(&rdev->wiphy,
2831a631
CHH
10154 NL80211_EXT_FEATURE_SAE_OFFLOAD) &&
10155 !wiphy_ext_feature_isset(&rdev->wiphy,
10156 NL80211_EXT_FEATURE_SAE_OFFLOAD_AP))
26f7044e
CHH
10157 return -EINVAL;
10158 settings->sae_pwd =
10159 nla_data(info->attrs[NL80211_ATTR_SAE_PASSWORD]);
10160 settings->sae_pwd_len =
10161 nla_len(info->attrs[NL80211_ATTR_SAE_PASSWORD]);
10162 }
10163
9f0ffa41
RD
10164 if (info->attrs[NL80211_ATTR_SAE_PWE])
10165 settings->sae_pwe =
10166 nla_get_u8(info->attrs[NL80211_ATTR_SAE_PWE]);
10167 else
10168 settings->sae_pwe = NL80211_SAE_PWE_UNSPECIFIED;
10169
b23aa676
SO
10170 return 0;
10171}
10172
636a5d36
JM
10173static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
10174{
4c476991
JB
10175 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10176 struct net_device *dev = info->user_ptr[1];
f444de05 10177 struct ieee80211_channel *chan;
f62fab73
JB
10178 struct cfg80211_assoc_request req = {};
10179 const u8 *bssid, *ssid;
10180 int err, ssid_len = 0;
942ba88b 10181 u32 freq;
636a5d36 10182
bad29297
AZ
10183 if (dev->ieee80211_ptr->conn_owner_nlportid &&
10184 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
10185 return -EPERM;
10186
f4a11bb0 10187 if (!info->attrs[NL80211_ATTR_MAC] ||
19957bb3
JB
10188 !info->attrs[NL80211_ATTR_SSID] ||
10189 !info->attrs[NL80211_ATTR_WIPHY_FREQ])
f4a11bb0
JB
10190 return -EINVAL;
10191
4c476991
JB
10192 if (!rdev->ops->assoc)
10193 return -EOPNOTSUPP;
636a5d36 10194
074ac8df 10195 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
10196 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
10197 return -EOPNOTSUPP;
eec60b03 10198
19957bb3 10199 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
636a5d36 10200
942ba88b
TP
10201 freq = MHZ_TO_KHZ(nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
10202 if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
10203 freq +=
10204 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
10205 chan = nl80211_get_valid_chan(&rdev->wiphy, freq);
664834de 10206 if (!chan)
4c476991 10207 return -EINVAL;
636a5d36 10208
19957bb3
JB
10209 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
10210 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
636a5d36
JM
10211
10212 if (info->attrs[NL80211_ATTR_IE]) {
f62fab73
JB
10213 req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
10214 req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
10215 }
10216
dc6382ce 10217 if (info->attrs[NL80211_ATTR_USE_MFP]) {
4f5dadce 10218 enum nl80211_mfp mfp =
dc6382ce 10219 nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
4f5dadce 10220 if (mfp == NL80211_MFP_REQUIRED)
f62fab73 10221 req.use_mfp = true;
4c476991
JB
10222 else if (mfp != NL80211_MFP_NO)
10223 return -EINVAL;
dc6382ce
JM
10224 }
10225
3e5d7649 10226 if (info->attrs[NL80211_ATTR_PREV_BSSID])
f62fab73 10227 req.prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
3e5d7649 10228
7e7c8926 10229 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
f62fab73 10230 req.flags |= ASSOC_REQ_DISABLE_HT;
7e7c8926
BG
10231
10232 if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
f62fab73
JB
10233 memcpy(&req.ht_capa_mask,
10234 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
10235 sizeof(req.ht_capa_mask));
7e7c8926
BG
10236
10237 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
f62fab73 10238 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
7e7c8926 10239 return -EINVAL;
f62fab73
JB
10240 memcpy(&req.ht_capa,
10241 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
10242 sizeof(req.ht_capa));
7e7c8926
BG
10243 }
10244
ee2aca34 10245 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT]))
f62fab73 10246 req.flags |= ASSOC_REQ_DISABLE_VHT;
ee2aca34 10247
b6db0f89
BG
10248 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HE]))
10249 req.flags |= ASSOC_REQ_DISABLE_HE;
10250
ee2aca34 10251 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
f62fab73
JB
10252 memcpy(&req.vht_capa_mask,
10253 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
10254 sizeof(req.vht_capa_mask));
ee2aca34
JB
10255
10256 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) {
f62fab73 10257 if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
ee2aca34 10258 return -EINVAL;
f62fab73
JB
10259 memcpy(&req.vht_capa,
10260 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]),
10261 sizeof(req.vht_capa));
ee2aca34
JB
10262 }
10263
bab5ab7d 10264 if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
0c9ca11b
BL
10265 if (!((rdev->wiphy.features &
10266 NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) &&
10267 (rdev->wiphy.features & NL80211_FEATURE_QUIET)) &&
10268 !wiphy_ext_feature_isset(&rdev->wiphy,
10269 NL80211_EXT_FEATURE_RRM))
bab5ab7d
AK
10270 return -EINVAL;
10271 req.flags |= ASSOC_REQ_USE_RRM;
10272 }
10273
348bd456
JM
10274 if (info->attrs[NL80211_ATTR_FILS_KEK]) {
10275 req.fils_kek = nla_data(info->attrs[NL80211_ATTR_FILS_KEK]);
10276 req.fils_kek_len = nla_len(info->attrs[NL80211_ATTR_FILS_KEK]);
10277 if (!info->attrs[NL80211_ATTR_FILS_NONCES])
10278 return -EINVAL;
10279 req.fils_nonces =
10280 nla_data(info->attrs[NL80211_ATTR_FILS_NONCES]);
10281 }
10282
d2b7588a
TP
10283 if (info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK]) {
10284 if (!info->attrs[NL80211_ATTR_S1G_CAPABILITY])
10285 return -EINVAL;
10286 memcpy(&req.s1g_capa_mask,
10287 nla_data(info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK]),
10288 sizeof(req.s1g_capa_mask));
10289 }
10290
10291 if (info->attrs[NL80211_ATTR_S1G_CAPABILITY]) {
10292 if (!info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK])
10293 return -EINVAL;
10294 memcpy(&req.s1g_capa,
10295 nla_data(info->attrs[NL80211_ATTR_S1G_CAPABILITY]),
10296 sizeof(req.s1g_capa));
10297 }
10298
f62fab73 10299 err = nl80211_crypto_settings(rdev, info, &req.crypto, 1);
91bf9b26
JB
10300 if (!err) {
10301 wdev_lock(dev->ieee80211_ptr);
bd2522b1 10302
f62fab73
JB
10303 err = cfg80211_mlme_assoc(rdev, dev, chan, bssid,
10304 ssid, ssid_len, &req);
bd2522b1
AZ
10305
10306 if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
10307 dev->ieee80211_ptr->conn_owner_nlportid =
10308 info->snd_portid;
10309 memcpy(dev->ieee80211_ptr->disconnect_bssid,
10310 bssid, ETH_ALEN);
10311 }
10312
91bf9b26
JB
10313 wdev_unlock(dev->ieee80211_ptr);
10314 }
636a5d36 10315
636a5d36
JM
10316 return err;
10317}
10318
10319static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
10320{
4c476991
JB
10321 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10322 struct net_device *dev = info->user_ptr[1];
19957bb3 10323 const u8 *ie = NULL, *bssid;
91bf9b26 10324 int ie_len = 0, err;
19957bb3 10325 u16 reason_code;
d5cdfacb 10326 bool local_state_change;
636a5d36 10327
bad29297
AZ
10328 if (dev->ieee80211_ptr->conn_owner_nlportid &&
10329 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
10330 return -EPERM;
10331
f4a11bb0
JB
10332 if (!info->attrs[NL80211_ATTR_MAC])
10333 return -EINVAL;
10334
10335 if (!info->attrs[NL80211_ATTR_REASON_CODE])
10336 return -EINVAL;
10337
4c476991
JB
10338 if (!rdev->ops->deauth)
10339 return -EOPNOTSUPP;
636a5d36 10340
074ac8df 10341 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
10342 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
10343 return -EOPNOTSUPP;
eec60b03 10344
19957bb3 10345 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
636a5d36 10346
19957bb3
JB
10347 reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
10348 if (reason_code == 0) {
f4a11bb0 10349 /* Reason Code 0 is reserved */
4c476991 10350 return -EINVAL;
255e737e 10351 }
636a5d36
JM
10352
10353 if (info->attrs[NL80211_ATTR_IE]) {
19957bb3
JB
10354 ie = nla_data(info->attrs[NL80211_ATTR_IE]);
10355 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
10356 }
10357
d5cdfacb
JM
10358 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
10359
91bf9b26
JB
10360 wdev_lock(dev->ieee80211_ptr);
10361 err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code,
10362 local_state_change);
10363 wdev_unlock(dev->ieee80211_ptr);
10364 return err;
636a5d36
JM
10365}
10366
10367static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
10368{
4c476991
JB
10369 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10370 struct net_device *dev = info->user_ptr[1];
19957bb3 10371 const u8 *ie = NULL, *bssid;
91bf9b26 10372 int ie_len = 0, err;
19957bb3 10373 u16 reason_code;
d5cdfacb 10374 bool local_state_change;
636a5d36 10375
bad29297
AZ
10376 if (dev->ieee80211_ptr->conn_owner_nlportid &&
10377 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
10378 return -EPERM;
10379
f4a11bb0
JB
10380 if (!info->attrs[NL80211_ATTR_MAC])
10381 return -EINVAL;
10382
10383 if (!info->attrs[NL80211_ATTR_REASON_CODE])
10384 return -EINVAL;
10385
4c476991
JB
10386 if (!rdev->ops->disassoc)
10387 return -EOPNOTSUPP;
636a5d36 10388
074ac8df 10389 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
10390 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
10391 return -EOPNOTSUPP;
eec60b03 10392
19957bb3 10393 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
636a5d36 10394
19957bb3
JB
10395 reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
10396 if (reason_code == 0) {
f4a11bb0 10397 /* Reason Code 0 is reserved */
4c476991 10398 return -EINVAL;
255e737e 10399 }
636a5d36
JM
10400
10401 if (info->attrs[NL80211_ATTR_IE]) {
19957bb3
JB
10402 ie = nla_data(info->attrs[NL80211_ATTR_IE]);
10403 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
10404 }
10405
d5cdfacb
JM
10406 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
10407
91bf9b26
JB
10408 wdev_lock(dev->ieee80211_ptr);
10409 err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code,
10410 local_state_change);
10411 wdev_unlock(dev->ieee80211_ptr);
10412 return err;
636a5d36
JM
10413}
10414
dd5b4cc7
FF
10415static bool
10416nl80211_parse_mcast_rate(struct cfg80211_registered_device *rdev,
57fbcce3 10417 int mcast_rate[NUM_NL80211_BANDS],
dd5b4cc7
FF
10418 int rateval)
10419{
10420 struct wiphy *wiphy = &rdev->wiphy;
10421 bool found = false;
10422 int band, i;
10423
57fbcce3 10424 for (band = 0; band < NUM_NL80211_BANDS; band++) {
dd5b4cc7
FF
10425 struct ieee80211_supported_band *sband;
10426
10427 sband = wiphy->bands[band];
10428 if (!sband)
10429 continue;
10430
10431 for (i = 0; i < sband->n_bitrates; i++) {
10432 if (sband->bitrates[i].bitrate == rateval) {
10433 mcast_rate[band] = i + 1;
10434 found = true;
10435 break;
10436 }
10437 }
10438 }
10439
10440 return found;
10441}
10442
04a773ad
JB
10443static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
10444{
4c476991
JB
10445 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10446 struct net_device *dev = info->user_ptr[1];
04a773ad
JB
10447 struct cfg80211_ibss_params ibss;
10448 struct wiphy *wiphy;
fffd0934 10449 struct cfg80211_cached_keys *connkeys = NULL;
04a773ad
JB
10450 int err;
10451
8e30bc55
JB
10452 memset(&ibss, 0, sizeof(ibss));
10453
683b6d3b 10454 if (!info->attrs[NL80211_ATTR_SSID] ||
04a773ad
JB
10455 !nla_len(info->attrs[NL80211_ATTR_SSID]))
10456 return -EINVAL;
10457
8e30bc55
JB
10458 ibss.beacon_interval = 100;
10459
12d20fc9 10460 if (info->attrs[NL80211_ATTR_BEACON_INTERVAL])
8e30bc55
JB
10461 ibss.beacon_interval =
10462 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
12d20fc9 10463
0c317a02
PK
10464 err = cfg80211_validate_beacon_int(rdev, NL80211_IFTYPE_ADHOC,
10465 ibss.beacon_interval);
12d20fc9
PK
10466 if (err)
10467 return err;
8e30bc55 10468
4c476991
JB
10469 if (!rdev->ops->join_ibss)
10470 return -EOPNOTSUPP;
04a773ad 10471
4c476991
JB
10472 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
10473 return -EOPNOTSUPP;
04a773ad 10474
79c97e97 10475 wiphy = &rdev->wiphy;
04a773ad 10476
39193498 10477 if (info->attrs[NL80211_ATTR_MAC]) {
04a773ad 10478 ibss.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
39193498
JB
10479
10480 if (!is_valid_ether_addr(ibss.bssid))
10481 return -EINVAL;
10482 }
04a773ad
JB
10483 ibss.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
10484 ibss.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
10485
10486 if (info->attrs[NL80211_ATTR_IE]) {
10487 ibss.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
10488 ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
10489 }
10490
683b6d3b
JB
10491 err = nl80211_parse_chandef(rdev, info, &ibss.chandef);
10492 if (err)
10493 return err;
04a773ad 10494
174e0cd2
IP
10495 if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef,
10496 NL80211_IFTYPE_ADHOC))
54858ee5
AS
10497 return -EINVAL;
10498
2f301ab2 10499 switch (ibss.chandef.width) {
bf372645
SW
10500 case NL80211_CHAN_WIDTH_5:
10501 case NL80211_CHAN_WIDTH_10:
2f301ab2
SW
10502 case NL80211_CHAN_WIDTH_20_NOHT:
10503 break;
10504 case NL80211_CHAN_WIDTH_20:
10505 case NL80211_CHAN_WIDTH_40:
ffc11991
JD
10506 if (!(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS))
10507 return -EINVAL;
10508 break;
10509 case NL80211_CHAN_WIDTH_80:
10510 case NL80211_CHAN_WIDTH_80P80:
10511 case NL80211_CHAN_WIDTH_160:
10512 if (!(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS))
10513 return -EINVAL;
10514 if (!wiphy_ext_feature_isset(&rdev->wiphy,
10515 NL80211_EXT_FEATURE_VHT_IBSS))
10516 return -EINVAL;
10517 break;
2f301ab2 10518 default:
c04d6150 10519 return -EINVAL;
2f301ab2 10520 }
db9c64cf 10521
04a773ad 10522 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
fffd0934
JB
10523 ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
10524
fbd2c8dc
TP
10525 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
10526 u8 *rates =
10527 nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
10528 int n_rates =
10529 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
10530 struct ieee80211_supported_band *sband =
683b6d3b 10531 wiphy->bands[ibss.chandef.chan->band];
fbd2c8dc 10532
34850ab2
JB
10533 err = ieee80211_get_ratemask(sband, rates, n_rates,
10534 &ibss.basic_rates);
10535 if (err)
10536 return err;
fbd2c8dc 10537 }
dd5b4cc7 10538
803768f5
SW
10539 if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
10540 memcpy(&ibss.ht_capa_mask,
10541 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
10542 sizeof(ibss.ht_capa_mask));
10543
10544 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
10545 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
10546 return -EINVAL;
10547 memcpy(&ibss.ht_capa,
10548 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
10549 sizeof(ibss.ht_capa));
10550 }
10551
dd5b4cc7
FF
10552 if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
10553 !nl80211_parse_mcast_rate(rdev, ibss.mcast_rate,
10554 nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE])))
10555 return -EINVAL;
fbd2c8dc 10556
4c476991 10557 if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
de7044ee
SM
10558 bool no_ht = false;
10559
768075eb 10560 connkeys = nl80211_parse_connkeys(rdev, info, &no_ht);
4c476991
JB
10561 if (IS_ERR(connkeys))
10562 return PTR_ERR(connkeys);
de7044ee 10563
3d9d1d66
JB
10564 if ((ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) &&
10565 no_ht) {
453431a5 10566 kfree_sensitive(connkeys);
de7044ee
SM
10567 return -EINVAL;
10568 }
4c476991 10569 }
04a773ad 10570
267335d6
AQ
10571 ibss.control_port =
10572 nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT]);
10573
c3bfe1f6
DK
10574 if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) {
10575 int r = validate_pae_over_nl80211(rdev, info);
10576
d350a0f4 10577 if (r < 0) {
453431a5 10578 kfree_sensitive(connkeys);
c3bfe1f6 10579 return r;
d350a0f4 10580 }
c3bfe1f6
DK
10581
10582 ibss.control_port_over_nl80211 = true;
10583 }
10584
5336fa88
SW
10585 ibss.userspace_handles_dfs =
10586 nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]);
10587
f8d16d3e
DK
10588 wdev_lock(dev->ieee80211_ptr);
10589 err = __cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
fffd0934 10590 if (err)
453431a5 10591 kfree_sensitive(connkeys);
f8d16d3e
DK
10592 else if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
10593 dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
10594 wdev_unlock(dev->ieee80211_ptr);
10595
04a773ad
JB
10596 return err;
10597}
10598
10599static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info)
10600{
4c476991
JB
10601 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10602 struct net_device *dev = info->user_ptr[1];
04a773ad 10603
4c476991
JB
10604 if (!rdev->ops->leave_ibss)
10605 return -EOPNOTSUPP;
04a773ad 10606
4c476991
JB
10607 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
10608 return -EOPNOTSUPP;
04a773ad 10609
4c476991 10610 return cfg80211_leave_ibss(rdev, dev, false);
04a773ad
JB
10611}
10612
f4e583c8
AQ
10613static int nl80211_set_mcast_rate(struct sk_buff *skb, struct genl_info *info)
10614{
10615 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10616 struct net_device *dev = info->user_ptr[1];
57fbcce3 10617 int mcast_rate[NUM_NL80211_BANDS];
f4e583c8
AQ
10618 u32 nla_rate;
10619 int err;
10620
10621 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
876dc930
BVB
10622 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
10623 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_OCB)
f4e583c8
AQ
10624 return -EOPNOTSUPP;
10625
10626 if (!rdev->ops->set_mcast_rate)
10627 return -EOPNOTSUPP;
10628
10629 memset(mcast_rate, 0, sizeof(mcast_rate));
10630
10631 if (!info->attrs[NL80211_ATTR_MCAST_RATE])
10632 return -EINVAL;
10633
10634 nla_rate = nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE]);
10635 if (!nl80211_parse_mcast_rate(rdev, mcast_rate, nla_rate))
10636 return -EINVAL;
10637
a1056b1b 10638 err = rdev_set_mcast_rate(rdev, dev, mcast_rate);
f4e583c8
AQ
10639
10640 return err;
10641}
10642
ad7e718c
JB
10643static struct sk_buff *
10644__cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev,
6c09e791
AK
10645 struct wireless_dev *wdev, int approxlen,
10646 u32 portid, u32 seq, enum nl80211_commands cmd,
567ffc35
JB
10647 enum nl80211_attrs attr,
10648 const struct nl80211_vendor_cmd_info *info,
10649 gfp_t gfp)
ad7e718c
JB
10650{
10651 struct sk_buff *skb;
10652 void *hdr;
10653 struct nlattr *data;
10654
10655 skb = nlmsg_new(approxlen + 100, gfp);
10656 if (!skb)
10657 return NULL;
10658
10659 hdr = nl80211hdr_put(skb, portid, seq, 0, cmd);
10660 if (!hdr) {
10661 kfree_skb(skb);
10662 return NULL;
10663 }
10664
10665 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
10666 goto nla_put_failure;
567ffc35
JB
10667
10668 if (info) {
10669 if (nla_put_u32(skb, NL80211_ATTR_VENDOR_ID,
10670 info->vendor_id))
10671 goto nla_put_failure;
10672 if (nla_put_u32(skb, NL80211_ATTR_VENDOR_SUBCMD,
10673 info->subcmd))
10674 goto nla_put_failure;
10675 }
10676
6c09e791 10677 if (wdev) {
2dad624e
ND
10678 if (nla_put_u64_64bit(skb, NL80211_ATTR_WDEV,
10679 wdev_id(wdev), NL80211_ATTR_PAD))
6c09e791
AK
10680 goto nla_put_failure;
10681 if (wdev->netdev &&
10682 nla_put_u32(skb, NL80211_ATTR_IFINDEX,
10683 wdev->netdev->ifindex))
10684 goto nla_put_failure;
10685 }
10686
ae0be8de 10687 data = nla_nest_start_noflag(skb, attr);
76e1fb4b
JB
10688 if (!data)
10689 goto nla_put_failure;
ad7e718c
JB
10690
10691 ((void **)skb->cb)[0] = rdev;
10692 ((void **)skb->cb)[1] = hdr;
10693 ((void **)skb->cb)[2] = data;
10694
10695 return skb;
10696
10697 nla_put_failure:
10698 kfree_skb(skb);
10699 return NULL;
10700}
f4e583c8 10701
e03ad6ea 10702struct sk_buff *__cfg80211_alloc_event_skb(struct wiphy *wiphy,
6c09e791 10703 struct wireless_dev *wdev,
e03ad6ea
JB
10704 enum nl80211_commands cmd,
10705 enum nl80211_attrs attr,
55c1fdf0 10706 unsigned int portid,
e03ad6ea
JB
10707 int vendor_event_idx,
10708 int approxlen, gfp_t gfp)
10709{
f26cbf40 10710 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
e03ad6ea
JB
10711 const struct nl80211_vendor_cmd_info *info;
10712
10713 switch (cmd) {
10714 case NL80211_CMD_TESTMODE:
10715 if (WARN_ON(vendor_event_idx != -1))
10716 return NULL;
10717 info = NULL;
10718 break;
10719 case NL80211_CMD_VENDOR:
10720 if (WARN_ON(vendor_event_idx < 0 ||
10721 vendor_event_idx >= wiphy->n_vendor_events))
10722 return NULL;
10723 info = &wiphy->vendor_events[vendor_event_idx];
10724 break;
10725 default:
10726 WARN_ON(1);
10727 return NULL;
10728 }
10729
55c1fdf0 10730 return __cfg80211_alloc_vendor_skb(rdev, wdev, approxlen, portid, 0,
e03ad6ea
JB
10731 cmd, attr, info, gfp);
10732}
10733EXPORT_SYMBOL(__cfg80211_alloc_event_skb);
10734
10735void __cfg80211_send_event_skb(struct sk_buff *skb, gfp_t gfp)
10736{
10737 struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
10738 void *hdr = ((void **)skb->cb)[1];
55c1fdf0 10739 struct nlmsghdr *nlhdr = nlmsg_hdr(skb);
e03ad6ea
JB
10740 struct nlattr *data = ((void **)skb->cb)[2];
10741 enum nl80211_multicast_groups mcgrp = NL80211_MCGRP_TESTMODE;
10742
bd8c78e7
JB
10743 /* clear CB data for netlink core to own from now on */
10744 memset(skb->cb, 0, sizeof(skb->cb));
10745
e03ad6ea
JB
10746 nla_nest_end(skb, data);
10747 genlmsg_end(skb, hdr);
10748
55c1fdf0
JB
10749 if (nlhdr->nlmsg_pid) {
10750 genlmsg_unicast(wiphy_net(&rdev->wiphy), skb,
10751 nlhdr->nlmsg_pid);
10752 } else {
10753 if (data->nla_type == NL80211_ATTR_VENDOR_DATA)
10754 mcgrp = NL80211_MCGRP_VENDOR;
e03ad6ea 10755
55c1fdf0
JB
10756 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
10757 skb, 0, mcgrp, gfp);
10758 }
e03ad6ea
JB
10759}
10760EXPORT_SYMBOL(__cfg80211_send_event_skb);
10761
aff89a9b 10762#ifdef CONFIG_NL80211_TESTMODE
aff89a9b
JB
10763static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
10764{
4c476991 10765 struct cfg80211_registered_device *rdev = info->user_ptr[0];
a05829a7 10766 struct wireless_dev *wdev;
aff89a9b
JB
10767 int err;
10768
a05829a7
JB
10769 lockdep_assert_held(&rdev->wiphy.mtx);
10770
10771 wdev = __cfg80211_wdev_from_attrs(rdev, genl_info_net(info),
10772 info->attrs);
10773
fc73f11f
DS
10774 if (!rdev->ops->testmode_cmd)
10775 return -EOPNOTSUPP;
10776
10777 if (IS_ERR(wdev)) {
10778 err = PTR_ERR(wdev);
10779 if (err != -EINVAL)
10780 return err;
10781 wdev = NULL;
10782 } else if (wdev->wiphy != &rdev->wiphy) {
10783 return -EINVAL;
10784 }
10785
aff89a9b
JB
10786 if (!info->attrs[NL80211_ATTR_TESTDATA])
10787 return -EINVAL;
10788
ad7e718c 10789 rdev->cur_cmd_info = info;
fc73f11f 10790 err = rdev_testmode_cmd(rdev, wdev,
aff89a9b
JB
10791 nla_data(info->attrs[NL80211_ATTR_TESTDATA]),
10792 nla_len(info->attrs[NL80211_ATTR_TESTDATA]));
ad7e718c 10793 rdev->cur_cmd_info = NULL;
aff89a9b 10794
aff89a9b
JB
10795 return err;
10796}
10797
71063f0e
WYG
10798static int nl80211_testmode_dump(struct sk_buff *skb,
10799 struct netlink_callback *cb)
10800{
00918d33 10801 struct cfg80211_registered_device *rdev;
50508d94 10802 struct nlattr **attrbuf = NULL;
71063f0e
WYG
10803 int err;
10804 long phy_idx;
10805 void *data = NULL;
10806 int data_len = 0;
10807
5fe231e8
JB
10808 rtnl_lock();
10809
71063f0e
WYG
10810 if (cb->args[0]) {
10811 /*
10812 * 0 is a valid index, but not valid for args[0],
10813 * so we need to offset by 1.
10814 */
10815 phy_idx = cb->args[0] - 1;
a4956dca
LC
10816
10817 rdev = cfg80211_rdev_by_wiphy_idx(phy_idx);
10818 if (!rdev) {
10819 err = -ENOENT;
10820 goto out_err;
10821 }
71063f0e 10822 } else {
50508d94
JB
10823 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf),
10824 GFP_KERNEL);
10825 if (!attrbuf) {
10826 err = -ENOMEM;
10827 goto out_err;
10828 }
c90c39da 10829
8cb08174
JB
10830 err = nlmsg_parse_deprecated(cb->nlh,
10831 GENL_HDRLEN + nl80211_fam.hdrsize,
10832 attrbuf, nl80211_fam.maxattr,
10833 nl80211_policy, NULL);
71063f0e 10834 if (err)
5fe231e8 10835 goto out_err;
00918d33 10836
c90c39da 10837 rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
2bd7e35d 10838 if (IS_ERR(rdev)) {
5fe231e8
JB
10839 err = PTR_ERR(rdev);
10840 goto out_err;
00918d33 10841 }
2bd7e35d 10842 phy_idx = rdev->wiphy_idx;
2bd7e35d 10843
c90c39da
JB
10844 if (attrbuf[NL80211_ATTR_TESTDATA])
10845 cb->args[1] = (long)attrbuf[NL80211_ATTR_TESTDATA];
71063f0e
WYG
10846 }
10847
10848 if (cb->args[1]) {
10849 data = nla_data((void *)cb->args[1]);
10850 data_len = nla_len((void *)cb->args[1]);
10851 }
10852
00918d33 10853 if (!rdev->ops->testmode_dump) {
71063f0e
WYG
10854 err = -EOPNOTSUPP;
10855 goto out_err;
10856 }
10857
10858 while (1) {
15e47304 10859 void *hdr = nl80211hdr_put(skb, NETLINK_CB(cb->skb).portid,
71063f0e
WYG
10860 cb->nlh->nlmsg_seq, NLM_F_MULTI,
10861 NL80211_CMD_TESTMODE);
10862 struct nlattr *tmdata;
10863
cb35fba3
DC
10864 if (!hdr)
10865 break;
10866
9360ffd1 10867 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, phy_idx)) {
71063f0e
WYG
10868 genlmsg_cancel(skb, hdr);
10869 break;
10870 }
10871
ae0be8de 10872 tmdata = nla_nest_start_noflag(skb, NL80211_ATTR_TESTDATA);
71063f0e
WYG
10873 if (!tmdata) {
10874 genlmsg_cancel(skb, hdr);
10875 break;
10876 }
e35e4d28 10877 err = rdev_testmode_dump(rdev, skb, cb, data, data_len);
71063f0e
WYG
10878 nla_nest_end(skb, tmdata);
10879
10880 if (err == -ENOBUFS || err == -ENOENT) {
10881 genlmsg_cancel(skb, hdr);
10882 break;
10883 } else if (err) {
10884 genlmsg_cancel(skb, hdr);
10885 goto out_err;
10886 }
10887
10888 genlmsg_end(skb, hdr);
10889 }
10890
10891 err = skb->len;
10892 /* see above */
10893 cb->args[0] = phy_idx + 1;
10894 out_err:
50508d94 10895 kfree(attrbuf);
5fe231e8 10896 rtnl_unlock();
71063f0e
WYG
10897 return err;
10898}
aff89a9b
JB
10899#endif
10900
b23aa676
SO
10901static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
10902{
4c476991
JB
10903 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10904 struct net_device *dev = info->user_ptr[1];
b23aa676
SO
10905 struct cfg80211_connect_params connect;
10906 struct wiphy *wiphy;
fffd0934 10907 struct cfg80211_cached_keys *connkeys = NULL;
942ba88b 10908 u32 freq = 0;
b23aa676
SO
10909 int err;
10910
10911 memset(&connect, 0, sizeof(connect));
10912
b23aa676
SO
10913 if (!info->attrs[NL80211_ATTR_SSID] ||
10914 !nla_len(info->attrs[NL80211_ATTR_SSID]))
10915 return -EINVAL;
10916
10917 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
10918 connect.auth_type =
10919 nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
e39e5b5e
JM
10920 if (!nl80211_valid_auth_type(rdev, connect.auth_type,
10921 NL80211_CMD_CONNECT))
b23aa676
SO
10922 return -EINVAL;
10923 } else
10924 connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
10925
10926 connect.privacy = info->attrs[NL80211_ATTR_PRIVACY];
10927
3a00df57
AS
10928 if (info->attrs[NL80211_ATTR_WANT_1X_4WAY_HS] &&
10929 !wiphy_ext_feature_isset(&rdev->wiphy,
10930 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
10931 return -EINVAL;
10932 connect.want_1x = info->attrs[NL80211_ATTR_WANT_1X_4WAY_HS];
10933
c0692b8f 10934 err = nl80211_crypto_settings(rdev, info, &connect.crypto,
3dc27d25 10935 NL80211_MAX_NR_CIPHER_SUITES);
b23aa676
SO
10936 if (err)
10937 return err;
b23aa676 10938
074ac8df 10939 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
10940 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
10941 return -EOPNOTSUPP;
b23aa676 10942
79c97e97 10943 wiphy = &rdev->wiphy;
b23aa676 10944
4486ea98
BS
10945 connect.bg_scan_period = -1;
10946 if (info->attrs[NL80211_ATTR_BG_SCAN_PERIOD] &&
10947 (wiphy->flags & WIPHY_FLAG_SUPPORTS_FW_ROAM)) {
10948 connect.bg_scan_period =
10949 nla_get_u16(info->attrs[NL80211_ATTR_BG_SCAN_PERIOD]);
10950 }
10951
b23aa676
SO
10952 if (info->attrs[NL80211_ATTR_MAC])
10953 connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
1df4a510
JM
10954 else if (info->attrs[NL80211_ATTR_MAC_HINT])
10955 connect.bssid_hint =
10956 nla_data(info->attrs[NL80211_ATTR_MAC_HINT]);
b23aa676
SO
10957 connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
10958 connect.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
10959
10960 if (info->attrs[NL80211_ATTR_IE]) {
10961 connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
10962 connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
10963 }
10964
cee00a95
JM
10965 if (info->attrs[NL80211_ATTR_USE_MFP]) {
10966 connect.mfp = nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
65026002
EG
10967 if (connect.mfp == NL80211_MFP_OPTIONAL &&
10968 !wiphy_ext_feature_isset(&rdev->wiphy,
10969 NL80211_EXT_FEATURE_MFP_OPTIONAL))
10970 return -EOPNOTSUPP;
cee00a95
JM
10971 } else {
10972 connect.mfp = NL80211_MFP_NO;
10973 }
10974
ba6fbacf
JM
10975 if (info->attrs[NL80211_ATTR_PREV_BSSID])
10976 connect.prev_bssid =
10977 nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
10978
942ba88b
TP
10979 if (info->attrs[NL80211_ATTR_WIPHY_FREQ])
10980 freq = MHZ_TO_KHZ(nla_get_u32(
10981 info->attrs[NL80211_ATTR_WIPHY_FREQ]));
10982 if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
10983 freq +=
10984 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
10985
10986 if (freq) {
10987 connect.channel = nl80211_get_valid_chan(wiphy, freq);
664834de 10988 if (!connect.channel)
1df4a510
JM
10989 return -EINVAL;
10990 } else if (info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]) {
942ba88b
TP
10991 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]);
10992 freq = MHZ_TO_KHZ(freq);
10993 connect.channel_hint = nl80211_get_valid_chan(wiphy, freq);
664834de 10994 if (!connect.channel_hint)
4c476991 10995 return -EINVAL;
b23aa676
SO
10996 }
10997
2a38075c
AAL
10998 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]) {
10999 connect.edmg.channels =
11000 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]);
11001
11002 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG])
11003 connect.edmg.bw_config =
11004 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]);
11005 }
11006
fffd0934 11007 if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) {
768075eb 11008 connkeys = nl80211_parse_connkeys(rdev, info, NULL);
4c476991
JB
11009 if (IS_ERR(connkeys))
11010 return PTR_ERR(connkeys);
fffd0934
JB
11011 }
11012
7e7c8926
BG
11013 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
11014 connect.flags |= ASSOC_REQ_DISABLE_HT;
11015
11016 if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
11017 memcpy(&connect.ht_capa_mask,
11018 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
11019 sizeof(connect.ht_capa_mask));
11020
11021 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
b4e4f47e 11022 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) {
453431a5 11023 kfree_sensitive(connkeys);
7e7c8926 11024 return -EINVAL;
b4e4f47e 11025 }
7e7c8926
BG
11026 memcpy(&connect.ht_capa,
11027 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
11028 sizeof(connect.ht_capa));
11029 }
11030
ee2aca34
JB
11031 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT]))
11032 connect.flags |= ASSOC_REQ_DISABLE_VHT;
11033
b6db0f89
BG
11034 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HE]))
11035 connect.flags |= ASSOC_REQ_DISABLE_HE;
11036
ee2aca34
JB
11037 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
11038 memcpy(&connect.vht_capa_mask,
11039 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
11040 sizeof(connect.vht_capa_mask));
11041
11042 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) {
11043 if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) {
453431a5 11044 kfree_sensitive(connkeys);
ee2aca34
JB
11045 return -EINVAL;
11046 }
11047 memcpy(&connect.vht_capa,
11048 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]),
11049 sizeof(connect.vht_capa));
11050 }
11051
bab5ab7d 11052 if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
0c9ca11b
BL
11053 if (!((rdev->wiphy.features &
11054 NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) &&
11055 (rdev->wiphy.features & NL80211_FEATURE_QUIET)) &&
11056 !wiphy_ext_feature_isset(&rdev->wiphy,
11057 NL80211_EXT_FEATURE_RRM)) {
453431a5 11058 kfree_sensitive(connkeys);
bab5ab7d 11059 return -EINVAL;
707554b4 11060 }
bab5ab7d
AK
11061 connect.flags |= ASSOC_REQ_USE_RRM;
11062 }
11063
34d50519 11064 connect.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
57fbcce3 11065 if (connect.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) {
453431a5 11066 kfree_sensitive(connkeys);
34d50519
LD
11067 return -EOPNOTSUPP;
11068 }
11069
38de03d2
AS
11070 if (info->attrs[NL80211_ATTR_BSS_SELECT]) {
11071 /* bss selection makes no sense if bssid is set */
11072 if (connect.bssid) {
453431a5 11073 kfree_sensitive(connkeys);
38de03d2
AS
11074 return -EINVAL;
11075 }
11076
11077 err = parse_bss_select(info->attrs[NL80211_ATTR_BSS_SELECT],
11078 wiphy, &connect.bss_select);
11079 if (err) {
453431a5 11080 kfree_sensitive(connkeys);
38de03d2
AS
11081 return err;
11082 }
11083 }
11084
a3caf744
VK
11085 if (wiphy_ext_feature_isset(&rdev->wiphy,
11086 NL80211_EXT_FEATURE_FILS_SK_OFFLOAD) &&
11087 info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] &&
11088 info->attrs[NL80211_ATTR_FILS_ERP_REALM] &&
11089 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] &&
11090 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
11091 connect.fils_erp_username =
11092 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
11093 connect.fils_erp_username_len =
11094 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
11095 connect.fils_erp_realm =
11096 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
11097 connect.fils_erp_realm_len =
11098 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
11099 connect.fils_erp_next_seq_num =
11100 nla_get_u16(
11101 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM]);
11102 connect.fils_erp_rrk =
11103 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
11104 connect.fils_erp_rrk_len =
11105 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
11106 } else if (info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] ||
11107 info->attrs[NL80211_ATTR_FILS_ERP_REALM] ||
11108 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] ||
11109 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
453431a5 11110 kfree_sensitive(connkeys);
a3caf744
VK
11111 return -EINVAL;
11112 }
11113
40cbfa90
SD
11114 if (nla_get_flag(info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])) {
11115 if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
453431a5 11116 kfree_sensitive(connkeys);
40cbfa90
SD
11117 GENL_SET_ERR_MSG(info,
11118 "external auth requires connection ownership");
11119 return -EINVAL;
11120 }
11121 connect.flags |= CONNECT_REQ_EXTERNAL_AUTH_SUPPORT;
11122 }
11123
83739b03 11124 wdev_lock(dev->ieee80211_ptr);
bd2522b1 11125
4ce2bd9c
JM
11126 err = cfg80211_connect(rdev, dev, &connect, connkeys,
11127 connect.prev_bssid);
fffd0934 11128 if (err)
453431a5 11129 kfree_sensitive(connkeys);
bd2522b1
AZ
11130
11131 if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
11132 dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
11133 if (connect.bssid)
11134 memcpy(dev->ieee80211_ptr->disconnect_bssid,
11135 connect.bssid, ETH_ALEN);
11136 else
3b1648f1 11137 eth_zero_addr(dev->ieee80211_ptr->disconnect_bssid);
bd2522b1
AZ
11138 }
11139
11140 wdev_unlock(dev->ieee80211_ptr);
11141
b23aa676
SO
11142 return err;
11143}
11144
088e8df8 11145static int nl80211_update_connect_params(struct sk_buff *skb,
11146 struct genl_info *info)
11147{
11148 struct cfg80211_connect_params connect = {};
11149 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11150 struct net_device *dev = info->user_ptr[1];
11151 struct wireless_dev *wdev = dev->ieee80211_ptr;
7f9a3e15
VK
11152 bool fils_sk_offload;
11153 u32 auth_type;
088e8df8 11154 u32 changed = 0;
11155 int ret;
11156
11157 if (!rdev->ops->update_connect_params)
11158 return -EOPNOTSUPP;
11159
11160 if (info->attrs[NL80211_ATTR_IE]) {
088e8df8 11161 connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
11162 connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
11163 changed |= UPDATE_ASSOC_IES;
11164 }
11165
7f9a3e15
VK
11166 fils_sk_offload = wiphy_ext_feature_isset(&rdev->wiphy,
11167 NL80211_EXT_FEATURE_FILS_SK_OFFLOAD);
11168
11169 /*
11170 * when driver supports fils-sk offload all attributes must be
11171 * provided. So the else covers "fils-sk-not-all" and
11172 * "no-fils-sk-any".
11173 */
11174 if (fils_sk_offload &&
11175 info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] &&
11176 info->attrs[NL80211_ATTR_FILS_ERP_REALM] &&
11177 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] &&
11178 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
11179 connect.fils_erp_username =
11180 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
11181 connect.fils_erp_username_len =
11182 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
11183 connect.fils_erp_realm =
11184 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
11185 connect.fils_erp_realm_len =
11186 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
11187 connect.fils_erp_next_seq_num =
11188 nla_get_u16(
11189 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM]);
11190 connect.fils_erp_rrk =
11191 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
11192 connect.fils_erp_rrk_len =
11193 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
11194 changed |= UPDATE_FILS_ERP_INFO;
11195 } else if (info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] ||
11196 info->attrs[NL80211_ATTR_FILS_ERP_REALM] ||
11197 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] ||
11198 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
11199 return -EINVAL;
11200 }
11201
11202 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
11203 auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
11204 if (!nl80211_valid_auth_type(rdev, auth_type,
11205 NL80211_CMD_CONNECT))
11206 return -EINVAL;
11207
11208 if (auth_type == NL80211_AUTHTYPE_FILS_SK &&
11209 fils_sk_offload && !(changed & UPDATE_FILS_ERP_INFO))
11210 return -EINVAL;
11211
11212 connect.auth_type = auth_type;
11213 changed |= UPDATE_AUTH_TYPE;
11214 }
11215
088e8df8 11216 wdev_lock(dev->ieee80211_ptr);
11217 if (!wdev->current_bss)
11218 ret = -ENOLINK;
11219 else
11220 ret = rdev_update_connect_params(rdev, dev, &connect, changed);
11221 wdev_unlock(dev->ieee80211_ptr);
11222
11223 return ret;
11224}
11225
b23aa676
SO
11226static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
11227{
4c476991
JB
11228 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11229 struct net_device *dev = info->user_ptr[1];
b23aa676 11230 u16 reason;
83739b03 11231 int ret;
b23aa676 11232
bad29297
AZ
11233 if (dev->ieee80211_ptr->conn_owner_nlportid &&
11234 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
11235 return -EPERM;
11236
b23aa676
SO
11237 if (!info->attrs[NL80211_ATTR_REASON_CODE])
11238 reason = WLAN_REASON_DEAUTH_LEAVING;
11239 else
11240 reason = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
11241
11242 if (reason == 0)
11243 return -EINVAL;
11244
074ac8df 11245 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
11246 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
11247 return -EOPNOTSUPP;
b23aa676 11248
83739b03
JB
11249 wdev_lock(dev->ieee80211_ptr);
11250 ret = cfg80211_disconnect(rdev, dev, reason, true);
11251 wdev_unlock(dev->ieee80211_ptr);
11252 return ret;
b23aa676
SO
11253}
11254
463d0183
JB
11255static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
11256{
4c476991 11257 struct cfg80211_registered_device *rdev = info->user_ptr[0];
463d0183
JB
11258 struct net *net;
11259 int err;
463d0183 11260
4b681c82
VK
11261 if (info->attrs[NL80211_ATTR_PID]) {
11262 u32 pid = nla_get_u32(info->attrs[NL80211_ATTR_PID]);
11263
11264 net = get_net_ns_by_pid(pid);
11265 } else if (info->attrs[NL80211_ATTR_NETNS_FD]) {
11266 u32 fd = nla_get_u32(info->attrs[NL80211_ATTR_NETNS_FD]);
463d0183 11267
4b681c82
VK
11268 net = get_net_ns_by_fd(fd);
11269 } else {
11270 return -EINVAL;
11271 }
463d0183 11272
4c476991
JB
11273 if (IS_ERR(net))
11274 return PTR_ERR(net);
463d0183
JB
11275
11276 err = 0;
11277
11278 /* check if anything to do */
4c476991
JB
11279 if (!net_eq(wiphy_net(&rdev->wiphy), net))
11280 err = cfg80211_switch_netns(rdev, net);
463d0183 11281
463d0183 11282 put_net(net);
463d0183
JB
11283 return err;
11284}
11285
67fbb16b
SO
11286static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info)
11287{
4c476991 11288 struct cfg80211_registered_device *rdev = info->user_ptr[0];
67fbb16b
SO
11289 int (*rdev_ops)(struct wiphy *wiphy, struct net_device *dev,
11290 struct cfg80211_pmksa *pmksa) = NULL;
4c476991 11291 struct net_device *dev = info->user_ptr[1];
67fbb16b
SO
11292 struct cfg80211_pmksa pmksa;
11293
11294 memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
11295
67fbb16b
SO
11296 if (!info->attrs[NL80211_ATTR_PMKID])
11297 return -EINVAL;
11298
67fbb16b 11299 pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
a3caf744
VK
11300
11301 if (info->attrs[NL80211_ATTR_MAC]) {
11302 pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
11303 } else if (info->attrs[NL80211_ATTR_SSID] &&
11304 info->attrs[NL80211_ATTR_FILS_CACHE_ID] &&
11305 (info->genlhdr->cmd == NL80211_CMD_DEL_PMKSA ||
11306 info->attrs[NL80211_ATTR_PMK])) {
11307 pmksa.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
11308 pmksa.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
11309 pmksa.cache_id =
11310 nla_data(info->attrs[NL80211_ATTR_FILS_CACHE_ID]);
11311 } else {
11312 return -EINVAL;
11313 }
11314 if (info->attrs[NL80211_ATTR_PMK]) {
11315 pmksa.pmk = nla_data(info->attrs[NL80211_ATTR_PMK]);
11316 pmksa.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]);
11317 }
67fbb16b 11318
7fc82af8
VJ
11319 if (info->attrs[NL80211_ATTR_PMK_LIFETIME])
11320 pmksa.pmk_lifetime =
11321 nla_get_u32(info->attrs[NL80211_ATTR_PMK_LIFETIME]);
11322
11323 if (info->attrs[NL80211_ATTR_PMK_REAUTH_THRESHOLD])
11324 pmksa.pmk_reauth_threshold =
11325 nla_get_u8(
11326 info->attrs[NL80211_ATTR_PMK_REAUTH_THRESHOLD]);
11327
074ac8df 11328 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
6c900360
LD
11329 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
11330 !(dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP &&
11331 wiphy_ext_feature_isset(&rdev->wiphy,
11332 NL80211_EXT_FEATURE_AP_PMKSA_CACHING)))
4c476991 11333 return -EOPNOTSUPP;
67fbb16b
SO
11334
11335 switch (info->genlhdr->cmd) {
11336 case NL80211_CMD_SET_PMKSA:
11337 rdev_ops = rdev->ops->set_pmksa;
11338 break;
11339 case NL80211_CMD_DEL_PMKSA:
11340 rdev_ops = rdev->ops->del_pmksa;
11341 break;
11342 default:
11343 WARN_ON(1);
11344 break;
11345 }
11346
4c476991
JB
11347 if (!rdev_ops)
11348 return -EOPNOTSUPP;
67fbb16b 11349
4c476991 11350 return rdev_ops(&rdev->wiphy, dev, &pmksa);
67fbb16b
SO
11351}
11352
11353static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info)
11354{
4c476991
JB
11355 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11356 struct net_device *dev = info->user_ptr[1];
67fbb16b 11357
074ac8df 11358 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
11359 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
11360 return -EOPNOTSUPP;
67fbb16b 11361
4c476991
JB
11362 if (!rdev->ops->flush_pmksa)
11363 return -EOPNOTSUPP;
67fbb16b 11364
e35e4d28 11365 return rdev_flush_pmksa(rdev, dev);
67fbb16b
SO
11366}
11367
109086ce
AN
11368static int nl80211_tdls_mgmt(struct sk_buff *skb, struct genl_info *info)
11369{
11370 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11371 struct net_device *dev = info->user_ptr[1];
11372 u8 action_code, dialog_token;
df942e7b 11373 u32 peer_capability = 0;
109086ce
AN
11374 u16 status_code;
11375 u8 *peer;
31fa97c5 11376 bool initiator;
109086ce
AN
11377
11378 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
11379 !rdev->ops->tdls_mgmt)
11380 return -EOPNOTSUPP;
11381
11382 if (!info->attrs[NL80211_ATTR_TDLS_ACTION] ||
11383 !info->attrs[NL80211_ATTR_STATUS_CODE] ||
11384 !info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN] ||
11385 !info->attrs[NL80211_ATTR_IE] ||
11386 !info->attrs[NL80211_ATTR_MAC])
11387 return -EINVAL;
11388
11389 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
11390 action_code = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_ACTION]);
11391 status_code = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
11392 dialog_token = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN]);
31fa97c5 11393 initiator = nla_get_flag(info->attrs[NL80211_ATTR_TDLS_INITIATOR]);
df942e7b
SDU
11394 if (info->attrs[NL80211_ATTR_TDLS_PEER_CAPABILITY])
11395 peer_capability =
11396 nla_get_u32(info->attrs[NL80211_ATTR_TDLS_PEER_CAPABILITY]);
109086ce 11397
e35e4d28 11398 return rdev_tdls_mgmt(rdev, dev, peer, action_code,
df942e7b 11399 dialog_token, status_code, peer_capability,
31fa97c5 11400 initiator,
e35e4d28
HG
11401 nla_data(info->attrs[NL80211_ATTR_IE]),
11402 nla_len(info->attrs[NL80211_ATTR_IE]));
109086ce
AN
11403}
11404
11405static int nl80211_tdls_oper(struct sk_buff *skb, struct genl_info *info)
11406{
11407 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11408 struct net_device *dev = info->user_ptr[1];
11409 enum nl80211_tdls_operation operation;
11410 u8 *peer;
11411
11412 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
11413 !rdev->ops->tdls_oper)
11414 return -EOPNOTSUPP;
11415
11416 if (!info->attrs[NL80211_ATTR_TDLS_OPERATION] ||
11417 !info->attrs[NL80211_ATTR_MAC])
11418 return -EINVAL;
11419
11420 operation = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_OPERATION]);
11421 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
11422
e35e4d28 11423 return rdev_tdls_oper(rdev, dev, peer, operation);
109086ce
AN
11424}
11425
9588bbd5
JM
11426static int nl80211_remain_on_channel(struct sk_buff *skb,
11427 struct genl_info *info)
11428{
4c476991 11429 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 11430 struct wireless_dev *wdev = info->user_ptr[1];
683b6d3b 11431 struct cfg80211_chan_def chandef;
34373d12 11432 const struct cfg80211_chan_def *compat_chandef;
9588bbd5
JM
11433 struct sk_buff *msg;
11434 void *hdr;
11435 u64 cookie;
683b6d3b 11436 u32 duration;
9588bbd5
JM
11437 int err;
11438
11439 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
11440 !info->attrs[NL80211_ATTR_DURATION])
11441 return -EINVAL;
11442
11443 duration = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
11444
ebf348fc
JB
11445 if (!rdev->ops->remain_on_channel ||
11446 !(rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL))
11447 return -EOPNOTSUPP;
11448
9588bbd5 11449 /*
ebf348fc
JB
11450 * We should be on that channel for at least a minimum amount of
11451 * time (10ms) but no longer than the driver supports.
9588bbd5 11452 */
ebf348fc 11453 if (duration < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
a293911d 11454 duration > rdev->wiphy.max_remain_on_channel_duration)
9588bbd5
JM
11455 return -EINVAL;
11456
683b6d3b
JB
11457 err = nl80211_parse_chandef(rdev, info, &chandef);
11458 if (err)
11459 return err;
9588bbd5 11460
34373d12
VT
11461 wdev_lock(wdev);
11462 if (!cfg80211_off_channel_oper_allowed(wdev) &&
11463 !cfg80211_chandef_identical(&wdev->chandef, &chandef)) {
11464 compat_chandef = cfg80211_chandef_compatible(&wdev->chandef,
11465 &chandef);
11466 if (compat_chandef != &chandef) {
11467 wdev_unlock(wdev);
11468 return -EBUSY;
11469 }
11470 }
11471 wdev_unlock(wdev);
11472
9588bbd5 11473 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
11474 if (!msg)
11475 return -ENOMEM;
9588bbd5 11476
15e47304 11477 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
9588bbd5 11478 NL80211_CMD_REMAIN_ON_CHANNEL);
cb35fba3
DC
11479 if (!hdr) {
11480 err = -ENOBUFS;
9588bbd5
JM
11481 goto free_msg;
11482 }
11483
683b6d3b
JB
11484 err = rdev_remain_on_channel(rdev, wdev, chandef.chan,
11485 duration, &cookie);
9588bbd5
JM
11486
11487 if (err)
11488 goto free_msg;
11489
2dad624e
ND
11490 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
11491 NL80211_ATTR_PAD))
9360ffd1 11492 goto nla_put_failure;
9588bbd5
JM
11493
11494 genlmsg_end(msg, hdr);
4c476991
JB
11495
11496 return genlmsg_reply(msg, info);
9588bbd5
JM
11497
11498 nla_put_failure:
11499 err = -ENOBUFS;
11500 free_msg:
11501 nlmsg_free(msg);
9588bbd5
JM
11502 return err;
11503}
11504
11505static int nl80211_cancel_remain_on_channel(struct sk_buff *skb,
11506 struct genl_info *info)
11507{
4c476991 11508 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 11509 struct wireless_dev *wdev = info->user_ptr[1];
9588bbd5 11510 u64 cookie;
9588bbd5
JM
11511
11512 if (!info->attrs[NL80211_ATTR_COOKIE])
11513 return -EINVAL;
11514
4c476991
JB
11515 if (!rdev->ops->cancel_remain_on_channel)
11516 return -EOPNOTSUPP;
9588bbd5 11517
9588bbd5
JM
11518 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
11519
e35e4d28 11520 return rdev_cancel_remain_on_channel(rdev, wdev, cookie);
9588bbd5
JM
11521}
11522
13ae75b1
JM
11523static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
11524 struct genl_info *info)
11525{
13ae75b1 11526 struct cfg80211_bitrate_mask mask;
a7c7fbff 11527 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 11528 struct net_device *dev = info->user_ptr[1];
a7c7fbff 11529 int err;
13ae75b1 11530
4c476991
JB
11531 if (!rdev->ops->set_bitrate_mask)
11532 return -EOPNOTSUPP;
13ae75b1 11533
9a5f6488 11534 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
eb89a6a6 11535 NL80211_ATTR_TX_RATES, &mask,
857b34c4 11536 dev, true);
a7c7fbff
PK
11537 if (err)
11538 return err;
13ae75b1 11539
e35e4d28 11540 return rdev_set_bitrate_mask(rdev, dev, NULL, &mask);
13ae75b1
JM
11541}
11542
2e161f78 11543static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
026331c4 11544{
4c476991 11545 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 11546 struct wireless_dev *wdev = info->user_ptr[1];
2e161f78 11547 u16 frame_type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION;
026331c4
JM
11548
11549 if (!info->attrs[NL80211_ATTR_FRAME_MATCH])
11550 return -EINVAL;
11551
2e161f78
JB
11552 if (info->attrs[NL80211_ATTR_FRAME_TYPE])
11553 frame_type = nla_get_u16(info->attrs[NL80211_ATTR_FRAME_TYPE]);
026331c4 11554
71bbc994
JB
11555 switch (wdev->iftype) {
11556 case NL80211_IFTYPE_STATION:
11557 case NL80211_IFTYPE_ADHOC:
11558 case NL80211_IFTYPE_P2P_CLIENT:
11559 case NL80211_IFTYPE_AP:
11560 case NL80211_IFTYPE_AP_VLAN:
11561 case NL80211_IFTYPE_MESH_POINT:
11562 case NL80211_IFTYPE_P2P_GO:
98104fde 11563 case NL80211_IFTYPE_P2P_DEVICE:
71bbc994 11564 break;
cb3b7d87 11565 case NL80211_IFTYPE_NAN:
71bbc994 11566 default:
4c476991 11567 return -EOPNOTSUPP;
71bbc994 11568 }
026331c4
JM
11569
11570 /* not much point in registering if we can't reply */
4c476991
JB
11571 if (!rdev->ops->mgmt_tx)
11572 return -EOPNOTSUPP;
026331c4 11573
9dba48a6
JB
11574 if (info->attrs[NL80211_ATTR_RECEIVE_MULTICAST] &&
11575 !wiphy_ext_feature_isset(&rdev->wiphy,
11576 NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS)) {
11577 GENL_SET_ERR_MSG(info,
11578 "multicast RX registrations are not supported");
11579 return -EOPNOTSUPP;
11580 }
11581
15e47304 11582 return cfg80211_mlme_register_mgmt(wdev, info->snd_portid, frame_type,
ff74c51e
IP
11583 nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]),
11584 nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]),
9dba48a6 11585 info->attrs[NL80211_ATTR_RECEIVE_MULTICAST],
ff74c51e 11586 info->extack);
026331c4
JM
11587}
11588
2e161f78 11589static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
026331c4 11590{
4c476991 11591 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 11592 struct wireless_dev *wdev = info->user_ptr[1];
683b6d3b 11593 struct cfg80211_chan_def chandef;
026331c4 11594 int err;
d64d373f 11595 void *hdr = NULL;
026331c4 11596 u64 cookie;
e247bd90 11597 struct sk_buff *msg = NULL;
b176e629
AO
11598 struct cfg80211_mgmt_tx_params params = {
11599 .dont_wait_for_ack =
11600 info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK],
11601 };
026331c4 11602
683b6d3b 11603 if (!info->attrs[NL80211_ATTR_FRAME])
026331c4
JM
11604 return -EINVAL;
11605
4c476991
JB
11606 if (!rdev->ops->mgmt_tx)
11607 return -EOPNOTSUPP;
026331c4 11608
71bbc994 11609 switch (wdev->iftype) {
ea141b75
AQ
11610 case NL80211_IFTYPE_P2P_DEVICE:
11611 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
11612 return -EINVAL;
d7832c71 11613 break;
71bbc994
JB
11614 case NL80211_IFTYPE_STATION:
11615 case NL80211_IFTYPE_ADHOC:
11616 case NL80211_IFTYPE_P2P_CLIENT:
11617 case NL80211_IFTYPE_AP:
11618 case NL80211_IFTYPE_AP_VLAN:
11619 case NL80211_IFTYPE_MESH_POINT:
11620 case NL80211_IFTYPE_P2P_GO:
11621 break;
cb3b7d87 11622 case NL80211_IFTYPE_NAN:
71bbc994 11623 default:
4c476991 11624 return -EOPNOTSUPP;
71bbc994 11625 }
026331c4 11626
f7ca38df 11627 if (info->attrs[NL80211_ATTR_DURATION]) {
7c4ef712 11628 if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
f7ca38df 11629 return -EINVAL;
b176e629 11630 params.wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
ebf348fc
JB
11631
11632 /*
11633 * We should wait on the channel for at least a minimum amount
11634 * of time (10ms) but no longer than the driver supports.
11635 */
b176e629
AO
11636 if (params.wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
11637 params.wait > rdev->wiphy.max_remain_on_channel_duration)
ebf348fc 11638 return -EINVAL;
f7ca38df
JB
11639 }
11640
b176e629 11641 params.offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK];
f7ca38df 11642
b176e629 11643 if (params.offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
7c4ef712
JB
11644 return -EINVAL;
11645
b176e629 11646 params.no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
e9f935e3 11647
ea141b75
AQ
11648 /* get the channel if any has been specified, otherwise pass NULL to
11649 * the driver. The latter will use the current one
11650 */
11651 chandef.chan = NULL;
11652 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
11653 err = nl80211_parse_chandef(rdev, info, &chandef);
11654 if (err)
11655 return err;
11656 }
11657
b176e629 11658 if (!chandef.chan && params.offchan)
ea141b75 11659 return -EINVAL;
026331c4 11660
34373d12
VT
11661 wdev_lock(wdev);
11662 if (params.offchan && !cfg80211_off_channel_oper_allowed(wdev)) {
11663 wdev_unlock(wdev);
11664 return -EBUSY;
11665 }
11666 wdev_unlock(wdev);
11667
34d22ce2
AO
11668 params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
11669 params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
11670
11671 if (info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]) {
11672 int len = nla_len(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]);
11673 int i;
11674
11675 if (len % sizeof(u16))
11676 return -EINVAL;
11677
11678 params.n_csa_offsets = len / sizeof(u16);
11679 params.csa_offsets =
11680 nla_data(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]);
11681
11682 /* check that all the offsets fit the frame */
11683 for (i = 0; i < params.n_csa_offsets; i++) {
11684 if (params.csa_offsets[i] >= params.len)
11685 return -EINVAL;
11686 }
11687 }
11688
b176e629 11689 if (!params.dont_wait_for_ack) {
e247bd90
JB
11690 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
11691 if (!msg)
11692 return -ENOMEM;
026331c4 11693
15e47304 11694 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
e247bd90 11695 NL80211_CMD_FRAME);
cb35fba3
DC
11696 if (!hdr) {
11697 err = -ENOBUFS;
e247bd90
JB
11698 goto free_msg;
11699 }
026331c4 11700 }
e247bd90 11701
b176e629
AO
11702 params.chan = chandef.chan;
11703 err = cfg80211_mlme_mgmt_tx(rdev, wdev, &params, &cookie);
026331c4
JM
11704 if (err)
11705 goto free_msg;
11706
e247bd90 11707 if (msg) {
2dad624e
ND
11708 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
11709 NL80211_ATTR_PAD))
9360ffd1 11710 goto nla_put_failure;
026331c4 11711
e247bd90
JB
11712 genlmsg_end(msg, hdr);
11713 return genlmsg_reply(msg, info);
11714 }
11715
11716 return 0;
026331c4
JM
11717
11718 nla_put_failure:
11719 err = -ENOBUFS;
11720 free_msg:
11721 nlmsg_free(msg);
026331c4
JM
11722 return err;
11723}
11724
f7ca38df
JB
11725static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *info)
11726{
11727 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 11728 struct wireless_dev *wdev = info->user_ptr[1];
f7ca38df
JB
11729 u64 cookie;
11730
11731 if (!info->attrs[NL80211_ATTR_COOKIE])
11732 return -EINVAL;
11733
11734 if (!rdev->ops->mgmt_tx_cancel_wait)
11735 return -EOPNOTSUPP;
11736
71bbc994
JB
11737 switch (wdev->iftype) {
11738 case NL80211_IFTYPE_STATION:
11739 case NL80211_IFTYPE_ADHOC:
11740 case NL80211_IFTYPE_P2P_CLIENT:
11741 case NL80211_IFTYPE_AP:
11742 case NL80211_IFTYPE_AP_VLAN:
11743 case NL80211_IFTYPE_P2P_GO:
98104fde 11744 case NL80211_IFTYPE_P2P_DEVICE:
71bbc994 11745 break;
cb3b7d87 11746 case NL80211_IFTYPE_NAN:
71bbc994 11747 default:
f7ca38df 11748 return -EOPNOTSUPP;
71bbc994 11749 }
f7ca38df
JB
11750
11751 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
11752
e35e4d28 11753 return rdev_mgmt_tx_cancel_wait(rdev, wdev, cookie);
f7ca38df
JB
11754}
11755
ffb9eb3d
KV
11756static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info)
11757{
4c476991 11758 struct cfg80211_registered_device *rdev = info->user_ptr[0];
ffb9eb3d 11759 struct wireless_dev *wdev;
4c476991 11760 struct net_device *dev = info->user_ptr[1];
ffb9eb3d
KV
11761 u8 ps_state;
11762 bool state;
11763 int err;
11764
4c476991
JB
11765 if (!info->attrs[NL80211_ATTR_PS_STATE])
11766 return -EINVAL;
ffb9eb3d
KV
11767
11768 ps_state = nla_get_u32(info->attrs[NL80211_ATTR_PS_STATE]);
11769
ffb9eb3d
KV
11770 wdev = dev->ieee80211_ptr;
11771
4c476991
JB
11772 if (!rdev->ops->set_power_mgmt)
11773 return -EOPNOTSUPP;
ffb9eb3d
KV
11774
11775 state = (ps_state == NL80211_PS_ENABLED) ? true : false;
11776
11777 if (state == wdev->ps)
4c476991 11778 return 0;
ffb9eb3d 11779
e35e4d28 11780 err = rdev_set_power_mgmt(rdev, dev, state, wdev->ps_timeout);
4c476991
JB
11781 if (!err)
11782 wdev->ps = state;
ffb9eb3d
KV
11783 return err;
11784}
11785
11786static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info)
11787{
4c476991 11788 struct cfg80211_registered_device *rdev = info->user_ptr[0];
ffb9eb3d
KV
11789 enum nl80211_ps_state ps_state;
11790 struct wireless_dev *wdev;
4c476991 11791 struct net_device *dev = info->user_ptr[1];
ffb9eb3d
KV
11792 struct sk_buff *msg;
11793 void *hdr;
11794 int err;
11795
ffb9eb3d
KV
11796 wdev = dev->ieee80211_ptr;
11797
4c476991
JB
11798 if (!rdev->ops->set_power_mgmt)
11799 return -EOPNOTSUPP;
ffb9eb3d
KV
11800
11801 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
11802 if (!msg)
11803 return -ENOMEM;
ffb9eb3d 11804
15e47304 11805 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
ffb9eb3d
KV
11806 NL80211_CMD_GET_POWER_SAVE);
11807 if (!hdr) {
4c476991 11808 err = -ENOBUFS;
ffb9eb3d
KV
11809 goto free_msg;
11810 }
11811
11812 if (wdev->ps)
11813 ps_state = NL80211_PS_ENABLED;
11814 else
11815 ps_state = NL80211_PS_DISABLED;
11816
9360ffd1
DM
11817 if (nla_put_u32(msg, NL80211_ATTR_PS_STATE, ps_state))
11818 goto nla_put_failure;
ffb9eb3d
KV
11819
11820 genlmsg_end(msg, hdr);
4c476991 11821 return genlmsg_reply(msg, info);
ffb9eb3d 11822
4c476991 11823 nla_put_failure:
ffb9eb3d 11824 err = -ENOBUFS;
4c476991 11825 free_msg:
ffb9eb3d 11826 nlmsg_free(msg);
ffb9eb3d
KV
11827 return err;
11828}
11829
94e860f1
JB
11830static const struct nla_policy
11831nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
4a4b8169 11832 [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_BINARY },
d6dc1a38
JO
11833 [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 },
11834 [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
84f10708
TP
11835 [NL80211_ATTR_CQM_TXE_RATE] = { .type = NLA_U32 },
11836 [NL80211_ATTR_CQM_TXE_PKTS] = { .type = NLA_U32 },
11837 [NL80211_ATTR_CQM_TXE_INTVL] = { .type = NLA_U32 },
bee427b8 11838 [NL80211_ATTR_CQM_RSSI_LEVEL] = { .type = NLA_S32 },
d6dc1a38
JO
11839};
11840
84f10708 11841static int nl80211_set_cqm_txe(struct genl_info *info,
d9d8b019 11842 u32 rate, u32 pkts, u32 intvl)
84f10708
TP
11843{
11844 struct cfg80211_registered_device *rdev = info->user_ptr[0];
84f10708 11845 struct net_device *dev = info->user_ptr[1];
1da5fcc8 11846 struct wireless_dev *wdev = dev->ieee80211_ptr;
84f10708 11847
d9d8b019 11848 if (rate > 100 || intvl > NL80211_CQM_TXE_MAX_INTVL)
84f10708
TP
11849 return -EINVAL;
11850
84f10708
TP
11851 if (!rdev->ops->set_cqm_txe_config)
11852 return -EOPNOTSUPP;
11853
11854 if (wdev->iftype != NL80211_IFTYPE_STATION &&
11855 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
11856 return -EOPNOTSUPP;
11857
e35e4d28 11858 return rdev_set_cqm_txe_config(rdev, dev, rate, pkts, intvl);
84f10708
TP
11859}
11860
4a4b8169
AZ
11861static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
11862 struct net_device *dev)
11863{
11864 struct wireless_dev *wdev = dev->ieee80211_ptr;
11865 s32 last, low, high;
11866 u32 hyst;
1222a160 11867 int i, n, low_index;
4a4b8169
AZ
11868 int err;
11869
11870 /* RSSI reporting disabled? */
11871 if (!wdev->cqm_config)
11872 return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0);
11873
11874 /*
11875 * Obtain current RSSI value if possible, if not and no RSSI threshold
11876 * event has been received yet, we should receive an event after a
11877 * connection is established and enough beacons received to calculate
11878 * the average.
11879 */
11880 if (!wdev->cqm_config->last_rssi_event_value && wdev->current_bss &&
11881 rdev->ops->get_station) {
73887fd9 11882 struct station_info sinfo = {};
4a4b8169
AZ
11883 u8 *mac_addr;
11884
11885 mac_addr = wdev->current_bss->pub.bssid;
11886
73887fd9
JB
11887 err = rdev_get_station(rdev, dev, mac_addr, &sinfo);
11888 if (err)
4a4b8169
AZ
11889 return err;
11890
df16737d 11891 cfg80211_sinfo_release_content(&sinfo);
397c657a 11892 if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG))
4a4b8169 11893 wdev->cqm_config->last_rssi_event_value =
73887fd9 11894 (s8) sinfo.rx_beacon_signal_avg;
4a4b8169
AZ
11895 }
11896
11897 last = wdev->cqm_config->last_rssi_event_value;
11898 hyst = wdev->cqm_config->rssi_hyst;
11899 n = wdev->cqm_config->n_rssi_thresholds;
11900
4b2c5a14
MH
11901 for (i = 0; i < n; i++) {
11902 i = array_index_nospec(i, n);
4a4b8169
AZ
11903 if (last < wdev->cqm_config->rssi_thresholds[i])
11904 break;
4b2c5a14 11905 }
4a4b8169 11906
1222a160
MH
11907 low_index = i - 1;
11908 if (low_index >= 0) {
11909 low_index = array_index_nospec(low_index, n);
11910 low = wdev->cqm_config->rssi_thresholds[low_index] - hyst;
11911 } else {
11912 low = S32_MIN;
11913 }
11914 if (i < n) {
11915 i = array_index_nospec(i, n);
11916 high = wdev->cqm_config->rssi_thresholds[i] + hyst - 1;
11917 } else {
11918 high = S32_MAX;
11919 }
4a4b8169
AZ
11920
11921 return rdev_set_cqm_rssi_range_config(rdev, dev, low, high);
11922}
11923
d6dc1a38 11924static int nl80211_set_cqm_rssi(struct genl_info *info,
4a4b8169
AZ
11925 const s32 *thresholds, int n_thresholds,
11926 u32 hysteresis)
d6dc1a38 11927{
4c476991 11928 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 11929 struct net_device *dev = info->user_ptr[1];
1da5fcc8 11930 struct wireless_dev *wdev = dev->ieee80211_ptr;
4a4b8169
AZ
11931 int i, err;
11932 s32 prev = S32_MIN;
d6dc1a38 11933
4a4b8169
AZ
11934 /* Check all values negative and sorted */
11935 for (i = 0; i < n_thresholds; i++) {
11936 if (thresholds[i] > 0 || thresholds[i] <= prev)
11937 return -EINVAL;
d6dc1a38 11938
4a4b8169
AZ
11939 prev = thresholds[i];
11940 }
d6dc1a38 11941
074ac8df 11942 if (wdev->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
11943 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
11944 return -EOPNOTSUPP;
d6dc1a38 11945
4a4b8169
AZ
11946 wdev_lock(wdev);
11947 cfg80211_cqm_config_free(wdev);
11948 wdev_unlock(wdev);
11949
11950 if (n_thresholds <= 1 && rdev->ops->set_cqm_rssi_config) {
11951 if (n_thresholds == 0 || thresholds[0] == 0) /* Disabling */
11952 return rdev_set_cqm_rssi_config(rdev, dev, 0, 0);
11953
11954 return rdev_set_cqm_rssi_config(rdev, dev,
11955 thresholds[0], hysteresis);
11956 }
11957
11958 if (!wiphy_ext_feature_isset(&rdev->wiphy,
11959 NL80211_EXT_FEATURE_CQM_RSSI_LIST))
11960 return -EOPNOTSUPP;
11961
11962 if (n_thresholds == 1 && thresholds[0] == 0) /* Disabling */
11963 n_thresholds = 0;
11964
11965 wdev_lock(wdev);
11966 if (n_thresholds) {
11967 struct cfg80211_cqm_config *cqm_config;
11968
40f231e7
LB
11969 cqm_config = kzalloc(struct_size(cqm_config, rssi_thresholds,
11970 n_thresholds),
11971 GFP_KERNEL);
4a4b8169
AZ
11972 if (!cqm_config) {
11973 err = -ENOMEM;
11974 goto unlock;
11975 }
11976
11977 cqm_config->rssi_hyst = hysteresis;
11978 cqm_config->n_rssi_thresholds = n_thresholds;
11979 memcpy(cqm_config->rssi_thresholds, thresholds,
40f231e7
LB
11980 flex_array_size(cqm_config, rssi_thresholds,
11981 n_thresholds));
4a4b8169
AZ
11982
11983 wdev->cqm_config = cqm_config;
11984 }
11985
11986 err = cfg80211_cqm_rssi_update(rdev, dev);
11987
11988unlock:
11989 wdev_unlock(wdev);
11990
11991 return err;
d6dc1a38
JO
11992}
11993
11994static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
11995{
11996 struct nlattr *attrs[NL80211_ATTR_CQM_MAX + 1];
11997 struct nlattr *cqm;
11998 int err;
11999
12000 cqm = info->attrs[NL80211_ATTR_CQM];
1da5fcc8
JB
12001 if (!cqm)
12002 return -EINVAL;
d6dc1a38 12003
8cb08174
JB
12004 err = nla_parse_nested_deprecated(attrs, NL80211_ATTR_CQM_MAX, cqm,
12005 nl80211_attr_cqm_policy,
12006 info->extack);
d6dc1a38 12007 if (err)
1da5fcc8 12008 return err;
d6dc1a38
JO
12009
12010 if (attrs[NL80211_ATTR_CQM_RSSI_THOLD] &&
12011 attrs[NL80211_ATTR_CQM_RSSI_HYST]) {
4a4b8169
AZ
12012 const s32 *thresholds =
12013 nla_data(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
12014 int len = nla_len(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
1da5fcc8 12015 u32 hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]);
d6dc1a38 12016
4a4b8169
AZ
12017 if (len % 4)
12018 return -EINVAL;
12019
12020 return nl80211_set_cqm_rssi(info, thresholds, len / 4,
12021 hysteresis);
1da5fcc8
JB
12022 }
12023
12024 if (attrs[NL80211_ATTR_CQM_TXE_RATE] &&
12025 attrs[NL80211_ATTR_CQM_TXE_PKTS] &&
12026 attrs[NL80211_ATTR_CQM_TXE_INTVL]) {
12027 u32 rate = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_RATE]);
12028 u32 pkts = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_PKTS]);
12029 u32 intvl = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_INTVL]);
12030
12031 return nl80211_set_cqm_txe(info, rate, pkts, intvl);
12032 }
12033
12034 return -EINVAL;
d6dc1a38
JO
12035}
12036
6e0bd6c3
RL
12037static int nl80211_join_ocb(struct sk_buff *skb, struct genl_info *info)
12038{
12039 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12040 struct net_device *dev = info->user_ptr[1];
12041 struct ocb_setup setup = {};
12042 int err;
12043
12044 err = nl80211_parse_chandef(rdev, info, &setup.chandef);
12045 if (err)
12046 return err;
12047
12048 return cfg80211_join_ocb(rdev, dev, &setup);
12049}
12050
12051static int nl80211_leave_ocb(struct sk_buff *skb, struct genl_info *info)
12052{
12053 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12054 struct net_device *dev = info->user_ptr[1];
12055
12056 return cfg80211_leave_ocb(rdev, dev);
12057}
12058
29cbe68c
JB
12059static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
12060{
12061 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12062 struct net_device *dev = info->user_ptr[1];
12063 struct mesh_config cfg;
c80d545d 12064 struct mesh_setup setup;
29cbe68c
JB
12065 int err;
12066
12067 /* start with default */
12068 memcpy(&cfg, &default_mesh_config, sizeof(cfg));
c80d545d 12069 memcpy(&setup, &default_mesh_setup, sizeof(setup));
29cbe68c 12070
24bdd9f4 12071 if (info->attrs[NL80211_ATTR_MESH_CONFIG]) {
29cbe68c 12072 /* and parse parameters if given */
24bdd9f4 12073 err = nl80211_parse_mesh_config(info, &cfg, NULL);
29cbe68c
JB
12074 if (err)
12075 return err;
12076 }
12077
12078 if (!info->attrs[NL80211_ATTR_MESH_ID] ||
12079 !nla_len(info->attrs[NL80211_ATTR_MESH_ID]))
12080 return -EINVAL;
12081
c80d545d
JC
12082 setup.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
12083 setup.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
12084
4bb62344
CYY
12085 if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
12086 !nl80211_parse_mcast_rate(rdev, setup.mcast_rate,
12087 nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE])))
12088 return -EINVAL;
12089
9bdbf04d
MP
12090 if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
12091 setup.beacon_interval =
12092 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
12d20fc9 12093
0c317a02
PK
12094 err = cfg80211_validate_beacon_int(rdev,
12095 NL80211_IFTYPE_MESH_POINT,
12096 setup.beacon_interval);
12d20fc9
PK
12097 if (err)
12098 return err;
9bdbf04d
MP
12099 }
12100
12101 if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
12102 setup.dtim_period =
12103 nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
12104 if (setup.dtim_period < 1 || setup.dtim_period > 100)
12105 return -EINVAL;
12106 }
12107
c80d545d
JC
12108 if (info->attrs[NL80211_ATTR_MESH_SETUP]) {
12109 /* parse additional setup parameters if given */
12110 err = nl80211_parse_mesh_setup(info, &setup);
12111 if (err)
12112 return err;
12113 }
12114
d37bb18a
TP
12115 if (setup.user_mpm)
12116 cfg.auto_open_plinks = false;
12117
cc1d2806 12118 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
683b6d3b
JB
12119 err = nl80211_parse_chandef(rdev, info, &setup.chandef);
12120 if (err)
12121 return err;
cc1d2806 12122 } else {
188c1b3c 12123 /* __cfg80211_join_mesh() will sort it out */
683b6d3b 12124 setup.chandef.chan = NULL;
cc1d2806
JB
12125 }
12126
ffb3cf30
AN
12127 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
12128 u8 *rates = nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
12129 int n_rates =
12130 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
12131 struct ieee80211_supported_band *sband;
12132
12133 if (!setup.chandef.chan)
12134 return -EINVAL;
12135
12136 sband = rdev->wiphy.bands[setup.chandef.chan->band];
12137
12138 err = ieee80211_get_ratemask(sband, rates, n_rates,
12139 &setup.basic_rates);
12140 if (err)
12141 return err;
12142 }
12143
8564e382 12144 if (info->attrs[NL80211_ATTR_TX_RATES]) {
9a5f6488
TC
12145 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
12146 NL80211_ATTR_TX_RATES,
eb89a6a6 12147 &setup.beacon_rate,
857b34c4 12148 dev, false);
8564e382
JB
12149 if (err)
12150 return err;
12151
265698d7
JB
12152 if (!setup.chandef.chan)
12153 return -EINVAL;
12154
8564e382
JB
12155 err = validate_beacon_tx_rate(rdev, setup.chandef.chan->band,
12156 &setup.beacon_rate);
12157 if (err)
12158 return err;
12159 }
12160
d37d49c2
BB
12161 setup.userspace_handles_dfs =
12162 nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]);
12163
1224f583
DK
12164 if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) {
12165 int r = validate_pae_over_nl80211(rdev, info);
12166
12167 if (r < 0)
12168 return r;
12169
12170 setup.control_port_over_nl80211 = true;
12171 }
12172
188c1b3c
DK
12173 wdev_lock(dev->ieee80211_ptr);
12174 err = __cfg80211_join_mesh(rdev, dev, &setup, &cfg);
12175 if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER])
12176 dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
12177 wdev_unlock(dev->ieee80211_ptr);
12178
12179 return err;
29cbe68c
JB
12180}
12181
12182static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info)
12183{
12184 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12185 struct net_device *dev = info->user_ptr[1];
12186
12187 return cfg80211_leave_mesh(rdev, dev);
12188}
12189
dfb89c56 12190#ifdef CONFIG_PM
bb92d199
AK
12191static int nl80211_send_wowlan_patterns(struct sk_buff *msg,
12192 struct cfg80211_registered_device *rdev)
12193{
6abb9cb9 12194 struct cfg80211_wowlan *wowlan = rdev->wiphy.wowlan_config;
bb92d199
AK
12195 struct nlattr *nl_pats, *nl_pat;
12196 int i, pat_len;
12197
6abb9cb9 12198 if (!wowlan->n_patterns)
bb92d199
AK
12199 return 0;
12200
ae0be8de 12201 nl_pats = nla_nest_start_noflag(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN);
bb92d199
AK
12202 if (!nl_pats)
12203 return -ENOBUFS;
12204
6abb9cb9 12205 for (i = 0; i < wowlan->n_patterns; i++) {
ae0be8de 12206 nl_pat = nla_nest_start_noflag(msg, i + 1);
bb92d199
AK
12207 if (!nl_pat)
12208 return -ENOBUFS;
6abb9cb9 12209 pat_len = wowlan->patterns[i].pattern_len;
50ac6607 12210 if (nla_put(msg, NL80211_PKTPAT_MASK, DIV_ROUND_UP(pat_len, 8),
6abb9cb9 12211 wowlan->patterns[i].mask) ||
50ac6607
AK
12212 nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
12213 wowlan->patterns[i].pattern) ||
12214 nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
6abb9cb9 12215 wowlan->patterns[i].pkt_offset))
bb92d199
AK
12216 return -ENOBUFS;
12217 nla_nest_end(msg, nl_pat);
12218 }
12219 nla_nest_end(msg, nl_pats);
12220
12221 return 0;
12222}
12223
2a0e047e
JB
12224static int nl80211_send_wowlan_tcp(struct sk_buff *msg,
12225 struct cfg80211_wowlan_tcp *tcp)
12226{
12227 struct nlattr *nl_tcp;
12228
12229 if (!tcp)
12230 return 0;
12231
ae0be8de
MK
12232 nl_tcp = nla_nest_start_noflag(msg,
12233 NL80211_WOWLAN_TRIG_TCP_CONNECTION);
2a0e047e
JB
12234 if (!nl_tcp)
12235 return -ENOBUFS;
12236
930345ea
JB
12237 if (nla_put_in_addr(msg, NL80211_WOWLAN_TCP_SRC_IPV4, tcp->src) ||
12238 nla_put_in_addr(msg, NL80211_WOWLAN_TCP_DST_IPV4, tcp->dst) ||
2a0e047e
JB
12239 nla_put(msg, NL80211_WOWLAN_TCP_DST_MAC, ETH_ALEN, tcp->dst_mac) ||
12240 nla_put_u16(msg, NL80211_WOWLAN_TCP_SRC_PORT, tcp->src_port) ||
12241 nla_put_u16(msg, NL80211_WOWLAN_TCP_DST_PORT, tcp->dst_port) ||
12242 nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
12243 tcp->payload_len, tcp->payload) ||
12244 nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
12245 tcp->data_interval) ||
12246 nla_put(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
12247 tcp->wake_len, tcp->wake_data) ||
12248 nla_put(msg, NL80211_WOWLAN_TCP_WAKE_MASK,
12249 DIV_ROUND_UP(tcp->wake_len, 8), tcp->wake_mask))
12250 return -ENOBUFS;
12251
12252 if (tcp->payload_seq.len &&
12253 nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ,
12254 sizeof(tcp->payload_seq), &tcp->payload_seq))
12255 return -ENOBUFS;
12256
12257 if (tcp->payload_tok.len &&
12258 nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
12259 sizeof(tcp->payload_tok) + tcp->tokens_size,
12260 &tcp->payload_tok))
12261 return -ENOBUFS;
12262
e248ad30
JB
12263 nla_nest_end(msg, nl_tcp);
12264
2a0e047e
JB
12265 return 0;
12266}
12267
75453ccb
LC
12268static int nl80211_send_wowlan_nd(struct sk_buff *msg,
12269 struct cfg80211_sched_scan_request *req)
12270{
3b06d277 12271 struct nlattr *nd, *freqs, *matches, *match, *scan_plans, *scan_plan;
75453ccb
LC
12272 int i;
12273
12274 if (!req)
12275 return 0;
12276
ae0be8de 12277 nd = nla_nest_start_noflag(msg, NL80211_WOWLAN_TRIG_NET_DETECT);
75453ccb
LC
12278 if (!nd)
12279 return -ENOBUFS;
12280
3b06d277
AS
12281 if (req->n_scan_plans == 1 &&
12282 nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL,
12283 req->scan_plans[0].interval * 1000))
75453ccb
LC
12284 return -ENOBUFS;
12285
21fea567
LC
12286 if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_DELAY, req->delay))
12287 return -ENOBUFS;
12288
bf95ecdb 12289 if (req->relative_rssi_set) {
12290 struct nl80211_bss_select_rssi_adjust rssi_adjust;
12291
12292 if (nla_put_s8(msg, NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI,
12293 req->relative_rssi))
12294 return -ENOBUFS;
12295
12296 rssi_adjust.band = req->rssi_adjust.band;
12297 rssi_adjust.delta = req->rssi_adjust.delta;
12298 if (nla_put(msg, NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST,
12299 sizeof(rssi_adjust), &rssi_adjust))
12300 return -ENOBUFS;
12301 }
12302
ae0be8de 12303 freqs = nla_nest_start_noflag(msg, NL80211_ATTR_SCAN_FREQUENCIES);
75453ccb
LC
12304 if (!freqs)
12305 return -ENOBUFS;
12306
53b18980
JB
12307 for (i = 0; i < req->n_channels; i++) {
12308 if (nla_put_u32(msg, i, req->channels[i]->center_freq))
12309 return -ENOBUFS;
12310 }
75453ccb
LC
12311
12312 nla_nest_end(msg, freqs);
12313
12314 if (req->n_match_sets) {
ae0be8de
MK
12315 matches = nla_nest_start_noflag(msg,
12316 NL80211_ATTR_SCHED_SCAN_MATCH);
76e1fb4b
JB
12317 if (!matches)
12318 return -ENOBUFS;
12319
75453ccb 12320 for (i = 0; i < req->n_match_sets; i++) {
ae0be8de 12321 match = nla_nest_start_noflag(msg, i);
76e1fb4b
JB
12322 if (!match)
12323 return -ENOBUFS;
12324
53b18980
JB
12325 if (nla_put(msg, NL80211_SCHED_SCAN_MATCH_ATTR_SSID,
12326 req->match_sets[i].ssid.ssid_len,
12327 req->match_sets[i].ssid.ssid))
12328 return -ENOBUFS;
75453ccb
LC
12329 nla_nest_end(msg, match);
12330 }
12331 nla_nest_end(msg, matches);
12332 }
12333
ae0be8de 12334 scan_plans = nla_nest_start_noflag(msg, NL80211_ATTR_SCHED_SCAN_PLANS);
3b06d277
AS
12335 if (!scan_plans)
12336 return -ENOBUFS;
12337
12338 for (i = 0; i < req->n_scan_plans; i++) {
ae0be8de 12339 scan_plan = nla_nest_start_noflag(msg, i + 1);
76e1fb4b
JB
12340 if (!scan_plan)
12341 return -ENOBUFS;
12342
67626964 12343 if (nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_INTERVAL,
3b06d277
AS
12344 req->scan_plans[i].interval) ||
12345 (req->scan_plans[i].iterations &&
12346 nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_ITERATIONS,
12347 req->scan_plans[i].iterations)))
12348 return -ENOBUFS;
12349 nla_nest_end(msg, scan_plan);
12350 }
12351 nla_nest_end(msg, scan_plans);
12352
75453ccb
LC
12353 nla_nest_end(msg, nd);
12354
12355 return 0;
12356}
12357
ff1b6e69
JB
12358static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
12359{
12360 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12361 struct sk_buff *msg;
12362 void *hdr;
2a0e047e 12363 u32 size = NLMSG_DEFAULT_SIZE;
ff1b6e69 12364
964dc9e2 12365 if (!rdev->wiphy.wowlan)
ff1b6e69
JB
12366 return -EOPNOTSUPP;
12367
6abb9cb9 12368 if (rdev->wiphy.wowlan_config && rdev->wiphy.wowlan_config->tcp) {
2a0e047e 12369 /* adjust size to have room for all the data */
6abb9cb9
JB
12370 size += rdev->wiphy.wowlan_config->tcp->tokens_size +
12371 rdev->wiphy.wowlan_config->tcp->payload_len +
12372 rdev->wiphy.wowlan_config->tcp->wake_len +
12373 rdev->wiphy.wowlan_config->tcp->wake_len / 8;
2a0e047e
JB
12374 }
12375
12376 msg = nlmsg_new(size, GFP_KERNEL);
ff1b6e69
JB
12377 if (!msg)
12378 return -ENOMEM;
12379
15e47304 12380 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
ff1b6e69
JB
12381 NL80211_CMD_GET_WOWLAN);
12382 if (!hdr)
12383 goto nla_put_failure;
12384
6abb9cb9 12385 if (rdev->wiphy.wowlan_config) {
ff1b6e69
JB
12386 struct nlattr *nl_wowlan;
12387
ae0be8de
MK
12388 nl_wowlan = nla_nest_start_noflag(msg,
12389 NL80211_ATTR_WOWLAN_TRIGGERS);
ff1b6e69
JB
12390 if (!nl_wowlan)
12391 goto nla_put_failure;
12392
6abb9cb9 12393 if ((rdev->wiphy.wowlan_config->any &&
9360ffd1 12394 nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
6abb9cb9 12395 (rdev->wiphy.wowlan_config->disconnect &&
9360ffd1 12396 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
6abb9cb9 12397 (rdev->wiphy.wowlan_config->magic_pkt &&
9360ffd1 12398 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
6abb9cb9 12399 (rdev->wiphy.wowlan_config->gtk_rekey_failure &&
9360ffd1 12400 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
6abb9cb9 12401 (rdev->wiphy.wowlan_config->eap_identity_req &&
9360ffd1 12402 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
6abb9cb9 12403 (rdev->wiphy.wowlan_config->four_way_handshake &&
9360ffd1 12404 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
6abb9cb9 12405 (rdev->wiphy.wowlan_config->rfkill_release &&
9360ffd1
DM
12406 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
12407 goto nla_put_failure;
2a0e047e 12408
bb92d199
AK
12409 if (nl80211_send_wowlan_patterns(msg, rdev))
12410 goto nla_put_failure;
2a0e047e 12411
6abb9cb9
JB
12412 if (nl80211_send_wowlan_tcp(msg,
12413 rdev->wiphy.wowlan_config->tcp))
2a0e047e 12414 goto nla_put_failure;
75453ccb
LC
12415
12416 if (nl80211_send_wowlan_nd(
12417 msg,
12418 rdev->wiphy.wowlan_config->nd_config))
12419 goto nla_put_failure;
2a0e047e 12420
ff1b6e69
JB
12421 nla_nest_end(msg, nl_wowlan);
12422 }
12423
12424 genlmsg_end(msg, hdr);
12425 return genlmsg_reply(msg, info);
12426
12427nla_put_failure:
12428 nlmsg_free(msg);
12429 return -ENOBUFS;
12430}
12431
2a0e047e
JB
12432static int nl80211_parse_wowlan_tcp(struct cfg80211_registered_device *rdev,
12433 struct nlattr *attr,
12434 struct cfg80211_wowlan *trig)
12435{
12436 struct nlattr *tb[NUM_NL80211_WOWLAN_TCP];
12437 struct cfg80211_wowlan_tcp *cfg;
12438 struct nl80211_wowlan_tcp_data_token *tok = NULL;
12439 struct nl80211_wowlan_tcp_data_seq *seq = NULL;
12440 u32 size;
12441 u32 data_size, wake_size, tokens_size = 0, wake_mask_size;
12442 int err, port;
12443
964dc9e2 12444 if (!rdev->wiphy.wowlan->tcp)
2a0e047e
JB
12445 return -EINVAL;
12446
8cb08174
JB
12447 err = nla_parse_nested_deprecated(tb, MAX_NL80211_WOWLAN_TCP, attr,
12448 nl80211_wowlan_tcp_policy, NULL);
2a0e047e
JB
12449 if (err)
12450 return err;
12451
12452 if (!tb[NL80211_WOWLAN_TCP_SRC_IPV4] ||
12453 !tb[NL80211_WOWLAN_TCP_DST_IPV4] ||
12454 !tb[NL80211_WOWLAN_TCP_DST_MAC] ||
12455 !tb[NL80211_WOWLAN_TCP_DST_PORT] ||
12456 !tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD] ||
12457 !tb[NL80211_WOWLAN_TCP_DATA_INTERVAL] ||
12458 !tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD] ||
12459 !tb[NL80211_WOWLAN_TCP_WAKE_MASK])
12460 return -EINVAL;
12461
12462 data_size = nla_len(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD]);
964dc9e2 12463 if (data_size > rdev->wiphy.wowlan->tcp->data_payload_max)
2a0e047e
JB
12464 return -EINVAL;
12465
12466 if (nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) >
964dc9e2 12467 rdev->wiphy.wowlan->tcp->data_interval_max ||
723d568a 12468 nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) == 0)
2a0e047e
JB
12469 return -EINVAL;
12470
12471 wake_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]);
964dc9e2 12472 if (wake_size > rdev->wiphy.wowlan->tcp->wake_payload_max)
2a0e047e
JB
12473 return -EINVAL;
12474
12475 wake_mask_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_MASK]);
12476 if (wake_mask_size != DIV_ROUND_UP(wake_size, 8))
12477 return -EINVAL;
12478
12479 if (tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]) {
12480 u32 tokln = nla_len(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]);
12481
12482 tok = nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]);
12483 tokens_size = tokln - sizeof(*tok);
12484
12485 if (!tok->len || tokens_size % tok->len)
12486 return -EINVAL;
964dc9e2 12487 if (!rdev->wiphy.wowlan->tcp->tok)
2a0e047e 12488 return -EINVAL;
964dc9e2 12489 if (tok->len > rdev->wiphy.wowlan->tcp->tok->max_len)
2a0e047e 12490 return -EINVAL;
964dc9e2 12491 if (tok->len < rdev->wiphy.wowlan->tcp->tok->min_len)
2a0e047e 12492 return -EINVAL;
964dc9e2 12493 if (tokens_size > rdev->wiphy.wowlan->tcp->tok->bufsize)
2a0e047e
JB
12494 return -EINVAL;
12495 if (tok->offset + tok->len > data_size)
12496 return -EINVAL;
12497 }
12498
12499 if (tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]) {
12500 seq = nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]);
964dc9e2 12501 if (!rdev->wiphy.wowlan->tcp->seq)
2a0e047e
JB
12502 return -EINVAL;
12503 if (seq->len == 0 || seq->len > 4)
12504 return -EINVAL;
12505 if (seq->len + seq->offset > data_size)
12506 return -EINVAL;
12507 }
12508
12509 size = sizeof(*cfg);
12510 size += data_size;
12511 size += wake_size + wake_mask_size;
12512 size += tokens_size;
12513
12514 cfg = kzalloc(size, GFP_KERNEL);
12515 if (!cfg)
12516 return -ENOMEM;
67b61f6c
JB
12517 cfg->src = nla_get_in_addr(tb[NL80211_WOWLAN_TCP_SRC_IPV4]);
12518 cfg->dst = nla_get_in_addr(tb[NL80211_WOWLAN_TCP_DST_IPV4]);
2a0e047e
JB
12519 memcpy(cfg->dst_mac, nla_data(tb[NL80211_WOWLAN_TCP_DST_MAC]),
12520 ETH_ALEN);
12521 if (tb[NL80211_WOWLAN_TCP_SRC_PORT])
12522 port = nla_get_u16(tb[NL80211_WOWLAN_TCP_SRC_PORT]);
12523 else
12524 port = 0;
12525#ifdef CONFIG_INET
12526 /* allocate a socket and port for it and use it */
12527 err = __sock_create(wiphy_net(&rdev->wiphy), PF_INET, SOCK_STREAM,
12528 IPPROTO_TCP, &cfg->sock, 1);
12529 if (err) {
12530 kfree(cfg);
12531 return err;
12532 }
12533 if (inet_csk_get_port(cfg->sock->sk, port)) {
12534 sock_release(cfg->sock);
12535 kfree(cfg);
12536 return -EADDRINUSE;
12537 }
12538 cfg->src_port = inet_sk(cfg->sock->sk)->inet_num;
12539#else
12540 if (!port) {
12541 kfree(cfg);
12542 return -EINVAL;
12543 }
12544 cfg->src_port = port;
12545#endif
12546
12547 cfg->dst_port = nla_get_u16(tb[NL80211_WOWLAN_TCP_DST_PORT]);
12548 cfg->payload_len = data_size;
12549 cfg->payload = (u8 *)cfg + sizeof(*cfg) + tokens_size;
12550 memcpy((void *)cfg->payload,
12551 nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD]),
12552 data_size);
12553 if (seq)
12554 cfg->payload_seq = *seq;
12555 cfg->data_interval = nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]);
12556 cfg->wake_len = wake_size;
12557 cfg->wake_data = (u8 *)cfg + sizeof(*cfg) + tokens_size + data_size;
12558 memcpy((void *)cfg->wake_data,
12559 nla_data(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]),
12560 wake_size);
12561 cfg->wake_mask = (u8 *)cfg + sizeof(*cfg) + tokens_size +
12562 data_size + wake_size;
12563 memcpy((void *)cfg->wake_mask,
12564 nla_data(tb[NL80211_WOWLAN_TCP_WAKE_MASK]),
12565 wake_mask_size);
12566 if (tok) {
12567 cfg->tokens_size = tokens_size;
12568 memcpy(&cfg->payload_tok, tok, sizeof(*tok) + tokens_size);
12569 }
12570
12571 trig->tcp = cfg;
12572
12573 return 0;
12574}
12575
8cd4d456
LC
12576static int nl80211_parse_wowlan_nd(struct cfg80211_registered_device *rdev,
12577 const struct wiphy_wowlan_support *wowlan,
12578 struct nlattr *attr,
12579 struct cfg80211_wowlan *trig)
12580{
12581 struct nlattr **tb;
12582 int err;
12583
6396bb22 12584 tb = kcalloc(NUM_NL80211_ATTR, sizeof(*tb), GFP_KERNEL);
8cd4d456
LC
12585 if (!tb)
12586 return -ENOMEM;
12587
12588 if (!(wowlan->flags & WIPHY_WOWLAN_NET_DETECT)) {
12589 err = -EOPNOTSUPP;
12590 goto out;
12591 }
12592
8cb08174
JB
12593 err = nla_parse_nested_deprecated(tb, NL80211_ATTR_MAX, attr,
12594 nl80211_policy, NULL);
8cd4d456
LC
12595 if (err)
12596 goto out;
12597
aad1e812
AVS
12598 trig->nd_config = nl80211_parse_sched_scan(&rdev->wiphy, NULL, tb,
12599 wowlan->max_nd_match_sets);
8cd4d456
LC
12600 err = PTR_ERR_OR_ZERO(trig->nd_config);
12601 if (err)
12602 trig->nd_config = NULL;
12603
12604out:
12605 kfree(tb);
12606 return err;
12607}
12608
ff1b6e69
JB
12609static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
12610{
12611 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12612 struct nlattr *tb[NUM_NL80211_WOWLAN_TRIG];
ff1b6e69 12613 struct cfg80211_wowlan new_triggers = {};
ae33bd81 12614 struct cfg80211_wowlan *ntrig;
964dc9e2 12615 const struct wiphy_wowlan_support *wowlan = rdev->wiphy.wowlan;
ff1b6e69 12616 int err, i;
6abb9cb9 12617 bool prev_enabled = rdev->wiphy.wowlan_config;
98fc4386 12618 bool regular = false;
ff1b6e69 12619
964dc9e2 12620 if (!wowlan)
ff1b6e69
JB
12621 return -EOPNOTSUPP;
12622
ae33bd81
JB
12623 if (!info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) {
12624 cfg80211_rdev_free_wowlan(rdev);
6abb9cb9 12625 rdev->wiphy.wowlan_config = NULL;
ae33bd81
JB
12626 goto set_wakeup;
12627 }
ff1b6e69 12628
8cb08174
JB
12629 err = nla_parse_nested_deprecated(tb, MAX_NL80211_WOWLAN_TRIG,
12630 info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS],
12631 nl80211_wowlan_policy, info->extack);
ff1b6e69
JB
12632 if (err)
12633 return err;
12634
12635 if (tb[NL80211_WOWLAN_TRIG_ANY]) {
12636 if (!(wowlan->flags & WIPHY_WOWLAN_ANY))
12637 return -EINVAL;
12638 new_triggers.any = true;
12639 }
12640
12641 if (tb[NL80211_WOWLAN_TRIG_DISCONNECT]) {
12642 if (!(wowlan->flags & WIPHY_WOWLAN_DISCONNECT))
12643 return -EINVAL;
12644 new_triggers.disconnect = true;
98fc4386 12645 regular = true;
ff1b6e69
JB
12646 }
12647
12648 if (tb[NL80211_WOWLAN_TRIG_MAGIC_PKT]) {
12649 if (!(wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT))
12650 return -EINVAL;
12651 new_triggers.magic_pkt = true;
98fc4386 12652 regular = true;
ff1b6e69
JB
12653 }
12654
77dbbb13
JB
12655 if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED])
12656 return -EINVAL;
12657
12658 if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE]) {
12659 if (!(wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE))
12660 return -EINVAL;
12661 new_triggers.gtk_rekey_failure = true;
98fc4386 12662 regular = true;
77dbbb13
JB
12663 }
12664
12665 if (tb[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST]) {
12666 if (!(wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ))
12667 return -EINVAL;
12668 new_triggers.eap_identity_req = true;
98fc4386 12669 regular = true;
77dbbb13
JB
12670 }
12671
12672 if (tb[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE]) {
12673 if (!(wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE))
12674 return -EINVAL;
12675 new_triggers.four_way_handshake = true;
98fc4386 12676 regular = true;
77dbbb13
JB
12677 }
12678
12679 if (tb[NL80211_WOWLAN_TRIG_RFKILL_RELEASE]) {
12680 if (!(wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE))
12681 return -EINVAL;
12682 new_triggers.rfkill_release = true;
98fc4386 12683 regular = true;
77dbbb13
JB
12684 }
12685
ff1b6e69
JB
12686 if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) {
12687 struct nlattr *pat;
12688 int n_patterns = 0;
bb92d199 12689 int rem, pat_len, mask_len, pkt_offset;
50ac6607 12690 struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
ff1b6e69 12691
98fc4386
JB
12692 regular = true;
12693
ff1b6e69
JB
12694 nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
12695 rem)
12696 n_patterns++;
12697 if (n_patterns > wowlan->n_patterns)
12698 return -EINVAL;
12699
12700 new_triggers.patterns = kcalloc(n_patterns,
12701 sizeof(new_triggers.patterns[0]),
12702 GFP_KERNEL);
12703 if (!new_triggers.patterns)
12704 return -ENOMEM;
12705
12706 new_triggers.n_patterns = n_patterns;
12707 i = 0;
12708
12709 nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
12710 rem) {
922bd80f
JB
12711 u8 *mask_pat;
12712
8cb08174
JB
12713 err = nla_parse_nested_deprecated(pat_tb,
12714 MAX_NL80211_PKTPAT,
12715 pat,
12716 nl80211_packet_pattern_policy,
12717 info->extack);
95bca62f
JB
12718 if (err)
12719 goto error;
12720
ff1b6e69 12721 err = -EINVAL;
50ac6607
AK
12722 if (!pat_tb[NL80211_PKTPAT_MASK] ||
12723 !pat_tb[NL80211_PKTPAT_PATTERN])
ff1b6e69 12724 goto error;
50ac6607 12725 pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
ff1b6e69 12726 mask_len = DIV_ROUND_UP(pat_len, 8);
50ac6607 12727 if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
ff1b6e69
JB
12728 goto error;
12729 if (pat_len > wowlan->pattern_max_len ||
12730 pat_len < wowlan->pattern_min_len)
12731 goto error;
12732
50ac6607 12733 if (!pat_tb[NL80211_PKTPAT_OFFSET])
bb92d199
AK
12734 pkt_offset = 0;
12735 else
12736 pkt_offset = nla_get_u32(
50ac6607 12737 pat_tb[NL80211_PKTPAT_OFFSET]);
bb92d199
AK
12738 if (pkt_offset > wowlan->max_pkt_offset)
12739 goto error;
12740 new_triggers.patterns[i].pkt_offset = pkt_offset;
12741
922bd80f
JB
12742 mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL);
12743 if (!mask_pat) {
ff1b6e69
JB
12744 err = -ENOMEM;
12745 goto error;
12746 }
922bd80f
JB
12747 new_triggers.patterns[i].mask = mask_pat;
12748 memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]),
ff1b6e69 12749 mask_len);
922bd80f
JB
12750 mask_pat += mask_len;
12751 new_triggers.patterns[i].pattern = mask_pat;
ff1b6e69 12752 new_triggers.patterns[i].pattern_len = pat_len;
922bd80f 12753 memcpy(mask_pat,
50ac6607 12754 nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
ff1b6e69
JB
12755 pat_len);
12756 i++;
12757 }
12758 }
12759
2a0e047e 12760 if (tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION]) {
98fc4386 12761 regular = true;
2a0e047e
JB
12762 err = nl80211_parse_wowlan_tcp(
12763 rdev, tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION],
12764 &new_triggers);
12765 if (err)
12766 goto error;
12767 }
12768
8cd4d456 12769 if (tb[NL80211_WOWLAN_TRIG_NET_DETECT]) {
98fc4386 12770 regular = true;
8cd4d456
LC
12771 err = nl80211_parse_wowlan_nd(
12772 rdev, wowlan, tb[NL80211_WOWLAN_TRIG_NET_DETECT],
12773 &new_triggers);
12774 if (err)
12775 goto error;
12776 }
12777
98fc4386
JB
12778 /* The 'any' trigger means the device continues operating more or less
12779 * as in its normal operation mode and wakes up the host on most of the
12780 * normal interrupts (like packet RX, ...)
12781 * It therefore makes little sense to combine with the more constrained
12782 * wakeup trigger modes.
12783 */
12784 if (new_triggers.any && regular) {
12785 err = -EINVAL;
12786 goto error;
12787 }
12788
ae33bd81
JB
12789 ntrig = kmemdup(&new_triggers, sizeof(new_triggers), GFP_KERNEL);
12790 if (!ntrig) {
12791 err = -ENOMEM;
12792 goto error;
ff1b6e69 12793 }
ae33bd81 12794 cfg80211_rdev_free_wowlan(rdev);
6abb9cb9 12795 rdev->wiphy.wowlan_config = ntrig;
ff1b6e69 12796
ae33bd81 12797 set_wakeup:
6abb9cb9
JB
12798 if (rdev->ops->set_wakeup &&
12799 prev_enabled != !!rdev->wiphy.wowlan_config)
12800 rdev_set_wakeup(rdev, rdev->wiphy.wowlan_config);
6d52563f 12801
ff1b6e69
JB
12802 return 0;
12803 error:
12804 for (i = 0; i < new_triggers.n_patterns; i++)
12805 kfree(new_triggers.patterns[i].mask);
12806 kfree(new_triggers.patterns);
2a0e047e
JB
12807 if (new_triggers.tcp && new_triggers.tcp->sock)
12808 sock_release(new_triggers.tcp->sock);
12809 kfree(new_triggers.tcp);
e5dbe070 12810 kfree(new_triggers.nd_config);
ff1b6e69
JB
12811 return err;
12812}
dfb89c56 12813#endif
ff1b6e69 12814
be29b99a
AK
12815static int nl80211_send_coalesce_rules(struct sk_buff *msg,
12816 struct cfg80211_registered_device *rdev)
12817{
12818 struct nlattr *nl_pats, *nl_pat, *nl_rule, *nl_rules;
12819 int i, j, pat_len;
12820 struct cfg80211_coalesce_rules *rule;
12821
12822 if (!rdev->coalesce->n_rules)
12823 return 0;
12824
ae0be8de 12825 nl_rules = nla_nest_start_noflag(msg, NL80211_ATTR_COALESCE_RULE);
be29b99a
AK
12826 if (!nl_rules)
12827 return -ENOBUFS;
12828
12829 for (i = 0; i < rdev->coalesce->n_rules; i++) {
ae0be8de 12830 nl_rule = nla_nest_start_noflag(msg, i + 1);
be29b99a
AK
12831 if (!nl_rule)
12832 return -ENOBUFS;
12833
12834 rule = &rdev->coalesce->rules[i];
12835 if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_DELAY,
12836 rule->delay))
12837 return -ENOBUFS;
12838
12839 if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_CONDITION,
12840 rule->condition))
12841 return -ENOBUFS;
12842
ae0be8de
MK
12843 nl_pats = nla_nest_start_noflag(msg,
12844 NL80211_ATTR_COALESCE_RULE_PKT_PATTERN);
be29b99a
AK
12845 if (!nl_pats)
12846 return -ENOBUFS;
12847
12848 for (j = 0; j < rule->n_patterns; j++) {
ae0be8de 12849 nl_pat = nla_nest_start_noflag(msg, j + 1);
be29b99a
AK
12850 if (!nl_pat)
12851 return -ENOBUFS;
12852 pat_len = rule->patterns[j].pattern_len;
12853 if (nla_put(msg, NL80211_PKTPAT_MASK,
12854 DIV_ROUND_UP(pat_len, 8),
12855 rule->patterns[j].mask) ||
12856 nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
12857 rule->patterns[j].pattern) ||
12858 nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
12859 rule->patterns[j].pkt_offset))
12860 return -ENOBUFS;
12861 nla_nest_end(msg, nl_pat);
12862 }
12863 nla_nest_end(msg, nl_pats);
12864 nla_nest_end(msg, nl_rule);
12865 }
12866 nla_nest_end(msg, nl_rules);
12867
12868 return 0;
12869}
12870
12871static int nl80211_get_coalesce(struct sk_buff *skb, struct genl_info *info)
12872{
12873 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12874 struct sk_buff *msg;
12875 void *hdr;
12876
12877 if (!rdev->wiphy.coalesce)
12878 return -EOPNOTSUPP;
12879
12880 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
12881 if (!msg)
12882 return -ENOMEM;
12883
12884 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
12885 NL80211_CMD_GET_COALESCE);
12886 if (!hdr)
12887 goto nla_put_failure;
12888
12889 if (rdev->coalesce && nl80211_send_coalesce_rules(msg, rdev))
12890 goto nla_put_failure;
12891
12892 genlmsg_end(msg, hdr);
12893 return genlmsg_reply(msg, info);
12894
12895nla_put_failure:
12896 nlmsg_free(msg);
12897 return -ENOBUFS;
12898}
12899
12900void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev)
12901{
12902 struct cfg80211_coalesce *coalesce = rdev->coalesce;
12903 int i, j;
12904 struct cfg80211_coalesce_rules *rule;
12905
12906 if (!coalesce)
12907 return;
12908
12909 for (i = 0; i < coalesce->n_rules; i++) {
12910 rule = &coalesce->rules[i];
12911 for (j = 0; j < rule->n_patterns; j++)
12912 kfree(rule->patterns[j].mask);
12913 kfree(rule->patterns);
12914 }
12915 kfree(coalesce->rules);
12916 kfree(coalesce);
12917 rdev->coalesce = NULL;
12918}
12919
12920static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev,
12921 struct nlattr *rule,
12922 struct cfg80211_coalesce_rules *new_rule)
12923{
12924 int err, i;
12925 const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce;
12926 struct nlattr *tb[NUM_NL80211_ATTR_COALESCE_RULE], *pat;
12927 int rem, pat_len, mask_len, pkt_offset, n_patterns = 0;
12928 struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
12929
8cb08174
JB
12930 err = nla_parse_nested_deprecated(tb, NL80211_ATTR_COALESCE_RULE_MAX,
12931 rule, nl80211_coalesce_policy, NULL);
be29b99a
AK
12932 if (err)
12933 return err;
12934
12935 if (tb[NL80211_ATTR_COALESCE_RULE_DELAY])
12936 new_rule->delay =
12937 nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_DELAY]);
12938 if (new_rule->delay > coalesce->max_delay)
12939 return -EINVAL;
12940
12941 if (tb[NL80211_ATTR_COALESCE_RULE_CONDITION])
12942 new_rule->condition =
12943 nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_CONDITION]);
be29b99a
AK
12944
12945 if (!tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN])
12946 return -EINVAL;
12947
12948 nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
12949 rem)
12950 n_patterns++;
12951 if (n_patterns > coalesce->n_patterns)
12952 return -EINVAL;
12953
12954 new_rule->patterns = kcalloc(n_patterns, sizeof(new_rule->patterns[0]),
12955 GFP_KERNEL);
12956 if (!new_rule->patterns)
12957 return -ENOMEM;
12958
12959 new_rule->n_patterns = n_patterns;
12960 i = 0;
12961
12962 nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
12963 rem) {
922bd80f
JB
12964 u8 *mask_pat;
12965
8cb08174
JB
12966 err = nla_parse_nested_deprecated(pat_tb, MAX_NL80211_PKTPAT,
12967 pat,
12968 nl80211_packet_pattern_policy,
12969 NULL);
95bca62f
JB
12970 if (err)
12971 return err;
12972
be29b99a
AK
12973 if (!pat_tb[NL80211_PKTPAT_MASK] ||
12974 !pat_tb[NL80211_PKTPAT_PATTERN])
12975 return -EINVAL;
12976 pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
12977 mask_len = DIV_ROUND_UP(pat_len, 8);
12978 if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
12979 return -EINVAL;
12980 if (pat_len > coalesce->pattern_max_len ||
12981 pat_len < coalesce->pattern_min_len)
12982 return -EINVAL;
12983
12984 if (!pat_tb[NL80211_PKTPAT_OFFSET])
12985 pkt_offset = 0;
12986 else
12987 pkt_offset = nla_get_u32(pat_tb[NL80211_PKTPAT_OFFSET]);
12988 if (pkt_offset > coalesce->max_pkt_offset)
12989 return -EINVAL;
12990 new_rule->patterns[i].pkt_offset = pkt_offset;
12991
922bd80f
JB
12992 mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL);
12993 if (!mask_pat)
be29b99a 12994 return -ENOMEM;
922bd80f
JB
12995
12996 new_rule->patterns[i].mask = mask_pat;
12997 memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]),
12998 mask_len);
12999
13000 mask_pat += mask_len;
13001 new_rule->patterns[i].pattern = mask_pat;
be29b99a 13002 new_rule->patterns[i].pattern_len = pat_len;
922bd80f
JB
13003 memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
13004 pat_len);
be29b99a
AK
13005 i++;
13006 }
13007
13008 return 0;
13009}
13010
13011static int nl80211_set_coalesce(struct sk_buff *skb, struct genl_info *info)
13012{
13013 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13014 const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce;
13015 struct cfg80211_coalesce new_coalesce = {};
13016 struct cfg80211_coalesce *n_coalesce;
13017 int err, rem_rule, n_rules = 0, i, j;
13018 struct nlattr *rule;
13019 struct cfg80211_coalesce_rules *tmp_rule;
13020
13021 if (!rdev->wiphy.coalesce || !rdev->ops->set_coalesce)
13022 return -EOPNOTSUPP;
13023
13024 if (!info->attrs[NL80211_ATTR_COALESCE_RULE]) {
13025 cfg80211_rdev_free_coalesce(rdev);
a1056b1b 13026 rdev_set_coalesce(rdev, NULL);
be29b99a
AK
13027 return 0;
13028 }
13029
13030 nla_for_each_nested(rule, info->attrs[NL80211_ATTR_COALESCE_RULE],
13031 rem_rule)
13032 n_rules++;
13033 if (n_rules > coalesce->n_rules)
13034 return -EINVAL;
13035
13036 new_coalesce.rules = kcalloc(n_rules, sizeof(new_coalesce.rules[0]),
13037 GFP_KERNEL);
13038 if (!new_coalesce.rules)
13039 return -ENOMEM;
13040
13041 new_coalesce.n_rules = n_rules;
13042 i = 0;
13043
13044 nla_for_each_nested(rule, info->attrs[NL80211_ATTR_COALESCE_RULE],
13045 rem_rule) {
13046 err = nl80211_parse_coalesce_rule(rdev, rule,
13047 &new_coalesce.rules[i]);
13048 if (err)
13049 goto error;
13050
13051 i++;
13052 }
13053
a1056b1b 13054 err = rdev_set_coalesce(rdev, &new_coalesce);
be29b99a
AK
13055 if (err)
13056 goto error;
13057
13058 n_coalesce = kmemdup(&new_coalesce, sizeof(new_coalesce), GFP_KERNEL);
13059 if (!n_coalesce) {
13060 err = -ENOMEM;
13061 goto error;
13062 }
13063 cfg80211_rdev_free_coalesce(rdev);
13064 rdev->coalesce = n_coalesce;
13065
13066 return 0;
13067error:
13068 for (i = 0; i < new_coalesce.n_rules; i++) {
13069 tmp_rule = &new_coalesce.rules[i];
13070 for (j = 0; j < tmp_rule->n_patterns; j++)
13071 kfree(tmp_rule->patterns[j].mask);
13072 kfree(tmp_rule->patterns);
13073 }
13074 kfree(new_coalesce.rules);
13075
13076 return err;
13077}
13078
e5497d76
JB
13079static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
13080{
13081 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13082 struct net_device *dev = info->user_ptr[1];
13083 struct wireless_dev *wdev = dev->ieee80211_ptr;
13084 struct nlattr *tb[NUM_NL80211_REKEY_DATA];
f495acd8 13085 struct cfg80211_gtk_rekey_data rekey_data = {};
e5497d76
JB
13086 int err;
13087
13088 if (!info->attrs[NL80211_ATTR_REKEY_DATA])
13089 return -EINVAL;
13090
8cb08174
JB
13091 err = nla_parse_nested_deprecated(tb, MAX_NL80211_REKEY_DATA,
13092 info->attrs[NL80211_ATTR_REKEY_DATA],
13093 nl80211_rekey_policy, info->extack);
e5497d76
JB
13094 if (err)
13095 return err;
13096
e785fa0a
VD
13097 if (!tb[NL80211_REKEY_DATA_REPLAY_CTR] || !tb[NL80211_REKEY_DATA_KEK] ||
13098 !tb[NL80211_REKEY_DATA_KCK])
13099 return -EINVAL;
093a48d2
NE
13100 if (nla_len(tb[NL80211_REKEY_DATA_KEK]) != NL80211_KEK_LEN &&
13101 !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK &&
13102 nla_len(tb[NL80211_REKEY_DATA_KEK]) == NL80211_KEK_EXT_LEN))
e5497d76 13103 return -ERANGE;
093a48d2
NE
13104 if (nla_len(tb[NL80211_REKEY_DATA_KCK]) != NL80211_KCK_LEN &&
13105 !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK &&
13106 nla_len(tb[NL80211_REKEY_DATA_KEK]) == NL80211_KCK_EXT_LEN))
e5497d76
JB
13107 return -ERANGE;
13108
78f686ca
JB
13109 rekey_data.kek = nla_data(tb[NL80211_REKEY_DATA_KEK]);
13110 rekey_data.kck = nla_data(tb[NL80211_REKEY_DATA_KCK]);
13111 rekey_data.replay_ctr = nla_data(tb[NL80211_REKEY_DATA_REPLAY_CTR]);
093a48d2
NE
13112 rekey_data.kek_len = nla_len(tb[NL80211_REKEY_DATA_KEK]);
13113 rekey_data.kck_len = nla_len(tb[NL80211_REKEY_DATA_KCK]);
13114 if (tb[NL80211_REKEY_DATA_AKM])
13115 rekey_data.akm = nla_get_u32(tb[NL80211_REKEY_DATA_AKM]);
e5497d76
JB
13116
13117 wdev_lock(wdev);
13118 if (!wdev->current_bss) {
13119 err = -ENOTCONN;
13120 goto out;
13121 }
13122
13123 if (!rdev->ops->set_rekey_data) {
13124 err = -EOPNOTSUPP;
13125 goto out;
13126 }
13127
e35e4d28 13128 err = rdev_set_rekey_data(rdev, dev, &rekey_data);
e5497d76
JB
13129 out:
13130 wdev_unlock(wdev);
13131 return err;
13132}
13133
28946da7
JB
13134static int nl80211_register_unexpected_frame(struct sk_buff *skb,
13135 struct genl_info *info)
13136{
13137 struct net_device *dev = info->user_ptr[1];
13138 struct wireless_dev *wdev = dev->ieee80211_ptr;
13139
13140 if (wdev->iftype != NL80211_IFTYPE_AP &&
13141 wdev->iftype != NL80211_IFTYPE_P2P_GO)
13142 return -EINVAL;
13143
15e47304 13144 if (wdev->ap_unexpected_nlportid)
28946da7
JB
13145 return -EBUSY;
13146
15e47304 13147 wdev->ap_unexpected_nlportid = info->snd_portid;
28946da7
JB
13148 return 0;
13149}
13150
7f6cf311
JB
13151static int nl80211_probe_client(struct sk_buff *skb,
13152 struct genl_info *info)
13153{
13154 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13155 struct net_device *dev = info->user_ptr[1];
13156 struct wireless_dev *wdev = dev->ieee80211_ptr;
13157 struct sk_buff *msg;
13158 void *hdr;
13159 const u8 *addr;
13160 u64 cookie;
13161 int err;
13162
13163 if (wdev->iftype != NL80211_IFTYPE_AP &&
13164 wdev->iftype != NL80211_IFTYPE_P2P_GO)
13165 return -EOPNOTSUPP;
13166
13167 if (!info->attrs[NL80211_ATTR_MAC])
13168 return -EINVAL;
13169
13170 if (!rdev->ops->probe_client)
13171 return -EOPNOTSUPP;
13172
13173 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
13174 if (!msg)
13175 return -ENOMEM;
13176
15e47304 13177 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
7f6cf311 13178 NL80211_CMD_PROBE_CLIENT);
cb35fba3
DC
13179 if (!hdr) {
13180 err = -ENOBUFS;
7f6cf311
JB
13181 goto free_msg;
13182 }
13183
13184 addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
13185
e35e4d28 13186 err = rdev_probe_client(rdev, dev, addr, &cookie);
7f6cf311
JB
13187 if (err)
13188 goto free_msg;
13189
2dad624e
ND
13190 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
13191 NL80211_ATTR_PAD))
9360ffd1 13192 goto nla_put_failure;
7f6cf311
JB
13193
13194 genlmsg_end(msg, hdr);
13195
13196 return genlmsg_reply(msg, info);
13197
13198 nla_put_failure:
13199 err = -ENOBUFS;
13200 free_msg:
13201 nlmsg_free(msg);
13202 return err;
13203}
13204
5e760230
JB
13205static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info)
13206{
13207 struct cfg80211_registered_device *rdev = info->user_ptr[0];
37c73b5f
BG
13208 struct cfg80211_beacon_registration *reg, *nreg;
13209 int rv;
5e760230
JB
13210
13211 if (!(rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS))
13212 return -EOPNOTSUPP;
13213
37c73b5f
BG
13214 nreg = kzalloc(sizeof(*nreg), GFP_KERNEL);
13215 if (!nreg)
13216 return -ENOMEM;
13217
13218 /* First, check if already registered. */
13219 spin_lock_bh(&rdev->beacon_registrations_lock);
13220 list_for_each_entry(reg, &rdev->beacon_registrations, list) {
13221 if (reg->nlportid == info->snd_portid) {
13222 rv = -EALREADY;
13223 goto out_err;
13224 }
13225 }
13226 /* Add it to the list */
13227 nreg->nlportid = info->snd_portid;
13228 list_add(&nreg->list, &rdev->beacon_registrations);
5e760230 13229
37c73b5f 13230 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230
JB
13231
13232 return 0;
37c73b5f
BG
13233out_err:
13234 spin_unlock_bh(&rdev->beacon_registrations_lock);
13235 kfree(nreg);
13236 return rv;
5e760230
JB
13237}
13238
98104fde
JB
13239static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
13240{
13241 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13242 struct wireless_dev *wdev = info->user_ptr[1];
13243 int err;
13244
13245 if (!rdev->ops->start_p2p_device)
13246 return -EOPNOTSUPP;
13247
13248 if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
13249 return -EOPNOTSUPP;
13250
73c7da3d 13251 if (wdev_running(wdev))
98104fde
JB
13252 return 0;
13253
358ae888 13254 if (rfkill_blocked(rdev->wiphy.rfkill))
b6a55015 13255 return -ERFKILL;
98104fde 13256
eeb126e9 13257 err = rdev_start_p2p_device(rdev, wdev);
98104fde
JB
13258 if (err)
13259 return err;
13260
73c7da3d 13261 wdev->is_running = true;
98104fde 13262 rdev->opencount++;
98104fde
JB
13263
13264 return 0;
13265}
13266
13267static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
13268{
13269 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13270 struct wireless_dev *wdev = info->user_ptr[1];
13271
13272 if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
13273 return -EOPNOTSUPP;
13274
13275 if (!rdev->ops->stop_p2p_device)
13276 return -EOPNOTSUPP;
13277
f9f47529 13278 cfg80211_stop_p2p_device(rdev, wdev);
98104fde
JB
13279
13280 return 0;
13281}
13282
cb3b7d87
AB
13283static int nl80211_start_nan(struct sk_buff *skb, struct genl_info *info)
13284{
13285 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13286 struct wireless_dev *wdev = info->user_ptr[1];
13287 struct cfg80211_nan_conf conf = {};
13288 int err;
13289
13290 if (wdev->iftype != NL80211_IFTYPE_NAN)
13291 return -EOPNOTSUPP;
13292
eeb04a96 13293 if (wdev_running(wdev))
cb3b7d87
AB
13294 return -EEXIST;
13295
358ae888 13296 if (rfkill_blocked(rdev->wiphy.rfkill))
cb3b7d87
AB
13297 return -ERFKILL;
13298
13299 if (!info->attrs[NL80211_ATTR_NAN_MASTER_PREF])
13300 return -EINVAL;
13301
cb3b7d87
AB
13302 conf.master_pref =
13303 nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]);
cb3b7d87 13304
8585989d
LC
13305 if (info->attrs[NL80211_ATTR_BANDS]) {
13306 u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]);
13307
13308 if (bands & ~(u32)wdev->wiphy->nan_supported_bands)
13309 return -EOPNOTSUPP;
13310
13311 if (bands && !(bands & BIT(NL80211_BAND_2GHZ)))
13312 return -EINVAL;
13313
13314 conf.bands = bands;
13315 }
cb3b7d87
AB
13316
13317 err = rdev_start_nan(rdev, wdev, &conf);
13318 if (err)
13319 return err;
13320
73c7da3d 13321 wdev->is_running = true;
cb3b7d87
AB
13322 rdev->opencount++;
13323
13324 return 0;
13325}
13326
13327static int nl80211_stop_nan(struct sk_buff *skb, struct genl_info *info)
13328{
13329 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13330 struct wireless_dev *wdev = info->user_ptr[1];
13331
13332 if (wdev->iftype != NL80211_IFTYPE_NAN)
13333 return -EOPNOTSUPP;
13334
13335 cfg80211_stop_nan(rdev, wdev);
13336
13337 return 0;
13338}
13339
a442b761
AB
13340static int validate_nan_filter(struct nlattr *filter_attr)
13341{
13342 struct nlattr *attr;
13343 int len = 0, n_entries = 0, rem;
13344
13345 nla_for_each_nested(attr, filter_attr, rem) {
13346 len += nla_len(attr);
13347 n_entries++;
13348 }
13349
13350 if (len >= U8_MAX)
13351 return -EINVAL;
13352
13353 return n_entries;
13354}
13355
13356static int handle_nan_filter(struct nlattr *attr_filter,
13357 struct cfg80211_nan_func *func,
13358 bool tx)
13359{
13360 struct nlattr *attr;
13361 int n_entries, rem, i;
13362 struct cfg80211_nan_func_filter *filter;
13363
13364 n_entries = validate_nan_filter(attr_filter);
13365 if (n_entries < 0)
13366 return n_entries;
13367
13368 BUILD_BUG_ON(sizeof(*func->rx_filters) != sizeof(*func->tx_filters));
13369
13370 filter = kcalloc(n_entries, sizeof(*func->rx_filters), GFP_KERNEL);
13371 if (!filter)
13372 return -ENOMEM;
13373
13374 i = 0;
13375 nla_for_each_nested(attr, attr_filter, rem) {
b15ca182 13376 filter[i].filter = nla_memdup(attr, GFP_KERNEL);
a442b761
AB
13377 filter[i].len = nla_len(attr);
13378 i++;
13379 }
13380 if (tx) {
13381 func->num_tx_filters = n_entries;
13382 func->tx_filters = filter;
13383 } else {
13384 func->num_rx_filters = n_entries;
13385 func->rx_filters = filter;
13386 }
13387
13388 return 0;
13389}
13390
13391static int nl80211_nan_add_func(struct sk_buff *skb,
13392 struct genl_info *info)
13393{
13394 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13395 struct wireless_dev *wdev = info->user_ptr[1];
13396 struct nlattr *tb[NUM_NL80211_NAN_FUNC_ATTR], *func_attr;
13397 struct cfg80211_nan_func *func;
13398 struct sk_buff *msg = NULL;
13399 void *hdr = NULL;
13400 int err = 0;
13401
13402 if (wdev->iftype != NL80211_IFTYPE_NAN)
13403 return -EOPNOTSUPP;
13404
73c7da3d 13405 if (!wdev_running(wdev))
a442b761
AB
13406 return -ENOTCONN;
13407
13408 if (!info->attrs[NL80211_ATTR_NAN_FUNC])
13409 return -EINVAL;
13410
8cb08174
JB
13411 err = nla_parse_nested_deprecated(tb, NL80211_NAN_FUNC_ATTR_MAX,
13412 info->attrs[NL80211_ATTR_NAN_FUNC],
13413 nl80211_nan_func_policy,
13414 info->extack);
a442b761
AB
13415 if (err)
13416 return err;
13417
13418 func = kzalloc(sizeof(*func), GFP_KERNEL);
13419 if (!func)
13420 return -ENOMEM;
13421
b60ad348 13422 func->cookie = cfg80211_assign_cookie(rdev);
a442b761 13423
cb9abd48 13424 if (!tb[NL80211_NAN_FUNC_TYPE]) {
a442b761
AB
13425 err = -EINVAL;
13426 goto out;
13427 }
13428
13429
13430 func->type = nla_get_u8(tb[NL80211_NAN_FUNC_TYPE]);
13431
13432 if (!tb[NL80211_NAN_FUNC_SERVICE_ID]) {
13433 err = -EINVAL;
13434 goto out;
13435 }
13436
13437 memcpy(func->service_id, nla_data(tb[NL80211_NAN_FUNC_SERVICE_ID]),
13438 sizeof(func->service_id));
13439
13440 func->close_range =
13441 nla_get_flag(tb[NL80211_NAN_FUNC_CLOSE_RANGE]);
13442
13443 if (tb[NL80211_NAN_FUNC_SERVICE_INFO]) {
13444 func->serv_spec_info_len =
13445 nla_len(tb[NL80211_NAN_FUNC_SERVICE_INFO]);
13446 func->serv_spec_info =
13447 kmemdup(nla_data(tb[NL80211_NAN_FUNC_SERVICE_INFO]),
13448 func->serv_spec_info_len,
13449 GFP_KERNEL);
13450 if (!func->serv_spec_info) {
13451 err = -ENOMEM;
13452 goto out;
13453 }
13454 }
13455
13456 if (tb[NL80211_NAN_FUNC_TTL])
13457 func->ttl = nla_get_u32(tb[NL80211_NAN_FUNC_TTL]);
13458
13459 switch (func->type) {
13460 case NL80211_NAN_FUNC_PUBLISH:
13461 if (!tb[NL80211_NAN_FUNC_PUBLISH_TYPE]) {
13462 err = -EINVAL;
13463 goto out;
13464 }
13465
13466 func->publish_type =
13467 nla_get_u8(tb[NL80211_NAN_FUNC_PUBLISH_TYPE]);
13468 func->publish_bcast =
13469 nla_get_flag(tb[NL80211_NAN_FUNC_PUBLISH_BCAST]);
13470
13471 if ((!(func->publish_type & NL80211_NAN_SOLICITED_PUBLISH)) &&
13472 func->publish_bcast) {
13473 err = -EINVAL;
13474 goto out;
13475 }
13476 break;
13477 case NL80211_NAN_FUNC_SUBSCRIBE:
13478 func->subscribe_active =
13479 nla_get_flag(tb[NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE]);
13480 break;
13481 case NL80211_NAN_FUNC_FOLLOW_UP:
13482 if (!tb[NL80211_NAN_FUNC_FOLLOW_UP_ID] ||
3ea15452
HC
13483 !tb[NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID] ||
13484 !tb[NL80211_NAN_FUNC_FOLLOW_UP_DEST]) {
a442b761
AB
13485 err = -EINVAL;
13486 goto out;
13487 }
13488
13489 func->followup_id =
13490 nla_get_u8(tb[NL80211_NAN_FUNC_FOLLOW_UP_ID]);
13491 func->followup_reqid =
13492 nla_get_u8(tb[NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID]);
13493 memcpy(func->followup_dest.addr,
13494 nla_data(tb[NL80211_NAN_FUNC_FOLLOW_UP_DEST]),
13495 sizeof(func->followup_dest.addr));
13496 if (func->ttl) {
13497 err = -EINVAL;
13498 goto out;
13499 }
13500 break;
13501 default:
13502 err = -EINVAL;
13503 goto out;
13504 }
13505
13506 if (tb[NL80211_NAN_FUNC_SRF]) {
13507 struct nlattr *srf_tb[NUM_NL80211_NAN_SRF_ATTR];
13508
8cb08174
JB
13509 err = nla_parse_nested_deprecated(srf_tb,
13510 NL80211_NAN_SRF_ATTR_MAX,
13511 tb[NL80211_NAN_FUNC_SRF],
13512 nl80211_nan_srf_policy,
13513 info->extack);
a442b761
AB
13514 if (err)
13515 goto out;
13516
13517 func->srf_include =
13518 nla_get_flag(srf_tb[NL80211_NAN_SRF_INCLUDE]);
13519
13520 if (srf_tb[NL80211_NAN_SRF_BF]) {
13521 if (srf_tb[NL80211_NAN_SRF_MAC_ADDRS] ||
13522 !srf_tb[NL80211_NAN_SRF_BF_IDX]) {
13523 err = -EINVAL;
13524 goto out;
13525 }
13526
13527 func->srf_bf_len =
13528 nla_len(srf_tb[NL80211_NAN_SRF_BF]);
13529 func->srf_bf =
13530 kmemdup(nla_data(srf_tb[NL80211_NAN_SRF_BF]),
13531 func->srf_bf_len, GFP_KERNEL);
13532 if (!func->srf_bf) {
13533 err = -ENOMEM;
13534 goto out;
13535 }
13536
13537 func->srf_bf_idx =
13538 nla_get_u8(srf_tb[NL80211_NAN_SRF_BF_IDX]);
13539 } else {
13540 struct nlattr *attr, *mac_attr =
13541 srf_tb[NL80211_NAN_SRF_MAC_ADDRS];
13542 int n_entries, rem, i = 0;
13543
13544 if (!mac_attr) {
13545 err = -EINVAL;
13546 goto out;
13547 }
13548
13549 n_entries = validate_acl_mac_addrs(mac_attr);
13550 if (n_entries <= 0) {
13551 err = -EINVAL;
13552 goto out;
13553 }
13554
13555 func->srf_num_macs = n_entries;
13556 func->srf_macs =
6396bb22 13557 kcalloc(n_entries, sizeof(*func->srf_macs),
a442b761
AB
13558 GFP_KERNEL);
13559 if (!func->srf_macs) {
13560 err = -ENOMEM;
13561 goto out;
13562 }
13563
13564 nla_for_each_nested(attr, mac_attr, rem)
13565 memcpy(func->srf_macs[i++].addr, nla_data(attr),
13566 sizeof(*func->srf_macs));
13567 }
13568 }
13569
13570 if (tb[NL80211_NAN_FUNC_TX_MATCH_FILTER]) {
13571 err = handle_nan_filter(tb[NL80211_NAN_FUNC_TX_MATCH_FILTER],
13572 func, true);
13573 if (err)
13574 goto out;
13575 }
13576
13577 if (tb[NL80211_NAN_FUNC_RX_MATCH_FILTER]) {
13578 err = handle_nan_filter(tb[NL80211_NAN_FUNC_RX_MATCH_FILTER],
13579 func, false);
13580 if (err)
13581 goto out;
13582 }
13583
13584 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
13585 if (!msg) {
13586 err = -ENOMEM;
13587 goto out;
13588 }
13589
13590 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
13591 NL80211_CMD_ADD_NAN_FUNCTION);
13592 /* This can't really happen - we just allocated 4KB */
13593 if (WARN_ON(!hdr)) {
13594 err = -ENOMEM;
13595 goto out;
13596 }
13597
13598 err = rdev_add_nan_func(rdev, wdev, func);
13599out:
13600 if (err < 0) {
13601 cfg80211_free_nan_func(func);
13602 nlmsg_free(msg);
13603 return err;
13604 }
13605
13606 /* propagate the instance id and cookie to userspace */
13607 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, func->cookie,
13608 NL80211_ATTR_PAD))
13609 goto nla_put_failure;
13610
ae0be8de 13611 func_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_FUNC);
a442b761
AB
13612 if (!func_attr)
13613 goto nla_put_failure;
13614
13615 if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID,
13616 func->instance_id))
13617 goto nla_put_failure;
13618
13619 nla_nest_end(msg, func_attr);
13620
13621 genlmsg_end(msg, hdr);
13622 return genlmsg_reply(msg, info);
13623
13624nla_put_failure:
13625 nlmsg_free(msg);
13626 return -ENOBUFS;
13627}
13628
13629static int nl80211_nan_del_func(struct sk_buff *skb,
13630 struct genl_info *info)
13631{
13632 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13633 struct wireless_dev *wdev = info->user_ptr[1];
13634 u64 cookie;
13635
13636 if (wdev->iftype != NL80211_IFTYPE_NAN)
13637 return -EOPNOTSUPP;
13638
73c7da3d 13639 if (!wdev_running(wdev))
a442b761
AB
13640 return -ENOTCONN;
13641
13642 if (!info->attrs[NL80211_ATTR_COOKIE])
13643 return -EINVAL;
13644
a442b761
AB
13645 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
13646
13647 rdev_del_nan_func(rdev, wdev, cookie);
13648
13649 return 0;
13650}
13651
a5a9dcf2
AB
13652static int nl80211_nan_change_config(struct sk_buff *skb,
13653 struct genl_info *info)
13654{
13655 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13656 struct wireless_dev *wdev = info->user_ptr[1];
13657 struct cfg80211_nan_conf conf = {};
13658 u32 changed = 0;
13659
13660 if (wdev->iftype != NL80211_IFTYPE_NAN)
13661 return -EOPNOTSUPP;
13662
73c7da3d 13663 if (!wdev_running(wdev))
a5a9dcf2
AB
13664 return -ENOTCONN;
13665
13666 if (info->attrs[NL80211_ATTR_NAN_MASTER_PREF]) {
13667 conf.master_pref =
13668 nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]);
13669 if (conf.master_pref <= 1 || conf.master_pref == 255)
13670 return -EINVAL;
13671
13672 changed |= CFG80211_NAN_CONF_CHANGED_PREF;
13673 }
13674
8585989d
LC
13675 if (info->attrs[NL80211_ATTR_BANDS]) {
13676 u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]);
13677
13678 if (bands & ~(u32)wdev->wiphy->nan_supported_bands)
13679 return -EOPNOTSUPP;
13680
13681 if (bands && !(bands & BIT(NL80211_BAND_2GHZ)))
13682 return -EINVAL;
13683
13684 conf.bands = bands;
13685 changed |= CFG80211_NAN_CONF_CHANGED_BANDS;
a5a9dcf2
AB
13686 }
13687
13688 if (!changed)
13689 return -EINVAL;
13690
13691 return rdev_nan_change_conf(rdev, wdev, &conf, changed);
13692}
13693
50bcd31d
AB
13694void cfg80211_nan_match(struct wireless_dev *wdev,
13695 struct cfg80211_nan_match_params *match, gfp_t gfp)
13696{
13697 struct wiphy *wiphy = wdev->wiphy;
13698 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
13699 struct nlattr *match_attr, *local_func_attr, *peer_func_attr;
13700 struct sk_buff *msg;
13701 void *hdr;
13702
13703 if (WARN_ON(!match->inst_id || !match->peer_inst_id || !match->addr))
13704 return;
13705
13706 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
13707 if (!msg)
13708 return;
13709
13710 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NAN_MATCH);
13711 if (!hdr) {
13712 nlmsg_free(msg);
13713 return;
13714 }
13715
13716 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
13717 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
13718 wdev->netdev->ifindex)) ||
13719 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
13720 NL80211_ATTR_PAD))
13721 goto nla_put_failure;
13722
13723 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, match->cookie,
13724 NL80211_ATTR_PAD) ||
13725 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, match->addr))
13726 goto nla_put_failure;
13727
ae0be8de 13728 match_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_MATCH);
50bcd31d
AB
13729 if (!match_attr)
13730 goto nla_put_failure;
13731
ae0be8de
MK
13732 local_func_attr = nla_nest_start_noflag(msg,
13733 NL80211_NAN_MATCH_FUNC_LOCAL);
50bcd31d
AB
13734 if (!local_func_attr)
13735 goto nla_put_failure;
13736
13737 if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, match->inst_id))
13738 goto nla_put_failure;
13739
13740 nla_nest_end(msg, local_func_attr);
13741
ae0be8de
MK
13742 peer_func_attr = nla_nest_start_noflag(msg,
13743 NL80211_NAN_MATCH_FUNC_PEER);
50bcd31d
AB
13744 if (!peer_func_attr)
13745 goto nla_put_failure;
13746
13747 if (nla_put_u8(msg, NL80211_NAN_FUNC_TYPE, match->type) ||
13748 nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, match->peer_inst_id))
13749 goto nla_put_failure;
13750
13751 if (match->info && match->info_len &&
13752 nla_put(msg, NL80211_NAN_FUNC_SERVICE_INFO, match->info_len,
13753 match->info))
13754 goto nla_put_failure;
13755
13756 nla_nest_end(msg, peer_func_attr);
13757 nla_nest_end(msg, match_attr);
13758 genlmsg_end(msg, hdr);
13759
13760 if (!wdev->owner_nlportid)
13761 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
13762 msg, 0, NL80211_MCGRP_NAN, gfp);
13763 else
13764 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
13765 wdev->owner_nlportid);
13766
13767 return;
13768
13769nla_put_failure:
13770 nlmsg_free(msg);
13771}
13772EXPORT_SYMBOL(cfg80211_nan_match);
13773
368e5a7b
AB
13774void cfg80211_nan_func_terminated(struct wireless_dev *wdev,
13775 u8 inst_id,
13776 enum nl80211_nan_func_term_reason reason,
13777 u64 cookie, gfp_t gfp)
13778{
13779 struct wiphy *wiphy = wdev->wiphy;
13780 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
13781 struct sk_buff *msg;
13782 struct nlattr *func_attr;
13783 void *hdr;
13784
13785 if (WARN_ON(!inst_id))
13786 return;
13787
13788 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
13789 if (!msg)
13790 return;
13791
13792 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DEL_NAN_FUNCTION);
13793 if (!hdr) {
13794 nlmsg_free(msg);
13795 return;
13796 }
13797
13798 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
13799 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
13800 wdev->netdev->ifindex)) ||
13801 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
13802 NL80211_ATTR_PAD))
13803 goto nla_put_failure;
13804
13805 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
13806 NL80211_ATTR_PAD))
13807 goto nla_put_failure;
13808
ae0be8de 13809 func_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_FUNC);
368e5a7b
AB
13810 if (!func_attr)
13811 goto nla_put_failure;
13812
13813 if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, inst_id) ||
13814 nla_put_u8(msg, NL80211_NAN_FUNC_TERM_REASON, reason))
13815 goto nla_put_failure;
13816
13817 nla_nest_end(msg, func_attr);
13818 genlmsg_end(msg, hdr);
13819
13820 if (!wdev->owner_nlportid)
13821 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
13822 msg, 0, NL80211_MCGRP_NAN, gfp);
13823 else
13824 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
13825 wdev->owner_nlportid);
13826
13827 return;
13828
13829nla_put_failure:
13830 nlmsg_free(msg);
13831}
13832EXPORT_SYMBOL(cfg80211_nan_func_terminated);
13833
3713b4e3
JB
13834static int nl80211_get_protocol_features(struct sk_buff *skb,
13835 struct genl_info *info)
13836{
13837 void *hdr;
13838 struct sk_buff *msg;
13839
13840 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
13841 if (!msg)
13842 return -ENOMEM;
13843
13844 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
13845 NL80211_CMD_GET_PROTOCOL_FEATURES);
13846 if (!hdr)
13847 goto nla_put_failure;
13848
13849 if (nla_put_u32(msg, NL80211_ATTR_PROTOCOL_FEATURES,
13850 NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP))
13851 goto nla_put_failure;
13852
13853 genlmsg_end(msg, hdr);
13854 return genlmsg_reply(msg, info);
13855
13856 nla_put_failure:
13857 kfree_skb(msg);
13858 return -ENOBUFS;
13859}
13860
355199e0
JM
13861static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info)
13862{
13863 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13864 struct cfg80211_update_ft_ies_params ft_params;
13865 struct net_device *dev = info->user_ptr[1];
13866
13867 if (!rdev->ops->update_ft_ies)
13868 return -EOPNOTSUPP;
13869
13870 if (!info->attrs[NL80211_ATTR_MDID] ||
3d7af878 13871 !info->attrs[NL80211_ATTR_IE])
355199e0
JM
13872 return -EINVAL;
13873
13874 memset(&ft_params, 0, sizeof(ft_params));
13875 ft_params.md = nla_get_u16(info->attrs[NL80211_ATTR_MDID]);
13876 ft_params.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
13877 ft_params.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
13878
13879 return rdev_update_ft_ies(rdev, dev, &ft_params);
13880}
13881
5de17984
AS
13882static int nl80211_crit_protocol_start(struct sk_buff *skb,
13883 struct genl_info *info)
13884{
13885 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13886 struct wireless_dev *wdev = info->user_ptr[1];
13887 enum nl80211_crit_proto_id proto = NL80211_CRIT_PROTO_UNSPEC;
13888 u16 duration;
13889 int ret;
13890
13891 if (!rdev->ops->crit_proto_start)
13892 return -EOPNOTSUPP;
13893
13894 if (WARN_ON(!rdev->ops->crit_proto_stop))
13895 return -EINVAL;
13896
13897 if (rdev->crit_proto_nlportid)
13898 return -EBUSY;
13899
13900 /* determine protocol if provided */
13901 if (info->attrs[NL80211_ATTR_CRIT_PROT_ID])
13902 proto = nla_get_u16(info->attrs[NL80211_ATTR_CRIT_PROT_ID]);
13903
13904 if (proto >= NUM_NL80211_CRIT_PROTO)
13905 return -EINVAL;
13906
13907 /* timeout must be provided */
13908 if (!info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION])
13909 return -EINVAL;
13910
13911 duration =
13912 nla_get_u16(info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION]);
13913
5de17984
AS
13914 ret = rdev_crit_proto_start(rdev, wdev, proto, duration);
13915 if (!ret)
13916 rdev->crit_proto_nlportid = info->snd_portid;
13917
13918 return ret;
13919}
13920
13921static int nl80211_crit_protocol_stop(struct sk_buff *skb,
13922 struct genl_info *info)
13923{
13924 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13925 struct wireless_dev *wdev = info->user_ptr[1];
13926
13927 if (!rdev->ops->crit_proto_stop)
13928 return -EOPNOTSUPP;
13929
13930 if (rdev->crit_proto_nlportid) {
13931 rdev->crit_proto_nlportid = 0;
13932 rdev_crit_proto_stop(rdev, wdev);
13933 }
13934 return 0;
13935}
13936
901bb989
JB
13937static int nl80211_vendor_check_policy(const struct wiphy_vendor_command *vcmd,
13938 struct nlattr *attr,
13939 struct netlink_ext_ack *extack)
13940{
13941 if (vcmd->policy == VENDOR_CMD_RAW_DATA) {
13942 if (attr->nla_type & NLA_F_NESTED) {
13943 NL_SET_ERR_MSG_ATTR(extack, attr,
13944 "unexpected nested data");
13945 return -EINVAL;
13946 }
13947
13948 return 0;
13949 }
13950
13951 if (!(attr->nla_type & NLA_F_NESTED)) {
13952 NL_SET_ERR_MSG_ATTR(extack, attr, "expected nested data");
13953 return -EINVAL;
13954 }
13955
32d5109a 13956 return nla_validate_nested(attr, vcmd->maxattr, vcmd->policy, extack);
901bb989
JB
13957}
13958
ad7e718c
JB
13959static int nl80211_vendor_cmd(struct sk_buff *skb, struct genl_info *info)
13960{
13961 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13962 struct wireless_dev *wdev =
a05829a7
JB
13963 __cfg80211_wdev_from_attrs(rdev, genl_info_net(info),
13964 info->attrs);
ad7e718c
JB
13965 int i, err;
13966 u32 vid, subcmd;
13967
13968 if (!rdev->wiphy.vendor_commands)
13969 return -EOPNOTSUPP;
13970
13971 if (IS_ERR(wdev)) {
13972 err = PTR_ERR(wdev);
13973 if (err != -EINVAL)
13974 return err;
13975 wdev = NULL;
13976 } else if (wdev->wiphy != &rdev->wiphy) {
13977 return -EINVAL;
13978 }
13979
13980 if (!info->attrs[NL80211_ATTR_VENDOR_ID] ||
13981 !info->attrs[NL80211_ATTR_VENDOR_SUBCMD])
13982 return -EINVAL;
13983
13984 vid = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_ID]);
13985 subcmd = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_SUBCMD]);
13986 for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) {
13987 const struct wiphy_vendor_command *vcmd;
13988 void *data = NULL;
13989 int len = 0;
13990
13991 vcmd = &rdev->wiphy.vendor_commands[i];
13992
13993 if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd)
13994 continue;
13995
13996 if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV |
13997 WIPHY_VENDOR_CMD_NEED_NETDEV)) {
13998 if (!wdev)
13999 return -EINVAL;
14000 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV &&
14001 !wdev->netdev)
14002 return -EINVAL;
14003
14004 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
73c7da3d 14005 if (!wdev_running(wdev))
ad7e718c
JB
14006 return -ENETDOWN;
14007 }
14008 } else {
14009 wdev = NULL;
14010 }
14011
4052d3d2
JS
14012 if (!vcmd->doit)
14013 return -EOPNOTSUPP;
14014
ad7e718c
JB
14015 if (info->attrs[NL80211_ATTR_VENDOR_DATA]) {
14016 data = nla_data(info->attrs[NL80211_ATTR_VENDOR_DATA]);
14017 len = nla_len(info->attrs[NL80211_ATTR_VENDOR_DATA]);
901bb989
JB
14018
14019 err = nl80211_vendor_check_policy(vcmd,
14020 info->attrs[NL80211_ATTR_VENDOR_DATA],
14021 info->extack);
14022 if (err)
14023 return err;
ad7e718c
JB
14024 }
14025
14026 rdev->cur_cmd_info = info;
901bb989 14027 err = vcmd->doit(&rdev->wiphy, wdev, data, len);
ad7e718c
JB
14028 rdev->cur_cmd_info = NULL;
14029 return err;
14030 }
14031
14032 return -EOPNOTSUPP;
14033}
14034
7bdbe400
JB
14035static int nl80211_prepare_vendor_dump(struct sk_buff *skb,
14036 struct netlink_callback *cb,
14037 struct cfg80211_registered_device **rdev,
14038 struct wireless_dev **wdev)
14039{
50508d94 14040 struct nlattr **attrbuf;
7bdbe400
JB
14041 u32 vid, subcmd;
14042 unsigned int i;
14043 int vcmd_idx = -1;
14044 int err;
14045 void *data = NULL;
14046 unsigned int data_len = 0;
14047
7bdbe400
JB
14048 if (cb->args[0]) {
14049 /* subtract the 1 again here */
14050 struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
14051 struct wireless_dev *tmp;
14052
ea90e0dc
JB
14053 if (!wiphy)
14054 return -ENODEV;
7bdbe400
JB
14055 *rdev = wiphy_to_rdev(wiphy);
14056 *wdev = NULL;
14057
14058 if (cb->args[1]) {
53873f13 14059 list_for_each_entry(tmp, &wiphy->wdev_list, list) {
7bdbe400
JB
14060 if (tmp->identifier == cb->args[1] - 1) {
14061 *wdev = tmp;
14062 break;
14063 }
14064 }
14065 }
14066
14067 /* keep rtnl locked in successful case */
14068 return 0;
14069 }
14070
50508d94
JB
14071 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), GFP_KERNEL);
14072 if (!attrbuf)
14073 return -ENOMEM;
14074
8cb08174
JB
14075 err = nlmsg_parse_deprecated(cb->nlh,
14076 GENL_HDRLEN + nl80211_fam.hdrsize,
14077 attrbuf, nl80211_fam.maxattr,
14078 nl80211_policy, NULL);
7bdbe400 14079 if (err)
50508d94 14080 goto out;
7bdbe400 14081
c90c39da 14082 if (!attrbuf[NL80211_ATTR_VENDOR_ID] ||
50508d94
JB
14083 !attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) {
14084 err = -EINVAL;
14085 goto out;
14086 }
7bdbe400 14087
a05829a7 14088 *wdev = __cfg80211_wdev_from_attrs(NULL, sock_net(skb->sk), attrbuf);
7bdbe400
JB
14089 if (IS_ERR(*wdev))
14090 *wdev = NULL;
14091
c90c39da 14092 *rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
50508d94
JB
14093 if (IS_ERR(*rdev)) {
14094 err = PTR_ERR(*rdev);
14095 goto out;
14096 }
7bdbe400 14097
c90c39da
JB
14098 vid = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_ID]);
14099 subcmd = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_SUBCMD]);
7bdbe400
JB
14100
14101 for (i = 0; i < (*rdev)->wiphy.n_vendor_commands; i++) {
14102 const struct wiphy_vendor_command *vcmd;
14103
14104 vcmd = &(*rdev)->wiphy.vendor_commands[i];
14105
14106 if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd)
14107 continue;
14108
50508d94
JB
14109 if (!vcmd->dumpit) {
14110 err = -EOPNOTSUPP;
14111 goto out;
14112 }
7bdbe400
JB
14113
14114 vcmd_idx = i;
14115 break;
14116 }
14117
50508d94
JB
14118 if (vcmd_idx < 0) {
14119 err = -EOPNOTSUPP;
14120 goto out;
14121 }
7bdbe400 14122
c90c39da
JB
14123 if (attrbuf[NL80211_ATTR_VENDOR_DATA]) {
14124 data = nla_data(attrbuf[NL80211_ATTR_VENDOR_DATA]);
14125 data_len = nla_len(attrbuf[NL80211_ATTR_VENDOR_DATA]);
901bb989
JB
14126
14127 err = nl80211_vendor_check_policy(
14128 &(*rdev)->wiphy.vendor_commands[vcmd_idx],
14129 attrbuf[NL80211_ATTR_VENDOR_DATA],
14130 cb->extack);
14131 if (err)
50508d94 14132 goto out;
7bdbe400
JB
14133 }
14134
14135 /* 0 is the first index - add 1 to parse only once */
14136 cb->args[0] = (*rdev)->wiphy_idx + 1;
14137 /* add 1 to know if it was NULL */
14138 cb->args[1] = *wdev ? (*wdev)->identifier + 1 : 0;
14139 cb->args[2] = vcmd_idx;
14140 cb->args[3] = (unsigned long)data;
14141 cb->args[4] = data_len;
14142
14143 /* keep rtnl locked in successful case */
50508d94
JB
14144 err = 0;
14145out:
14146 kfree(attrbuf);
14147 return err;
7bdbe400
JB
14148}
14149
14150static int nl80211_vendor_cmd_dump(struct sk_buff *skb,
14151 struct netlink_callback *cb)
14152{
14153 struct cfg80211_registered_device *rdev;
14154 struct wireless_dev *wdev;
14155 unsigned int vcmd_idx;
14156 const struct wiphy_vendor_command *vcmd;
14157 void *data;
14158 int data_len;
14159 int err;
14160 struct nlattr *vendor_data;
14161
ea90e0dc 14162 rtnl_lock();
7bdbe400
JB
14163 err = nl80211_prepare_vendor_dump(skb, cb, &rdev, &wdev);
14164 if (err)
ea90e0dc 14165 goto out;
7bdbe400
JB
14166
14167 vcmd_idx = cb->args[2];
14168 data = (void *)cb->args[3];
14169 data_len = cb->args[4];
14170 vcmd = &rdev->wiphy.vendor_commands[vcmd_idx];
14171
14172 if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV |
14173 WIPHY_VENDOR_CMD_NEED_NETDEV)) {
ea90e0dc
JB
14174 if (!wdev) {
14175 err = -EINVAL;
14176 goto out;
14177 }
7bdbe400 14178 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV &&
ea90e0dc
JB
14179 !wdev->netdev) {
14180 err = -EINVAL;
14181 goto out;
14182 }
7bdbe400
JB
14183
14184 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
ea90e0dc
JB
14185 if (!wdev_running(wdev)) {
14186 err = -ENETDOWN;
14187 goto out;
14188 }
7bdbe400
JB
14189 }
14190 }
14191
14192 while (1) {
14193 void *hdr = nl80211hdr_put(skb, NETLINK_CB(cb->skb).portid,
14194 cb->nlh->nlmsg_seq, NLM_F_MULTI,
14195 NL80211_CMD_VENDOR);
14196 if (!hdr)
14197 break;
14198
14199 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
2dad624e
ND
14200 (wdev && nla_put_u64_64bit(skb, NL80211_ATTR_WDEV,
14201 wdev_id(wdev),
14202 NL80211_ATTR_PAD))) {
7bdbe400
JB
14203 genlmsg_cancel(skb, hdr);
14204 break;
14205 }
14206
ae0be8de
MK
14207 vendor_data = nla_nest_start_noflag(skb,
14208 NL80211_ATTR_VENDOR_DATA);
7bdbe400
JB
14209 if (!vendor_data) {
14210 genlmsg_cancel(skb, hdr);
14211 break;
14212 }
14213
14214 err = vcmd->dumpit(&rdev->wiphy, wdev, skb, data, data_len,
14215 (unsigned long *)&cb->args[5]);
14216 nla_nest_end(skb, vendor_data);
14217
14218 if (err == -ENOBUFS || err == -ENOENT) {
14219 genlmsg_cancel(skb, hdr);
14220 break;
9c167b2d 14221 } else if (err <= 0) {
7bdbe400
JB
14222 genlmsg_cancel(skb, hdr);
14223 goto out;
14224 }
14225
14226 genlmsg_end(skb, hdr);
14227 }
14228
14229 err = skb->len;
14230 out:
14231 rtnl_unlock();
14232 return err;
14233}
14234
ad7e718c
JB
14235struct sk_buff *__cfg80211_alloc_reply_skb(struct wiphy *wiphy,
14236 enum nl80211_commands cmd,
14237 enum nl80211_attrs attr,
14238 int approxlen)
14239{
f26cbf40 14240 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
ad7e718c
JB
14241
14242 if (WARN_ON(!rdev->cur_cmd_info))
14243 return NULL;
14244
6c09e791 14245 return __cfg80211_alloc_vendor_skb(rdev, NULL, approxlen,
ad7e718c
JB
14246 rdev->cur_cmd_info->snd_portid,
14247 rdev->cur_cmd_info->snd_seq,
567ffc35 14248 cmd, attr, NULL, GFP_KERNEL);
ad7e718c
JB
14249}
14250EXPORT_SYMBOL(__cfg80211_alloc_reply_skb);
14251
14252int cfg80211_vendor_cmd_reply(struct sk_buff *skb)
14253{
14254 struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
14255 void *hdr = ((void **)skb->cb)[1];
14256 struct nlattr *data = ((void **)skb->cb)[2];
14257
bd8c78e7
JB
14258 /* clear CB data for netlink core to own from now on */
14259 memset(skb->cb, 0, sizeof(skb->cb));
14260
ad7e718c
JB
14261 if (WARN_ON(!rdev->cur_cmd_info)) {
14262 kfree_skb(skb);
14263 return -EINVAL;
14264 }
14265
14266 nla_nest_end(skb, data);
14267 genlmsg_end(skb, hdr);
14268 return genlmsg_reply(skb, rdev->cur_cmd_info);
14269}
14270EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_reply);
14271
55c1fdf0
JB
14272unsigned int cfg80211_vendor_cmd_get_sender(struct wiphy *wiphy)
14273{
14274 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
14275
14276 if (WARN_ON(!rdev->cur_cmd_info))
14277 return 0;
14278
14279 return rdev->cur_cmd_info->snd_portid;
14280}
14281EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_get_sender);
14282
fa9ffc74
KP
14283static int nl80211_set_qos_map(struct sk_buff *skb,
14284 struct genl_info *info)
14285{
14286 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14287 struct cfg80211_qos_map *qos_map = NULL;
14288 struct net_device *dev = info->user_ptr[1];
14289 u8 *pos, len, num_des, des_len, des;
14290 int ret;
14291
14292 if (!rdev->ops->set_qos_map)
14293 return -EOPNOTSUPP;
14294
14295 if (info->attrs[NL80211_ATTR_QOS_MAP]) {
14296 pos = nla_data(info->attrs[NL80211_ATTR_QOS_MAP]);
14297 len = nla_len(info->attrs[NL80211_ATTR_QOS_MAP]);
14298
c8b82802 14299 if (len % 2)
fa9ffc74
KP
14300 return -EINVAL;
14301
14302 qos_map = kzalloc(sizeof(struct cfg80211_qos_map), GFP_KERNEL);
14303 if (!qos_map)
14304 return -ENOMEM;
14305
14306 num_des = (len - IEEE80211_QOS_MAP_LEN_MIN) >> 1;
14307 if (num_des) {
14308 des_len = num_des *
14309 sizeof(struct cfg80211_dscp_exception);
14310 memcpy(qos_map->dscp_exception, pos, des_len);
14311 qos_map->num_des = num_des;
14312 for (des = 0; des < num_des; des++) {
14313 if (qos_map->dscp_exception[des].up > 7) {
14314 kfree(qos_map);
14315 return -EINVAL;
14316 }
14317 }
14318 pos += des_len;
14319 }
14320 memcpy(qos_map->up, pos, IEEE80211_QOS_MAP_LEN_MIN);
14321 }
14322
14323 wdev_lock(dev->ieee80211_ptr);
14324 ret = nl80211_key_allowed(dev->ieee80211_ptr);
14325 if (!ret)
14326 ret = rdev_set_qos_map(rdev, dev, qos_map);
14327 wdev_unlock(dev->ieee80211_ptr);
14328
14329 kfree(qos_map);
14330 return ret;
14331}
14332
960d01ac
JB
14333static int nl80211_add_tx_ts(struct sk_buff *skb, struct genl_info *info)
14334{
14335 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14336 struct net_device *dev = info->user_ptr[1];
14337 struct wireless_dev *wdev = dev->ieee80211_ptr;
14338 const u8 *peer;
14339 u8 tsid, up;
14340 u16 admitted_time = 0;
14341 int err;
14342
723e73ac 14343 if (!(rdev->wiphy.features & NL80211_FEATURE_SUPPORTS_WMM_ADMISSION))
960d01ac
JB
14344 return -EOPNOTSUPP;
14345
14346 if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC] ||
14347 !info->attrs[NL80211_ATTR_USER_PRIO])
14348 return -EINVAL;
14349
14350 tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
960d01ac 14351 up = nla_get_u8(info->attrs[NL80211_ATTR_USER_PRIO]);
960d01ac
JB
14352
14353 /* WMM uses TIDs 0-7 even for TSPEC */
723e73ac 14354 if (tsid >= IEEE80211_FIRST_TSPEC_TSID) {
960d01ac 14355 /* TODO: handle 802.11 TSPEC/admission control
723e73ac
JB
14356 * need more attributes for that (e.g. BA session requirement);
14357 * change the WMM adminssion test above to allow both then
960d01ac
JB
14358 */
14359 return -EINVAL;
14360 }
14361
14362 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
14363
14364 if (info->attrs[NL80211_ATTR_ADMITTED_TIME]) {
14365 admitted_time =
14366 nla_get_u16(info->attrs[NL80211_ATTR_ADMITTED_TIME]);
14367 if (!admitted_time)
14368 return -EINVAL;
14369 }
14370
14371 wdev_lock(wdev);
14372 switch (wdev->iftype) {
14373 case NL80211_IFTYPE_STATION:
14374 case NL80211_IFTYPE_P2P_CLIENT:
14375 if (wdev->current_bss)
14376 break;
14377 err = -ENOTCONN;
14378 goto out;
14379 default:
14380 err = -EOPNOTSUPP;
14381 goto out;
14382 }
14383
14384 err = rdev_add_tx_ts(rdev, dev, tsid, peer, up, admitted_time);
14385
14386 out:
14387 wdev_unlock(wdev);
14388 return err;
14389}
14390
14391static int nl80211_del_tx_ts(struct sk_buff *skb, struct genl_info *info)
14392{
14393 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14394 struct net_device *dev = info->user_ptr[1];
14395 struct wireless_dev *wdev = dev->ieee80211_ptr;
14396 const u8 *peer;
14397 u8 tsid;
14398 int err;
14399
14400 if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC])
14401 return -EINVAL;
14402
14403 tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
14404 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
14405
14406 wdev_lock(wdev);
14407 err = rdev_del_tx_ts(rdev, dev, tsid, peer);
14408 wdev_unlock(wdev);
14409
14410 return err;
14411}
14412
1057d35e
AN
14413static int nl80211_tdls_channel_switch(struct sk_buff *skb,
14414 struct genl_info *info)
14415{
14416 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14417 struct net_device *dev = info->user_ptr[1];
14418 struct wireless_dev *wdev = dev->ieee80211_ptr;
14419 struct cfg80211_chan_def chandef = {};
14420 const u8 *addr;
14421 u8 oper_class;
14422 int err;
14423
14424 if (!rdev->ops->tdls_channel_switch ||
14425 !(rdev->wiphy.features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH))
14426 return -EOPNOTSUPP;
14427
14428 switch (dev->ieee80211_ptr->iftype) {
14429 case NL80211_IFTYPE_STATION:
14430 case NL80211_IFTYPE_P2P_CLIENT:
14431 break;
14432 default:
14433 return -EOPNOTSUPP;
14434 }
14435
14436 if (!info->attrs[NL80211_ATTR_MAC] ||
14437 !info->attrs[NL80211_ATTR_OPER_CLASS])
14438 return -EINVAL;
14439
14440 err = nl80211_parse_chandef(rdev, info, &chandef);
14441 if (err)
14442 return err;
14443
14444 /*
14445 * Don't allow wide channels on the 2.4Ghz band, as per IEEE802.11-2012
14446 * section 10.22.6.2.1. Disallow 5/10Mhz channels as well for now, the
14447 * specification is not defined for them.
14448 */
57fbcce3 14449 if (chandef.chan->band == NL80211_BAND_2GHZ &&
1057d35e
AN
14450 chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
14451 chandef.width != NL80211_CHAN_WIDTH_20)
14452 return -EINVAL;
14453
14454 /* we will be active on the TDLS link */
923b352f
AN
14455 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
14456 wdev->iftype))
1057d35e
AN
14457 return -EINVAL;
14458
14459 /* don't allow switching to DFS channels */
14460 if (cfg80211_chandef_dfs_required(wdev->wiphy, &chandef, wdev->iftype))
14461 return -EINVAL;
14462
14463 addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
14464 oper_class = nla_get_u8(info->attrs[NL80211_ATTR_OPER_CLASS]);
14465
14466 wdev_lock(wdev);
14467 err = rdev_tdls_channel_switch(rdev, dev, addr, oper_class, &chandef);
14468 wdev_unlock(wdev);
14469
14470 return err;
14471}
14472
14473static int nl80211_tdls_cancel_channel_switch(struct sk_buff *skb,
14474 struct genl_info *info)
14475{
14476 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14477 struct net_device *dev = info->user_ptr[1];
14478 struct wireless_dev *wdev = dev->ieee80211_ptr;
14479 const u8 *addr;
14480
14481 if (!rdev->ops->tdls_channel_switch ||
14482 !rdev->ops->tdls_cancel_channel_switch ||
14483 !(rdev->wiphy.features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH))
14484 return -EOPNOTSUPP;
14485
14486 switch (dev->ieee80211_ptr->iftype) {
14487 case NL80211_IFTYPE_STATION:
14488 case NL80211_IFTYPE_P2P_CLIENT:
14489 break;
14490 default:
14491 return -EOPNOTSUPP;
14492 }
14493
14494 if (!info->attrs[NL80211_ATTR_MAC])
14495 return -EINVAL;
14496
14497 addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
14498
14499 wdev_lock(wdev);
14500 rdev_tdls_cancel_channel_switch(rdev, dev, addr);
14501 wdev_unlock(wdev);
14502
14503 return 0;
14504}
14505
ce0ce13a
MB
14506static int nl80211_set_multicast_to_unicast(struct sk_buff *skb,
14507 struct genl_info *info)
14508{
14509 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14510 struct net_device *dev = info->user_ptr[1];
14511 struct wireless_dev *wdev = dev->ieee80211_ptr;
14512 const struct nlattr *nla;
14513 bool enabled;
14514
ce0ce13a
MB
14515 if (!rdev->ops->set_multicast_to_unicast)
14516 return -EOPNOTSUPP;
14517
14518 if (wdev->iftype != NL80211_IFTYPE_AP &&
14519 wdev->iftype != NL80211_IFTYPE_P2P_GO)
14520 return -EOPNOTSUPP;
14521
14522 nla = info->attrs[NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED];
14523 enabled = nla_get_flag(nla);
14524
14525 return rdev_set_multicast_to_unicast(rdev, dev, enabled);
14526}
14527
3a00df57
AS
14528static int nl80211_set_pmk(struct sk_buff *skb, struct genl_info *info)
14529{
14530 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14531 struct net_device *dev = info->user_ptr[1];
14532 struct wireless_dev *wdev = dev->ieee80211_ptr;
14533 struct cfg80211_pmk_conf pmk_conf = {};
14534 int ret;
14535
14536 if (wdev->iftype != NL80211_IFTYPE_STATION &&
14537 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
14538 return -EOPNOTSUPP;
14539
14540 if (!wiphy_ext_feature_isset(&rdev->wiphy,
14541 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
14542 return -EOPNOTSUPP;
14543
14544 if (!info->attrs[NL80211_ATTR_MAC] || !info->attrs[NL80211_ATTR_PMK])
14545 return -EINVAL;
14546
14547 wdev_lock(wdev);
14548 if (!wdev->current_bss) {
14549 ret = -ENOTCONN;
14550 goto out;
14551 }
14552
14553 pmk_conf.aa = nla_data(info->attrs[NL80211_ATTR_MAC]);
14554 if (memcmp(pmk_conf.aa, wdev->current_bss->pub.bssid, ETH_ALEN)) {
14555 ret = -EINVAL;
14556 goto out;
14557 }
14558
14559 pmk_conf.pmk = nla_data(info->attrs[NL80211_ATTR_PMK]);
14560 pmk_conf.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]);
14561 if (pmk_conf.pmk_len != WLAN_PMK_LEN &&
14562 pmk_conf.pmk_len != WLAN_PMK_LEN_SUITE_B_192) {
14563 ret = -EINVAL;
14564 goto out;
14565 }
14566
cb9abd48 14567 if (info->attrs[NL80211_ATTR_PMKR0_NAME])
3a00df57
AS
14568 pmk_conf.pmk_r0_name =
14569 nla_data(info->attrs[NL80211_ATTR_PMKR0_NAME]);
3a00df57
AS
14570
14571 ret = rdev_set_pmk(rdev, dev, &pmk_conf);
14572out:
14573 wdev_unlock(wdev);
14574 return ret;
14575}
14576
14577static int nl80211_del_pmk(struct sk_buff *skb, struct genl_info *info)
14578{
14579 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14580 struct net_device *dev = info->user_ptr[1];
14581 struct wireless_dev *wdev = dev->ieee80211_ptr;
14582 const u8 *aa;
14583 int ret;
14584
14585 if (wdev->iftype != NL80211_IFTYPE_STATION &&
14586 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
14587 return -EOPNOTSUPP;
14588
14589 if (!wiphy_ext_feature_isset(&rdev->wiphy,
14590 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
14591 return -EOPNOTSUPP;
14592
14593 if (!info->attrs[NL80211_ATTR_MAC])
14594 return -EINVAL;
14595
14596 wdev_lock(wdev);
14597 aa = nla_data(info->attrs[NL80211_ATTR_MAC]);
14598 ret = rdev_del_pmk(rdev, dev, aa);
14599 wdev_unlock(wdev);
14600
14601 return ret;
14602}
14603
40cbfa90
SD
14604static int nl80211_external_auth(struct sk_buff *skb, struct genl_info *info)
14605{
14606 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14607 struct net_device *dev = info->user_ptr[1];
14608 struct cfg80211_external_auth_params params;
14609
db8d93a7 14610 if (!rdev->ops->external_auth)
40cbfa90
SD
14611 return -EOPNOTSUPP;
14612
fe494370
SD
14613 if (!info->attrs[NL80211_ATTR_SSID] &&
14614 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
14615 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
40cbfa90
SD
14616 return -EINVAL;
14617
14618 if (!info->attrs[NL80211_ATTR_BSSID])
14619 return -EINVAL;
14620
14621 if (!info->attrs[NL80211_ATTR_STATUS_CODE])
14622 return -EINVAL;
14623
14624 memset(&params, 0, sizeof(params));
14625
fe494370
SD
14626 if (info->attrs[NL80211_ATTR_SSID]) {
14627 params.ssid.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
cb9abd48 14628 if (params.ssid.ssid_len == 0)
fe494370
SD
14629 return -EINVAL;
14630 memcpy(params.ssid.ssid,
14631 nla_data(info->attrs[NL80211_ATTR_SSID]),
14632 params.ssid.ssid_len);
14633 }
40cbfa90
SD
14634
14635 memcpy(params.bssid, nla_data(info->attrs[NL80211_ATTR_BSSID]),
14636 ETH_ALEN);
14637
14638 params.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
14639
fe494370
SD
14640 if (info->attrs[NL80211_ATTR_PMKID])
14641 params.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
14642
40cbfa90
SD
14643 return rdev_external_auth(rdev, dev, &params);
14644}
14645
2576a9ac
DK
14646static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
14647{
dca9ca2d 14648 bool dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK];
2576a9ac
DK
14649 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14650 struct net_device *dev = info->user_ptr[1];
14651 struct wireless_dev *wdev = dev->ieee80211_ptr;
14652 const u8 *buf;
14653 size_t len;
14654 u8 *dest;
14655 u16 proto;
14656 bool noencrypt;
dca9ca2d 14657 u64 cookie = 0;
2576a9ac
DK
14658 int err;
14659
14660 if (!wiphy_ext_feature_isset(&rdev->wiphy,
14661 NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211))
14662 return -EOPNOTSUPP;
14663
14664 if (!rdev->ops->tx_control_port)
14665 return -EOPNOTSUPP;
14666
14667 if (!info->attrs[NL80211_ATTR_FRAME] ||
14668 !info->attrs[NL80211_ATTR_MAC] ||
14669 !info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) {
14670 GENL_SET_ERR_MSG(info, "Frame, MAC or ethertype missing");
14671 return -EINVAL;
14672 }
14673
14674 wdev_lock(wdev);
14675
14676 switch (wdev->iftype) {
14677 case NL80211_IFTYPE_AP:
14678 case NL80211_IFTYPE_P2P_GO:
14679 case NL80211_IFTYPE_MESH_POINT:
14680 break;
14681 case NL80211_IFTYPE_ADHOC:
14682 case NL80211_IFTYPE_STATION:
14683 case NL80211_IFTYPE_P2P_CLIENT:
14684 if (wdev->current_bss)
14685 break;
14686 err = -ENOTCONN;
14687 goto out;
14688 default:
14689 err = -EOPNOTSUPP;
14690 goto out;
14691 }
14692
14693 wdev_unlock(wdev);
14694
14695 buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
14696 len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
14697 dest = nla_data(info->attrs[NL80211_ATTR_MAC]);
14698 proto = nla_get_u16(info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]);
14699 noencrypt =
14700 nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]);
14701
dca9ca2d
MT
14702 err = rdev_tx_control_port(rdev, dev, buf, len,
14703 dest, cpu_to_be16(proto), noencrypt,
14704 dont_wait_for_ack ? NULL : &cookie);
14705 if (!err && !dont_wait_for_ack)
14706 nl_set_extack_cookie_u64(info->extack, cookie);
14707 return err;
2576a9ac
DK
14708 out:
14709 wdev_unlock(wdev);
14710 return err;
14711}
14712
81e54d08
PKC
14713static int nl80211_get_ftm_responder_stats(struct sk_buff *skb,
14714 struct genl_info *info)
14715{
14716 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14717 struct net_device *dev = info->user_ptr[1];
14718 struct wireless_dev *wdev = dev->ieee80211_ptr;
14719 struct cfg80211_ftm_responder_stats ftm_stats = {};
14720 struct sk_buff *msg;
14721 void *hdr;
14722 struct nlattr *ftm_stats_attr;
14723 int err;
14724
14725 if (wdev->iftype != NL80211_IFTYPE_AP || !wdev->beacon_interval)
14726 return -EOPNOTSUPP;
14727
14728 err = rdev_get_ftm_responder_stats(rdev, dev, &ftm_stats);
14729 if (err)
14730 return err;
14731
14732 if (!ftm_stats.filled)
14733 return -ENODATA;
14734
14735 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
14736 if (!msg)
14737 return -ENOMEM;
14738
14739 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
14740 NL80211_CMD_GET_FTM_RESPONDER_STATS);
14741 if (!hdr)
1399c59f 14742 goto nla_put_failure;
81e54d08
PKC
14743
14744 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
14745 goto nla_put_failure;
14746
ae0be8de
MK
14747 ftm_stats_attr = nla_nest_start_noflag(msg,
14748 NL80211_ATTR_FTM_RESPONDER_STATS);
81e54d08
PKC
14749 if (!ftm_stats_attr)
14750 goto nla_put_failure;
14751
14752#define SET_FTM(field, name, type) \
14753 do { if ((ftm_stats.filled & BIT(NL80211_FTM_STATS_ ## name)) && \
14754 nla_put_ ## type(msg, NL80211_FTM_STATS_ ## name, \
14755 ftm_stats.field)) \
14756 goto nla_put_failure; } while (0)
14757#define SET_FTM_U64(field, name) \
14758 do { if ((ftm_stats.filled & BIT(NL80211_FTM_STATS_ ## name)) && \
14759 nla_put_u64_64bit(msg, NL80211_FTM_STATS_ ## name, \
14760 ftm_stats.field, NL80211_FTM_STATS_PAD)) \
14761 goto nla_put_failure; } while (0)
14762
14763 SET_FTM(success_num, SUCCESS_NUM, u32);
14764 SET_FTM(partial_num, PARTIAL_NUM, u32);
14765 SET_FTM(failed_num, FAILED_NUM, u32);
14766 SET_FTM(asap_num, ASAP_NUM, u32);
14767 SET_FTM(non_asap_num, NON_ASAP_NUM, u32);
14768 SET_FTM_U64(total_duration_ms, TOTAL_DURATION_MSEC);
14769 SET_FTM(unknown_triggers_num, UNKNOWN_TRIGGERS_NUM, u32);
14770 SET_FTM(reschedule_requests_num, RESCHEDULE_REQUESTS_NUM, u32);
14771 SET_FTM(out_of_window_triggers_num, OUT_OF_WINDOW_TRIGGERS_NUM, u32);
14772#undef SET_FTM
14773
14774 nla_nest_end(msg, ftm_stats_attr);
14775
14776 genlmsg_end(msg, hdr);
14777 return genlmsg_reply(msg, info);
14778
14779nla_put_failure:
14780 nlmsg_free(msg);
14781 return -ENOBUFS;
14782}
14783
cb74e977
SD
14784static int nl80211_update_owe_info(struct sk_buff *skb, struct genl_info *info)
14785{
14786 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14787 struct cfg80211_update_owe_info owe_info;
14788 struct net_device *dev = info->user_ptr[1];
14789
14790 if (!rdev->ops->update_owe_info)
14791 return -EOPNOTSUPP;
14792
14793 if (!info->attrs[NL80211_ATTR_STATUS_CODE] ||
14794 !info->attrs[NL80211_ATTR_MAC])
14795 return -EINVAL;
14796
14797 memset(&owe_info, 0, sizeof(owe_info));
14798 owe_info.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
14799 nla_memcpy(owe_info.peer, info->attrs[NL80211_ATTR_MAC], ETH_ALEN);
14800
14801 if (info->attrs[NL80211_ATTR_IE]) {
14802 owe_info.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
14803 owe_info.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
14804 }
14805
14806 return rdev_update_owe_info(rdev, dev, &owe_info);
14807}
14808
5ab92e7f
RM
14809static int nl80211_probe_mesh_link(struct sk_buff *skb, struct genl_info *info)
14810{
14811 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14812 struct net_device *dev = info->user_ptr[1];
14813 struct wireless_dev *wdev = dev->ieee80211_ptr;
14814 struct station_info sinfo = {};
14815 const u8 *buf;
14816 size_t len;
14817 u8 *dest;
14818 int err;
14819
14820 if (!rdev->ops->probe_mesh_link || !rdev->ops->get_station)
14821 return -EOPNOTSUPP;
14822
14823 if (!info->attrs[NL80211_ATTR_MAC] ||
14824 !info->attrs[NL80211_ATTR_FRAME]) {
14825 GENL_SET_ERR_MSG(info, "Frame or MAC missing");
14826 return -EINVAL;
14827 }
14828
14829 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
14830 return -EOPNOTSUPP;
14831
14832 dest = nla_data(info->attrs[NL80211_ATTR_MAC]);
14833 buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
14834 len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
14835
14836 if (len < sizeof(struct ethhdr))
14837 return -EINVAL;
14838
14839 if (!ether_addr_equal(buf, dest) || is_multicast_ether_addr(buf) ||
14840 !ether_addr_equal(buf + ETH_ALEN, dev->dev_addr))
14841 return -EINVAL;
14842
14843 err = rdev_get_station(rdev, dev, dest, &sinfo);
14844 if (err)
14845 return err;
14846
2a279b34
FF
14847 cfg80211_sinfo_release_content(&sinfo);
14848
5ab92e7f
RM
14849 return rdev_probe_mesh_link(rdev, dev, dest, buf, len);
14850}
14851
77f576de
T
14852static int parse_tid_conf(struct cfg80211_registered_device *rdev,
14853 struct nlattr *attrs[], struct net_device *dev,
3710a8a6 14854 struct cfg80211_tid_cfg *tid_conf,
77f576de
T
14855 struct genl_info *info, const u8 *peer)
14856{
14857 struct netlink_ext_ack *extack = info->extack;
3710a8a6 14858 u64 mask;
77f576de
T
14859 int err;
14860
14861 if (!attrs[NL80211_TID_CONFIG_ATTR_TIDS])
14862 return -EINVAL;
14863
14864 tid_conf->config_override =
14865 nla_get_flag(attrs[NL80211_TID_CONFIG_ATTR_OVERRIDE]);
3710a8a6 14866 tid_conf->tids = nla_get_u16(attrs[NL80211_TID_CONFIG_ATTR_TIDS]);
77f576de
T
14867
14868 if (tid_conf->config_override) {
14869 if (rdev->ops->reset_tid_config) {
14870 err = rdev_reset_tid_config(rdev, dev, peer,
3710a8a6 14871 tid_conf->tids);
c0336955 14872 if (err)
77f576de
T
14873 return err;
14874 } else {
14875 return -EINVAL;
14876 }
14877 }
14878
14879 if (attrs[NL80211_TID_CONFIG_ATTR_NOACK]) {
3710a8a6 14880 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_NOACK);
77f576de
T
14881 tid_conf->noack =
14882 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_NOACK]);
14883 }
14884
6a21d16c
T
14885 if (attrs[NL80211_TID_CONFIG_ATTR_RETRY_SHORT]) {
14886 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RETRY_SHORT);
14887 tid_conf->retry_short =
14888 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RETRY_SHORT]);
14889
14890 if (tid_conf->retry_short > rdev->wiphy.max_data_retry_count)
14891 return -EINVAL;
14892 }
14893
14894 if (attrs[NL80211_TID_CONFIG_ATTR_RETRY_LONG]) {
14895 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RETRY_LONG);
14896 tid_conf->retry_long =
14897 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RETRY_LONG]);
14898
14899 if (tid_conf->retry_long > rdev->wiphy.max_data_retry_count)
14900 return -EINVAL;
14901 }
14902
ade274b2
T
14903 if (attrs[NL80211_TID_CONFIG_ATTR_AMPDU_CTRL]) {
14904 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL);
14905 tid_conf->ampdu =
14906 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_AMPDU_CTRL]);
14907 }
14908
04f7d142
T
14909 if (attrs[NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL]) {
14910 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL);
14911 tid_conf->rtscts =
14912 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL]);
14913 }
14914
33462e68
SM
14915 if (attrs[NL80211_TID_CONFIG_ATTR_AMSDU_CTRL]) {
14916 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_AMSDU_CTRL);
14917 tid_conf->amsdu =
14918 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_AMSDU_CTRL]);
14919 }
14920
9a5f6488
TC
14921 if (attrs[NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE]) {
14922 u32 idx = NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE, attr;
14923
14924 tid_conf->txrate_type = nla_get_u8(attrs[idx]);
14925
14926 if (tid_conf->txrate_type != NL80211_TX_RATE_AUTOMATIC) {
14927 attr = NL80211_TID_CONFIG_ATTR_TX_RATE;
14928 err = nl80211_parse_tx_bitrate_mask(info, attrs, attr,
857b34c4
RM
14929 &tid_conf->txrate_mask, dev,
14930 true);
9a5f6488
TC
14931 if (err)
14932 return err;
14933
14934 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_TX_RATE);
14935 }
14936 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE);
14937 }
14938
3710a8a6
JB
14939 if (peer)
14940 mask = rdev->wiphy.tid_config_support.peer;
14941 else
14942 mask = rdev->wiphy.tid_config_support.vif;
14943
14944 if (tid_conf->mask & ~mask) {
14945 NL_SET_ERR_MSG(extack, "unsupported TID configuration");
14946 return -ENOTSUPP;
14947 }
14948
77f576de
T
14949 return 0;
14950}
14951
14952static int nl80211_set_tid_config(struct sk_buff *skb,
14953 struct genl_info *info)
14954{
14955 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14956 struct nlattr *attrs[NL80211_TID_CONFIG_ATTR_MAX + 1];
14957 struct net_device *dev = info->user_ptr[1];
3710a8a6 14958 struct cfg80211_tid_config *tid_config;
77f576de
T
14959 struct nlattr *tid;
14960 int conf_idx = 0, rem_conf;
14961 int ret = -EINVAL;
14962 u32 num_conf = 0;
14963
14964 if (!info->attrs[NL80211_ATTR_TID_CONFIG])
14965 return -EINVAL;
14966
14967 if (!rdev->ops->set_tid_config)
14968 return -EOPNOTSUPP;
14969
14970 nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
14971 rem_conf)
14972 num_conf++;
14973
14974 tid_config = kzalloc(struct_size(tid_config, tid_conf, num_conf),
14975 GFP_KERNEL);
14976 if (!tid_config)
14977 return -ENOMEM;
14978
14979 tid_config->n_tid_conf = num_conf;
14980
14981 if (info->attrs[NL80211_ATTR_MAC])
14982 tid_config->peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
14983
14984 nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
14985 rem_conf) {
14986 ret = nla_parse_nested(attrs, NL80211_TID_CONFIG_ATTR_MAX,
14987 tid, NULL, NULL);
14988
14989 if (ret)
14990 goto bad_tid_conf;
14991
14992 ret = parse_tid_conf(rdev, attrs, dev,
14993 &tid_config->tid_conf[conf_idx],
14994 info, tid_config->peer);
14995 if (ret)
14996 goto bad_tid_conf;
14997
14998 conf_idx++;
14999 }
15000
15001 ret = rdev_set_tid_config(rdev, dev, tid_config);
15002
15003bad_tid_conf:
15004 kfree(tid_config);
15005 return ret;
15006}
15007
0d2ab3ae
JC
15008static int nl80211_color_change(struct sk_buff *skb, struct genl_info *info)
15009{
15010 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15011 struct cfg80211_color_change_settings params = {};
15012 struct net_device *dev = info->user_ptr[1];
15013 struct wireless_dev *wdev = dev->ieee80211_ptr;
15014 struct nlattr **tb;
15015 u16 offset;
15016 int err;
15017
15018 if (!rdev->ops->color_change)
15019 return -EOPNOTSUPP;
15020
15021 if (!wiphy_ext_feature_isset(&rdev->wiphy,
15022 NL80211_EXT_FEATURE_BSS_COLOR))
15023 return -EOPNOTSUPP;
15024
15025 if (wdev->iftype != NL80211_IFTYPE_AP)
15026 return -EOPNOTSUPP;
15027
15028 if (!info->attrs[NL80211_ATTR_COLOR_CHANGE_COUNT] ||
15029 !info->attrs[NL80211_ATTR_COLOR_CHANGE_COLOR] ||
15030 !info->attrs[NL80211_ATTR_COLOR_CHANGE_ELEMS])
15031 return -EINVAL;
15032
15033 params.count = nla_get_u8(info->attrs[NL80211_ATTR_COLOR_CHANGE_COUNT]);
15034 params.color = nla_get_u8(info->attrs[NL80211_ATTR_COLOR_CHANGE_COLOR]);
15035
15036 err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon_next);
15037 if (err)
15038 return err;
15039
15040 tb = kcalloc(NL80211_ATTR_MAX + 1, sizeof(*tb), GFP_KERNEL);
15041 if (!tb)
15042 return -ENOMEM;
15043
15044 err = nla_parse_nested(tb, NL80211_ATTR_MAX,
15045 info->attrs[NL80211_ATTR_COLOR_CHANGE_ELEMS],
15046 nl80211_policy, info->extack);
15047 if (err)
15048 goto out;
15049
15050 err = nl80211_parse_beacon(rdev, tb, &params.beacon_color_change);
15051 if (err)
15052 goto out;
15053
15054 if (!tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]) {
15055 err = -EINVAL;
15056 goto out;
15057 }
15058
15059 if (nla_len(tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]) != sizeof(u16)) {
15060 err = -EINVAL;
15061 goto out;
15062 }
15063
15064 offset = nla_get_u16(tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
15065 if (offset >= params.beacon_color_change.tail_len) {
15066 err = -EINVAL;
15067 goto out;
15068 }
15069
15070 if (params.beacon_color_change.tail[offset] != params.count) {
15071 err = -EINVAL;
15072 goto out;
15073 }
15074
15075 params.counter_offset_beacon = offset;
15076
15077 if (tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]) {
15078 if (nla_len(tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]) !=
15079 sizeof(u16)) {
15080 err = -EINVAL;
15081 goto out;
15082 }
15083
15084 offset = nla_get_u16(tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
15085 if (offset >= params.beacon_color_change.probe_resp_len) {
15086 err = -EINVAL;
15087 goto out;
15088 }
15089
15090 if (params.beacon_color_change.probe_resp[offset] !=
15091 params.count) {
15092 err = -EINVAL;
15093 goto out;
15094 }
15095
15096 params.counter_offset_presp = offset;
15097 }
15098
15099 wdev_lock(wdev);
15100 err = rdev_color_change(rdev, dev, &params);
15101 wdev_unlock(wdev);
15102
15103out:
dc1e3cb8
JC
15104 kfree(params.beacon_next.mbssid_ies);
15105 kfree(params.beacon_color_change.mbssid_ies);
0d2ab3ae
JC
15106 kfree(tb);
15107 return err;
15108}
15109
e306784a
SM
15110static int nl80211_set_fils_aad(struct sk_buff *skb,
15111 struct genl_info *info)
15112{
15113 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15114 struct net_device *dev = info->user_ptr[1];
15115 struct cfg80211_fils_aad fils_aad = {};
15116 u8 *nonces;
15117
15118 if (!info->attrs[NL80211_ATTR_MAC] ||
15119 !info->attrs[NL80211_ATTR_FILS_KEK] ||
15120 !info->attrs[NL80211_ATTR_FILS_NONCES])
15121 return -EINVAL;
15122
15123 fils_aad.macaddr = nla_data(info->attrs[NL80211_ATTR_MAC]);
15124 fils_aad.kek_len = nla_len(info->attrs[NL80211_ATTR_FILS_KEK]);
15125 fils_aad.kek = nla_data(info->attrs[NL80211_ATTR_FILS_KEK]);
15126 nonces = nla_data(info->attrs[NL80211_ATTR_FILS_NONCES]);
15127 fils_aad.snonce = nonces;
15128 fils_aad.anonce = nonces + FILS_NONCE_LEN;
15129
15130 return rdev_set_fils_aad(rdev, dev, &fils_aad);
15131}
15132
4c476991
JB
15133#define NL80211_FLAG_NEED_WIPHY 0x01
15134#define NL80211_FLAG_NEED_NETDEV 0x02
15135#define NL80211_FLAG_NEED_RTNL 0x04
41265714
JB
15136#define NL80211_FLAG_CHECK_NETDEV_UP 0x08
15137#define NL80211_FLAG_NEED_NETDEV_UP (NL80211_FLAG_NEED_NETDEV |\
15138 NL80211_FLAG_CHECK_NETDEV_UP)
1bf614ef 15139#define NL80211_FLAG_NEED_WDEV 0x10
98104fde 15140/* If a netdev is associated, it must be UP, P2P must be started */
1bf614ef
JB
15141#define NL80211_FLAG_NEED_WDEV_UP (NL80211_FLAG_NEED_WDEV |\
15142 NL80211_FLAG_CHECK_NETDEV_UP)
5393b917 15143#define NL80211_FLAG_CLEAR_SKB 0x20
77cbf790 15144#define NL80211_FLAG_NO_WIPHY_MTX 0x40
4c476991 15145
f84f771d 15146static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
4c476991
JB
15147 struct genl_info *info)
15148{
a05829a7 15149 struct cfg80211_registered_device *rdev = NULL;
89a54e48 15150 struct wireless_dev *wdev;
4c476991 15151 struct net_device *dev;
4c476991 15152
a05829a7 15153 rtnl_lock();
4c476991 15154 if (ops->internal_flags & NL80211_FLAG_NEED_WIPHY) {
4f7eff10 15155 rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
4c476991 15156 if (IS_ERR(rdev)) {
a05829a7 15157 rtnl_unlock();
4c476991
JB
15158 return PTR_ERR(rdev);
15159 }
15160 info->user_ptr[0] = rdev;
1bf614ef
JB
15161 } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV ||
15162 ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
a05829a7 15163 wdev = __cfg80211_wdev_from_attrs(NULL, genl_info_net(info),
89a54e48
JB
15164 info->attrs);
15165 if (IS_ERR(wdev)) {
a05829a7 15166 rtnl_unlock();
89a54e48 15167 return PTR_ERR(wdev);
4c476991 15168 }
89a54e48 15169
89a54e48 15170 dev = wdev->netdev;
f26cbf40 15171 rdev = wiphy_to_rdev(wdev->wiphy);
89a54e48 15172
1bf614ef
JB
15173 if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
15174 if (!dev) {
a05829a7 15175 rtnl_unlock();
1bf614ef
JB
15176 return -EINVAL;
15177 }
15178
15179 info->user_ptr[1] = dev;
15180 } else {
15181 info->user_ptr[1] = wdev;
41265714 15182 }
1bf614ef 15183
73c7da3d
AVS
15184 if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
15185 !wdev_running(wdev)) {
a05829a7 15186 rtnl_unlock();
73c7da3d
AVS
15187 return -ENETDOWN;
15188 }
1bf614ef 15189
1160dfa1 15190 dev_hold(dev);
4c476991 15191 info->user_ptr[0] = rdev;
4c476991
JB
15192 }
15193
77cbf790 15194 if (rdev && !(ops->internal_flags & NL80211_FLAG_NO_WIPHY_MTX)) {
a05829a7
JB
15195 wiphy_lock(&rdev->wiphy);
15196 /* we keep the mutex locked until post_doit */
15197 __release(&rdev->wiphy.mtx);
15198 }
15199 if (!(ops->internal_flags & NL80211_FLAG_NEED_RTNL))
15200 rtnl_unlock();
15201
4c476991
JB
15202 return 0;
15203}
15204
f84f771d 15205static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
4c476991
JB
15206 struct genl_info *info)
15207{
1bf614ef
JB
15208 if (info->user_ptr[1]) {
15209 if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
15210 struct wireless_dev *wdev = info->user_ptr[1];
15211
1160dfa1 15212 dev_put(wdev->netdev);
1bf614ef
JB
15213 } else {
15214 dev_put(info->user_ptr[1]);
15215 }
15216 }
5393b917 15217
77cbf790
JB
15218 if (info->user_ptr[0] &&
15219 !(ops->internal_flags & NL80211_FLAG_NO_WIPHY_MTX)) {
a05829a7
JB
15220 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15221
15222 /* we kept the mutex locked since pre_doit */
15223 __acquire(&rdev->wiphy.mtx);
15224 wiphy_unlock(&rdev->wiphy);
15225 }
15226
4c476991
JB
15227 if (ops->internal_flags & NL80211_FLAG_NEED_RTNL)
15228 rtnl_unlock();
5393b917
JB
15229
15230 /* If needed, clear the netlink message payload from the SKB
15231 * as it might contain key data that shouldn't stick around on
15232 * the heap after the SKB is freed. The netlink message header
15233 * is still needed for further processing, so leave it intact.
15234 */
15235 if (ops->internal_flags & NL80211_FLAG_CLEAR_SKB) {
15236 struct nlmsghdr *nlh = nlmsg_hdr(skb);
15237
15238 memset(nlmsg_data(nlh), 0, nlmsg_len(nlh));
15239 }
4c476991
JB
15240}
15241
6bdb68ce
CH
15242static int nl80211_set_sar_sub_specs(struct cfg80211_registered_device *rdev,
15243 struct cfg80211_sar_specs *sar_specs,
15244 struct nlattr *spec[], int index)
15245{
15246 u32 range_index, i;
15247
15248 if (!sar_specs || !spec)
15249 return -EINVAL;
15250
15251 if (!spec[NL80211_SAR_ATTR_SPECS_POWER] ||
15252 !spec[NL80211_SAR_ATTR_SPECS_RANGE_INDEX])
15253 return -EINVAL;
15254
15255 range_index = nla_get_u32(spec[NL80211_SAR_ATTR_SPECS_RANGE_INDEX]);
15256
15257 /* check if range_index exceeds num_freq_ranges */
15258 if (range_index >= rdev->wiphy.sar_capa->num_freq_ranges)
15259 return -EINVAL;
15260
15261 /* check if range_index duplicates */
15262 for (i = 0; i < index; i++) {
15263 if (sar_specs->sub_specs[i].freq_range_index == range_index)
15264 return -EINVAL;
15265 }
15266
15267 sar_specs->sub_specs[index].power =
15268 nla_get_s32(spec[NL80211_SAR_ATTR_SPECS_POWER]);
15269
15270 sar_specs->sub_specs[index].freq_range_index = range_index;
15271
15272 return 0;
15273}
15274
15275static int nl80211_set_sar_specs(struct sk_buff *skb, struct genl_info *info)
15276{
15277 struct cfg80211_registered_device *rdev = info->user_ptr[0];
15278 struct nlattr *spec[NL80211_SAR_ATTR_SPECS_MAX + 1];
15279 struct nlattr *tb[NL80211_SAR_ATTR_MAX + 1];
15280 struct cfg80211_sar_specs *sar_spec;
15281 enum nl80211_sar_type type;
15282 struct nlattr *spec_list;
15283 u32 specs;
15284 int rem, err;
15285
15286 if (!rdev->wiphy.sar_capa || !rdev->ops->set_sar_specs)
15287 return -EOPNOTSUPP;
15288
15289 if (!info->attrs[NL80211_ATTR_SAR_SPEC])
15290 return -EINVAL;
15291
15292 nla_parse_nested(tb, NL80211_SAR_ATTR_MAX,
15293 info->attrs[NL80211_ATTR_SAR_SPEC],
15294 NULL, NULL);
15295
15296 if (!tb[NL80211_SAR_ATTR_TYPE] || !tb[NL80211_SAR_ATTR_SPECS])
15297 return -EINVAL;
15298
15299 type = nla_get_u32(tb[NL80211_SAR_ATTR_TYPE]);
15300 if (type != rdev->wiphy.sar_capa->type)
15301 return -EINVAL;
15302
15303 specs = 0;
15304 nla_for_each_nested(spec_list, tb[NL80211_SAR_ATTR_SPECS], rem)
15305 specs++;
15306
15307 if (specs > rdev->wiphy.sar_capa->num_freq_ranges)
15308 return -EINVAL;
15309
40f231e7 15310 sar_spec = kzalloc(struct_size(sar_spec, sub_specs, specs), GFP_KERNEL);
6bdb68ce
CH
15311 if (!sar_spec)
15312 return -ENOMEM;
15313
15314 sar_spec->type = type;
15315 specs = 0;
15316 nla_for_each_nested(spec_list, tb[NL80211_SAR_ATTR_SPECS], rem) {
15317 nla_parse_nested(spec, NL80211_SAR_ATTR_SPECS_MAX,
15318 spec_list, NULL, NULL);
15319
15320 switch (type) {
15321 case NL80211_SAR_TYPE_POWER:
15322 if (nl80211_set_sar_sub_specs(rdev, sar_spec,
15323 spec, specs)) {
15324 err = -EINVAL;
15325 goto error;
15326 }
15327 break;
15328 default:
15329 err = -EINVAL;
15330 goto error;
15331 }
15332 specs++;
15333 }
15334
15335 sar_spec->num_sub_specs = specs;
15336
15337 rdev->cur_cmd_info = info;
15338 err = rdev_set_sar_specs(rdev, sar_spec);
15339 rdev->cur_cmd_info = NULL;
15340error:
15341 kfree(sar_spec);
15342 return err;
15343}
15344
4534de83 15345static const struct genl_ops nl80211_ops[] = {
55682965
JB
15346 {
15347 .cmd = NL80211_CMD_GET_WIPHY,
ef6243ac 15348 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965
JB
15349 .doit = nl80211_get_wiphy,
15350 .dumpit = nl80211_dump_wiphy,
86e8cf98 15351 .done = nl80211_dump_wiphy_done,
55682965 15352 /* can be retrieved by unprivileged users */
a05829a7 15353 .internal_flags = NL80211_FLAG_NEED_WIPHY,
55682965 15354 },
66a9b928
JK
15355};
15356
15357static const struct genl_small_ops nl80211_small_ops[] = {
55682965
JB
15358 {
15359 .cmd = NL80211_CMD_SET_WIPHY,
ef6243ac 15360 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 15361 .doit = nl80211_set_wiphy,
5617c6cd 15362 .flags = GENL_UNS_ADMIN_PERM,
55682965
JB
15363 },
15364 {
15365 .cmd = NL80211_CMD_GET_INTERFACE,
ef6243ac 15366 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965
JB
15367 .doit = nl80211_get_interface,
15368 .dumpit = nl80211_dump_interface,
55682965 15369 /* can be retrieved by unprivileged users */
a05829a7 15370 .internal_flags = NL80211_FLAG_NEED_WDEV,
55682965
JB
15371 },
15372 {
15373 .cmd = NL80211_CMD_SET_INTERFACE,
ef6243ac 15374 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 15375 .doit = nl80211_set_interface,
5617c6cd 15376 .flags = GENL_UNS_ADMIN_PERM,
4c476991
JB
15377 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15378 NL80211_FLAG_NEED_RTNL,
55682965
JB
15379 },
15380 {
15381 .cmd = NL80211_CMD_NEW_INTERFACE,
ef6243ac 15382 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 15383 .doit = nl80211_new_interface,
5617c6cd 15384 .flags = GENL_UNS_ADMIN_PERM,
4c476991 15385 .internal_flags = NL80211_FLAG_NEED_WIPHY |
ea6b2098
JB
15386 NL80211_FLAG_NEED_RTNL |
15387 /* we take the wiphy mutex later ourselves */
15388 NL80211_FLAG_NO_WIPHY_MTX,
55682965
JB
15389 },
15390 {
15391 .cmd = NL80211_CMD_DEL_INTERFACE,
ef6243ac 15392 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 15393 .doit = nl80211_del_interface,
5617c6cd 15394 .flags = GENL_UNS_ADMIN_PERM,
84efbb84 15395 .internal_flags = NL80211_FLAG_NEED_WDEV |
4c476991 15396 NL80211_FLAG_NEED_RTNL,
41ade00f
JB
15397 },
15398 {
15399 .cmd = NL80211_CMD_GET_KEY,
ef6243ac 15400 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 15401 .doit = nl80211_get_key,
5617c6cd 15402 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15403 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
41ade00f
JB
15404 },
15405 {
15406 .cmd = NL80211_CMD_SET_KEY,
ef6243ac 15407 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 15408 .doit = nl80211_set_key,
5617c6cd 15409 .flags = GENL_UNS_ADMIN_PERM,
41265714 15410 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
5393b917 15411 NL80211_FLAG_CLEAR_SKB,
41ade00f
JB
15412 },
15413 {
15414 .cmd = NL80211_CMD_NEW_KEY,
ef6243ac 15415 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 15416 .doit = nl80211_new_key,
5617c6cd 15417 .flags = GENL_UNS_ADMIN_PERM,
41265714 15418 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
5393b917 15419 NL80211_FLAG_CLEAR_SKB,
41ade00f
JB
15420 },
15421 {
15422 .cmd = NL80211_CMD_DEL_KEY,
ef6243ac 15423 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 15424 .doit = nl80211_del_key,
5617c6cd 15425 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15426 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
55682965 15427 },
ed1b6cc7
JB
15428 {
15429 .cmd = NL80211_CMD_SET_BEACON,
ef6243ac 15430 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5617c6cd 15431 .flags = GENL_UNS_ADMIN_PERM,
8860020e 15432 .doit = nl80211_set_beacon,
a05829a7 15433 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
ed1b6cc7
JB
15434 },
15435 {
8860020e 15436 .cmd = NL80211_CMD_START_AP,
ef6243ac 15437 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5617c6cd 15438 .flags = GENL_UNS_ADMIN_PERM,
8860020e 15439 .doit = nl80211_start_ap,
a05829a7 15440 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
ed1b6cc7
JB
15441 },
15442 {
8860020e 15443 .cmd = NL80211_CMD_STOP_AP,
ef6243ac 15444 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5617c6cd 15445 .flags = GENL_UNS_ADMIN_PERM,
8860020e 15446 .doit = nl80211_stop_ap,
a05829a7 15447 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
ed1b6cc7 15448 },
5727ef1b
JB
15449 {
15450 .cmd = NL80211_CMD_GET_STATION,
ef6243ac 15451 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 15452 .doit = nl80211_get_station,
2ec600d6 15453 .dumpit = nl80211_dump_station,
a05829a7 15454 .internal_flags = NL80211_FLAG_NEED_NETDEV,
5727ef1b
JB
15455 },
15456 {
15457 .cmd = NL80211_CMD_SET_STATION,
ef6243ac 15458 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 15459 .doit = nl80211_set_station,
5617c6cd 15460 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15461 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
5727ef1b
JB
15462 },
15463 {
15464 .cmd = NL80211_CMD_NEW_STATION,
ef6243ac 15465 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 15466 .doit = nl80211_new_station,
5617c6cd 15467 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15468 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
5727ef1b
JB
15469 },
15470 {
15471 .cmd = NL80211_CMD_DEL_STATION,
ef6243ac 15472 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 15473 .doit = nl80211_del_station,
5617c6cd 15474 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15475 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
2ec600d6
LCC
15476 },
15477 {
15478 .cmd = NL80211_CMD_GET_MPATH,
ef6243ac 15479 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6
LCC
15480 .doit = nl80211_get_mpath,
15481 .dumpit = nl80211_dump_mpath,
5617c6cd 15482 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15483 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
2ec600d6 15484 },
66be7d2b
HR
15485 {
15486 .cmd = NL80211_CMD_GET_MPP,
ef6243ac 15487 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
66be7d2b
HR
15488 .doit = nl80211_get_mpp,
15489 .dumpit = nl80211_dump_mpp,
5617c6cd 15490 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15491 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
66be7d2b 15492 },
2ec600d6
LCC
15493 {
15494 .cmd = NL80211_CMD_SET_MPATH,
ef6243ac 15495 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6 15496 .doit = nl80211_set_mpath,
5617c6cd 15497 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15498 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
2ec600d6
LCC
15499 },
15500 {
15501 .cmd = NL80211_CMD_NEW_MPATH,
ef6243ac 15502 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6 15503 .doit = nl80211_new_mpath,
5617c6cd 15504 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15505 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
2ec600d6
LCC
15506 },
15507 {
15508 .cmd = NL80211_CMD_DEL_MPATH,
ef6243ac 15509 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6 15510 .doit = nl80211_del_mpath,
5617c6cd 15511 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15512 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
9f1ba906
JM
15513 },
15514 {
15515 .cmd = NL80211_CMD_SET_BSS,
ef6243ac 15516 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9f1ba906 15517 .doit = nl80211_set_bss,
5617c6cd 15518 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15519 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
b2e1b302 15520 },
f130347c
LR
15521 {
15522 .cmd = NL80211_CMD_GET_REG,
ef6243ac 15523 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ad30ca2c
AN
15524 .doit = nl80211_get_reg_do,
15525 .dumpit = nl80211_get_reg_dump,
a05829a7 15526 .internal_flags = 0,
f130347c
LR
15527 /* can be retrieved by unprivileged users */
15528 },
b6863036 15529#ifdef CONFIG_CFG80211_CRDA_SUPPORT
b2e1b302
LR
15530 {
15531 .cmd = NL80211_CMD_SET_REG,
ef6243ac 15532 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b2e1b302 15533 .doit = nl80211_set_reg,
b2e1b302 15534 .flags = GENL_ADMIN_PERM,
a05829a7 15535 .internal_flags = 0,
b2e1b302 15536 },
b6863036 15537#endif
b2e1b302
LR
15538 {
15539 .cmd = NL80211_CMD_REQ_SET_REG,
ef6243ac 15540 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b2e1b302 15541 .doit = nl80211_req_set_reg,
93da9cc1 15542 .flags = GENL_ADMIN_PERM,
15543 },
1ea4ff3e
JB
15544 {
15545 .cmd = NL80211_CMD_RELOAD_REGDB,
ef6243ac 15546 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1ea4ff3e 15547 .doit = nl80211_reload_regdb,
1ea4ff3e
JB
15548 .flags = GENL_ADMIN_PERM,
15549 },
93da9cc1 15550 {
24bdd9f4 15551 .cmd = NL80211_CMD_GET_MESH_CONFIG,
ef6243ac 15552 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
24bdd9f4 15553 .doit = nl80211_get_mesh_config,
93da9cc1 15554 /* can be retrieved by unprivileged users */
a05829a7 15555 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
93da9cc1 15556 },
15557 {
24bdd9f4 15558 .cmd = NL80211_CMD_SET_MESH_CONFIG,
ef6243ac 15559 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
24bdd9f4 15560 .doit = nl80211_update_mesh_config,
5617c6cd 15561 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15562 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
9aed3cc1 15563 },
2a519311
JB
15564 {
15565 .cmd = NL80211_CMD_TRIGGER_SCAN,
ef6243ac 15566 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2a519311 15567 .doit = nl80211_trigger_scan,
5617c6cd 15568 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15569 .internal_flags = NL80211_FLAG_NEED_WDEV_UP,
2a519311 15570 },
91d3ab46
VK
15571 {
15572 .cmd = NL80211_CMD_ABORT_SCAN,
ef6243ac 15573 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
91d3ab46 15574 .doit = nl80211_abort_scan,
5617c6cd 15575 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15576 .internal_flags = NL80211_FLAG_NEED_WDEV_UP,
91d3ab46 15577 },
2a519311
JB
15578 {
15579 .cmd = NL80211_CMD_GET_SCAN,
ef6243ac 15580 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2a519311
JB
15581 .dumpit = nl80211_dump_scan,
15582 },
807f8a8c
LC
15583 {
15584 .cmd = NL80211_CMD_START_SCHED_SCAN,
ef6243ac 15585 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
807f8a8c 15586 .doit = nl80211_start_sched_scan,
5617c6cd 15587 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15588 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
807f8a8c
LC
15589 },
15590 {
15591 .cmd = NL80211_CMD_STOP_SCHED_SCAN,
ef6243ac 15592 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
807f8a8c 15593 .doit = nl80211_stop_sched_scan,
5617c6cd 15594 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15595 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
807f8a8c 15596 },
636a5d36
JM
15597 {
15598 .cmd = NL80211_CMD_AUTHENTICATE,
ef6243ac 15599 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 15600 .doit = nl80211_authenticate,
5617c6cd 15601 .flags = GENL_UNS_ADMIN_PERM,
41265714 15602 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
a05829a7 15603 0 |
5393b917 15604 NL80211_FLAG_CLEAR_SKB,
636a5d36
JM
15605 },
15606 {
15607 .cmd = NL80211_CMD_ASSOCIATE,
ef6243ac 15608 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 15609 .doit = nl80211_associate,
5617c6cd 15610 .flags = GENL_UNS_ADMIN_PERM,
41265714 15611 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
a05829a7 15612 0 |
d6db02a8 15613 NL80211_FLAG_CLEAR_SKB,
636a5d36
JM
15614 },
15615 {
15616 .cmd = NL80211_CMD_DEAUTHENTICATE,
ef6243ac 15617 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 15618 .doit = nl80211_deauthenticate,
5617c6cd 15619 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15620 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
636a5d36
JM
15621 },
15622 {
15623 .cmd = NL80211_CMD_DISASSOCIATE,
ef6243ac 15624 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 15625 .doit = nl80211_disassociate,
5617c6cd 15626 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15627 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
636a5d36 15628 },
04a773ad
JB
15629 {
15630 .cmd = NL80211_CMD_JOIN_IBSS,
ef6243ac 15631 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
04a773ad 15632 .doit = nl80211_join_ibss,
5617c6cd 15633 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15634 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
04a773ad
JB
15635 },
15636 {
15637 .cmd = NL80211_CMD_LEAVE_IBSS,
ef6243ac 15638 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
04a773ad 15639 .doit = nl80211_leave_ibss,
5617c6cd 15640 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15641 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
04a773ad 15642 },
aff89a9b
JB
15643#ifdef CONFIG_NL80211_TESTMODE
15644 {
15645 .cmd = NL80211_CMD_TESTMODE,
ef6243ac 15646 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
aff89a9b 15647 .doit = nl80211_testmode_do,
71063f0e 15648 .dumpit = nl80211_testmode_dump,
5617c6cd 15649 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15650 .internal_flags = NL80211_FLAG_NEED_WIPHY,
aff89a9b
JB
15651 },
15652#endif
b23aa676
SO
15653 {
15654 .cmd = NL80211_CMD_CONNECT,
ef6243ac 15655 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b23aa676 15656 .doit = nl80211_connect,
5617c6cd 15657 .flags = GENL_UNS_ADMIN_PERM,
41265714 15658 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
a05829a7 15659 0 |
d6db02a8 15660 NL80211_FLAG_CLEAR_SKB,
b23aa676 15661 },
088e8df8 15662 {
15663 .cmd = NL80211_CMD_UPDATE_CONNECT_PARAMS,
ef6243ac 15664 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
088e8df8 15665 .doit = nl80211_update_connect_params,
088e8df8 15666 .flags = GENL_ADMIN_PERM,
15667 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
a05829a7 15668 0 |
d6db02a8 15669 NL80211_FLAG_CLEAR_SKB,
088e8df8 15670 },
b23aa676
SO
15671 {
15672 .cmd = NL80211_CMD_DISCONNECT,
ef6243ac 15673 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b23aa676 15674 .doit = nl80211_disconnect,
5617c6cd 15675 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15676 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
b23aa676 15677 },
463d0183
JB
15678 {
15679 .cmd = NL80211_CMD_SET_WIPHY_NETNS,
ef6243ac 15680 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
463d0183 15681 .doit = nl80211_wiphy_netns,
5617c6cd 15682 .flags = GENL_UNS_ADMIN_PERM,
77cbf790
JB
15683 .internal_flags = NL80211_FLAG_NEED_WIPHY |
15684 NL80211_FLAG_NEED_RTNL |
15685 NL80211_FLAG_NO_WIPHY_MTX,
463d0183 15686 },
61fa713c
HS
15687 {
15688 .cmd = NL80211_CMD_GET_SURVEY,
ef6243ac 15689 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
61fa713c
HS
15690 .dumpit = nl80211_dump_survey,
15691 },
67fbb16b
SO
15692 {
15693 .cmd = NL80211_CMD_SET_PMKSA,
ef6243ac 15694 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
67fbb16b 15695 .doit = nl80211_setdel_pmksa,
5617c6cd 15696 .flags = GENL_UNS_ADMIN_PERM,
2b5f8b0b 15697 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
a05829a7 15698 0 |
d6db02a8 15699 NL80211_FLAG_CLEAR_SKB,
67fbb16b
SO
15700 },
15701 {
15702 .cmd = NL80211_CMD_DEL_PMKSA,
ef6243ac 15703 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
67fbb16b 15704 .doit = nl80211_setdel_pmksa,
5617c6cd 15705 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15706 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
67fbb16b
SO
15707 },
15708 {
15709 .cmd = NL80211_CMD_FLUSH_PMKSA,
ef6243ac 15710 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
67fbb16b 15711 .doit = nl80211_flush_pmksa,
5617c6cd 15712 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15713 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
67fbb16b 15714 },
9588bbd5
JM
15715 {
15716 .cmd = NL80211_CMD_REMAIN_ON_CHANNEL,
ef6243ac 15717 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9588bbd5 15718 .doit = nl80211_remain_on_channel,
5617c6cd 15719 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15720 .internal_flags = NL80211_FLAG_NEED_WDEV_UP,
9588bbd5
JM
15721 },
15722 {
15723 .cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
ef6243ac 15724 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9588bbd5 15725 .doit = nl80211_cancel_remain_on_channel,
5617c6cd 15726 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15727 .internal_flags = NL80211_FLAG_NEED_WDEV_UP,
9588bbd5 15728 },
13ae75b1
JM
15729 {
15730 .cmd = NL80211_CMD_SET_TX_BITRATE_MASK,
ef6243ac 15731 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
13ae75b1 15732 .doit = nl80211_set_tx_bitrate_mask,
5617c6cd 15733 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15734 .internal_flags = NL80211_FLAG_NEED_NETDEV,
13ae75b1 15735 },
026331c4 15736 {
2e161f78 15737 .cmd = NL80211_CMD_REGISTER_FRAME,
ef6243ac 15738 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2e161f78 15739 .doit = nl80211_register_mgmt,
5617c6cd 15740 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15741 .internal_flags = NL80211_FLAG_NEED_WDEV,
026331c4
JM
15742 },
15743 {
2e161f78 15744 .cmd = NL80211_CMD_FRAME,
ef6243ac 15745 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2e161f78 15746 .doit = nl80211_tx_mgmt,
5617c6cd 15747 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15748 .internal_flags = NL80211_FLAG_NEED_WDEV_UP,
f7ca38df
JB
15749 },
15750 {
15751 .cmd = NL80211_CMD_FRAME_WAIT_CANCEL,
ef6243ac 15752 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
f7ca38df 15753 .doit = nl80211_tx_mgmt_cancel_wait,
5617c6cd 15754 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15755 .internal_flags = NL80211_FLAG_NEED_WDEV_UP,
026331c4 15756 },
ffb9eb3d
KV
15757 {
15758 .cmd = NL80211_CMD_SET_POWER_SAVE,
ef6243ac 15759 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ffb9eb3d 15760 .doit = nl80211_set_power_save,
5617c6cd 15761 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15762 .internal_flags = NL80211_FLAG_NEED_NETDEV,
ffb9eb3d
KV
15763 },
15764 {
15765 .cmd = NL80211_CMD_GET_POWER_SAVE,
ef6243ac 15766 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ffb9eb3d 15767 .doit = nl80211_get_power_save,
ffb9eb3d 15768 /* can be retrieved by unprivileged users */
a05829a7 15769 .internal_flags = NL80211_FLAG_NEED_NETDEV,
ffb9eb3d 15770 },
d6dc1a38
JO
15771 {
15772 .cmd = NL80211_CMD_SET_CQM,
ef6243ac 15773 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
d6dc1a38 15774 .doit = nl80211_set_cqm,
5617c6cd 15775 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15776 .internal_flags = NL80211_FLAG_NEED_NETDEV,
d6dc1a38 15777 },
f444de05
JB
15778 {
15779 .cmd = NL80211_CMD_SET_CHANNEL,
ef6243ac 15780 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
f444de05 15781 .doit = nl80211_set_channel,
5617c6cd 15782 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15783 .internal_flags = NL80211_FLAG_NEED_NETDEV,
f444de05 15784 },
29cbe68c
JB
15785 {
15786 .cmd = NL80211_CMD_JOIN_MESH,
ef6243ac 15787 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
29cbe68c 15788 .doit = nl80211_join_mesh,
5617c6cd 15789 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15790 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
29cbe68c
JB
15791 },
15792 {
15793 .cmd = NL80211_CMD_LEAVE_MESH,
ef6243ac 15794 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
29cbe68c 15795 .doit = nl80211_leave_mesh,
5617c6cd 15796 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15797 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
29cbe68c 15798 },
6e0bd6c3
RL
15799 {
15800 .cmd = NL80211_CMD_JOIN_OCB,
ef6243ac 15801 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6e0bd6c3 15802 .doit = nl80211_join_ocb,
5617c6cd 15803 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15804 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
6e0bd6c3
RL
15805 },
15806 {
15807 .cmd = NL80211_CMD_LEAVE_OCB,
ef6243ac 15808 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6e0bd6c3 15809 .doit = nl80211_leave_ocb,
5617c6cd 15810 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15811 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
6e0bd6c3 15812 },
dfb89c56 15813#ifdef CONFIG_PM
ff1b6e69
JB
15814 {
15815 .cmd = NL80211_CMD_GET_WOWLAN,
ef6243ac 15816 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ff1b6e69 15817 .doit = nl80211_get_wowlan,
ff1b6e69 15818 /* can be retrieved by unprivileged users */
a05829a7 15819 .internal_flags = NL80211_FLAG_NEED_WIPHY,
ff1b6e69
JB
15820 },
15821 {
15822 .cmd = NL80211_CMD_SET_WOWLAN,
ef6243ac 15823 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ff1b6e69 15824 .doit = nl80211_set_wowlan,
5617c6cd 15825 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15826 .internal_flags = NL80211_FLAG_NEED_WIPHY,
ff1b6e69 15827 },
dfb89c56 15828#endif
e5497d76
JB
15829 {
15830 .cmd = NL80211_CMD_SET_REKEY_OFFLOAD,
ef6243ac 15831 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
e5497d76 15832 .doit = nl80211_set_rekey_data,
5617c6cd 15833 .flags = GENL_UNS_ADMIN_PERM,
e5497d76 15834 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
a05829a7 15835 0 |
5393b917 15836 NL80211_FLAG_CLEAR_SKB,
e5497d76 15837 },
109086ce
AN
15838 {
15839 .cmd = NL80211_CMD_TDLS_MGMT,
ef6243ac 15840 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
109086ce 15841 .doit = nl80211_tdls_mgmt,
5617c6cd 15842 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15843 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
109086ce
AN
15844 },
15845 {
15846 .cmd = NL80211_CMD_TDLS_OPER,
ef6243ac 15847 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
109086ce 15848 .doit = nl80211_tdls_oper,
5617c6cd 15849 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15850 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
109086ce 15851 },
28946da7
JB
15852 {
15853 .cmd = NL80211_CMD_UNEXPECTED_FRAME,
ef6243ac 15854 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
28946da7 15855 .doit = nl80211_register_unexpected_frame,
5617c6cd 15856 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15857 .internal_flags = NL80211_FLAG_NEED_NETDEV,
28946da7 15858 },
7f6cf311
JB
15859 {
15860 .cmd = NL80211_CMD_PROBE_CLIENT,
ef6243ac 15861 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
7f6cf311 15862 .doit = nl80211_probe_client,
5617c6cd 15863 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15864 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
7f6cf311 15865 },
5e760230
JB
15866 {
15867 .cmd = NL80211_CMD_REGISTER_BEACONS,
ef6243ac 15868 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5e760230 15869 .doit = nl80211_register_beacons,
5617c6cd 15870 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15871 .internal_flags = NL80211_FLAG_NEED_WIPHY,
5e760230 15872 },
1d9d9213
SW
15873 {
15874 .cmd = NL80211_CMD_SET_NOACK_MAP,
ef6243ac 15875 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1d9d9213 15876 .doit = nl80211_set_noack_map,
5617c6cd 15877 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15878 .internal_flags = NL80211_FLAG_NEED_NETDEV,
1d9d9213 15879 },
98104fde
JB
15880 {
15881 .cmd = NL80211_CMD_START_P2P_DEVICE,
ef6243ac 15882 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
98104fde 15883 .doit = nl80211_start_p2p_device,
5617c6cd 15884 .flags = GENL_UNS_ADMIN_PERM,
98104fde
JB
15885 .internal_flags = NL80211_FLAG_NEED_WDEV |
15886 NL80211_FLAG_NEED_RTNL,
15887 },
15888 {
15889 .cmd = NL80211_CMD_STOP_P2P_DEVICE,
ef6243ac 15890 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
98104fde 15891 .doit = nl80211_stop_p2p_device,
5617c6cd 15892 .flags = GENL_UNS_ADMIN_PERM,
98104fde
JB
15893 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
15894 NL80211_FLAG_NEED_RTNL,
cb3b7d87
AB
15895 },
15896 {
15897 .cmd = NL80211_CMD_START_NAN,
ef6243ac 15898 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
cb3b7d87 15899 .doit = nl80211_start_nan,
cb3b7d87
AB
15900 .flags = GENL_ADMIN_PERM,
15901 .internal_flags = NL80211_FLAG_NEED_WDEV |
15902 NL80211_FLAG_NEED_RTNL,
15903 },
15904 {
15905 .cmd = NL80211_CMD_STOP_NAN,
ef6243ac 15906 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
cb3b7d87 15907 .doit = nl80211_stop_nan,
cb3b7d87
AB
15908 .flags = GENL_ADMIN_PERM,
15909 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
15910 NL80211_FLAG_NEED_RTNL,
a442b761
AB
15911 },
15912 {
15913 .cmd = NL80211_CMD_ADD_NAN_FUNCTION,
ef6243ac 15914 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
a442b761 15915 .doit = nl80211_nan_add_func,
a442b761 15916 .flags = GENL_ADMIN_PERM,
a05829a7 15917 .internal_flags = NL80211_FLAG_NEED_WDEV_UP,
a442b761
AB
15918 },
15919 {
15920 .cmd = NL80211_CMD_DEL_NAN_FUNCTION,
ef6243ac 15921 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
a442b761 15922 .doit = nl80211_nan_del_func,
a442b761 15923 .flags = GENL_ADMIN_PERM,
a05829a7 15924 .internal_flags = NL80211_FLAG_NEED_WDEV_UP,
a5a9dcf2
AB
15925 },
15926 {
15927 .cmd = NL80211_CMD_CHANGE_NAN_CONFIG,
ef6243ac 15928 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
a5a9dcf2 15929 .doit = nl80211_nan_change_config,
a5a9dcf2 15930 .flags = GENL_ADMIN_PERM,
a05829a7 15931 .internal_flags = NL80211_FLAG_NEED_WDEV_UP,
98104fde 15932 },
f4e583c8
AQ
15933 {
15934 .cmd = NL80211_CMD_SET_MCAST_RATE,
ef6243ac 15935 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
f4e583c8 15936 .doit = nl80211_set_mcast_rate,
5617c6cd 15937 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15938 .internal_flags = NL80211_FLAG_NEED_NETDEV,
77765eaf
VT
15939 },
15940 {
15941 .cmd = NL80211_CMD_SET_MAC_ACL,
ef6243ac 15942 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
77765eaf 15943 .doit = nl80211_set_mac_acl,
5617c6cd 15944 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15945 .internal_flags = NL80211_FLAG_NEED_NETDEV,
f4e583c8 15946 },
04f39047
SW
15947 {
15948 .cmd = NL80211_CMD_RADAR_DETECT,
ef6243ac 15949 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
04f39047 15950 .doit = nl80211_start_radar_detection,
5617c6cd 15951 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15952 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
04f39047 15953 },
3713b4e3
JB
15954 {
15955 .cmd = NL80211_CMD_GET_PROTOCOL_FEATURES,
ef6243ac 15956 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3713b4e3 15957 .doit = nl80211_get_protocol_features,
3713b4e3 15958 },
355199e0
JM
15959 {
15960 .cmd = NL80211_CMD_UPDATE_FT_IES,
ef6243ac 15961 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
355199e0 15962 .doit = nl80211_update_ft_ies,
5617c6cd 15963 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15964 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
355199e0 15965 },
5de17984
AS
15966 {
15967 .cmd = NL80211_CMD_CRIT_PROTOCOL_START,
ef6243ac 15968 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5de17984 15969 .doit = nl80211_crit_protocol_start,
5617c6cd 15970 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15971 .internal_flags = NL80211_FLAG_NEED_WDEV_UP,
5de17984
AS
15972 },
15973 {
15974 .cmd = NL80211_CMD_CRIT_PROTOCOL_STOP,
ef6243ac 15975 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5de17984 15976 .doit = nl80211_crit_protocol_stop,
5617c6cd 15977 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15978 .internal_flags = NL80211_FLAG_NEED_WDEV_UP,
be29b99a
AK
15979 },
15980 {
15981 .cmd = NL80211_CMD_GET_COALESCE,
ef6243ac 15982 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
be29b99a 15983 .doit = nl80211_get_coalesce,
a05829a7 15984 .internal_flags = NL80211_FLAG_NEED_WIPHY,
be29b99a
AK
15985 },
15986 {
15987 .cmd = NL80211_CMD_SET_COALESCE,
ef6243ac 15988 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
be29b99a 15989 .doit = nl80211_set_coalesce,
5617c6cd 15990 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15991 .internal_flags = NL80211_FLAG_NEED_WIPHY,
16ef1fe2
SW
15992 },
15993 {
15994 .cmd = NL80211_CMD_CHANNEL_SWITCH,
ef6243ac 15995 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
16ef1fe2 15996 .doit = nl80211_channel_switch,
5617c6cd 15997 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 15998 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
16ef1fe2 15999 },
ad7e718c
JB
16000 {
16001 .cmd = NL80211_CMD_VENDOR,
ef6243ac 16002 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ad7e718c 16003 .doit = nl80211_vendor_cmd,
7bdbe400 16004 .dumpit = nl80211_vendor_cmd_dump,
5617c6cd 16005 .flags = GENL_UNS_ADMIN_PERM,
ad7e718c 16006 .internal_flags = NL80211_FLAG_NEED_WIPHY |
a05829a7 16007 0 |
d6db02a8 16008 NL80211_FLAG_CLEAR_SKB,
ad7e718c 16009 },
fa9ffc74
KP
16010 {
16011 .cmd = NL80211_CMD_SET_QOS_MAP,
ef6243ac 16012 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
fa9ffc74 16013 .doit = nl80211_set_qos_map,
5617c6cd 16014 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 16015 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
fa9ffc74 16016 },
960d01ac
JB
16017 {
16018 .cmd = NL80211_CMD_ADD_TX_TS,
ef6243ac 16019 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
960d01ac 16020 .doit = nl80211_add_tx_ts,
5617c6cd 16021 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 16022 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
960d01ac
JB
16023 },
16024 {
16025 .cmd = NL80211_CMD_DEL_TX_TS,
ef6243ac 16026 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
960d01ac 16027 .doit = nl80211_del_tx_ts,
5617c6cd 16028 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 16029 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
960d01ac 16030 },
1057d35e
AN
16031 {
16032 .cmd = NL80211_CMD_TDLS_CHANNEL_SWITCH,
ef6243ac 16033 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1057d35e 16034 .doit = nl80211_tdls_channel_switch,
5617c6cd 16035 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 16036 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
1057d35e
AN
16037 },
16038 {
16039 .cmd = NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH,
ef6243ac 16040 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1057d35e 16041 .doit = nl80211_tdls_cancel_channel_switch,
5617c6cd 16042 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 16043 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
1057d35e 16044 },
ce0ce13a
MB
16045 {
16046 .cmd = NL80211_CMD_SET_MULTICAST_TO_UNICAST,
ef6243ac 16047 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ce0ce13a 16048 .doit = nl80211_set_multicast_to_unicast,
ce0ce13a 16049 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 16050 .internal_flags = NL80211_FLAG_NEED_NETDEV,
ce0ce13a 16051 },
3a00df57
AS
16052 {
16053 .cmd = NL80211_CMD_SET_PMK,
ef6243ac 16054 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3a00df57 16055 .doit = nl80211_set_pmk,
3a00df57 16056 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
a05829a7 16057 0 |
d6db02a8 16058 NL80211_FLAG_CLEAR_SKB,
3a00df57
AS
16059 },
16060 {
16061 .cmd = NL80211_CMD_DEL_PMK,
ef6243ac 16062 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3a00df57 16063 .doit = nl80211_del_pmk,
a05829a7 16064 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
3a00df57 16065 },
40cbfa90
SD
16066 {
16067 .cmd = NL80211_CMD_EXTERNAL_AUTH,
ef6243ac 16068 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
40cbfa90 16069 .doit = nl80211_external_auth,
40cbfa90 16070 .flags = GENL_ADMIN_PERM,
a05829a7 16071 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
40cbfa90 16072 },
2576a9ac
DK
16073 {
16074 .cmd = NL80211_CMD_CONTROL_PORT_FRAME,
ef6243ac 16075 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2576a9ac 16076 .doit = nl80211_tx_control_port,
2576a9ac 16077 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 16078 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
2576a9ac 16079 },
81e54d08
PKC
16080 {
16081 .cmd = NL80211_CMD_GET_FTM_RESPONDER_STATS,
ef6243ac 16082 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
81e54d08 16083 .doit = nl80211_get_ftm_responder_stats,
a05829a7 16084 .internal_flags = NL80211_FLAG_NEED_NETDEV,
81e54d08 16085 },
9bb7e0f2
JB
16086 {
16087 .cmd = NL80211_CMD_PEER_MEASUREMENT_START,
ef6243ac 16088 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9bb7e0f2 16089 .doit = nl80211_pmsr_start,
9bb7e0f2 16090 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 16091 .internal_flags = NL80211_FLAG_NEED_WDEV_UP,
9bb7e0f2 16092 },
30c63115
S
16093 {
16094 .cmd = NL80211_CMD_NOTIFY_RADAR,
ef6243ac 16095 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
30c63115 16096 .doit = nl80211_notify_radar_detection,
30c63115 16097 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 16098 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
30c63115 16099 },
cb74e977
SD
16100 {
16101 .cmd = NL80211_CMD_UPDATE_OWE_INFO,
16102 .doit = nl80211_update_owe_info,
16103 .flags = GENL_ADMIN_PERM,
a05829a7 16104 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
5ab92e7f
RM
16105 },
16106 {
16107 .cmd = NL80211_CMD_PROBE_MESH_LINK,
16108 .doit = nl80211_probe_mesh_link,
16109 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 16110 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
cb74e977 16111 },
77f576de
T
16112 {
16113 .cmd = NL80211_CMD_SET_TID_CONFIG,
16114 .doit = nl80211_set_tid_config,
16115 .flags = GENL_UNS_ADMIN_PERM,
a05829a7 16116 .internal_flags = NL80211_FLAG_NEED_NETDEV,
77f576de 16117 },
6bdb68ce
CH
16118 {
16119 .cmd = NL80211_CMD_SET_SAR_SPECS,
16120 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
16121 .doit = nl80211_set_sar_specs,
16122 .flags = GENL_UNS_ADMIN_PERM,
16123 .internal_flags = NL80211_FLAG_NEED_WIPHY |
16124 NL80211_FLAG_NEED_RTNL,
16125 },
0d2ab3ae
JC
16126 {
16127 .cmd = NL80211_CMD_COLOR_CHANGE_REQUEST,
16128 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
16129 .doit = nl80211_color_change,
16130 .flags = GENL_UNS_ADMIN_PERM,
16131 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
16132 NL80211_FLAG_NEED_RTNL,
16133 },
e306784a
SM
16134 {
16135 .cmd = NL80211_CMD_SET_FILS_AAD,
16136 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
16137 .doit = nl80211_set_fils_aad,
16138 .flags = GENL_UNS_ADMIN_PERM,
16139 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
16140 },
55682965 16141};
9588bbd5 16142
56989f6d 16143static struct genl_family nl80211_fam __ro_after_init = {
489111e5
JB
16144 .name = NL80211_GENL_NAME, /* have users key off the name instead */
16145 .hdrsize = 0, /* no private header */
16146 .version = 1, /* no particular meaning now */
16147 .maxattr = NL80211_ATTR_MAX,
3b0f31f2 16148 .policy = nl80211_policy,
489111e5
JB
16149 .netnsok = true,
16150 .pre_doit = nl80211_pre_doit,
16151 .post_doit = nl80211_post_doit,
16152 .module = THIS_MODULE,
16153 .ops = nl80211_ops,
16154 .n_ops = ARRAY_SIZE(nl80211_ops),
66a9b928
JK
16155 .small_ops = nl80211_small_ops,
16156 .n_small_ops = ARRAY_SIZE(nl80211_small_ops),
489111e5
JB
16157 .mcgrps = nl80211_mcgrps,
16158 .n_mcgrps = ARRAY_SIZE(nl80211_mcgrps),
50508d94 16159 .parallel_ops = true,
489111e5
JB
16160};
16161
55682965
JB
16162/* notification functions */
16163
3bb20556
JB
16164void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev,
16165 enum nl80211_commands cmd)
55682965
JB
16166{
16167 struct sk_buff *msg;
86e8cf98 16168 struct nl80211_dump_wiphy_state state = {};
55682965 16169
3bb20556
JB
16170 WARN_ON(cmd != NL80211_CMD_NEW_WIPHY &&
16171 cmd != NL80211_CMD_DEL_WIPHY);
16172
fd2120ca 16173 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
55682965
JB
16174 if (!msg)
16175 return;
16176
3bb20556 16177 if (nl80211_send_wiphy(rdev, cmd, msg, 0, 0, 0, &state) < 0) {
55682965
JB
16178 nlmsg_free(msg);
16179 return;
16180 }
16181
68eb5503 16182 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16183 NL80211_MCGRP_CONFIG, GFP_KERNEL);
55682965
JB
16184}
16185
896ff063
DK
16186void nl80211_notify_iface(struct cfg80211_registered_device *rdev,
16187 struct wireless_dev *wdev,
16188 enum nl80211_commands cmd)
16189{
16190 struct sk_buff *msg;
16191
896ff063
DK
16192 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
16193 if (!msg)
16194 return;
16195
3d1a5bbf 16196 if (nl80211_send_iface(msg, 0, 0, 0, rdev, wdev, cmd) < 0) {
896ff063
DK
16197 nlmsg_free(msg);
16198 return;
16199 }
16200
16201 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
16202 NL80211_MCGRP_CONFIG, GFP_KERNEL);
16203}
16204
362a415d
JB
16205static int nl80211_add_scan_req(struct sk_buff *msg,
16206 struct cfg80211_registered_device *rdev)
16207{
16208 struct cfg80211_scan_request *req = rdev->scan_req;
16209 struct nlattr *nest;
16210 int i;
c8cb5b85 16211 struct cfg80211_scan_info *info;
362a415d
JB
16212
16213 if (WARN_ON(!req))
16214 return 0;
16215
ae0be8de 16216 nest = nla_nest_start_noflag(msg, NL80211_ATTR_SCAN_SSIDS);
362a415d
JB
16217 if (!nest)
16218 goto nla_put_failure;
9360ffd1
DM
16219 for (i = 0; i < req->n_ssids; i++) {
16220 if (nla_put(msg, i, req->ssids[i].ssid_len, req->ssids[i].ssid))
16221 goto nla_put_failure;
16222 }
362a415d
JB
16223 nla_nest_end(msg, nest);
16224
2032f3b2
TP
16225 if (req->flags & NL80211_SCAN_FLAG_FREQ_KHZ) {
16226 nest = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQ_KHZ);
16227 if (!nest)
16228 goto nla_put_failure;
16229 for (i = 0; i < req->n_channels; i++) {
16230 if (nla_put_u32(msg, i,
16231 ieee80211_channel_to_khz(req->channels[i])))
16232 goto nla_put_failure;
16233 }
16234 nla_nest_end(msg, nest);
16235 } else {
16236 nest = nla_nest_start_noflag(msg,
16237 NL80211_ATTR_SCAN_FREQUENCIES);
16238 if (!nest)
9360ffd1 16239 goto nla_put_failure;
2032f3b2
TP
16240 for (i = 0; i < req->n_channels; i++) {
16241 if (nla_put_u32(msg, i, req->channels[i]->center_freq))
16242 goto nla_put_failure;
16243 }
16244 nla_nest_end(msg, nest);
9360ffd1 16245 }
362a415d 16246
9360ffd1
DM
16247 if (req->ie &&
16248 nla_put(msg, NL80211_ATTR_IE, req->ie_len, req->ie))
16249 goto nla_put_failure;
362a415d 16250
ae917c9f
JB
16251 if (req->flags &&
16252 nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags))
16253 goto nla_put_failure;
ed473771 16254
c8cb5b85
TM
16255 info = rdev->int_scan_req ? &rdev->int_scan_req->info :
16256 &rdev->scan_req->info;
16257 if (info->scan_start_tsf &&
1d76250b 16258 (nla_put_u64_64bit(msg, NL80211_ATTR_SCAN_START_TIME_TSF,
c8cb5b85 16259 info->scan_start_tsf, NL80211_BSS_PAD) ||
1d76250b 16260 nla_put(msg, NL80211_ATTR_SCAN_START_TIME_TSF_BSSID, ETH_ALEN,
c8cb5b85 16261 info->tsf_bssid)))
1d76250b
AS
16262 goto nla_put_failure;
16263
362a415d
JB
16264 return 0;
16265 nla_put_failure:
16266 return -ENOBUFS;
16267}
16268
505a2e88 16269static int nl80211_prep_scan_msg(struct sk_buff *msg,
a538e2d5 16270 struct cfg80211_registered_device *rdev,
fd014284 16271 struct wireless_dev *wdev,
15e47304 16272 u32 portid, u32 seq, int flags,
a538e2d5 16273 u32 cmd)
2a519311
JB
16274{
16275 void *hdr;
16276
15e47304 16277 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
2a519311
JB
16278 if (!hdr)
16279 return -1;
16280
9360ffd1 16281 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
fd014284
JB
16282 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
16283 wdev->netdev->ifindex)) ||
2dad624e
ND
16284 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
16285 NL80211_ATTR_PAD))
9360ffd1 16286 goto nla_put_failure;
2a519311 16287
362a415d
JB
16288 /* ignore errors and send incomplete event anyway */
16289 nl80211_add_scan_req(msg, rdev);
2a519311 16290
053c095a
JB
16291 genlmsg_end(msg, hdr);
16292 return 0;
2a519311
JB
16293
16294 nla_put_failure:
16295 genlmsg_cancel(msg, hdr);
16296 return -EMSGSIZE;
16297}
16298
807f8a8c 16299static int
505a2e88 16300nl80211_prep_sched_scan_msg(struct sk_buff *msg,
96b08fd6 16301 struct cfg80211_sched_scan_request *req, u32 cmd)
807f8a8c
LC
16302{
16303 void *hdr;
16304
96b08fd6 16305 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
807f8a8c
LC
16306 if (!hdr)
16307 return -1;
16308
96b08fd6
AVS
16309 if (nla_put_u32(msg, NL80211_ATTR_WIPHY,
16310 wiphy_to_rdev(req->wiphy)->wiphy_idx) ||
16311 nla_put_u32(msg, NL80211_ATTR_IFINDEX, req->dev->ifindex) ||
16312 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, req->reqid,
16313 NL80211_ATTR_PAD))
9360ffd1 16314 goto nla_put_failure;
807f8a8c 16315
053c095a
JB
16316 genlmsg_end(msg, hdr);
16317 return 0;
807f8a8c
LC
16318
16319 nla_put_failure:
16320 genlmsg_cancel(msg, hdr);
16321 return -EMSGSIZE;
16322}
16323
a538e2d5 16324void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
fd014284 16325 struct wireless_dev *wdev)
a538e2d5
JB
16326{
16327 struct sk_buff *msg;
16328
58050fce 16329 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
a538e2d5
JB
16330 if (!msg)
16331 return;
16332
505a2e88 16333 if (nl80211_prep_scan_msg(msg, rdev, wdev, 0, 0, 0,
a538e2d5
JB
16334 NL80211_CMD_TRIGGER_SCAN) < 0) {
16335 nlmsg_free(msg);
16336 return;
16337 }
16338
68eb5503 16339 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16340 NL80211_MCGRP_SCAN, GFP_KERNEL);
a538e2d5
JB
16341}
16342
f9d15d16
JB
16343struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
16344 struct wireless_dev *wdev, bool aborted)
2a519311
JB
16345{
16346 struct sk_buff *msg;
16347
fd2120ca 16348 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2a519311 16349 if (!msg)
f9d15d16 16350 return NULL;
2a519311 16351
505a2e88 16352 if (nl80211_prep_scan_msg(msg, rdev, wdev, 0, 0, 0,
f9d15d16
JB
16353 aborted ? NL80211_CMD_SCAN_ABORTED :
16354 NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
2a519311 16355 nlmsg_free(msg);
f9d15d16 16356 return NULL;
2a519311
JB
16357 }
16358
f9d15d16 16359 return msg;
2a519311
JB
16360}
16361
505a2e88
AVS
16362/* send message created by nl80211_build_scan_msg() */
16363void nl80211_send_scan_msg(struct cfg80211_registered_device *rdev,
16364 struct sk_buff *msg)
807f8a8c 16365{
807f8a8c
LC
16366 if (!msg)
16367 return;
16368
68eb5503 16369 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16370 NL80211_MCGRP_SCAN, GFP_KERNEL);
807f8a8c
LC
16371}
16372
96b08fd6 16373void nl80211_send_sched_scan(struct cfg80211_sched_scan_request *req, u32 cmd)
807f8a8c
LC
16374{
16375 struct sk_buff *msg;
16376
58050fce 16377 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
807f8a8c
LC
16378 if (!msg)
16379 return;
16380
96b08fd6 16381 if (nl80211_prep_sched_scan_msg(msg, req, cmd) < 0) {
807f8a8c
LC
16382 nlmsg_free(msg);
16383 return;
16384 }
16385
96b08fd6 16386 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(req->wiphy), msg, 0,
2a94fe48 16387 NL80211_MCGRP_SCAN, GFP_KERNEL);
807f8a8c
LC
16388}
16389
b0d7aa59
JD
16390static bool nl80211_reg_change_event_fill(struct sk_buff *msg,
16391 struct regulatory_request *request)
73d54c9e 16392{
73d54c9e 16393 /* Userspace can always count this one always being set */
9360ffd1
DM
16394 if (nla_put_u8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator))
16395 goto nla_put_failure;
16396
16397 if (request->alpha2[0] == '0' && request->alpha2[1] == '0') {
16398 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
16399 NL80211_REGDOM_TYPE_WORLD))
16400 goto nla_put_failure;
16401 } else if (request->alpha2[0] == '9' && request->alpha2[1] == '9') {
16402 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
16403 NL80211_REGDOM_TYPE_CUSTOM_WORLD))
16404 goto nla_put_failure;
16405 } else if ((request->alpha2[0] == '9' && request->alpha2[1] == '8') ||
16406 request->intersect) {
16407 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
16408 NL80211_REGDOM_TYPE_INTERSECTION))
16409 goto nla_put_failure;
16410 } else {
16411 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
16412 NL80211_REGDOM_TYPE_COUNTRY) ||
16413 nla_put_string(msg, NL80211_ATTR_REG_ALPHA2,
16414 request->alpha2))
16415 goto nla_put_failure;
16416 }
16417
ad30ca2c
AN
16418 if (request->wiphy_idx != WIPHY_IDX_INVALID) {
16419 struct wiphy *wiphy = wiphy_idx_to_wiphy(request->wiphy_idx);
16420
16421 if (wiphy &&
16422 nla_put_u32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx))
16423 goto nla_put_failure;
1bdd716c
AN
16424
16425 if (wiphy &&
16426 wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
16427 nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
16428 goto nla_put_failure;
ad30ca2c 16429 }
73d54c9e 16430
b0d7aa59
JD
16431 return true;
16432
16433nla_put_failure:
16434 return false;
16435}
16436
16437/*
16438 * This can happen on global regulatory changes or device specific settings
16439 * based on custom regulatory domains.
16440 */
16441void nl80211_common_reg_change_event(enum nl80211_commands cmd_id,
16442 struct regulatory_request *request)
16443{
16444 struct sk_buff *msg;
16445 void *hdr;
16446
16447 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
16448 if (!msg)
16449 return;
16450
16451 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd_id);
24f6d765 16452 if (!hdr)
16453 goto nla_put_failure;
b0d7aa59 16454
24f6d765 16455 if (!nl80211_reg_change_event_fill(msg, request))
b0d7aa59
JD
16456 goto nla_put_failure;
16457
3b7b72ee 16458 genlmsg_end(msg, hdr);
73d54c9e 16459
bc43b28c 16460 rcu_read_lock();
68eb5503 16461 genlmsg_multicast_allns(&nl80211_fam, msg, 0,
2a94fe48 16462 NL80211_MCGRP_REGULATORY, GFP_ATOMIC);
bc43b28c 16463 rcu_read_unlock();
73d54c9e
LR
16464
16465 return;
16466
16467nla_put_failure:
73d54c9e
LR
16468 nlmsg_free(msg);
16469}
16470
6039f6d2
JM
16471static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
16472 struct net_device *netdev,
16473 const u8 *buf, size_t len,
b0b6aa2c 16474 enum nl80211_commands cmd, gfp_t gfp,
4d9ec73d 16475 int uapsd_queues, const u8 *req_ies,
3bb02143 16476 size_t req_ies_len, bool reconnect)
6039f6d2
JM
16477{
16478 struct sk_buff *msg;
16479 void *hdr;
16480
4d9ec73d 16481 msg = nlmsg_new(100 + len + req_ies_len, gfp);
6039f6d2
JM
16482 if (!msg)
16483 return;
16484
16485 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
16486 if (!hdr) {
16487 nlmsg_free(msg);
16488 return;
16489 }
16490
9360ffd1
DM
16491 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16492 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
4d9ec73d
JM
16493 nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
16494 (req_ies &&
16495 nla_put(msg, NL80211_ATTR_REQ_IE, req_ies_len, req_ies)))
9360ffd1 16496 goto nla_put_failure;
6039f6d2 16497
3bb02143
JB
16498 if (reconnect && nla_put_flag(msg, NL80211_ATTR_RECONNECT_REQUESTED))
16499 goto nla_put_failure;
16500
b0b6aa2c
EP
16501 if (uapsd_queues >= 0) {
16502 struct nlattr *nla_wmm =
ae0be8de 16503 nla_nest_start_noflag(msg, NL80211_ATTR_STA_WME);
b0b6aa2c
EP
16504 if (!nla_wmm)
16505 goto nla_put_failure;
16506
16507 if (nla_put_u8(msg, NL80211_STA_WME_UAPSD_QUEUES,
16508 uapsd_queues))
16509 goto nla_put_failure;
16510
16511 nla_nest_end(msg, nla_wmm);
16512 }
16513
3b7b72ee 16514 genlmsg_end(msg, hdr);
6039f6d2 16515
68eb5503 16516 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16517 NL80211_MCGRP_MLME, gfp);
6039f6d2
JM
16518 return;
16519
16520 nla_put_failure:
6039f6d2
JM
16521 nlmsg_free(msg);
16522}
16523
16524void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
e6d6e342
JB
16525 struct net_device *netdev, const u8 *buf,
16526 size_t len, gfp_t gfp)
6039f6d2
JM
16527{
16528 nl80211_send_mlme_event(rdev, netdev, buf, len,
3bb02143
JB
16529 NL80211_CMD_AUTHENTICATE, gfp, -1, NULL, 0,
16530 false);
6039f6d2
JM
16531}
16532
16533void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
16534 struct net_device *netdev, const u8 *buf,
4d9ec73d
JM
16535 size_t len, gfp_t gfp, int uapsd_queues,
16536 const u8 *req_ies, size_t req_ies_len)
6039f6d2 16537{
e6d6e342 16538 nl80211_send_mlme_event(rdev, netdev, buf, len,
4d9ec73d 16539 NL80211_CMD_ASSOCIATE, gfp, uapsd_queues,
3bb02143 16540 req_ies, req_ies_len, false);
6039f6d2
JM
16541}
16542
53b46b84 16543void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
e6d6e342 16544 struct net_device *netdev, const u8 *buf,
3bb02143 16545 size_t len, bool reconnect, gfp_t gfp)
6039f6d2
JM
16546{
16547 nl80211_send_mlme_event(rdev, netdev, buf, len,
3bb02143
JB
16548 NL80211_CMD_DEAUTHENTICATE, gfp, -1, NULL, 0,
16549 reconnect);
6039f6d2
JM
16550}
16551
53b46b84
JM
16552void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
16553 struct net_device *netdev, const u8 *buf,
3bb02143 16554 size_t len, bool reconnect, gfp_t gfp)
6039f6d2
JM
16555{
16556 nl80211_send_mlme_event(rdev, netdev, buf, len,
3bb02143
JB
16557 NL80211_CMD_DISASSOCIATE, gfp, -1, NULL, 0,
16558 reconnect);
6039f6d2
JM
16559}
16560
6ff57cf8
JB
16561void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf,
16562 size_t len)
cf4e594e 16563{
947add36
JB
16564 struct wireless_dev *wdev = dev->ieee80211_ptr;
16565 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 16566 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
6ff57cf8
JB
16567 const struct ieee80211_mgmt *mgmt = (void *)buf;
16568 u32 cmd;
947add36 16569
6ff57cf8
JB
16570 if (WARN_ON(len < 2))
16571 return;
cf4e594e 16572
4d797fce 16573 if (ieee80211_is_deauth(mgmt->frame_control)) {
6ff57cf8 16574 cmd = NL80211_CMD_UNPROT_DEAUTHENTICATE;
4d797fce 16575 } else if (ieee80211_is_disassoc(mgmt->frame_control)) {
6ff57cf8 16576 cmd = NL80211_CMD_UNPROT_DISASSOCIATE;
4d797fce
JM
16577 } else if (ieee80211_is_beacon(mgmt->frame_control)) {
16578 if (wdev->unprot_beacon_reported &&
16579 elapsed_jiffies_msecs(wdev->unprot_beacon_reported) < 10000)
16580 return;
16581 cmd = NL80211_CMD_UNPROT_BEACON;
16582 wdev->unprot_beacon_reported = jiffies;
16583 } else {
16584 return;
16585 }
947add36 16586
6ff57cf8 16587 trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len);
4d9ec73d 16588 nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1,
3bb02143 16589 NULL, 0, false);
cf4e594e 16590}
6ff57cf8 16591EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt);
cf4e594e 16592
1b06bb40
LR
16593static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev,
16594 struct net_device *netdev, int cmd,
e6d6e342 16595 const u8 *addr, gfp_t gfp)
1965c853
JM
16596{
16597 struct sk_buff *msg;
16598 void *hdr;
16599
e6d6e342 16600 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
1965c853
JM
16601 if (!msg)
16602 return;
16603
16604 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
16605 if (!hdr) {
16606 nlmsg_free(msg);
16607 return;
16608 }
16609
9360ffd1
DM
16610 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16611 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
16612 nla_put_flag(msg, NL80211_ATTR_TIMED_OUT) ||
16613 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
16614 goto nla_put_failure;
1965c853 16615
3b7b72ee 16616 genlmsg_end(msg, hdr);
1965c853 16617
68eb5503 16618 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16619 NL80211_MCGRP_MLME, gfp);
1965c853
JM
16620 return;
16621
16622 nla_put_failure:
1965c853
JM
16623 nlmsg_free(msg);
16624}
16625
16626void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
e6d6e342
JB
16627 struct net_device *netdev, const u8 *addr,
16628 gfp_t gfp)
1965c853
JM
16629{
16630 nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_AUTHENTICATE,
e6d6e342 16631 addr, gfp);
1965c853
JM
16632}
16633
16634void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev,
e6d6e342
JB
16635 struct net_device *netdev, const u8 *addr,
16636 gfp_t gfp)
1965c853 16637{
e6d6e342
JB
16638 nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_ASSOCIATE,
16639 addr, gfp);
1965c853
JM
16640}
16641
b23aa676 16642void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
5349a0f7
VK
16643 struct net_device *netdev,
16644 struct cfg80211_connect_resp_params *cr,
3093ebbe 16645 gfp_t gfp)
b23aa676
SO
16646{
16647 struct sk_buff *msg;
16648 void *hdr;
16649
a3caf744 16650 msg = nlmsg_new(100 + cr->req_ie_len + cr->resp_ie_len +
76804d28
AVS
16651 cr->fils.kek_len + cr->fils.pmk_len +
16652 (cr->fils.pmkid ? WLAN_PMKID_LEN : 0), gfp);
b23aa676
SO
16653 if (!msg)
16654 return;
16655
16656 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONNECT);
16657 if (!hdr) {
16658 nlmsg_free(msg);
16659 return;
16660 }
16661
9360ffd1
DM
16662 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16663 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
5349a0f7
VK
16664 (cr->bssid &&
16665 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, cr->bssid)) ||
bf1ecd21 16666 nla_put_u16(msg, NL80211_ATTR_STATUS_CODE,
5349a0f7
VK
16667 cr->status < 0 ? WLAN_STATUS_UNSPECIFIED_FAILURE :
16668 cr->status) ||
16669 (cr->status < 0 &&
3093ebbe 16670 (nla_put_flag(msg, NL80211_ATTR_TIMED_OUT) ||
5349a0f7
VK
16671 nla_put_u32(msg, NL80211_ATTR_TIMEOUT_REASON,
16672 cr->timeout_reason))) ||
16673 (cr->req_ie &&
16674 nla_put(msg, NL80211_ATTR_REQ_IE, cr->req_ie_len, cr->req_ie)) ||
16675 (cr->resp_ie &&
16676 nla_put(msg, NL80211_ATTR_RESP_IE, cr->resp_ie_len,
a3caf744 16677 cr->resp_ie)) ||
76804d28 16678 (cr->fils.update_erp_next_seq_num &&
a3caf744 16679 nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM,
76804d28 16680 cr->fils.erp_next_seq_num)) ||
a3caf744 16681 (cr->status == WLAN_STATUS_SUCCESS &&
76804d28
AVS
16682 ((cr->fils.kek &&
16683 nla_put(msg, NL80211_ATTR_FILS_KEK, cr->fils.kek_len,
16684 cr->fils.kek)) ||
16685 (cr->fils.pmk &&
16686 nla_put(msg, NL80211_ATTR_PMK, cr->fils.pmk_len, cr->fils.pmk)) ||
16687 (cr->fils.pmkid &&
16688 nla_put(msg, NL80211_ATTR_PMKID, WLAN_PMKID_LEN, cr->fils.pmkid)))))
9360ffd1 16689 goto nla_put_failure;
b23aa676 16690
3b7b72ee 16691 genlmsg_end(msg, hdr);
b23aa676 16692
68eb5503 16693 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16694 NL80211_MCGRP_MLME, gfp);
b23aa676
SO
16695 return;
16696
16697 nla_put_failure:
b23aa676 16698 nlmsg_free(msg);
b23aa676
SO
16699}
16700
16701void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
29ce6ecb
AS
16702 struct net_device *netdev,
16703 struct cfg80211_roam_info *info, gfp_t gfp)
b23aa676
SO
16704{
16705 struct sk_buff *msg;
16706 void *hdr;
29ce6ecb 16707 const u8 *bssid = info->bss ? info->bss->bssid : info->bssid;
b23aa676 16708
e841b7b1
AVS
16709 msg = nlmsg_new(100 + info->req_ie_len + info->resp_ie_len +
16710 info->fils.kek_len + info->fils.pmk_len +
16711 (info->fils.pmkid ? WLAN_PMKID_LEN : 0), gfp);
b23aa676
SO
16712 if (!msg)
16713 return;
16714
16715 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ROAM);
16716 if (!hdr) {
16717 nlmsg_free(msg);
16718 return;
16719 }
16720
9360ffd1
DM
16721 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16722 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
16723 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid) ||
29ce6ecb
AS
16724 (info->req_ie &&
16725 nla_put(msg, NL80211_ATTR_REQ_IE, info->req_ie_len,
16726 info->req_ie)) ||
16727 (info->resp_ie &&
16728 nla_put(msg, NL80211_ATTR_RESP_IE, info->resp_ie_len,
e841b7b1
AVS
16729 info->resp_ie)) ||
16730 (info->fils.update_erp_next_seq_num &&
16731 nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM,
16732 info->fils.erp_next_seq_num)) ||
16733 (info->fils.kek &&
16734 nla_put(msg, NL80211_ATTR_FILS_KEK, info->fils.kek_len,
16735 info->fils.kek)) ||
16736 (info->fils.pmk &&
16737 nla_put(msg, NL80211_ATTR_PMK, info->fils.pmk_len, info->fils.pmk)) ||
16738 (info->fils.pmkid &&
16739 nla_put(msg, NL80211_ATTR_PMKID, WLAN_PMKID_LEN, info->fils.pmkid)))
9360ffd1 16740 goto nla_put_failure;
b23aa676 16741
3b7b72ee 16742 genlmsg_end(msg, hdr);
b23aa676 16743
68eb5503 16744 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16745 NL80211_MCGRP_MLME, gfp);
b23aa676
SO
16746 return;
16747
503c1fb9 16748 nla_put_failure:
503c1fb9
AS
16749 nlmsg_free(msg);
16750}
16751
16752void nl80211_send_port_authorized(struct cfg80211_registered_device *rdev,
16753 struct net_device *netdev, const u8 *bssid)
16754{
16755 struct sk_buff *msg;
16756 void *hdr;
16757
16758 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
16759 if (!msg)
16760 return;
16761
16762 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PORT_AUTHORIZED);
16763 if (!hdr) {
16764 nlmsg_free(msg);
16765 return;
16766 }
16767
f4d75993
CHH
16768 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16769 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
16770 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
503c1fb9
AS
16771 goto nla_put_failure;
16772
16773 genlmsg_end(msg, hdr);
16774
16775 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
16776 NL80211_MCGRP_MLME, GFP_KERNEL);
16777 return;
16778
b23aa676 16779 nla_put_failure:
b23aa676 16780 nlmsg_free(msg);
b23aa676
SO
16781}
16782
16783void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
16784 struct net_device *netdev, u16 reason,
667503dd 16785 const u8 *ie, size_t ie_len, bool from_ap)
b23aa676
SO
16786{
16787 struct sk_buff *msg;
16788 void *hdr;
16789
4ef8c1c9 16790 msg = nlmsg_new(100 + ie_len, GFP_KERNEL);
b23aa676
SO
16791 if (!msg)
16792 return;
16793
16794 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DISCONNECT);
16795 if (!hdr) {
16796 nlmsg_free(msg);
16797 return;
16798 }
16799
9360ffd1
DM
16800 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16801 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
86b6c465 16802 (reason &&
9360ffd1
DM
16803 nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason)) ||
16804 (from_ap &&
16805 nla_put_flag(msg, NL80211_ATTR_DISCONNECTED_BY_AP)) ||
16806 (ie && nla_put(msg, NL80211_ATTR_IE, ie_len, ie)))
16807 goto nla_put_failure;
b23aa676 16808
3b7b72ee 16809 genlmsg_end(msg, hdr);
b23aa676 16810
68eb5503 16811 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16812 NL80211_MCGRP_MLME, GFP_KERNEL);
b23aa676
SO
16813 return;
16814
16815 nla_put_failure:
b23aa676 16816 nlmsg_free(msg);
b23aa676
SO
16817}
16818
04a773ad
JB
16819void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
16820 struct net_device *netdev, const u8 *bssid,
16821 gfp_t gfp)
16822{
16823 struct sk_buff *msg;
16824 void *hdr;
16825
fd2120ca 16826 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
04a773ad
JB
16827 if (!msg)
16828 return;
16829
16830 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_JOIN_IBSS);
16831 if (!hdr) {
16832 nlmsg_free(msg);
16833 return;
16834 }
16835
9360ffd1
DM
16836 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16837 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
16838 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
16839 goto nla_put_failure;
04a773ad 16840
3b7b72ee 16841 genlmsg_end(msg, hdr);
04a773ad 16842
68eb5503 16843 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16844 NL80211_MCGRP_MLME, gfp);
04a773ad
JB
16845 return;
16846
16847 nla_put_failure:
04a773ad
JB
16848 nlmsg_free(msg);
16849}
16850
947add36 16851void cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr,
ecbc12ad
BC
16852 const u8 *ie, u8 ie_len,
16853 int sig_dbm, gfp_t gfp)
c93b5e71 16854{
947add36 16855 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 16856 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
c93b5e71
JC
16857 struct sk_buff *msg;
16858 void *hdr;
16859
947add36
JB
16860 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT))
16861 return;
16862
16863 trace_cfg80211_notify_new_peer_candidate(dev, addr);
16864
4ef8c1c9 16865 msg = nlmsg_new(100 + ie_len, gfp);
c93b5e71
JC
16866 if (!msg)
16867 return;
16868
16869 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NEW_PEER_CANDIDATE);
16870 if (!hdr) {
16871 nlmsg_free(msg);
16872 return;
16873 }
16874
9360ffd1 16875 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
947add36
JB
16876 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
16877 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
9360ffd1 16878 (ie_len && ie &&
ecbc12ad
BC
16879 nla_put(msg, NL80211_ATTR_IE, ie_len, ie)) ||
16880 (sig_dbm &&
16881 nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)))
9360ffd1 16882 goto nla_put_failure;
c93b5e71 16883
3b7b72ee 16884 genlmsg_end(msg, hdr);
c93b5e71 16885
68eb5503 16886 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16887 NL80211_MCGRP_MLME, gfp);
c93b5e71
JC
16888 return;
16889
16890 nla_put_failure:
c93b5e71
JC
16891 nlmsg_free(msg);
16892}
947add36 16893EXPORT_SYMBOL(cfg80211_notify_new_peer_candidate);
c93b5e71 16894
a3b8b056
JM
16895void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
16896 struct net_device *netdev, const u8 *addr,
16897 enum nl80211_key_type key_type, int key_id,
e6d6e342 16898 const u8 *tsc, gfp_t gfp)
a3b8b056
JM
16899{
16900 struct sk_buff *msg;
16901 void *hdr;
16902
e6d6e342 16903 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
a3b8b056
JM
16904 if (!msg)
16905 return;
16906
16907 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_MICHAEL_MIC_FAILURE);
16908 if (!hdr) {
16909 nlmsg_free(msg);
16910 return;
16911 }
16912
9360ffd1
DM
16913 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16914 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
16915 (addr && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) ||
16916 nla_put_u32(msg, NL80211_ATTR_KEY_TYPE, key_type) ||
16917 (key_id != -1 &&
16918 nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_id)) ||
16919 (tsc && nla_put(msg, NL80211_ATTR_KEY_SEQ, 6, tsc)))
16920 goto nla_put_failure;
a3b8b056 16921
3b7b72ee 16922 genlmsg_end(msg, hdr);
a3b8b056 16923
68eb5503 16924 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16925 NL80211_MCGRP_MLME, gfp);
a3b8b056
JM
16926 return;
16927
16928 nla_put_failure:
a3b8b056
JM
16929 nlmsg_free(msg);
16930}
16931
6bad8766
LR
16932void nl80211_send_beacon_hint_event(struct wiphy *wiphy,
16933 struct ieee80211_channel *channel_before,
16934 struct ieee80211_channel *channel_after)
16935{
16936 struct sk_buff *msg;
16937 void *hdr;
16938 struct nlattr *nl_freq;
16939
fd2120ca 16940 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
6bad8766
LR
16941 if (!msg)
16942 return;
16943
16944 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_BEACON_HINT);
16945 if (!hdr) {
16946 nlmsg_free(msg);
16947 return;
16948 }
16949
16950 /*
16951 * Since we are applying the beacon hint to a wiphy we know its
16952 * wiphy_idx is valid
16953 */
9360ffd1
DM
16954 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
16955 goto nla_put_failure;
6bad8766
LR
16956
16957 /* Before */
ae0be8de 16958 nl_freq = nla_nest_start_noflag(msg, NL80211_ATTR_FREQ_BEFORE);
6bad8766
LR
16959 if (!nl_freq)
16960 goto nla_put_failure;
50f32718
HD
16961
16962 if (nl80211_msg_put_channel(msg, wiphy, channel_before, false))
6bad8766
LR
16963 goto nla_put_failure;
16964 nla_nest_end(msg, nl_freq);
16965
16966 /* After */
ae0be8de 16967 nl_freq = nla_nest_start_noflag(msg, NL80211_ATTR_FREQ_AFTER);
6bad8766
LR
16968 if (!nl_freq)
16969 goto nla_put_failure;
50f32718
HD
16970
16971 if (nl80211_msg_put_channel(msg, wiphy, channel_after, false))
6bad8766
LR
16972 goto nla_put_failure;
16973 nla_nest_end(msg, nl_freq);
16974
3b7b72ee 16975 genlmsg_end(msg, hdr);
6bad8766 16976
463d0183 16977 rcu_read_lock();
68eb5503 16978 genlmsg_multicast_allns(&nl80211_fam, msg, 0,
2a94fe48 16979 NL80211_MCGRP_REGULATORY, GFP_ATOMIC);
463d0183 16980 rcu_read_unlock();
6bad8766
LR
16981
16982 return;
16983
16984nla_put_failure:
6bad8766
LR
16985 nlmsg_free(msg);
16986}
16987
9588bbd5
JM
16988static void nl80211_send_remain_on_chan_event(
16989 int cmd, struct cfg80211_registered_device *rdev,
71bbc994 16990 struct wireless_dev *wdev, u64 cookie,
9588bbd5 16991 struct ieee80211_channel *chan,
9588bbd5
JM
16992 unsigned int duration, gfp_t gfp)
16993{
16994 struct sk_buff *msg;
16995 void *hdr;
16996
16997 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
16998 if (!msg)
16999 return;
17000
17001 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
17002 if (!hdr) {
17003 nlmsg_free(msg);
17004 return;
17005 }
17006
9360ffd1 17007 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
71bbc994
JB
17008 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
17009 wdev->netdev->ifindex)) ||
2dad624e
ND
17010 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
17011 NL80211_ATTR_PAD) ||
9360ffd1 17012 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq) ||
42d97a59
JB
17013 nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
17014 NL80211_CHAN_NO_HT) ||
2dad624e
ND
17015 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
17016 NL80211_ATTR_PAD))
9360ffd1 17017 goto nla_put_failure;
9588bbd5 17018
9360ffd1
DM
17019 if (cmd == NL80211_CMD_REMAIN_ON_CHANNEL &&
17020 nla_put_u32(msg, NL80211_ATTR_DURATION, duration))
17021 goto nla_put_failure;
9588bbd5 17022
3b7b72ee 17023 genlmsg_end(msg, hdr);
9588bbd5 17024
68eb5503 17025 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17026 NL80211_MCGRP_MLME, gfp);
9588bbd5
JM
17027 return;
17028
17029 nla_put_failure:
9588bbd5
JM
17030 nlmsg_free(msg);
17031}
17032
947add36
JB
17033void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
17034 struct ieee80211_channel *chan,
17035 unsigned int duration, gfp_t gfp)
9588bbd5 17036{
947add36 17037 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 17038 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
17039
17040 trace_cfg80211_ready_on_channel(wdev, cookie, chan, duration);
9588bbd5 17041 nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL,
71bbc994 17042 rdev, wdev, cookie, chan,
42d97a59 17043 duration, gfp);
9588bbd5 17044}
947add36 17045EXPORT_SYMBOL(cfg80211_ready_on_channel);
9588bbd5 17046
947add36
JB
17047void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
17048 struct ieee80211_channel *chan,
17049 gfp_t gfp)
9588bbd5 17050{
947add36 17051 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 17052 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
17053
17054 trace_cfg80211_ready_on_channel_expired(wdev, cookie, chan);
9588bbd5 17055 nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
42d97a59 17056 rdev, wdev, cookie, chan, 0, gfp);
9588bbd5 17057}
947add36 17058EXPORT_SYMBOL(cfg80211_remain_on_channel_expired);
9588bbd5 17059
1c38c7f2
JP
17060void cfg80211_tx_mgmt_expired(struct wireless_dev *wdev, u64 cookie,
17061 struct ieee80211_channel *chan,
17062 gfp_t gfp)
17063{
17064 struct wiphy *wiphy = wdev->wiphy;
17065 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
17066
17067 trace_cfg80211_tx_mgmt_expired(wdev, cookie, chan);
17068 nl80211_send_remain_on_chan_event(NL80211_CMD_FRAME_WAIT_CANCEL,
17069 rdev, wdev, cookie, chan, 0, gfp);
17070}
17071EXPORT_SYMBOL(cfg80211_tx_mgmt_expired);
17072
947add36
JB
17073void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
17074 struct station_info *sinfo, gfp_t gfp)
98b62183 17075{
947add36 17076 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
f26cbf40 17077 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
98b62183
JB
17078 struct sk_buff *msg;
17079
947add36
JB
17080 trace_cfg80211_new_sta(dev, mac_addr, sinfo);
17081
58050fce 17082 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
98b62183
JB
17083 if (!msg)
17084 return;
17085
cf5ead82 17086 if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION, 0, 0, 0,
66266b3a 17087 rdev, dev, mac_addr, sinfo) < 0) {
98b62183
JB
17088 nlmsg_free(msg);
17089 return;
17090 }
17091
68eb5503 17092 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17093 NL80211_MCGRP_MLME, gfp);
98b62183 17094}
947add36 17095EXPORT_SYMBOL(cfg80211_new_sta);
98b62183 17096
cf5ead82
JB
17097void cfg80211_del_sta_sinfo(struct net_device *dev, const u8 *mac_addr,
17098 struct station_info *sinfo, gfp_t gfp)
ec15e68b 17099{
947add36 17100 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
f26cbf40 17101 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
ec15e68b 17102 struct sk_buff *msg;
73887fd9 17103 struct station_info empty_sinfo = {};
cf5ead82 17104
73887fd9
JB
17105 if (!sinfo)
17106 sinfo = &empty_sinfo;
ec15e68b 17107
947add36
JB
17108 trace_cfg80211_del_sta(dev, mac_addr);
17109
58050fce 17110 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
7ea3e110
JB
17111 if (!msg) {
17112 cfg80211_sinfo_release_content(sinfo);
73887fd9 17113 return;
7ea3e110 17114 }
ec15e68b 17115
cf5ead82 17116 if (nl80211_send_station(msg, NL80211_CMD_DEL_STATION, 0, 0, 0,
57007121 17117 rdev, dev, mac_addr, sinfo) < 0) {
ec15e68b 17118 nlmsg_free(msg);
73887fd9 17119 return;
ec15e68b
JM
17120 }
17121
68eb5503 17122 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17123 NL80211_MCGRP_MLME, gfp);
ec15e68b 17124}
cf5ead82 17125EXPORT_SYMBOL(cfg80211_del_sta_sinfo);
ec15e68b 17126
947add36
JB
17127void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr,
17128 enum nl80211_connect_failed_reason reason,
17129 gfp_t gfp)
ed44a951 17130{
947add36 17131 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
f26cbf40 17132 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
ed44a951
PP
17133 struct sk_buff *msg;
17134 void *hdr;
17135
17136 msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
17137 if (!msg)
17138 return;
17139
17140 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONN_FAILED);
17141 if (!hdr) {
17142 nlmsg_free(msg);
17143 return;
17144 }
17145
17146 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
17147 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) ||
17148 nla_put_u32(msg, NL80211_ATTR_CONN_FAILED_REASON, reason))
17149 goto nla_put_failure;
17150
17151 genlmsg_end(msg, hdr);
17152
68eb5503 17153 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17154 NL80211_MCGRP_MLME, gfp);
ed44a951
PP
17155 return;
17156
17157 nla_put_failure:
ed44a951
PP
17158 nlmsg_free(msg);
17159}
947add36 17160EXPORT_SYMBOL(cfg80211_conn_failed);
ed44a951 17161
b92ab5d8
JB
17162static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd,
17163 const u8 *addr, gfp_t gfp)
28946da7
JB
17164{
17165 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 17166 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
28946da7
JB
17167 struct sk_buff *msg;
17168 void *hdr;
6aa7de05 17169 u32 nlportid = READ_ONCE(wdev->ap_unexpected_nlportid);
28946da7 17170
15e47304 17171 if (!nlportid)
28946da7
JB
17172 return false;
17173
17174 msg = nlmsg_new(100, gfp);
17175 if (!msg)
17176 return true;
17177
b92ab5d8 17178 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
28946da7
JB
17179 if (!hdr) {
17180 nlmsg_free(msg);
17181 return true;
17182 }
17183
9360ffd1
DM
17184 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17185 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
17186 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
17187 goto nla_put_failure;
28946da7 17188
9c90a9f6 17189 genlmsg_end(msg, hdr);
15e47304 17190 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
28946da7
JB
17191 return true;
17192
17193 nla_put_failure:
28946da7
JB
17194 nlmsg_free(msg);
17195 return true;
17196}
17197
947add36
JB
17198bool cfg80211_rx_spurious_frame(struct net_device *dev,
17199 const u8 *addr, gfp_t gfp)
b92ab5d8 17200{
947add36
JB
17201 struct wireless_dev *wdev = dev->ieee80211_ptr;
17202 bool ret;
17203
17204 trace_cfg80211_rx_spurious_frame(dev, addr);
17205
17206 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
17207 wdev->iftype != NL80211_IFTYPE_P2P_GO)) {
17208 trace_cfg80211_return_bool(false);
17209 return false;
17210 }
17211 ret = __nl80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME,
17212 addr, gfp);
17213 trace_cfg80211_return_bool(ret);
17214 return ret;
b92ab5d8 17215}
947add36 17216EXPORT_SYMBOL(cfg80211_rx_spurious_frame);
b92ab5d8 17217
947add36
JB
17218bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
17219 const u8 *addr, gfp_t gfp)
b92ab5d8 17220{
947add36
JB
17221 struct wireless_dev *wdev = dev->ieee80211_ptr;
17222 bool ret;
17223
17224 trace_cfg80211_rx_unexpected_4addr_frame(dev, addr);
17225
17226 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
17227 wdev->iftype != NL80211_IFTYPE_P2P_GO &&
17228 wdev->iftype != NL80211_IFTYPE_AP_VLAN)) {
17229 trace_cfg80211_return_bool(false);
17230 return false;
17231 }
17232 ret = __nl80211_unexpected_frame(dev,
17233 NL80211_CMD_UNEXPECTED_4ADDR_FRAME,
17234 addr, gfp);
17235 trace_cfg80211_return_bool(ret);
17236 return ret;
b92ab5d8 17237}
947add36 17238EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame);
b92ab5d8 17239
2e161f78 17240int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
15e47304 17241 struct wireless_dev *wdev, u32 nlportid,
804483e9 17242 int freq, int sig_dbm,
19504cf5 17243 const u8 *buf, size_t len, u32 flags, gfp_t gfp)
026331c4 17244{
71bbc994 17245 struct net_device *netdev = wdev->netdev;
026331c4
JM
17246 struct sk_buff *msg;
17247 void *hdr;
026331c4 17248
4ef8c1c9 17249 msg = nlmsg_new(100 + len, gfp);
026331c4
JM
17250 if (!msg)
17251 return -ENOMEM;
17252
2e161f78 17253 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME);
026331c4
JM
17254 if (!hdr) {
17255 nlmsg_free(msg);
17256 return -ENOMEM;
17257 }
17258
9360ffd1 17259 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
71bbc994
JB
17260 (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
17261 netdev->ifindex)) ||
2dad624e
ND
17262 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
17263 NL80211_ATTR_PAD) ||
e76fede8 17264 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, KHZ_TO_MHZ(freq)) ||
942ba88b 17265 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET, freq % 1000) ||
9360ffd1
DM
17266 (sig_dbm &&
17267 nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||
19504cf5
VK
17268 nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
17269 (flags &&
17270 nla_put_u32(msg, NL80211_ATTR_RXMGMT_FLAGS, flags)))
9360ffd1 17271 goto nla_put_failure;
026331c4 17272
3b7b72ee 17273 genlmsg_end(msg, hdr);
026331c4 17274
15e47304 17275 return genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
026331c4
JM
17276
17277 nla_put_failure:
026331c4
JM
17278 nlmsg_free(msg);
17279 return -ENOBUFS;
17280}
17281
dca9ca2d
MT
17282static void nl80211_frame_tx_status(struct wireless_dev *wdev, u64 cookie,
17283 const u8 *buf, size_t len, bool ack,
17284 gfp_t gfp, enum nl80211_commands command)
026331c4 17285{
947add36 17286 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 17287 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
71bbc994 17288 struct net_device *netdev = wdev->netdev;
026331c4
JM
17289 struct sk_buff *msg;
17290 void *hdr;
17291
dca9ca2d
MT
17292 if (command == NL80211_CMD_FRAME_TX_STATUS)
17293 trace_cfg80211_mgmt_tx_status(wdev, cookie, ack);
17294 else
17295 trace_cfg80211_control_port_tx_status(wdev, cookie, ack);
947add36 17296
4ef8c1c9 17297 msg = nlmsg_new(100 + len, gfp);
026331c4
JM
17298 if (!msg)
17299 return;
17300
dca9ca2d 17301 hdr = nl80211hdr_put(msg, 0, 0, 0, command);
026331c4
JM
17302 if (!hdr) {
17303 nlmsg_free(msg);
17304 return;
17305 }
17306
9360ffd1 17307 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
71bbc994
JB
17308 (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
17309 netdev->ifindex)) ||
2dad624e
ND
17310 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
17311 NL80211_ATTR_PAD) ||
9360ffd1 17312 nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
2dad624e
ND
17313 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
17314 NL80211_ATTR_PAD) ||
9360ffd1
DM
17315 (ack && nla_put_flag(msg, NL80211_ATTR_ACK)))
17316 goto nla_put_failure;
026331c4 17317
3b7b72ee 17318 genlmsg_end(msg, hdr);
026331c4 17319
68eb5503 17320 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17321 NL80211_MCGRP_MLME, gfp);
026331c4
JM
17322 return;
17323
dca9ca2d 17324nla_put_failure:
026331c4
JM
17325 nlmsg_free(msg);
17326}
dca9ca2d
MT
17327
17328void cfg80211_control_port_tx_status(struct wireless_dev *wdev, u64 cookie,
17329 const u8 *buf, size_t len, bool ack,
17330 gfp_t gfp)
17331{
17332 nl80211_frame_tx_status(wdev, cookie, buf, len, ack, gfp,
17333 NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS);
17334}
17335EXPORT_SYMBOL(cfg80211_control_port_tx_status);
17336
17337void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
17338 const u8 *buf, size_t len, bool ack, gfp_t gfp)
17339{
17340 nl80211_frame_tx_status(wdev, cookie, buf, len, ack, gfp,
17341 NL80211_CMD_FRAME_TX_STATUS);
17342}
947add36 17343EXPORT_SYMBOL(cfg80211_mgmt_tx_status);
026331c4 17344
6a671a50 17345static int __nl80211_rx_control_port(struct net_device *dev,
a948f713 17346 struct sk_buff *skb,
6a671a50
DK
17347 bool unencrypted, gfp_t gfp)
17348{
17349 struct wireless_dev *wdev = dev->ieee80211_ptr;
17350 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
a948f713 17351 struct ethhdr *ehdr = eth_hdr(skb);
8d74a623 17352 const u8 *addr = ehdr->h_source;
a948f713 17353 u16 proto = be16_to_cpu(skb->protocol);
6a671a50
DK
17354 struct sk_buff *msg;
17355 void *hdr;
a948f713
DK
17356 struct nlattr *frame;
17357
6a671a50
DK
17358 u32 nlportid = READ_ONCE(wdev->conn_owner_nlportid);
17359
17360 if (!nlportid)
17361 return -ENOENT;
17362
a948f713 17363 msg = nlmsg_new(100 + skb->len, gfp);
6a671a50
DK
17364 if (!msg)
17365 return -ENOMEM;
17366
17367 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONTROL_PORT_FRAME);
17368 if (!hdr) {
17369 nlmsg_free(msg);
17370 return -ENOBUFS;
17371 }
17372
17373 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17374 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
17375 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
17376 NL80211_ATTR_PAD) ||
8d74a623 17377 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
6a671a50
DK
17378 nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, proto) ||
17379 (unencrypted && nla_put_flag(msg,
17380 NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)))
17381 goto nla_put_failure;
17382
a948f713
DK
17383 frame = nla_reserve(msg, NL80211_ATTR_FRAME, skb->len);
17384 if (!frame)
17385 goto nla_put_failure;
17386
17387 skb_copy_bits(skb, 0, nla_data(frame), skb->len);
6a671a50
DK
17388 genlmsg_end(msg, hdr);
17389
17390 return genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
17391
17392 nla_put_failure:
17393 nlmsg_free(msg);
17394 return -ENOBUFS;
17395}
17396
17397bool cfg80211_rx_control_port(struct net_device *dev,
a948f713 17398 struct sk_buff *skb, bool unencrypted)
6a671a50
DK
17399{
17400 int ret;
17401
a948f713
DK
17402 trace_cfg80211_rx_control_port(dev, skb, unencrypted);
17403 ret = __nl80211_rx_control_port(dev, skb, unencrypted, GFP_ATOMIC);
6a671a50
DK
17404 trace_cfg80211_return_bool(ret == 0);
17405 return ret == 0;
17406}
17407EXPORT_SYMBOL(cfg80211_rx_control_port);
17408
5b97f49d
JB
17409static struct sk_buff *cfg80211_prepare_cqm(struct net_device *dev,
17410 const char *mac, gfp_t gfp)
d6dc1a38 17411{
947add36 17412 struct wireless_dev *wdev = dev->ieee80211_ptr;
5b97f49d
JB
17413 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
17414 struct sk_buff *msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
17415 void **cb;
947add36 17416
d6dc1a38 17417 if (!msg)
5b97f49d 17418 return NULL;
d6dc1a38 17419
5b97f49d
JB
17420 cb = (void **)msg->cb;
17421
17422 cb[0] = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_CQM);
17423 if (!cb[0]) {
d6dc1a38 17424 nlmsg_free(msg);
5b97f49d 17425 return NULL;
d6dc1a38
JO
17426 }
17427
9360ffd1 17428 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
947add36 17429 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
9360ffd1 17430 goto nla_put_failure;
d6dc1a38 17431
5b97f49d 17432 if (mac && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac))
d6dc1a38
JO
17433 goto nla_put_failure;
17434
ae0be8de 17435 cb[1] = nla_nest_start_noflag(msg, NL80211_ATTR_CQM);
5b97f49d 17436 if (!cb[1])
9360ffd1 17437 goto nla_put_failure;
d6dc1a38 17438
5b97f49d 17439 cb[2] = rdev;
d6dc1a38 17440
5b97f49d
JB
17441 return msg;
17442 nla_put_failure:
17443 nlmsg_free(msg);
17444 return NULL;
17445}
17446
17447static void cfg80211_send_cqm(struct sk_buff *msg, gfp_t gfp)
17448{
17449 void **cb = (void **)msg->cb;
17450 struct cfg80211_registered_device *rdev = cb[2];
17451
17452 nla_nest_end(msg, cb[1]);
17453 genlmsg_end(msg, cb[0]);
17454
17455 memset(msg->cb, 0, sizeof(msg->cb));
d6dc1a38 17456
68eb5503 17457 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17458 NL80211_MCGRP_MLME, gfp);
5b97f49d
JB
17459}
17460
17461void cfg80211_cqm_rssi_notify(struct net_device *dev,
17462 enum nl80211_cqm_rssi_threshold_event rssi_event,
bee427b8 17463 s32 rssi_level, gfp_t gfp)
5b97f49d
JB
17464{
17465 struct sk_buff *msg;
4a4b8169
AZ
17466 struct wireless_dev *wdev = dev->ieee80211_ptr;
17467 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
5b97f49d 17468
bee427b8 17469 trace_cfg80211_cqm_rssi_notify(dev, rssi_event, rssi_level);
5b97f49d 17470
98f03342
JB
17471 if (WARN_ON(rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW &&
17472 rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH))
17473 return;
17474
4a4b8169
AZ
17475 if (wdev->cqm_config) {
17476 wdev->cqm_config->last_rssi_event_value = rssi_level;
17477
17478 cfg80211_cqm_rssi_update(rdev, dev);
17479
17480 if (rssi_level == 0)
17481 rssi_level = wdev->cqm_config->last_rssi_event_value;
17482 }
17483
5b97f49d
JB
17484 msg = cfg80211_prepare_cqm(dev, NULL, gfp);
17485 if (!msg)
17486 return;
17487
17488 if (nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT,
17489 rssi_event))
17490 goto nla_put_failure;
17491
bee427b8
AZ
17492 if (rssi_level && nla_put_s32(msg, NL80211_ATTR_CQM_RSSI_LEVEL,
17493 rssi_level))
17494 goto nla_put_failure;
17495
5b97f49d
JB
17496 cfg80211_send_cqm(msg, gfp);
17497
d6dc1a38
JO
17498 return;
17499
17500 nla_put_failure:
d6dc1a38
JO
17501 nlmsg_free(msg);
17502}
947add36 17503EXPORT_SYMBOL(cfg80211_cqm_rssi_notify);
d6dc1a38 17504
5b97f49d
JB
17505void cfg80211_cqm_txe_notify(struct net_device *dev,
17506 const u8 *peer, u32 num_packets,
17507 u32 rate, u32 intvl, gfp_t gfp)
17508{
17509 struct sk_buff *msg;
17510
17511 msg = cfg80211_prepare_cqm(dev, peer, gfp);
17512 if (!msg)
17513 return;
17514
17515 if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_PKTS, num_packets))
17516 goto nla_put_failure;
17517
17518 if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_RATE, rate))
17519 goto nla_put_failure;
17520
17521 if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_INTVL, intvl))
17522 goto nla_put_failure;
17523
17524 cfg80211_send_cqm(msg, gfp);
17525 return;
17526
17527 nla_put_failure:
17528 nlmsg_free(msg);
17529}
17530EXPORT_SYMBOL(cfg80211_cqm_txe_notify);
17531
17532void cfg80211_cqm_pktloss_notify(struct net_device *dev,
17533 const u8 *peer, u32 num_packets, gfp_t gfp)
17534{
17535 struct sk_buff *msg;
17536
17537 trace_cfg80211_cqm_pktloss_notify(dev, peer, num_packets);
17538
17539 msg = cfg80211_prepare_cqm(dev, peer, gfp);
17540 if (!msg)
17541 return;
17542
17543 if (nla_put_u32(msg, NL80211_ATTR_CQM_PKT_LOSS_EVENT, num_packets))
17544 goto nla_put_failure;
17545
17546 cfg80211_send_cqm(msg, gfp);
17547 return;
17548
17549 nla_put_failure:
17550 nlmsg_free(msg);
17551}
17552EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify);
17553
98f03342
JB
17554void cfg80211_cqm_beacon_loss_notify(struct net_device *dev, gfp_t gfp)
17555{
17556 struct sk_buff *msg;
17557
17558 msg = cfg80211_prepare_cqm(dev, NULL, gfp);
17559 if (!msg)
17560 return;
17561
17562 if (nla_put_flag(msg, NL80211_ATTR_CQM_BEACON_LOSS_EVENT))
17563 goto nla_put_failure;
17564
17565 cfg80211_send_cqm(msg, gfp);
17566 return;
17567
17568 nla_put_failure:
17569 nlmsg_free(msg);
17570}
17571EXPORT_SYMBOL(cfg80211_cqm_beacon_loss_notify);
17572
947add36
JB
17573static void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
17574 struct net_device *netdev, const u8 *bssid,
17575 const u8 *replay_ctr, gfp_t gfp)
e5497d76
JB
17576{
17577 struct sk_buff *msg;
17578 struct nlattr *rekey_attr;
17579 void *hdr;
17580
58050fce 17581 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
e5497d76
JB
17582 if (!msg)
17583 return;
17584
17585 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_REKEY_OFFLOAD);
17586 if (!hdr) {
17587 nlmsg_free(msg);
17588 return;
17589 }
17590
9360ffd1
DM
17591 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17592 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
17593 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
17594 goto nla_put_failure;
e5497d76 17595
ae0be8de 17596 rekey_attr = nla_nest_start_noflag(msg, NL80211_ATTR_REKEY_DATA);
e5497d76
JB
17597 if (!rekey_attr)
17598 goto nla_put_failure;
17599
9360ffd1
DM
17600 if (nla_put(msg, NL80211_REKEY_DATA_REPLAY_CTR,
17601 NL80211_REPLAY_CTR_LEN, replay_ctr))
17602 goto nla_put_failure;
e5497d76
JB
17603
17604 nla_nest_end(msg, rekey_attr);
17605
3b7b72ee 17606 genlmsg_end(msg, hdr);
e5497d76 17607
68eb5503 17608 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17609 NL80211_MCGRP_MLME, gfp);
e5497d76
JB
17610 return;
17611
17612 nla_put_failure:
e5497d76
JB
17613 nlmsg_free(msg);
17614}
17615
947add36
JB
17616void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,
17617 const u8 *replay_ctr, gfp_t gfp)
17618{
17619 struct wireless_dev *wdev = dev->ieee80211_ptr;
17620 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 17621 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
17622
17623 trace_cfg80211_gtk_rekey_notify(dev, bssid);
17624 nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp);
17625}
17626EXPORT_SYMBOL(cfg80211_gtk_rekey_notify);
17627
17628static void
17629nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev,
17630 struct net_device *netdev, int index,
17631 const u8 *bssid, bool preauth, gfp_t gfp)
c9df56b4
JM
17632{
17633 struct sk_buff *msg;
17634 struct nlattr *attr;
17635 void *hdr;
17636
58050fce 17637 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
c9df56b4
JM
17638 if (!msg)
17639 return;
17640
17641 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PMKSA_CANDIDATE);
17642 if (!hdr) {
17643 nlmsg_free(msg);
17644 return;
17645 }
17646
9360ffd1
DM
17647 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17648 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
17649 goto nla_put_failure;
c9df56b4 17650
ae0be8de 17651 attr = nla_nest_start_noflag(msg, NL80211_ATTR_PMKSA_CANDIDATE);
c9df56b4
JM
17652 if (!attr)
17653 goto nla_put_failure;
17654
9360ffd1
DM
17655 if (nla_put_u32(msg, NL80211_PMKSA_CANDIDATE_INDEX, index) ||
17656 nla_put(msg, NL80211_PMKSA_CANDIDATE_BSSID, ETH_ALEN, bssid) ||
17657 (preauth &&
17658 nla_put_flag(msg, NL80211_PMKSA_CANDIDATE_PREAUTH)))
17659 goto nla_put_failure;
c9df56b4
JM
17660
17661 nla_nest_end(msg, attr);
17662
3b7b72ee 17663 genlmsg_end(msg, hdr);
c9df56b4 17664
68eb5503 17665 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17666 NL80211_MCGRP_MLME, gfp);
c9df56b4
JM
17667 return;
17668
17669 nla_put_failure:
c9df56b4
JM
17670 nlmsg_free(msg);
17671}
17672
947add36
JB
17673void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
17674 const u8 *bssid, bool preauth, gfp_t gfp)
17675{
17676 struct wireless_dev *wdev = dev->ieee80211_ptr;
17677 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 17678 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
17679
17680 trace_cfg80211_pmksa_candidate_notify(dev, index, bssid, preauth);
17681 nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp);
17682}
17683EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
17684
17685static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
17686 struct net_device *netdev,
17687 struct cfg80211_chan_def *chandef,
f8d7552e
LC
17688 gfp_t gfp,
17689 enum nl80211_commands notif,
669b8413 17690 u8 count, bool quiet)
5314526b
TP
17691{
17692 struct sk_buff *msg;
17693 void *hdr;
17694
58050fce 17695 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
5314526b
TP
17696 if (!msg)
17697 return;
17698
f8d7552e 17699 hdr = nl80211hdr_put(msg, 0, 0, 0, notif);
5314526b
TP
17700 if (!hdr) {
17701 nlmsg_free(msg);
17702 return;
17703 }
17704
683b6d3b
JB
17705 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
17706 goto nla_put_failure;
17707
17708 if (nl80211_send_chandef(msg, chandef))
7eab0f64 17709 goto nla_put_failure;
5314526b 17710
669b8413
JB
17711 if (notif == NL80211_CMD_CH_SWITCH_STARTED_NOTIFY) {
17712 if (nla_put_u32(msg, NL80211_ATTR_CH_SWITCH_COUNT, count))
f8d7552e 17713 goto nla_put_failure;
669b8413
JB
17714 if (quiet &&
17715 nla_put_flag(msg, NL80211_ATTR_CH_SWITCH_BLOCK_TX))
f8d7552e 17716 goto nla_put_failure;
669b8413 17717 }
f8d7552e 17718
5314526b
TP
17719 genlmsg_end(msg, hdr);
17720
68eb5503 17721 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17722 NL80211_MCGRP_MLME, gfp);
5314526b
TP
17723 return;
17724
17725 nla_put_failure:
5314526b
TP
17726 nlmsg_free(msg);
17727}
17728
947add36
JB
17729void cfg80211_ch_switch_notify(struct net_device *dev,
17730 struct cfg80211_chan_def *chandef)
84f10708 17731{
947add36
JB
17732 struct wireless_dev *wdev = dev->ieee80211_ptr;
17733 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 17734 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36 17735
e487eaeb 17736 ASSERT_WDEV_LOCK(wdev);
947add36 17737
e487eaeb 17738 trace_cfg80211_ch_switch_notify(dev, chandef);
947add36 17739
9e0e2961 17740 wdev->chandef = *chandef;
96f55f12 17741 wdev->preset_chandef = *chandef;
5dc8cdce
SM
17742
17743 if (wdev->iftype == NL80211_IFTYPE_STATION &&
17744 !WARN_ON(!wdev->current_bss))
0afd425b 17745 cfg80211_update_assoc_bss_entry(wdev, chandef->chan);
5dc8cdce 17746
d34990bb
MV
17747 cfg80211_sched_dfs_chan_update(rdev);
17748
f8d7552e 17749 nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
669b8413 17750 NL80211_CMD_CH_SWITCH_NOTIFY, 0, false);
947add36
JB
17751}
17752EXPORT_SYMBOL(cfg80211_ch_switch_notify);
17753
f8d7552e
LC
17754void cfg80211_ch_switch_started_notify(struct net_device *dev,
17755 struct cfg80211_chan_def *chandef,
669b8413 17756 u8 count, bool quiet)
f8d7552e
LC
17757{
17758 struct wireless_dev *wdev = dev->ieee80211_ptr;
17759 struct wiphy *wiphy = wdev->wiphy;
17760 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
17761
17762 trace_cfg80211_ch_switch_started_notify(dev, chandef);
17763
17764 nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
669b8413
JB
17765 NL80211_CMD_CH_SWITCH_STARTED_NOTIFY,
17766 count, quiet);
f8d7552e
LC
17767}
17768EXPORT_SYMBOL(cfg80211_ch_switch_started_notify);
17769
0d2ab3ae
JC
17770int cfg80211_bss_color_notify(struct net_device *dev, gfp_t gfp,
17771 enum nl80211_commands cmd, u8 count,
17772 u64 color_bitmap)
17773{
17774 struct wireless_dev *wdev = dev->ieee80211_ptr;
17775 struct wiphy *wiphy = wdev->wiphy;
17776 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
17777 struct sk_buff *msg;
17778 void *hdr;
17779
17780 ASSERT_WDEV_LOCK(wdev);
17781
17782 trace_cfg80211_bss_color_notify(dev, cmd, count, color_bitmap);
17783
17784 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
17785 if (!msg)
17786 return -ENOMEM;
17787
17788 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
17789 if (!hdr)
17790 goto nla_put_failure;
17791
17792 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
17793 goto nla_put_failure;
17794
17795 if (cmd == NL80211_CMD_COLOR_CHANGE_STARTED &&
17796 nla_put_u32(msg, NL80211_ATTR_COLOR_CHANGE_COUNT, count))
17797 goto nla_put_failure;
17798
17799 if (cmd == NL80211_CMD_OBSS_COLOR_COLLISION &&
17800 nla_put_u64_64bit(msg, NL80211_ATTR_OBSS_COLOR_BITMAP,
17801 color_bitmap, NL80211_ATTR_PAD))
17802 goto nla_put_failure;
17803
17804 genlmsg_end(msg, hdr);
17805
17806 return genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
17807 msg, 0, NL80211_MCGRP_MLME, gfp);
17808
17809nla_put_failure:
17810 nlmsg_free(msg);
17811 return -EINVAL;
17812}
17813EXPORT_SYMBOL(cfg80211_bss_color_notify);
17814
04f39047
SW
17815void
17816nl80211_radar_notify(struct cfg80211_registered_device *rdev,
d2859df5 17817 const struct cfg80211_chan_def *chandef,
04f39047
SW
17818 enum nl80211_radar_event event,
17819 struct net_device *netdev, gfp_t gfp)
17820{
17821 struct sk_buff *msg;
17822 void *hdr;
17823
17824 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
17825 if (!msg)
17826 return;
17827
17828 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_RADAR_DETECT);
17829 if (!hdr) {
17830 nlmsg_free(msg);
17831 return;
17832 }
17833
17834 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
17835 goto nla_put_failure;
17836
17837 /* NOP and radar events don't need a netdev parameter */
17838 if (netdev) {
17839 struct wireless_dev *wdev = netdev->ieee80211_ptr;
17840
17841 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
2dad624e
ND
17842 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
17843 NL80211_ATTR_PAD))
04f39047
SW
17844 goto nla_put_failure;
17845 }
17846
17847 if (nla_put_u32(msg, NL80211_ATTR_RADAR_EVENT, event))
17848 goto nla_put_failure;
17849
17850 if (nl80211_send_chandef(msg, chandef))
17851 goto nla_put_failure;
17852
9c90a9f6 17853 genlmsg_end(msg, hdr);
04f39047 17854
68eb5503 17855 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17856 NL80211_MCGRP_MLME, gfp);
04f39047
SW
17857 return;
17858
17859 nla_put_failure:
04f39047
SW
17860 nlmsg_free(msg);
17861}
17862
466b9936 17863void cfg80211_sta_opmode_change_notify(struct net_device *dev, const u8 *mac,
17864 struct sta_opmode_info *sta_opmode,
17865 gfp_t gfp)
17866{
17867 struct sk_buff *msg;
17868 struct wireless_dev *wdev = dev->ieee80211_ptr;
17869 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
17870 void *hdr;
17871
17872 if (WARN_ON(!mac))
17873 return;
17874
17875 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
17876 if (!msg)
17877 return;
17878
17879 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STA_OPMODE_CHANGED);
17880 if (!hdr) {
17881 nlmsg_free(msg);
17882 return;
17883 }
17884
17885 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
17886 goto nla_put_failure;
17887
17888 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
17889 goto nla_put_failure;
17890
17891 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac))
17892 goto nla_put_failure;
17893
17894 if ((sta_opmode->changed & STA_OPMODE_SMPS_MODE_CHANGED) &&
17895 nla_put_u8(msg, NL80211_ATTR_SMPS_MODE, sta_opmode->smps_mode))
17896 goto nla_put_failure;
17897
17898 if ((sta_opmode->changed & STA_OPMODE_MAX_BW_CHANGED) &&
0016d320 17899 nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, sta_opmode->bw))
466b9936 17900 goto nla_put_failure;
17901
17902 if ((sta_opmode->changed & STA_OPMODE_N_SS_CHANGED) &&
17903 nla_put_u8(msg, NL80211_ATTR_NSS, sta_opmode->rx_nss))
17904 goto nla_put_failure;
17905
17906 genlmsg_end(msg, hdr);
17907
17908 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
17909 NL80211_MCGRP_MLME, gfp);
17910
17911 return;
17912
17913nla_put_failure:
17914 nlmsg_free(msg);
17915}
17916EXPORT_SYMBOL(cfg80211_sta_opmode_change_notify);
17917
7f6cf311 17918void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
c4b50cd3
VN
17919 u64 cookie, bool acked, s32 ack_signal,
17920 bool is_valid_ack_signal, gfp_t gfp)
7f6cf311
JB
17921{
17922 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 17923 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
7f6cf311
JB
17924 struct sk_buff *msg;
17925 void *hdr;
7f6cf311 17926
4ee3e063
BL
17927 trace_cfg80211_probe_status(dev, addr, cookie, acked);
17928
58050fce 17929 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
4ee3e063 17930
7f6cf311
JB
17931 if (!msg)
17932 return;
17933
17934 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PROBE_CLIENT);
17935 if (!hdr) {
17936 nlmsg_free(msg);
17937 return;
17938 }
17939
9360ffd1
DM
17940 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17941 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
17942 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
2dad624e
ND
17943 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
17944 NL80211_ATTR_PAD) ||
c4b50cd3
VN
17945 (acked && nla_put_flag(msg, NL80211_ATTR_ACK)) ||
17946 (is_valid_ack_signal && nla_put_s32(msg, NL80211_ATTR_ACK_SIGNAL,
17947 ack_signal)))
9360ffd1 17948 goto nla_put_failure;
7f6cf311 17949
9c90a9f6 17950 genlmsg_end(msg, hdr);
7f6cf311 17951
68eb5503 17952 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17953 NL80211_MCGRP_MLME, gfp);
7f6cf311
JB
17954 return;
17955
17956 nla_put_failure:
7f6cf311
JB
17957 nlmsg_free(msg);
17958}
17959EXPORT_SYMBOL(cfg80211_probe_status);
17960
e76fede8
TP
17961void cfg80211_report_obss_beacon_khz(struct wiphy *wiphy, const u8 *frame,
17962 size_t len, int freq, int sig_dbm)
5e760230 17963{
f26cbf40 17964 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
5e760230
JB
17965 struct sk_buff *msg;
17966 void *hdr;
37c73b5f 17967 struct cfg80211_beacon_registration *reg;
5e760230 17968
4ee3e063
BL
17969 trace_cfg80211_report_obss_beacon(wiphy, frame, len, freq, sig_dbm);
17970
37c73b5f
BG
17971 spin_lock_bh(&rdev->beacon_registrations_lock);
17972 list_for_each_entry(reg, &rdev->beacon_registrations, list) {
17973 msg = nlmsg_new(len + 100, GFP_ATOMIC);
17974 if (!msg) {
17975 spin_unlock_bh(&rdev->beacon_registrations_lock);
17976 return;
17977 }
5e760230 17978
37c73b5f
BG
17979 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME);
17980 if (!hdr)
17981 goto nla_put_failure;
5e760230 17982
37c73b5f
BG
17983 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17984 (freq &&
942ba88b
TP
17985 (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
17986 KHZ_TO_MHZ(freq)) ||
17987 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
17988 freq % 1000))) ||
37c73b5f
BG
17989 (sig_dbm &&
17990 nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||
17991 nla_put(msg, NL80211_ATTR_FRAME, len, frame))
17992 goto nla_put_failure;
5e760230 17993
37c73b5f 17994 genlmsg_end(msg, hdr);
5e760230 17995
37c73b5f
BG
17996 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, reg->nlportid);
17997 }
17998 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230
JB
17999 return;
18000
18001 nla_put_failure:
37c73b5f 18002 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230
JB
18003 nlmsg_free(msg);
18004}
e76fede8 18005EXPORT_SYMBOL(cfg80211_report_obss_beacon_khz);
5e760230 18006
cd8f7cb4 18007#ifdef CONFIG_PM
8cd4d456
LC
18008static int cfg80211_net_detect_results(struct sk_buff *msg,
18009 struct cfg80211_wowlan_wakeup *wakeup)
18010{
18011 struct cfg80211_wowlan_nd_info *nd = wakeup->net_detect;
18012 struct nlattr *nl_results, *nl_match, *nl_freqs;
18013 int i, j;
18014
ae0be8de
MK
18015 nl_results = nla_nest_start_noflag(msg,
18016 NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS);
8cd4d456
LC
18017 if (!nl_results)
18018 return -EMSGSIZE;
18019
18020 for (i = 0; i < nd->n_matches; i++) {
18021 struct cfg80211_wowlan_nd_match *match = nd->matches[i];
18022
ae0be8de 18023 nl_match = nla_nest_start_noflag(msg, i);
8cd4d456
LC
18024 if (!nl_match)
18025 break;
18026
18027 /* The SSID attribute is optional in nl80211, but for
18028 * simplicity reasons it's always present in the
18029 * cfg80211 structure. If a driver can't pass the
18030 * SSID, that needs to be changed. A zero length SSID
18031 * is still a valid SSID (wildcard), so it cannot be
18032 * used for this purpose.
18033 */
18034 if (nla_put(msg, NL80211_ATTR_SSID, match->ssid.ssid_len,
18035 match->ssid.ssid)) {
18036 nla_nest_cancel(msg, nl_match);
18037 goto out;
18038 }
18039
18040 if (match->n_channels) {
ae0be8de
MK
18041 nl_freqs = nla_nest_start_noflag(msg,
18042 NL80211_ATTR_SCAN_FREQUENCIES);
8cd4d456
LC
18043 if (!nl_freqs) {
18044 nla_nest_cancel(msg, nl_match);
18045 goto out;
18046 }
18047
18048 for (j = 0; j < match->n_channels; j++) {
5528fae8 18049 if (nla_put_u32(msg, j, match->channels[j])) {
8cd4d456
LC
18050 nla_nest_cancel(msg, nl_freqs);
18051 nla_nest_cancel(msg, nl_match);
18052 goto out;
18053 }
18054 }
18055
18056 nla_nest_end(msg, nl_freqs);
18057 }
18058
18059 nla_nest_end(msg, nl_match);
18060 }
18061
18062out:
18063 nla_nest_end(msg, nl_results);
18064 return 0;
18065}
18066
cd8f7cb4
JB
18067void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
18068 struct cfg80211_wowlan_wakeup *wakeup,
18069 gfp_t gfp)
18070{
f26cbf40 18071 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
cd8f7cb4
JB
18072 struct sk_buff *msg;
18073 void *hdr;
9c90a9f6 18074 int size = 200;
cd8f7cb4
JB
18075
18076 trace_cfg80211_report_wowlan_wakeup(wdev->wiphy, wdev, wakeup);
18077
18078 if (wakeup)
18079 size += wakeup->packet_present_len;
18080
18081 msg = nlmsg_new(size, gfp);
18082 if (!msg)
18083 return;
18084
18085 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_WOWLAN);
18086 if (!hdr)
18087 goto free_msg;
18088
18089 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
2dad624e
ND
18090 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
18091 NL80211_ATTR_PAD))
cd8f7cb4
JB
18092 goto free_msg;
18093
18094 if (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
18095 wdev->netdev->ifindex))
18096 goto free_msg;
18097
18098 if (wakeup) {
18099 struct nlattr *reasons;
18100
ae0be8de
MK
18101 reasons = nla_nest_start_noflag(msg,
18102 NL80211_ATTR_WOWLAN_TRIGGERS);
7fa322c8
JB
18103 if (!reasons)
18104 goto free_msg;
cd8f7cb4
JB
18105
18106 if (wakeup->disconnect &&
18107 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT))
18108 goto free_msg;
18109 if (wakeup->magic_pkt &&
18110 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT))
18111 goto free_msg;
18112 if (wakeup->gtk_rekey_failure &&
18113 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE))
18114 goto free_msg;
18115 if (wakeup->eap_identity_req &&
18116 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST))
18117 goto free_msg;
18118 if (wakeup->four_way_handshake &&
18119 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE))
18120 goto free_msg;
18121 if (wakeup->rfkill_release &&
18122 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))
18123 goto free_msg;
18124
18125 if (wakeup->pattern_idx >= 0 &&
18126 nla_put_u32(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
18127 wakeup->pattern_idx))
18128 goto free_msg;
18129
ae917c9f
JB
18130 if (wakeup->tcp_match &&
18131 nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH))
18132 goto free_msg;
2a0e047e 18133
ae917c9f
JB
18134 if (wakeup->tcp_connlost &&
18135 nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST))
18136 goto free_msg;
2a0e047e 18137
ae917c9f
JB
18138 if (wakeup->tcp_nomoretokens &&
18139 nla_put_flag(msg,
18140 NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS))
18141 goto free_msg;
2a0e047e 18142
cd8f7cb4
JB
18143 if (wakeup->packet) {
18144 u32 pkt_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211;
18145 u32 len_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN;
18146
18147 if (!wakeup->packet_80211) {
18148 pkt_attr =
18149 NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023;
18150 len_attr =
18151 NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN;
18152 }
18153
18154 if (wakeup->packet_len &&
18155 nla_put_u32(msg, len_attr, wakeup->packet_len))
18156 goto free_msg;
18157
18158 if (nla_put(msg, pkt_attr, wakeup->packet_present_len,
18159 wakeup->packet))
18160 goto free_msg;
18161 }
18162
8cd4d456
LC
18163 if (wakeup->net_detect &&
18164 cfg80211_net_detect_results(msg, wakeup))
18165 goto free_msg;
18166
cd8f7cb4
JB
18167 nla_nest_end(msg, reasons);
18168 }
18169
9c90a9f6 18170 genlmsg_end(msg, hdr);
cd8f7cb4 18171
68eb5503 18172 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18173 NL80211_MCGRP_MLME, gfp);
cd8f7cb4
JB
18174 return;
18175
18176 free_msg:
18177 nlmsg_free(msg);
18178}
18179EXPORT_SYMBOL(cfg80211_report_wowlan_wakeup);
18180#endif
18181
3475b094
JM
18182void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer,
18183 enum nl80211_tdls_operation oper,
18184 u16 reason_code, gfp_t gfp)
18185{
18186 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 18187 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
3475b094
JM
18188 struct sk_buff *msg;
18189 void *hdr;
3475b094
JM
18190
18191 trace_cfg80211_tdls_oper_request(wdev->wiphy, dev, peer, oper,
18192 reason_code);
18193
18194 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
18195 if (!msg)
18196 return;
18197
18198 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_TDLS_OPER);
18199 if (!hdr) {
18200 nlmsg_free(msg);
18201 return;
18202 }
18203
18204 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18205 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
18206 nla_put_u8(msg, NL80211_ATTR_TDLS_OPERATION, oper) ||
18207 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer) ||
18208 (reason_code > 0 &&
18209 nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code)))
18210 goto nla_put_failure;
18211
9c90a9f6 18212 genlmsg_end(msg, hdr);
3475b094 18213
68eb5503 18214 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18215 NL80211_MCGRP_MLME, gfp);
3475b094
JM
18216 return;
18217
18218 nla_put_failure:
3475b094
JM
18219 nlmsg_free(msg);
18220}
18221EXPORT_SYMBOL(cfg80211_tdls_oper_request);
18222
026331c4
JM
18223static int nl80211_netlink_notify(struct notifier_block * nb,
18224 unsigned long state,
18225 void *_notify)
18226{
18227 struct netlink_notify *notify = _notify;
18228 struct cfg80211_registered_device *rdev;
18229 struct wireless_dev *wdev;
37c73b5f 18230 struct cfg80211_beacon_registration *reg, *tmp;
026331c4 18231
8f815cdd 18232 if (state != NETLINK_URELEASE || notify->protocol != NETLINK_GENERIC)
026331c4
JM
18233 return NOTIFY_DONE;
18234
18235 rcu_read_lock();
18236
5e760230 18237 list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
ca986ad9 18238 struct cfg80211_sched_scan_request *sched_scan_req;
753aacfd 18239
ca986ad9
AVS
18240 list_for_each_entry_rcu(sched_scan_req,
18241 &rdev->sched_scan_req_list,
18242 list) {
18243 if (sched_scan_req->owner_nlportid == notify->portid) {
18244 sched_scan_req->nl_owner_dead = true;
753aacfd 18245 schedule_work(&rdev->sched_scan_stop_wk);
ca986ad9 18246 }
753aacfd 18247 }
78f22b6a 18248
53873f13 18249 list_for_each_entry_rcu(wdev, &rdev->wiphy.wdev_list, list) {
15e47304 18250 cfg80211_mlme_unregister_socket(wdev, notify->portid);
37c73b5f 18251
ab81007a
JB
18252 if (wdev->owner_nlportid == notify->portid) {
18253 wdev->nl_owner_dead = true;
18254 schedule_work(&rdev->destroy_work);
18255 } else if (wdev->conn_owner_nlportid == notify->portid) {
bd2522b1 18256 schedule_work(&wdev->disconnect_wk);
ab81007a 18257 }
9bb7e0f2
JB
18258
18259 cfg80211_release_pmsr(wdev, notify->portid);
78f22b6a
JB
18260 }
18261
37c73b5f
BG
18262 spin_lock_bh(&rdev->beacon_registrations_lock);
18263 list_for_each_entry_safe(reg, tmp, &rdev->beacon_registrations,
18264 list) {
18265 if (reg->nlportid == notify->portid) {
18266 list_del(&reg->list);
18267 kfree(reg);
18268 break;
18269 }
18270 }
18271 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230 18272 }
026331c4
JM
18273
18274 rcu_read_unlock();
18275
05050753
I
18276 /*
18277 * It is possible that the user space process that is controlling the
18278 * indoor setting disappeared, so notify the regulatory core.
18279 */
18280 regulatory_netlink_notify(notify->portid);
6784c7db 18281 return NOTIFY_OK;
026331c4
JM
18282}
18283
18284static struct notifier_block nl80211_netlink_notifier = {
18285 .notifier_call = nl80211_netlink_notify,
18286};
18287
355199e0
JM
18288void cfg80211_ft_event(struct net_device *netdev,
18289 struct cfg80211_ft_event_params *ft_event)
18290{
18291 struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy;
f26cbf40 18292 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
355199e0
JM
18293 struct sk_buff *msg;
18294 void *hdr;
355199e0
JM
18295
18296 trace_cfg80211_ft_event(wiphy, netdev, ft_event);
18297
18298 if (!ft_event->target_ap)
18299 return;
18300
1039d081
DL
18301 msg = nlmsg_new(100 + ft_event->ies_len + ft_event->ric_ies_len,
18302 GFP_KERNEL);
355199e0
JM
18303 if (!msg)
18304 return;
18305
18306 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FT_EVENT);
ae917c9f
JB
18307 if (!hdr)
18308 goto out;
355199e0 18309
ae917c9f
JB
18310 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18311 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
18312 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ft_event->target_ap))
18313 goto out;
355199e0 18314
ae917c9f
JB
18315 if (ft_event->ies &&
18316 nla_put(msg, NL80211_ATTR_IE, ft_event->ies_len, ft_event->ies))
18317 goto out;
18318 if (ft_event->ric_ies &&
18319 nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len,
18320 ft_event->ric_ies))
18321 goto out;
355199e0 18322
9c90a9f6 18323 genlmsg_end(msg, hdr);
355199e0 18324
68eb5503 18325 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 18326 NL80211_MCGRP_MLME, GFP_KERNEL);
ae917c9f
JB
18327 return;
18328 out:
18329 nlmsg_free(msg);
355199e0
JM
18330}
18331EXPORT_SYMBOL(cfg80211_ft_event);
18332
5de17984
AS
18333void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp)
18334{
18335 struct cfg80211_registered_device *rdev;
18336 struct sk_buff *msg;
18337 void *hdr;
18338 u32 nlportid;
18339
f26cbf40 18340 rdev = wiphy_to_rdev(wdev->wiphy);
5de17984
AS
18341 if (!rdev->crit_proto_nlportid)
18342 return;
18343
18344 nlportid = rdev->crit_proto_nlportid;
18345 rdev->crit_proto_nlportid = 0;
18346
18347 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
18348 if (!msg)
18349 return;
18350
18351 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CRIT_PROTOCOL_STOP);
18352 if (!hdr)
18353 goto nla_put_failure;
18354
18355 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
2dad624e
ND
18356 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
18357 NL80211_ATTR_PAD))
5de17984
AS
18358 goto nla_put_failure;
18359
18360 genlmsg_end(msg, hdr);
18361
18362 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
18363 return;
18364
18365 nla_put_failure:
5de17984 18366 nlmsg_free(msg);
5de17984
AS
18367}
18368EXPORT_SYMBOL(cfg80211_crit_proto_stopped);
18369
348baf0e
JB
18370void nl80211_send_ap_stopped(struct wireless_dev *wdev)
18371{
18372 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 18373 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
348baf0e
JB
18374 struct sk_buff *msg;
18375 void *hdr;
18376
18377 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
18378 if (!msg)
18379 return;
18380
18381 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STOP_AP);
18382 if (!hdr)
18383 goto out;
18384
18385 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18386 nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) ||
2dad624e
ND
18387 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
18388 NL80211_ATTR_PAD))
348baf0e
JB
18389 goto out;
18390
18391 genlmsg_end(msg, hdr);
18392
18393 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0,
18394 NL80211_MCGRP_MLME, GFP_KERNEL);
18395 return;
18396 out:
18397 nlmsg_free(msg);
18398}
18399
40cbfa90
SD
18400int cfg80211_external_auth_request(struct net_device *dev,
18401 struct cfg80211_external_auth_params *params,
18402 gfp_t gfp)
18403{
18404 struct wireless_dev *wdev = dev->ieee80211_ptr;
18405 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
18406 struct sk_buff *msg;
18407 void *hdr;
18408
18409 if (!wdev->conn_owner_nlportid)
18410 return -EINVAL;
18411
18412 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
18413 if (!msg)
18414 return -ENOMEM;
18415
18416 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_EXTERNAL_AUTH);
18417 if (!hdr)
18418 goto nla_put_failure;
18419
18420 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18421 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
18422 nla_put_u32(msg, NL80211_ATTR_AKM_SUITES, params->key_mgmt_suite) ||
18423 nla_put_u32(msg, NL80211_ATTR_EXTERNAL_AUTH_ACTION,
18424 params->action) ||
18425 nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, params->bssid) ||
18426 nla_put(msg, NL80211_ATTR_SSID, params->ssid.ssid_len,
18427 params->ssid.ssid))
18428 goto nla_put_failure;
18429
18430 genlmsg_end(msg, hdr);
18431 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
18432 wdev->conn_owner_nlportid);
18433 return 0;
18434
18435 nla_put_failure:
18436 nlmsg_free(msg);
18437 return -ENOBUFS;
18438}
18439EXPORT_SYMBOL(cfg80211_external_auth_request);
18440
cb74e977
SD
18441void cfg80211_update_owe_info_event(struct net_device *netdev,
18442 struct cfg80211_update_owe_info *owe_info,
18443 gfp_t gfp)
18444{
18445 struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy;
18446 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
18447 struct sk_buff *msg;
18448 void *hdr;
18449
18450 trace_cfg80211_update_owe_info_event(wiphy, netdev, owe_info);
18451
18452 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
18453 if (!msg)
18454 return;
18455
18456 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_UPDATE_OWE_INFO);
18457 if (!hdr)
18458 goto nla_put_failure;
18459
18460 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18461 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
18462 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, owe_info->peer))
18463 goto nla_put_failure;
18464
18465 if (!owe_info->ie_len ||
18466 nla_put(msg, NL80211_ATTR_IE, owe_info->ie_len, owe_info->ie))
18467 goto nla_put_failure;
18468
18469 genlmsg_end(msg, hdr);
18470
18471 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
18472 NL80211_MCGRP_MLME, gfp);
18473 return;
18474
18475nla_put_failure:
18476 genlmsg_cancel(msg, hdr);
18477 nlmsg_free(msg);
18478}
18479EXPORT_SYMBOL(cfg80211_update_owe_info_event);
18480
55682965
JB
18481/* initialisation/exit functions */
18482
56989f6d 18483int __init nl80211_init(void)
55682965 18484{
0d63cbb5 18485 int err;
55682965 18486
489111e5 18487 err = genl_register_family(&nl80211_fam);
55682965
JB
18488 if (err)
18489 return err;
18490
026331c4
JM
18491 err = netlink_register_notifier(&nl80211_netlink_notifier);
18492 if (err)
18493 goto err_out;
18494
55682965
JB
18495 return 0;
18496 err_out:
18497 genl_unregister_family(&nl80211_fam);
18498 return err;
18499}
18500
18501void nl80211_exit(void)
18502{
026331c4 18503 netlink_unregister_notifier(&nl80211_netlink_notifier);
55682965
JB
18504 genl_unregister_family(&nl80211_fam);
18505}