mac80211: remove WDS-related code
[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
7e8d6f12 8 * Copyright (C) 2018-2020 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 *
67__cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
55682965 68{
89a54e48
JB
69 struct cfg80211_registered_device *rdev;
70 struct wireless_dev *result = NULL;
71 bool have_ifidx = attrs[NL80211_ATTR_IFINDEX];
72 bool have_wdev_id = attrs[NL80211_ATTR_WDEV];
73 u64 wdev_id;
74 int wiphy_idx = -1;
75 int ifidx = -1;
55682965 76
5fe231e8 77 ASSERT_RTNL();
55682965 78
89a54e48
JB
79 if (!have_ifidx && !have_wdev_id)
80 return ERR_PTR(-EINVAL);
55682965 81
89a54e48
JB
82 if (have_ifidx)
83 ifidx = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
84 if (have_wdev_id) {
85 wdev_id = nla_get_u64(attrs[NL80211_ATTR_WDEV]);
86 wiphy_idx = wdev_id >> 32;
55682965
JB
87 }
88
89a54e48
JB
89 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
90 struct wireless_dev *wdev;
91
92 if (wiphy_net(&rdev->wiphy) != netns)
93 continue;
94
95 if (have_wdev_id && rdev->wiphy_idx != wiphy_idx)
96 continue;
97
53873f13 98 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
89a54e48
JB
99 if (have_ifidx && wdev->netdev &&
100 wdev->netdev->ifindex == ifidx) {
101 result = wdev;
102 break;
103 }
104 if (have_wdev_id && wdev->identifier == (u32)wdev_id) {
105 result = wdev;
106 break;
107 }
108 }
89a54e48
JB
109
110 if (result)
111 break;
112 }
113
114 if (result)
115 return result;
116 return ERR_PTR(-ENODEV);
55682965
JB
117}
118
a9455408 119static struct cfg80211_registered_device *
878d9ec7 120__cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
a9455408 121{
7fee4778
JB
122 struct cfg80211_registered_device *rdev = NULL, *tmp;
123 struct net_device *netdev;
a9455408 124
5fe231e8 125 ASSERT_RTNL();
a9455408 126
878d9ec7 127 if (!attrs[NL80211_ATTR_WIPHY] &&
89a54e48
JB
128 !attrs[NL80211_ATTR_IFINDEX] &&
129 !attrs[NL80211_ATTR_WDEV])
7fee4778
JB
130 return ERR_PTR(-EINVAL);
131
878d9ec7 132 if (attrs[NL80211_ATTR_WIPHY])
7fee4778 133 rdev = cfg80211_rdev_by_wiphy_idx(
878d9ec7 134 nla_get_u32(attrs[NL80211_ATTR_WIPHY]));
a9455408 135
89a54e48
JB
136 if (attrs[NL80211_ATTR_WDEV]) {
137 u64 wdev_id = nla_get_u64(attrs[NL80211_ATTR_WDEV]);
138 struct wireless_dev *wdev;
139 bool found = false;
140
141 tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32);
142 if (tmp) {
143 /* make sure wdev exists */
53873f13 144 list_for_each_entry(wdev, &tmp->wiphy.wdev_list, list) {
89a54e48
JB
145 if (wdev->identifier != (u32)wdev_id)
146 continue;
147 found = true;
148 break;
149 }
89a54e48
JB
150
151 if (!found)
152 tmp = NULL;
153
154 if (rdev && tmp != rdev)
155 return ERR_PTR(-EINVAL);
156 rdev = tmp;
157 }
158 }
159
878d9ec7
JB
160 if (attrs[NL80211_ATTR_IFINDEX]) {
161 int ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
7a087e74 162
7f2b8562 163 netdev = __dev_get_by_index(netns, ifindex);
7fee4778
JB
164 if (netdev) {
165 if (netdev->ieee80211_ptr)
f26cbf40
ZG
166 tmp = wiphy_to_rdev(
167 netdev->ieee80211_ptr->wiphy);
7fee4778
JB
168 else
169 tmp = NULL;
170
7fee4778
JB
171 /* not wireless device -- return error */
172 if (!tmp)
173 return ERR_PTR(-EINVAL);
174
175 /* mismatch -- return error */
176 if (rdev && tmp != rdev)
177 return ERR_PTR(-EINVAL);
178
179 rdev = tmp;
a9455408 180 }
a9455408 181 }
a9455408 182
4f7eff10
JB
183 if (!rdev)
184 return ERR_PTR(-ENODEV);
a9455408 185
4f7eff10
JB
186 if (netns != wiphy_net(&rdev->wiphy))
187 return ERR_PTR(-ENODEV);
188
189 return rdev;
a9455408
JB
190}
191
192/*
193 * This function returns a pointer to the driver
194 * that the genl_info item that is passed refers to.
a9455408
JB
195 *
196 * The result of this can be a PTR_ERR and hence must
197 * be checked with IS_ERR() for errors.
198 */
199static struct cfg80211_registered_device *
4f7eff10 200cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info)
a9455408 201{
5fe231e8 202 return __cfg80211_rdev_from_attrs(netns, info->attrs);
a9455408
JB
203}
204
f88eb7c0
JB
205static int validate_beacon_head(const struct nlattr *attr,
206 struct netlink_ext_ack *extack)
207{
208 const u8 *data = nla_data(attr);
209 unsigned int len = nla_len(attr);
210 const struct element *elem;
211 const struct ieee80211_mgmt *mgmt = (void *)data;
1d47f119
TP
212 bool s1g_bcn = ieee80211_is_s1g_beacon(mgmt->frame_control);
213 unsigned int fixedlen, hdrlen;
214
215 if (s1g_bcn) {
216 fixedlen = offsetof(struct ieee80211_ext,
217 u.s1g_beacon.variable);
218 hdrlen = offsetof(struct ieee80211_ext, u.s1g_beacon);
219 } else {
220 fixedlen = offsetof(struct ieee80211_mgmt,
221 u.beacon.variable);
222 hdrlen = offsetof(struct ieee80211_mgmt, u.beacon);
223 }
f88eb7c0
JB
224
225 if (len < fixedlen)
226 goto err;
227
1d47f119 228 if (ieee80211_hdrlen(mgmt->frame_control) != hdrlen)
f88eb7c0
JB
229 goto err;
230
231 data += fixedlen;
232 len -= fixedlen;
233
234 for_each_element(elem, data, len) {
235 /* nothing */
236 }
237
238 if (for_each_element_completed(elem, data, len))
239 return 0;
240
241err:
242 NL_SET_ERR_MSG_ATTR(extack, attr, "malformed beacon head");
243 return -EINVAL;
244}
245
3d7af878
JB
246static int validate_ie_attr(const struct nlattr *attr,
247 struct netlink_ext_ack *extack)
248{
9f308616
JB
249 const u8 *data = nla_data(attr);
250 unsigned int len = nla_len(attr);
7388afe0 251 const struct element *elem;
3d7af878 252
9f308616
JB
253 for_each_element(elem, data, len) {
254 /* nothing */
3d7af878
JB
255 }
256
9f308616
JB
257 if (for_each_element_completed(elem, data, len))
258 return 0;
259
3d7af878
JB
260 NL_SET_ERR_MSG_ATTR(extack, attr, "malformed information elements");
261 return -EINVAL;
262}
263
55682965 264/* policy for the attributes */
d15da2a2
JB
265static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR];
266
81e54d08
PKC
267static const struct nla_policy
268nl80211_ftm_responder_policy[NL80211_FTM_RESP_ATTR_MAX + 1] = {
269 [NL80211_FTM_RESP_ATTR_ENABLED] = { .type = NLA_FLAG, },
270 [NL80211_FTM_RESP_ATTR_LCI] = { .type = NLA_BINARY,
271 .len = U8_MAX },
272 [NL80211_FTM_RESP_ATTR_CIVICLOC] = { .type = NLA_BINARY,
273 .len = U8_MAX },
274};
275
9bb7e0f2
JB
276static const struct nla_policy
277nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = {
278 [NL80211_PMSR_FTM_REQ_ATTR_ASAP] = { .type = NLA_FLAG },
279 [NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE] = { .type = NLA_U32 },
280 [NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP] =
281 NLA_POLICY_MAX(NLA_U8, 15),
282 [NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD] = { .type = NLA_U16 },
283 [NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION] =
284 NLA_POLICY_MAX(NLA_U8, 15),
285 [NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST] =
ea18709a 286 NLA_POLICY_MAX(NLA_U8, 31),
9bb7e0f2
JB
287 [NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES] = { .type = NLA_U8 },
288 [NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI] = { .type = NLA_FLAG },
289 [NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC] = { .type = NLA_FLAG },
efb5520d
AS
290 [NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED] = { .type = NLA_FLAG },
291 [NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED] = { .type = NLA_FLAG },
9bb7e0f2
JB
292};
293
294static const struct nla_policy
295nl80211_pmsr_req_data_policy[NL80211_PMSR_TYPE_MAX + 1] = {
296 [NL80211_PMSR_TYPE_FTM] =
23323289 297 NLA_POLICY_NESTED(nl80211_pmsr_ftm_req_attr_policy),
9bb7e0f2
JB
298};
299
300static const struct nla_policy
301nl80211_pmsr_req_attr_policy[NL80211_PMSR_REQ_ATTR_MAX + 1] = {
302 [NL80211_PMSR_REQ_ATTR_DATA] =
23323289 303 NLA_POLICY_NESTED(nl80211_pmsr_req_data_policy),
9bb7e0f2
JB
304 [NL80211_PMSR_REQ_ATTR_GET_AP_TSF] = { .type = NLA_FLAG },
305};
306
307static const struct nla_policy
308nl80211_psmr_peer_attr_policy[NL80211_PMSR_PEER_ATTR_MAX + 1] = {
309 [NL80211_PMSR_PEER_ATTR_ADDR] = NLA_POLICY_ETH_ADDR,
d15da2a2 310 [NL80211_PMSR_PEER_ATTR_CHAN] = NLA_POLICY_NESTED(nl80211_policy),
9bb7e0f2 311 [NL80211_PMSR_PEER_ATTR_REQ] =
23323289 312 NLA_POLICY_NESTED(nl80211_pmsr_req_attr_policy),
9bb7e0f2
JB
313 [NL80211_PMSR_PEER_ATTR_RESP] = { .type = NLA_REJECT },
314};
315
316static const struct nla_policy
317nl80211_pmsr_attr_policy[NL80211_PMSR_ATTR_MAX + 1] = {
318 [NL80211_PMSR_ATTR_MAX_PEERS] = { .type = NLA_REJECT },
319 [NL80211_PMSR_ATTR_REPORT_AP_TSF] = { .type = NLA_REJECT },
320 [NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR] = { .type = NLA_REJECT },
321 [NL80211_PMSR_ATTR_TYPE_CAPA] = { .type = NLA_REJECT },
322 [NL80211_PMSR_ATTR_PEERS] =
23323289 323 NLA_POLICY_NESTED_ARRAY(nl80211_psmr_peer_attr_policy),
9bb7e0f2
JB
324};
325
796e90f4
JC
326static const struct nla_policy
327he_obss_pd_policy[NL80211_HE_OBSS_PD_ATTR_MAX + 1] = {
328 [NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET] =
329 NLA_POLICY_RANGE(NLA_U8, 1, 20),
330 [NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET] =
331 NLA_POLICY_RANGE(NLA_U8, 1, 20),
f5bec330
RM
332 [NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET] =
333 NLA_POLICY_RANGE(NLA_U8, 1, 20),
334 [NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP] =
335 NLA_POLICY_EXACT_LEN(8),
336 [NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP] =
337 NLA_POLICY_EXACT_LEN(8),
338 [NL80211_HE_OBSS_PD_ATTR_SR_CTRL] = { .type = NLA_U8 },
796e90f4
JC
339};
340
5c5e52d1
JC
341static const struct nla_policy
342he_bss_color_policy[NL80211_HE_BSS_COLOR_ATTR_MAX + 1] = {
343 [NL80211_HE_BSS_COLOR_ATTR_COLOR] = NLA_POLICY_RANGE(NLA_U8, 1, 63),
344 [NL80211_HE_BSS_COLOR_ATTR_DISABLED] = { .type = NLA_FLAG },
345 [NL80211_HE_BSS_COLOR_ATTR_PARTIAL] = { .type = NLA_FLAG },
346};
347
9a5f6488
TC
348static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = {
349 [NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY,
350 .len = NL80211_MAX_SUPP_RATES },
351 [NL80211_TXRATE_HT] = { .type = NLA_BINARY,
352 .len = NL80211_MAX_SUPP_HT_RATES },
353 [NL80211_TXRATE_VHT] = NLA_POLICY_EXACT_LEN_WARN(sizeof(struct nl80211_txrate_vht)),
354 [NL80211_TXRATE_GI] = { .type = NLA_U8 },
eb89a6a6
MH
355 [NL80211_TXRATE_HE] = NLA_POLICY_EXACT_LEN(sizeof(struct nl80211_txrate_he)),
356 [NL80211_TXRATE_HE_GI] = NLA_POLICY_RANGE(NLA_U8,
357 NL80211_RATE_INFO_HE_GI_0_8,
358 NL80211_RATE_INFO_HE_GI_3_2),
359 [NL80211_TXRATE_HE_LTF] = NLA_POLICY_RANGE(NLA_U8,
360 NL80211_RATE_INFO_HE_1XLTF,
361 NL80211_RATE_INFO_HE_4XLTF),
9a5f6488
TC
362};
363
77f576de
T
364static const struct nla_policy
365nl80211_tid_config_attr_policy[NL80211_TID_CONFIG_ATTR_MAX + 1] = {
3710a8a6
JB
366 [NL80211_TID_CONFIG_ATTR_VIF_SUPP] = { .type = NLA_U64 },
367 [NL80211_TID_CONFIG_ATTR_PEER_SUPP] = { .type = NLA_U64 },
77f576de 368 [NL80211_TID_CONFIG_ATTR_OVERRIDE] = { .type = NLA_FLAG },
3710a8a6 369 [NL80211_TID_CONFIG_ATTR_TIDS] = NLA_POLICY_RANGE(NLA_U16, 1, 0xff),
77f576de
T
370 [NL80211_TID_CONFIG_ATTR_NOACK] =
371 NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
6a21d16c
T
372 [NL80211_TID_CONFIG_ATTR_RETRY_SHORT] = NLA_POLICY_MIN(NLA_U8, 1),
373 [NL80211_TID_CONFIG_ATTR_RETRY_LONG] = NLA_POLICY_MIN(NLA_U8, 1),
ade274b2
T
374 [NL80211_TID_CONFIG_ATTR_AMPDU_CTRL] =
375 NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
04f7d142
T
376 [NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL] =
377 NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
33462e68
SM
378 [NL80211_TID_CONFIG_ATTR_AMSDU_CTRL] =
379 NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
9a5f6488
TC
380 [NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE] =
381 NLA_POLICY_MAX(NLA_U8, NL80211_TX_RATE_FIXED),
382 [NL80211_TID_CONFIG_ATTR_TX_RATE] =
383 NLA_POLICY_NESTED(nl80211_txattr_policy),
77f576de
T
384};
385
291c49de
AD
386static const struct nla_policy
387nl80211_fils_discovery_policy[NL80211_FILS_DISCOVERY_ATTR_MAX + 1] = {
388 [NL80211_FILS_DISCOVERY_ATTR_INT_MIN] = NLA_POLICY_MAX(NLA_U32, 10000),
389 [NL80211_FILS_DISCOVERY_ATTR_INT_MAX] = NLA_POLICY_MAX(NLA_U32, 10000),
390 NLA_POLICY_RANGE(NLA_BINARY,
391 NL80211_FILS_DISCOVERY_TMPL_MIN_LEN,
392 IEEE80211_MAX_DATA_LEN),
393};
394
7443dcd1
AD
395static const struct nla_policy
396nl80211_unsol_bcast_probe_resp_policy[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX + 1] = {
397 [NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT] = NLA_POLICY_MAX(NLA_U32, 20),
398 [NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL] = { .type = NLA_BINARY,
399 .len = IEEE80211_MAX_DATA_LEN }
400};
401
d15da2a2 402static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
6d4dd4ef 403 [0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD },
55682965
JB
404 [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
405 [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
079e24ed 406 .len = 20-1 },
31888487 407 [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED },
3d9d1d66 408
72bdcf34 409 [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
094d05dc 410 [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 },
2a38075c
AAL
411 [NL80211_ATTR_WIPHY_EDMG_CHANNELS] = NLA_POLICY_RANGE(NLA_U8,
412 NL80211_EDMG_CHANNELS_MIN,
413 NL80211_EDMG_CHANNELS_MAX),
414 [NL80211_ATTR_WIPHY_EDMG_BW_CONFIG] = NLA_POLICY_RANGE(NLA_U8,
415 NL80211_EDMG_BW_CONFIG_MIN,
416 NL80211_EDMG_BW_CONFIG_MAX),
417
3d9d1d66
JB
418 [NL80211_ATTR_CHANNEL_WIDTH] = { .type = NLA_U32 },
419 [NL80211_ATTR_CENTER_FREQ1] = { .type = NLA_U32 },
942ba88b 420 [NL80211_ATTR_CENTER_FREQ1_OFFSET] = NLA_POLICY_RANGE(NLA_U32, 0, 999),
3d9d1d66
JB
421 [NL80211_ATTR_CENTER_FREQ2] = { .type = NLA_U32 },
422
ab0d76f6
JB
423 [NL80211_ATTR_WIPHY_RETRY_SHORT] = NLA_POLICY_MIN(NLA_U8, 1),
424 [NL80211_ATTR_WIPHY_RETRY_LONG] = NLA_POLICY_MIN(NLA_U8, 1),
b9a5f8ca
JM
425 [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 },
426 [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 },
81077e82 427 [NL80211_ATTR_WIPHY_COVERAGE_CLASS] = { .type = NLA_U8 },
3057dbfd 428 [NL80211_ATTR_WIPHY_DYN_ACK] = { .type = NLA_FLAG },
55682965 429
ab0d76f6 430 [NL80211_ATTR_IFTYPE] = NLA_POLICY_MAX(NLA_U32, NL80211_IFTYPE_MAX),
55682965
JB
431 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
432 [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
41ade00f 433
c7721c05
JB
434 [NL80211_ATTR_MAC] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
435 [NL80211_ATTR_PREV_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
41ade00f 436
b9454e83 437 [NL80211_ATTR_KEY] = { .type = NLA_NESTED, },
41ade00f
JB
438 [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
439 .len = WLAN_MAX_KEY_LEN },
56be393f 440 [NL80211_ATTR_KEY_IDX] = NLA_POLICY_MAX(NLA_U8, 7),
41ade00f
JB
441 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
442 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
81962267 443 [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
ab0d76f6
JB
444 [NL80211_ATTR_KEY_TYPE] =
445 NLA_POLICY_MAX(NLA_U32, NUM_NL80211_KEYTYPES),
ed1b6cc7
JB
446
447 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
448 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
f88eb7c0
JB
449 [NL80211_ATTR_BEACON_HEAD] =
450 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_beacon_head,
451 IEEE80211_MAX_DATA_LEN),
3d7af878
JB
452 [NL80211_ATTR_BEACON_TAIL] =
453 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
454 IEEE80211_MAX_DATA_LEN),
ab0d76f6
JB
455 [NL80211_ATTR_STA_AID] =
456 NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
5727ef1b
JB
457 [NL80211_ATTR_STA_FLAGS] = { .type = NLA_NESTED },
458 [NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 },
459 [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
460 .len = NL80211_MAX_SUPP_RATES },
ab0d76f6
JB
461 [NL80211_ATTR_STA_PLINK_ACTION] =
462 NLA_POLICY_MAX(NLA_U8, NUM_NL80211_PLINK_ACTIONS - 1),
e96d1cd2
ARN
463 [NL80211_ATTR_STA_TX_POWER_SETTING] =
464 NLA_POLICY_RANGE(NLA_U8,
465 NL80211_TX_POWER_AUTOMATIC,
466 NL80211_TX_POWER_FIXED),
467 [NL80211_ATTR_STA_TX_POWER] = { .type = NLA_S16 },
5727ef1b 468 [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
0a9542ee 469 [NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ },
2ec600d6 470 [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
a4f606ea 471 .len = IEEE80211_MAX_MESH_ID_LEN },
1fab1b89 472 [NL80211_ATTR_MPATH_NEXT_HOP] = NLA_POLICY_ETH_ADDR_COMPAT,
9f1ba906 473
b2e1b302
LR
474 [NL80211_ATTR_REG_ALPHA2] = { .type = NLA_STRING, .len = 2 },
475 [NL80211_ATTR_REG_RULES] = { .type = NLA_NESTED },
476
9f1ba906
JM
477 [NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 },
478 [NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 },
479 [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 },
90c97a04
JM
480 [NL80211_ATTR_BSS_BASIC_RATES] = { .type = NLA_BINARY,
481 .len = NL80211_MAX_SUPP_RATES },
50b12f59 482 [NL80211_ATTR_BSS_HT_OPMODE] = { .type = NLA_U16 },
36aedc90 483
24bdd9f4 484 [NL80211_ATTR_MESH_CONFIG] = { .type = NLA_NESTED },
15d5dda6 485 [NL80211_ATTR_SUPPORT_MESH_AUTH] = { .type = NLA_FLAG },
93da9cc1 486
c7721c05 487 [NL80211_ATTR_HT_CAPABILITY] = NLA_POLICY_EXACT_LEN_WARN(NL80211_HT_CAPABILITY_LEN),
9aed3cc1
JM
488
489 [NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 },
3d7af878
JB
490 [NL80211_ATTR_IE] = NLA_POLICY_VALIDATE_FN(NLA_BINARY,
491 validate_ie_attr,
492 IEEE80211_MAX_DATA_LEN),
2a519311
JB
493 [NL80211_ATTR_SCAN_FREQUENCIES] = { .type = NLA_NESTED },
494 [NL80211_ATTR_SCAN_SSIDS] = { .type = NLA_NESTED },
636a5d36
JM
495
496 [NL80211_ATTR_SSID] = { .type = NLA_BINARY,
497 .len = IEEE80211_MAX_SSID_LEN },
498 [NL80211_ATTR_AUTH_TYPE] = { .type = NLA_U32 },
499 [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 },
04a773ad 500 [NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG },
1965c853 501 [NL80211_ATTR_TIMED_OUT] = { .type = NLA_FLAG },
ab0d76f6
JB
502 [NL80211_ATTR_USE_MFP] = NLA_POLICY_RANGE(NLA_U32,
503 NL80211_MFP_NO,
504 NL80211_MFP_OPTIONAL),
eccb8e8f
JB
505 [NL80211_ATTR_STA_FLAGS2] = {
506 .len = sizeof(struct nl80211_sta_flag_update),
507 },
3f77316c 508 [NL80211_ATTR_CONTROL_PORT] = { .type = NLA_FLAG },
c0692b8f
JB
509 [NL80211_ATTR_CONTROL_PORT_ETHERTYPE] = { .type = NLA_U16 },
510 [NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT] = { .type = NLA_FLAG },
64bf3d4b 511 [NL80211_ATTR_CONTROL_PORT_OVER_NL80211] = { .type = NLA_FLAG },
b23aa676 512 [NL80211_ATTR_PRIVACY] = { .type = NLA_FLAG },
ea750801 513 [NL80211_ATTR_STATUS_CODE] = { .type = NLA_U16 },
b23aa676
SO
514 [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 },
515 [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
463d0183 516 [NL80211_ATTR_PID] = { .type = NLA_U32 },
8b787643 517 [NL80211_ATTR_4ADDR] = { .type = NLA_U8 },
c7721c05 518 [NL80211_ATTR_PMKID] = NLA_POLICY_EXACT_LEN_WARN(WLAN_PMKID_LEN),
9588bbd5
JM
519 [NL80211_ATTR_DURATION] = { .type = NLA_U32 },
520 [NL80211_ATTR_COOKIE] = { .type = NLA_U64 },
13ae75b1 521 [NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED },
026331c4
JM
522 [NL80211_ATTR_FRAME] = { .type = NLA_BINARY,
523 .len = IEEE80211_MAX_DATA_LEN },
524 [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, },
ab0d76f6
JB
525 [NL80211_ATTR_PS_STATE] = NLA_POLICY_RANGE(NLA_U32,
526 NL80211_PS_DISABLED,
527 NL80211_PS_ENABLED),
d6dc1a38 528 [NL80211_ATTR_CQM] = { .type = NLA_NESTED, },
d5cdfacb 529 [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG },
fd8aaaf3 530 [NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 },
98d2ff8b
JO
531 [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 },
532 [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 },
2e161f78 533 [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 },
afe0cbf8
BR
534 [NL80211_ATTR_WIPHY_ANTENNA_TX] = { .type = NLA_U32 },
535 [NL80211_ATTR_WIPHY_ANTENNA_RX] = { .type = NLA_U32 },
885a46d0 536 [NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 },
f7ca38df 537 [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG },
dbd2fd65 538 [NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
ff1b6e69 539 [NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED },
ab0d76f6
JB
540 [NL80211_ATTR_STA_PLINK_STATE] =
541 NLA_POLICY_MAX(NLA_U8, NUM_NL80211_PLINK_STATES - 1),
056e9375
JK
542 [NL80211_ATTR_MEASUREMENT_DURATION] = { .type = NLA_U16 },
543 [NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY] = { .type = NLA_FLAG },
ab0d76f6
JB
544 [NL80211_ATTR_MESH_PEER_AID] =
545 NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
bbe6ad6d 546 [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 },
e5497d76 547 [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED },
34850ab2 548 [NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED },
ab0d76f6
JB
549 [NL80211_ATTR_HIDDEN_SSID] =
550 NLA_POLICY_RANGE(NLA_U32,
551 NL80211_HIDDEN_SSID_NOT_IN_USE,
552 NL80211_HIDDEN_SSID_ZERO_CONTENTS),
3d7af878
JB
553 [NL80211_ATTR_IE_PROBE_RESP] =
554 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
555 IEEE80211_MAX_DATA_LEN),
556 [NL80211_ATTR_IE_ASSOC_RESP] =
557 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
558 IEEE80211_MAX_DATA_LEN),
f4b34b55 559 [NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG },
a1f1c21c 560 [NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED },
e9f935e3 561 [NL80211_ATTR_TX_NO_CCK_RATE] = { .type = NLA_FLAG },
109086ce
AN
562 [NL80211_ATTR_TDLS_ACTION] = { .type = NLA_U8 },
563 [NL80211_ATTR_TDLS_DIALOG_TOKEN] = { .type = NLA_U8 },
564 [NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 },
565 [NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG },
566 [NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG },
31fa97c5 567 [NL80211_ATTR_TDLS_INITIATOR] = { .type = NLA_FLAG },
e247bd90 568 [NL80211_ATTR_DONT_WAIT_FOR_ACK] = { .type = NLA_FLAG },
00f740e1
AN
569 [NL80211_ATTR_PROBE_RESP] = { .type = NLA_BINARY,
570 .len = IEEE80211_MAX_DATA_LEN },
8b60b078 571 [NL80211_ATTR_DFS_REGION] = { .type = NLA_U8 },
7e7c8926
BG
572 [NL80211_ATTR_DISABLE_HT] = { .type = NLA_FLAG },
573 [NL80211_ATTR_HT_CAPABILITY_MASK] = {
574 .len = NL80211_HT_CAPABILITY_LEN
575 },
1d9d9213 576 [NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 },
1b658f11 577 [NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 },
4486ea98 578 [NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
89a54e48 579 [NL80211_ATTR_WDEV] = { .type = NLA_U64 },
57b5ce07 580 [NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },
cb9abd48
JB
581
582 /* need to include at least Auth Transaction and Status Code */
583 [NL80211_ATTR_AUTH_DATA] = NLA_POLICY_MIN_LEN(4),
584
c7721c05 585 [NL80211_ATTR_VHT_CAPABILITY] = NLA_POLICY_EXACT_LEN_WARN(NL80211_VHT_CAPABILITY_LEN),
ed473771 586 [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
ab0d76f6
JB
587 [NL80211_ATTR_P2P_CTWINDOW] = NLA_POLICY_MAX(NLA_U8, 127),
588 [NL80211_ATTR_P2P_OPPPS] = NLA_POLICY_MAX(NLA_U8, 1),
589 [NL80211_ATTR_LOCAL_MESH_POWER_MODE] =
590 NLA_POLICY_RANGE(NLA_U32,
591 NL80211_MESH_POWER_UNKNOWN + 1,
592 NL80211_MESH_POWER_MAX),
77765eaf
VT
593 [NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 },
594 [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED },
9d62a986
JM
595 [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 },
596 [NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, },
3713b4e3 597 [NL80211_ATTR_SPLIT_WIPHY_DUMP] = { .type = NLA_FLAG, },
ee2aca34
JB
598 [NL80211_ATTR_DISABLE_VHT] = { .type = NLA_FLAG },
599 [NL80211_ATTR_VHT_CAPABILITY_MASK] = {
600 .len = NL80211_VHT_CAPABILITY_LEN,
601 },
355199e0
JM
602 [NL80211_ATTR_MDID] = { .type = NLA_U16 },
603 [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,
604 .len = IEEE80211_MAX_DATA_LEN },
0e1a1d85 605 [NL80211_ATTR_CRIT_PROT_ID] = { .type = NLA_U16 },
cb9abd48
JB
606 [NL80211_ATTR_MAX_CRIT_PROT_DURATION] =
607 NLA_POLICY_MAX(NLA_U16, NL80211_CRIT_PROTO_MAX_DURATION),
ab0d76f6
JB
608 [NL80211_ATTR_PEER_AID] =
609 NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
16ef1fe2
SW
610 [NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 },
611 [NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG },
612 [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED },
00c207ed
JC
613 [NL80211_ATTR_CNTDWN_OFFS_BEACON] = { .type = NLA_BINARY },
614 [NL80211_ATTR_CNTDWN_OFFS_PRESP] = { .type = NLA_BINARY },
cb9abd48 615 [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = NLA_POLICY_MIN_LEN(2),
c8b82802
JB
616 /*
617 * The value of the Length field of the Supported Operating
618 * Classes element is between 2 and 253.
619 */
620 [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] =
621 NLA_POLICY_RANGE(NLA_BINARY, 2, 253),
5336fa88 622 [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG },
60f4a7b1 623 [NL80211_ATTR_OPMODE_NOTIF] = { .type = NLA_U8 },
ad7e718c
JB
624 [NL80211_ATTR_VENDOR_ID] = { .type = NLA_U32 },
625 [NL80211_ATTR_VENDOR_SUBCMD] = { .type = NLA_U32 },
626 [NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY },
c8b82802
JB
627 [NL80211_ATTR_QOS_MAP] = NLA_POLICY_RANGE(NLA_BINARY,
628 IEEE80211_QOS_MAP_LEN_MIN,
629 IEEE80211_QOS_MAP_LEN_MAX),
c7721c05 630 [NL80211_ATTR_MAC_HINT] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
1df4a510 631 [NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 },
df942e7b 632 [NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 },
18e5ca65 633 [NL80211_ATTR_SOCKET_OWNER] = { .type = NLA_FLAG },
34d22ce2 634 [NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY },
bab5ab7d 635 [NL80211_ATTR_USE_RRM] = { .type = NLA_FLAG },
ab0d76f6
JB
636 [NL80211_ATTR_TSID] = NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_TIDS - 1),
637 [NL80211_ATTR_USER_PRIO] =
638 NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_UPS - 1),
960d01ac 639 [NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 },
18998c38 640 [NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 },
5cde05c6 641 [NL80211_ATTR_OPER_CLASS] = { .type = NLA_U8 },
c7721c05 642 [NL80211_ATTR_MAC_MASK] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
1bdd716c 643 [NL80211_ATTR_WIPHY_SELF_MANAGED_REG] = { .type = NLA_FLAG },
4b681c82 644 [NL80211_ATTR_NETNS_FD] = { .type = NLA_U32 },
9c748934 645 [NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 },
05050753 646 [NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG },
34d50519 647 [NL80211_ATTR_PBSS] = { .type = NLA_FLAG },
38de03d2 648 [NL80211_ATTR_BSS_SELECT] = { .type = NLA_NESTED },
ab0d76f6
JB
649 [NL80211_ATTR_STA_SUPPORT_P2P_PS] =
650 NLA_POLICY_MAX(NLA_U8, NUM_NL80211_P2P_PS_STATUS - 1),
c6e6a0c8
AE
651 [NL80211_ATTR_MU_MIMO_GROUP_DATA] = {
652 .len = VHT_MUMIMO_GROUPS_DATA_LEN
653 },
c7721c05 654 [NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
ab0d76f6 655 [NL80211_ATTR_NAN_MASTER_PREF] = NLA_POLICY_MIN(NLA_U8, 1),
8585989d 656 [NL80211_ATTR_BANDS] = { .type = NLA_U32 },
a442b761 657 [NL80211_ATTR_NAN_FUNC] = { .type = NLA_NESTED },
348bd456
JM
658 [NL80211_ATTR_FILS_KEK] = { .type = NLA_BINARY,
659 .len = FILS_MAX_KEK_LEN },
c7721c05 660 [NL80211_ATTR_FILS_NONCES] = NLA_POLICY_EXACT_LEN_WARN(2 * FILS_NONCE_LEN),
ce0ce13a 661 [NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED] = { .type = NLA_FLAG, },
c7721c05 662 [NL80211_ATTR_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
bf95ecdb 663 [NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] = { .type = NLA_S8 },
664 [NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST] = {
665 .len = sizeof(struct nl80211_bss_select_rssi_adjust)
666 },
3093ebbe 667 [NL80211_ATTR_TIMEOUT_REASON] = { .type = NLA_U32 },
a3caf744
VK
668 [NL80211_ATTR_FILS_ERP_USERNAME] = { .type = NLA_BINARY,
669 .len = FILS_ERP_MAX_USERNAME_LEN },
670 [NL80211_ATTR_FILS_ERP_REALM] = { .type = NLA_BINARY,
671 .len = FILS_ERP_MAX_REALM_LEN },
672 [NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] = { .type = NLA_U16 },
673 [NL80211_ATTR_FILS_ERP_RRK] = { .type = NLA_BINARY,
674 .len = FILS_ERP_MAX_RRK_LEN },
c7721c05 675 [NL80211_ATTR_FILS_CACHE_ID] = NLA_POLICY_EXACT_LEN_WARN(2),
a3caf744 676 [NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN },
cb9abd48 677 [NL80211_ATTR_PMKR0_NAME] = NLA_POLICY_EXACT_LEN(WLAN_PMK_NAME_LEN),
ca986ad9 678 [NL80211_ATTR_SCHED_SCAN_MULTI] = { .type = NLA_FLAG },
40cbfa90 679 [NL80211_ATTR_EXTERNAL_AUTH_SUPPORT] = { .type = NLA_FLAG },
52539ca8
THJ
680
681 [NL80211_ATTR_TXQ_LIMIT] = { .type = NLA_U32 },
682 [NL80211_ATTR_TXQ_MEMORY_LIMIT] = { .type = NLA_U32 },
683 [NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 },
c8b82802
JB
684 [NL80211_ATTR_HE_CAPABILITY] =
685 NLA_POLICY_RANGE(NLA_BINARY,
686 NL80211_HE_MIN_CAPABILITY_LEN,
687 NL80211_HE_MAX_CAPABILITY_LEN),
0e012b4e
JB
688 [NL80211_ATTR_FTM_RESPONDER] =
689 NLA_POLICY_NESTED(nl80211_ftm_responder_policy),
9bb7e0f2
JB
690 [NL80211_ATTR_TIMEOUT] = NLA_POLICY_MIN(NLA_U32, 1),
691 [NL80211_ATTR_PEER_MEASUREMENTS] =
23323289 692 NLA_POLICY_NESTED(nl80211_pmsr_attr_policy),
36647055 693 [NL80211_ATTR_AIRTIME_WEIGHT] = NLA_POLICY_MIN(NLA_U16, 1),
26f7044e
CHH
694 [NL80211_ATTR_SAE_PASSWORD] = { .type = NLA_BINARY,
695 .len = SAE_PASSWORD_MAX_LEN },
a0de1ca3 696 [NL80211_ATTR_TWT_RESPONDER] = { .type = NLA_FLAG },
796e90f4 697 [NL80211_ATTR_HE_OBSS_PD] = NLA_POLICY_NESTED(he_obss_pd_policy),
14f34e36 698 [NL80211_ATTR_VLAN_ID] = NLA_POLICY_RANGE(NLA_U16, 1, VLAN_N_VID - 2),
5c5e52d1 699 [NL80211_ATTR_HE_BSS_COLOR] = NLA_POLICY_NESTED(he_bss_color_policy),
77f576de
T
700 [NL80211_ATTR_TID_CONFIG] =
701 NLA_POLICY_NESTED_ARRAY(nl80211_tid_config_attr_policy),
5631d96a 702 [NL80211_ATTR_CONTROL_PORT_NO_PREAUTH] = { .type = NLA_FLAG },
7fc82af8
VJ
703 [NL80211_ATTR_PMK_LIFETIME] = NLA_POLICY_MIN(NLA_U32, 1),
704 [NL80211_ATTR_PMK_REAUTH_THRESHOLD] = NLA_POLICY_RANGE(NLA_U8, 1, 100),
9dba48a6 705 [NL80211_ATTR_RECEIVE_MULTICAST] = { .type = NLA_FLAG },
942ba88b 706 [NL80211_ATTR_WIPHY_FREQ_OFFSET] = NLA_POLICY_RANGE(NLA_U32, 0, 999),
2032f3b2 707 [NL80211_ATTR_SCAN_FREQ_KHZ] = { .type = NLA_NESTED },
8140860c
JB
708 [NL80211_ATTR_HE_6GHZ_CAPABILITY] =
709 NLA_POLICY_EXACT_LEN(sizeof(struct ieee80211_he_6ghz_capa)),
291c49de
AD
710 [NL80211_ATTR_FILS_DISCOVERY] =
711 NLA_POLICY_NESTED(nl80211_fils_discovery_policy),
7443dcd1
AD
712 [NL80211_ATTR_UNSOL_BCAST_PROBE_RESP] =
713 NLA_POLICY_NESTED(nl80211_unsol_bcast_probe_resp_policy),
d2b7588a
TP
714 [NL80211_ATTR_S1G_CAPABILITY] =
715 NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN),
716 [NL80211_ATTR_S1G_CAPABILITY_MASK] =
717 NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN),
9f0ffa41
RD
718 [NL80211_ATTR_SAE_PWE] =
719 NLA_POLICY_RANGE(NLA_U8, NL80211_SAE_PWE_HUNT_AND_PECK,
720 NL80211_SAE_PWE_BOTH),
55682965
JB
721};
722
e31b8213 723/* policy for the key attributes */
b54452b0 724static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = {
fffd0934 725 [NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN },
b9454e83
JB
726 [NL80211_KEY_IDX] = { .type = NLA_U8 },
727 [NL80211_KEY_CIPHER] = { .type = NLA_U32 },
81962267 728 [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
b9454e83
JB
729 [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG },
730 [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
ab0d76f6 731 [NL80211_KEY_TYPE] = NLA_POLICY_MAX(NLA_U32, NUM_NL80211_KEYTYPES - 1),
dbd2fd65 732 [NL80211_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
6cdd3979 733 [NL80211_KEY_MODE] = NLA_POLICY_RANGE(NLA_U8, 0, NL80211_KEY_SET_TX),
dbd2fd65
JB
734};
735
736/* policy for the key default flags */
737static const struct nla_policy
738nl80211_key_default_policy[NUM_NL80211_KEY_DEFAULT_TYPES] = {
739 [NL80211_KEY_DEFAULT_TYPE_UNICAST] = { .type = NLA_FLAG },
740 [NL80211_KEY_DEFAULT_TYPE_MULTICAST] = { .type = NLA_FLAG },
b9454e83
JB
741};
742
f83ace3b 743#ifdef CONFIG_PM
ff1b6e69
JB
744/* policy for WoWLAN attributes */
745static const struct nla_policy
746nl80211_wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = {
747 [NL80211_WOWLAN_TRIG_ANY] = { .type = NLA_FLAG },
748 [NL80211_WOWLAN_TRIG_DISCONNECT] = { .type = NLA_FLAG },
749 [NL80211_WOWLAN_TRIG_MAGIC_PKT] = { .type = NLA_FLAG },
750 [NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .type = NLA_NESTED },
77dbbb13
JB
751 [NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE] = { .type = NLA_FLAG },
752 [NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST] = { .type = NLA_FLAG },
753 [NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE] = { .type = NLA_FLAG },
754 [NL80211_WOWLAN_TRIG_RFKILL_RELEASE] = { .type = NLA_FLAG },
2a0e047e 755 [NL80211_WOWLAN_TRIG_TCP_CONNECTION] = { .type = NLA_NESTED },
8cd4d456 756 [NL80211_WOWLAN_TRIG_NET_DETECT] = { .type = NLA_NESTED },
2a0e047e
JB
757};
758
759static const struct nla_policy
760nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = {
761 [NL80211_WOWLAN_TCP_SRC_IPV4] = { .type = NLA_U32 },
762 [NL80211_WOWLAN_TCP_DST_IPV4] = { .type = NLA_U32 },
c7721c05 763 [NL80211_WOWLAN_TCP_DST_MAC] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
2a0e047e
JB
764 [NL80211_WOWLAN_TCP_SRC_PORT] = { .type = NLA_U16 },
765 [NL80211_WOWLAN_TCP_DST_PORT] = { .type = NLA_U16 },
bc043585 766 [NL80211_WOWLAN_TCP_DATA_PAYLOAD] = NLA_POLICY_MIN_LEN(1),
2a0e047e
JB
767 [NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ] = {
768 .len = sizeof(struct nl80211_wowlan_tcp_data_seq)
769 },
770 [NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN] = {
771 .len = sizeof(struct nl80211_wowlan_tcp_data_token)
772 },
773 [NL80211_WOWLAN_TCP_DATA_INTERVAL] = { .type = NLA_U32 },
bc043585
JB
774 [NL80211_WOWLAN_TCP_WAKE_PAYLOAD] = NLA_POLICY_MIN_LEN(1),
775 [NL80211_WOWLAN_TCP_WAKE_MASK] = NLA_POLICY_MIN_LEN(1),
ff1b6e69 776};
f83ace3b 777#endif /* CONFIG_PM */
ff1b6e69 778
be29b99a
AK
779/* policy for coalesce rule attributes */
780static const struct nla_policy
781nl80211_coalesce_policy[NUM_NL80211_ATTR_COALESCE_RULE] = {
782 [NL80211_ATTR_COALESCE_RULE_DELAY] = { .type = NLA_U32 },
ab0d76f6
JB
783 [NL80211_ATTR_COALESCE_RULE_CONDITION] =
784 NLA_POLICY_RANGE(NLA_U32,
785 NL80211_COALESCE_CONDITION_MATCH,
786 NL80211_COALESCE_CONDITION_NO_MATCH),
be29b99a
AK
787 [NL80211_ATTR_COALESCE_RULE_PKT_PATTERN] = { .type = NLA_NESTED },
788};
789
e5497d76
JB
790/* policy for GTK rekey offload attributes */
791static const struct nla_policy
792nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = {
093a48d2
NE
793 [NL80211_REKEY_DATA_KEK] = {
794 .type = NLA_BINARY,
795 .len = NL80211_KEK_EXT_LEN
796 },
797 [NL80211_REKEY_DATA_KCK] = {
798 .type = NLA_BINARY,
799 .len = NL80211_KCK_EXT_LEN
800 },
cb9abd48 801 [NL80211_REKEY_DATA_REPLAY_CTR] = NLA_POLICY_EXACT_LEN(NL80211_REPLAY_CTR_LEN),
093a48d2 802 [NL80211_REKEY_DATA_AKM] = { .type = NLA_U32 },
e5497d76
JB
803};
804
1e1b11b6 805static const struct nla_policy
806nl80211_match_band_rssi_policy[NUM_NL80211_BANDS] = {
807 [NL80211_BAND_2GHZ] = { .type = NLA_S32 },
808 [NL80211_BAND_5GHZ] = { .type = NLA_S32 },
e548a1c3 809 [NL80211_BAND_6GHZ] = { .type = NLA_S32 },
1e1b11b6 810 [NL80211_BAND_60GHZ] = { .type = NLA_S32 },
811};
812
a1f1c21c
LC
813static const struct nla_policy
814nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = {
4a4ab0d7 815 [NL80211_SCHED_SCAN_MATCH_ATTR_SSID] = { .type = NLA_BINARY,
a1f1c21c 816 .len = IEEE80211_MAX_SSID_LEN },
c7721c05 817 [NL80211_SCHED_SCAN_MATCH_ATTR_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
88e920b4 818 [NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] = { .type = NLA_U32 },
1e1b11b6 819 [NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI] =
820 NLA_POLICY_NESTED(nl80211_match_band_rssi_policy),
a1f1c21c
LC
821};
822
3b06d277
AS
823static const struct nla_policy
824nl80211_plan_policy[NL80211_SCHED_SCAN_PLAN_MAX + 1] = {
825 [NL80211_SCHED_SCAN_PLAN_INTERVAL] = { .type = NLA_U32 },
826 [NL80211_SCHED_SCAN_PLAN_ITERATIONS] = { .type = NLA_U32 },
827};
828
38de03d2
AS
829static const struct nla_policy
830nl80211_bss_select_policy[NL80211_BSS_SELECT_ATTR_MAX + 1] = {
831 [NL80211_BSS_SELECT_ATTR_RSSI] = { .type = NLA_FLAG },
832 [NL80211_BSS_SELECT_ATTR_BAND_PREF] = { .type = NLA_U32 },
833 [NL80211_BSS_SELECT_ATTR_RSSI_ADJUST] = {
834 .len = sizeof(struct nl80211_bss_select_rssi_adjust)
835 },
836};
837
a442b761
AB
838/* policy for NAN function attributes */
839static const struct nla_policy
840nl80211_nan_func_policy[NL80211_NAN_FUNC_ATTR_MAX + 1] = {
cb9abd48
JB
841 [NL80211_NAN_FUNC_TYPE] =
842 NLA_POLICY_MAX(NLA_U8, NL80211_NAN_FUNC_MAX_TYPE),
0a27844c 843 [NL80211_NAN_FUNC_SERVICE_ID] = {
a442b761
AB
844 .len = NL80211_NAN_FUNC_SERVICE_ID_LEN },
845 [NL80211_NAN_FUNC_PUBLISH_TYPE] = { .type = NLA_U8 },
846 [NL80211_NAN_FUNC_PUBLISH_BCAST] = { .type = NLA_FLAG },
847 [NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE] = { .type = NLA_FLAG },
848 [NL80211_NAN_FUNC_FOLLOW_UP_ID] = { .type = NLA_U8 },
849 [NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID] = { .type = NLA_U8 },
c7721c05 850 [NL80211_NAN_FUNC_FOLLOW_UP_DEST] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
a442b761
AB
851 [NL80211_NAN_FUNC_CLOSE_RANGE] = { .type = NLA_FLAG },
852 [NL80211_NAN_FUNC_TTL] = { .type = NLA_U32 },
853 [NL80211_NAN_FUNC_SERVICE_INFO] = { .type = NLA_BINARY,
854 .len = NL80211_NAN_FUNC_SERVICE_SPEC_INFO_MAX_LEN },
855 [NL80211_NAN_FUNC_SRF] = { .type = NLA_NESTED },
856 [NL80211_NAN_FUNC_RX_MATCH_FILTER] = { .type = NLA_NESTED },
857 [NL80211_NAN_FUNC_TX_MATCH_FILTER] = { .type = NLA_NESTED },
858 [NL80211_NAN_FUNC_INSTANCE_ID] = { .type = NLA_U8 },
859 [NL80211_NAN_FUNC_TERM_REASON] = { .type = NLA_U8 },
860};
861
862/* policy for Service Response Filter attributes */
863static const struct nla_policy
864nl80211_nan_srf_policy[NL80211_NAN_SRF_ATTR_MAX + 1] = {
865 [NL80211_NAN_SRF_INCLUDE] = { .type = NLA_FLAG },
866 [NL80211_NAN_SRF_BF] = { .type = NLA_BINARY,
867 .len = NL80211_NAN_FUNC_SRF_MAX_LEN },
868 [NL80211_NAN_SRF_BF_IDX] = { .type = NLA_U8 },
869 [NL80211_NAN_SRF_MAC_ADDRS] = { .type = NLA_NESTED },
870};
871
ad670233
PX
872/* policy for packet pattern attributes */
873static const struct nla_policy
874nl80211_packet_pattern_policy[MAX_NL80211_PKTPAT + 1] = {
875 [NL80211_PKTPAT_MASK] = { .type = NLA_BINARY, },
876 [NL80211_PKTPAT_PATTERN] = { .type = NLA_BINARY, },
877 [NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 },
878};
879
9bb7e0f2
JB
880int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
881 struct cfg80211_registered_device **rdev,
882 struct wireless_dev **wdev)
a043897a 883{
97990a06 884 int err;
a043897a 885
97990a06 886 if (!cb->args[0]) {
50508d94
JB
887 struct nlattr **attrbuf;
888
889 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf),
890 GFP_KERNEL);
891 if (!attrbuf)
892 return -ENOMEM;
893
8cb08174
JB
894 err = nlmsg_parse_deprecated(cb->nlh,
895 GENL_HDRLEN + nl80211_fam.hdrsize,
50508d94 896 attrbuf, nl80211_fam.maxattr,
8cb08174 897 nl80211_policy, NULL);
50508d94
JB
898 if (err) {
899 kfree(attrbuf);
ea90e0dc 900 return err;
50508d94 901 }
67748893 902
50508d94
JB
903 *wdev = __cfg80211_wdev_from_attrs(sock_net(cb->skb->sk),
904 attrbuf);
905 kfree(attrbuf);
ea90e0dc
JB
906 if (IS_ERR(*wdev))
907 return PTR_ERR(*wdev);
f26cbf40 908 *rdev = wiphy_to_rdev((*wdev)->wiphy);
c319d50b
JB
909 /* 0 is the first index - add 1 to parse only once */
910 cb->args[0] = (*rdev)->wiphy_idx + 1;
97990a06
JB
911 cb->args[1] = (*wdev)->identifier;
912 } else {
c319d50b
JB
913 /* subtract the 1 again here */
914 struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
97990a06 915 struct wireless_dev *tmp;
67748893 916
ea90e0dc
JB
917 if (!wiphy)
918 return -ENODEV;
f26cbf40 919 *rdev = wiphy_to_rdev(wiphy);
97990a06 920 *wdev = NULL;
67748893 921
53873f13 922 list_for_each_entry(tmp, &(*rdev)->wiphy.wdev_list, list) {
97990a06
JB
923 if (tmp->identifier == cb->args[1]) {
924 *wdev = tmp;
925 break;
926 }
927 }
67748893 928
ea90e0dc
JB
929 if (!*wdev)
930 return -ENODEV;
67748893
JB
931 }
932
67748893 933 return 0;
67748893
JB
934}
935
55682965 936/* message building helper */
9bb7e0f2
JB
937void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
938 int flags, u8 cmd)
55682965
JB
939{
940 /* since there is no private header just add the generic one */
15e47304 941 return genlmsg_put(skb, portid, seq, &nl80211_fam, flags, cmd);
55682965
JB
942}
943
50f32718
HD
944static int nl80211_msg_put_wmm_rules(struct sk_buff *msg,
945 const struct ieee80211_reg_rule *rule)
946{
947 int j;
948 struct nlattr *nl_wmm_rules =
ae0be8de 949 nla_nest_start_noflag(msg, NL80211_FREQUENCY_ATTR_WMM);
50f32718
HD
950
951 if (!nl_wmm_rules)
952 goto nla_put_failure;
953
954 for (j = 0; j < IEEE80211_NUM_ACS; j++) {
ae0be8de 955 struct nlattr *nl_wmm_rule = nla_nest_start_noflag(msg, j);
50f32718
HD
956
957 if (!nl_wmm_rule)
958 goto nla_put_failure;
959
960 if (nla_put_u16(msg, NL80211_WMMR_CW_MIN,
38cb87ee 961 rule->wmm_rule.client[j].cw_min) ||
50f32718 962 nla_put_u16(msg, NL80211_WMMR_CW_MAX,
38cb87ee 963 rule->wmm_rule.client[j].cw_max) ||
50f32718 964 nla_put_u8(msg, NL80211_WMMR_AIFSN,
38cb87ee 965 rule->wmm_rule.client[j].aifsn) ||
d3c89bbc
HD
966 nla_put_u16(msg, NL80211_WMMR_TXOP,
967 rule->wmm_rule.client[j].cot))
50f32718
HD
968 goto nla_put_failure;
969
970 nla_nest_end(msg, nl_wmm_rule);
971 }
972 nla_nest_end(msg, nl_wmm_rules);
973
974 return 0;
975
976nla_put_failure:
977 return -ENOBUFS;
978}
979
980static int nl80211_msg_put_channel(struct sk_buff *msg, struct wiphy *wiphy,
cdc89b97
JB
981 struct ieee80211_channel *chan,
982 bool large)
5dab3b8a 983{
ea077c1c
RL
984 /* Some channels must be completely excluded from the
985 * list to protect old user-space tools from breaking
986 */
987 if (!large && chan->flags &
988 (IEEE80211_CHAN_NO_10MHZ | IEEE80211_CHAN_NO_20MHZ))
989 return 0;
f8d504ca
JB
990 if (!large && chan->freq_offset)
991 return 0;
ea077c1c 992
9360ffd1
DM
993 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_FREQ,
994 chan->center_freq))
995 goto nla_put_failure;
5dab3b8a 996
942ba88b
TP
997 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_OFFSET, chan->freq_offset))
998 goto nla_put_failure;
999
9360ffd1
DM
1000 if ((chan->flags & IEEE80211_CHAN_DISABLED) &&
1001 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_DISABLED))
1002 goto nla_put_failure;
8fe02e16
LR
1003 if (chan->flags & IEEE80211_CHAN_NO_IR) {
1004 if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IR))
1005 goto nla_put_failure;
1006 if (nla_put_flag(msg, __NL80211_FREQUENCY_ATTR_NO_IBSS))
1007 goto nla_put_failure;
1008 }
cdc89b97
JB
1009 if (chan->flags & IEEE80211_CHAN_RADAR) {
1010 if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
1011 goto nla_put_failure;
1012 if (large) {
1013 u32 time;
1014
1015 time = elapsed_jiffies_msecs(chan->dfs_state_entered);
1016
1017 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_STATE,
1018 chan->dfs_state))
1019 goto nla_put_failure;
1020 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME,
1021 time))
1022 goto nla_put_failure;
089027e5
JD
1023 if (nla_put_u32(msg,
1024 NL80211_FREQUENCY_ATTR_DFS_CAC_TIME,
1025 chan->dfs_cac_ms))
1026 goto nla_put_failure;
cdc89b97
JB
1027 }
1028 }
5dab3b8a 1029
fe1abafd
JB
1030 if (large) {
1031 if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) &&
1032 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS))
1033 goto nla_put_failure;
1034 if ((chan->flags & IEEE80211_CHAN_NO_HT40PLUS) &&
1035 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_PLUS))
1036 goto nla_put_failure;
1037 if ((chan->flags & IEEE80211_CHAN_NO_80MHZ) &&
1038 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_80MHZ))
1039 goto nla_put_failure;
1040 if ((chan->flags & IEEE80211_CHAN_NO_160MHZ) &&
1041 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_160MHZ))
1042 goto nla_put_failure;
570dbde1
DS
1043 if ((chan->flags & IEEE80211_CHAN_INDOOR_ONLY) &&
1044 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_INDOOR_ONLY))
1045 goto nla_put_failure;
06f207fc
AN
1046 if ((chan->flags & IEEE80211_CHAN_IR_CONCURRENT) &&
1047 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_IR_CONCURRENT))
570dbde1 1048 goto nla_put_failure;
ea077c1c
RL
1049 if ((chan->flags & IEEE80211_CHAN_NO_20MHZ) &&
1050 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_20MHZ))
1051 goto nla_put_failure;
1052 if ((chan->flags & IEEE80211_CHAN_NO_10MHZ) &&
1053 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_10MHZ))
1054 goto nla_put_failure;
1e61d82c
HD
1055 if ((chan->flags & IEEE80211_CHAN_NO_HE) &&
1056 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HE))
1057 goto nla_put_failure;
d65a9770
TP
1058 if ((chan->flags & IEEE80211_CHAN_1MHZ) &&
1059 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_1MHZ))
1060 goto nla_put_failure;
1061 if ((chan->flags & IEEE80211_CHAN_2MHZ) &&
1062 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_2MHZ))
1063 goto nla_put_failure;
1064 if ((chan->flags & IEEE80211_CHAN_4MHZ) &&
1065 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_4MHZ))
1066 goto nla_put_failure;
1067 if ((chan->flags & IEEE80211_CHAN_8MHZ) &&
1068 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_8MHZ))
1069 goto nla_put_failure;
1070 if ((chan->flags & IEEE80211_CHAN_16MHZ) &&
1071 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_16MHZ))
1072 goto nla_put_failure;
fe1abafd
JB
1073 }
1074
9360ffd1
DM
1075 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
1076 DBM_TO_MBM(chan->max_power)))
1077 goto nla_put_failure;
5dab3b8a 1078
50f32718
HD
1079 if (large) {
1080 const struct ieee80211_reg_rule *rule =
b88d26d9 1081 freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq));
50f32718 1082
38cb87ee 1083 if (!IS_ERR_OR_NULL(rule) && rule->has_wmm) {
50f32718
HD
1084 if (nl80211_msg_put_wmm_rules(msg, rule))
1085 goto nla_put_failure;
1086 }
1087 }
1088
5dab3b8a
LR
1089 return 0;
1090
1091 nla_put_failure:
1092 return -ENOBUFS;
1093}
1094
52539ca8
THJ
1095static bool nl80211_put_txq_stats(struct sk_buff *msg,
1096 struct cfg80211_txq_stats *txqstats,
1097 int attrtype)
1098{
1099 struct nlattr *txqattr;
1100
1101#define PUT_TXQVAL_U32(attr, memb) do { \
1102 if (txqstats->filled & BIT(NL80211_TXQ_STATS_ ## attr) && \
1103 nla_put_u32(msg, NL80211_TXQ_STATS_ ## attr, txqstats->memb)) \
1104 return false; \
1105 } while (0)
1106
ae0be8de 1107 txqattr = nla_nest_start_noflag(msg, attrtype);
52539ca8
THJ
1108 if (!txqattr)
1109 return false;
1110
1111 PUT_TXQVAL_U32(BACKLOG_BYTES, backlog_bytes);
1112 PUT_TXQVAL_U32(BACKLOG_PACKETS, backlog_packets);
1113 PUT_TXQVAL_U32(FLOWS, flows);
1114 PUT_TXQVAL_U32(DROPS, drops);
1115 PUT_TXQVAL_U32(ECN_MARKS, ecn_marks);
1116 PUT_TXQVAL_U32(OVERLIMIT, overlimit);
1117 PUT_TXQVAL_U32(OVERMEMORY, overmemory);
1118 PUT_TXQVAL_U32(COLLISIONS, collisions);
1119 PUT_TXQVAL_U32(TX_BYTES, tx_bytes);
1120 PUT_TXQVAL_U32(TX_PACKETS, tx_packets);
1121 PUT_TXQVAL_U32(MAX_FLOWS, max_flows);
1122 nla_nest_end(msg, txqattr);
1123
1124#undef PUT_TXQVAL_U32
1125 return true;
1126}
1127
55682965
JB
1128/* netlink command implementations */
1129
b9454e83
JB
1130struct key_parse {
1131 struct key_params p;
1132 int idx;
e31b8213 1133 int type;
56be393f 1134 bool def, defmgmt, defbeacon;
dbd2fd65 1135 bool def_uni, def_multi;
b9454e83
JB
1136};
1137
768075eb
JB
1138static int nl80211_parse_key_new(struct genl_info *info, struct nlattr *key,
1139 struct key_parse *k)
b9454e83
JB
1140{
1141 struct nlattr *tb[NL80211_KEY_MAX + 1];
8cb08174
JB
1142 int err = nla_parse_nested_deprecated(tb, NL80211_KEY_MAX, key,
1143 nl80211_key_policy,
1144 info->extack);
b9454e83
JB
1145 if (err)
1146 return err;
1147
1148 k->def = !!tb[NL80211_KEY_DEFAULT];
1149 k->defmgmt = !!tb[NL80211_KEY_DEFAULT_MGMT];
56be393f 1150 k->defbeacon = !!tb[NL80211_KEY_DEFAULT_BEACON];
b9454e83 1151
dbd2fd65
JB
1152 if (k->def) {
1153 k->def_uni = true;
1154 k->def_multi = true;
1155 }
56be393f 1156 if (k->defmgmt || k->defbeacon)
dbd2fd65
JB
1157 k->def_multi = true;
1158
b9454e83
JB
1159 if (tb[NL80211_KEY_IDX])
1160 k->idx = nla_get_u8(tb[NL80211_KEY_IDX]);
1161
1162 if (tb[NL80211_KEY_DATA]) {
1163 k->p.key = nla_data(tb[NL80211_KEY_DATA]);
1164 k->p.key_len = nla_len(tb[NL80211_KEY_DATA]);
1165 }
1166
1167 if (tb[NL80211_KEY_SEQ]) {
1168 k->p.seq = nla_data(tb[NL80211_KEY_SEQ]);
1169 k->p.seq_len = nla_len(tb[NL80211_KEY_SEQ]);
1170 }
1171
1172 if (tb[NL80211_KEY_CIPHER])
1173 k->p.cipher = nla_get_u32(tb[NL80211_KEY_CIPHER]);
1174
ab0d76f6 1175 if (tb[NL80211_KEY_TYPE])
e31b8213 1176 k->type = nla_get_u32(tb[NL80211_KEY_TYPE]);
e31b8213 1177
dbd2fd65
JB
1178 if (tb[NL80211_KEY_DEFAULT_TYPES]) {
1179 struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
7a087e74 1180
8cb08174
JB
1181 err = nla_parse_nested_deprecated(kdt,
1182 NUM_NL80211_KEY_DEFAULT_TYPES - 1,
1183 tb[NL80211_KEY_DEFAULT_TYPES],
1184 nl80211_key_default_policy,
1185 info->extack);
dbd2fd65
JB
1186 if (err)
1187 return err;
1188
1189 k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST];
1190 k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
1191 }
1192
6cdd3979
AW
1193 if (tb[NL80211_KEY_MODE])
1194 k->p.mode = nla_get_u8(tb[NL80211_KEY_MODE]);
1195
b9454e83
JB
1196 return 0;
1197}
1198
1199static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k)
1200{
1201 if (info->attrs[NL80211_ATTR_KEY_DATA]) {
1202 k->p.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]);
1203 k->p.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
1204 }
1205
1206 if (info->attrs[NL80211_ATTR_KEY_SEQ]) {
1207 k->p.seq = nla_data(info->attrs[NL80211_ATTR_KEY_SEQ]);
1208 k->p.seq_len = nla_len(info->attrs[NL80211_ATTR_KEY_SEQ]);
1209 }
1210
1211 if (info->attrs[NL80211_ATTR_KEY_IDX])
1212 k->idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
1213
1214 if (info->attrs[NL80211_ATTR_KEY_CIPHER])
1215 k->p.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);
1216
1217 k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT];
1218 k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT];
1219
dbd2fd65
JB
1220 if (k->def) {
1221 k->def_uni = true;
1222 k->def_multi = true;
1223 }
1224 if (k->defmgmt)
1225 k->def_multi = true;
1226
ab0d76f6 1227 if (info->attrs[NL80211_ATTR_KEY_TYPE])
e31b8213 1228 k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
e31b8213 1229
dbd2fd65
JB
1230 if (info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES]) {
1231 struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
8cb08174
JB
1232 int err = nla_parse_nested_deprecated(kdt,
1233 NUM_NL80211_KEY_DEFAULT_TYPES - 1,
1234 info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES],
1235 nl80211_key_default_policy,
1236 info->extack);
dbd2fd65
JB
1237 if (err)
1238 return err;
1239
1240 k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST];
1241 k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
1242 }
1243
b9454e83
JB
1244 return 0;
1245}
1246
1247static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)
1248{
1249 int err;
1250
1251 memset(k, 0, sizeof(*k));
1252 k->idx = -1;
e31b8213 1253 k->type = -1;
b9454e83
JB
1254
1255 if (info->attrs[NL80211_ATTR_KEY])
768075eb 1256 err = nl80211_parse_key_new(info, info->attrs[NL80211_ATTR_KEY], k);
b9454e83
JB
1257 else
1258 err = nl80211_parse_key_old(info, k);
1259
1260 if (err)
1261 return err;
1262
56be393f
JM
1263 if ((k->def ? 1 : 0) + (k->defmgmt ? 1 : 0) +
1264 (k->defbeacon ? 1 : 0) > 1) {
1265 GENL_SET_ERR_MSG(info,
1266 "key with multiple default flags is invalid");
b9454e83 1267 return -EINVAL;
768075eb 1268 }
b9454e83 1269
56be393f 1270 if (k->defmgmt || k->defbeacon) {
768075eb 1271 if (k->def_uni || !k->def_multi) {
56be393f
JM
1272 GENL_SET_ERR_MSG(info,
1273 "defmgmt/defbeacon key must be mcast");
dbd2fd65 1274 return -EINVAL;
768075eb 1275 }
dbd2fd65
JB
1276 }
1277
b9454e83
JB
1278 if (k->idx != -1) {
1279 if (k->defmgmt) {
768075eb
JB
1280 if (k->idx < 4 || k->idx > 5) {
1281 GENL_SET_ERR_MSG(info,
1282 "defmgmt key idx not 4 or 5");
b9454e83 1283 return -EINVAL;
768075eb 1284 }
56be393f
JM
1285 } else if (k->defbeacon) {
1286 if (k->idx < 6 || k->idx > 7) {
1287 GENL_SET_ERR_MSG(info,
1288 "defbeacon key idx not 6 or 7");
1289 return -EINVAL;
1290 }
b9454e83 1291 } else if (k->def) {
768075eb
JB
1292 if (k->idx < 0 || k->idx > 3) {
1293 GENL_SET_ERR_MSG(info, "def key idx not 0-3");
b9454e83 1294 return -EINVAL;
768075eb 1295 }
b9454e83 1296 } else {
56be393f
JM
1297 if (k->idx < 0 || k->idx > 7) {
1298 GENL_SET_ERR_MSG(info, "key idx not 0-7");
b9454e83 1299 return -EINVAL;
768075eb 1300 }
b9454e83
JB
1301 }
1302 }
1303
1304 return 0;
1305}
1306
fffd0934
JB
1307static struct cfg80211_cached_keys *
1308nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
768075eb 1309 struct genl_info *info, bool *no_ht)
fffd0934 1310{
768075eb 1311 struct nlattr *keys = info->attrs[NL80211_ATTR_KEYS];
fffd0934
JB
1312 struct key_parse parse;
1313 struct nlattr *key;
1314 struct cfg80211_cached_keys *result;
1315 int rem, err, def = 0;
f1c1f17a
JB
1316 bool have_key = false;
1317
1318 nla_for_each_nested(key, keys, rem) {
1319 have_key = true;
1320 break;
1321 }
1322
1323 if (!have_key)
1324 return NULL;
fffd0934
JB
1325
1326 result = kzalloc(sizeof(*result), GFP_KERNEL);
1327 if (!result)
1328 return ERR_PTR(-ENOMEM);
1329
1330 result->def = -1;
fffd0934
JB
1331
1332 nla_for_each_nested(key, keys, rem) {
1333 memset(&parse, 0, sizeof(parse));
1334 parse.idx = -1;
1335
768075eb 1336 err = nl80211_parse_key_new(info, key, &parse);
fffd0934
JB
1337 if (err)
1338 goto error;
1339 err = -EINVAL;
1340 if (!parse.p.key)
1341 goto error;
768075eb
JB
1342 if (parse.idx < 0 || parse.idx > 3) {
1343 GENL_SET_ERR_MSG(info, "key index out of range [0-3]");
fffd0934 1344 goto error;
768075eb 1345 }
fffd0934 1346 if (parse.def) {
768075eb
JB
1347 if (def) {
1348 GENL_SET_ERR_MSG(info,
1349 "only one key can be default");
fffd0934 1350 goto error;
768075eb 1351 }
fffd0934
JB
1352 def = 1;
1353 result->def = parse.idx;
dbd2fd65
JB
1354 if (!parse.def_uni || !parse.def_multi)
1355 goto error;
fffd0934
JB
1356 } else if (parse.defmgmt)
1357 goto error;
1358 err = cfg80211_validate_key_settings(rdev, &parse.p,
e31b8213 1359 parse.idx, false, NULL);
fffd0934
JB
1360 if (err)
1361 goto error;
386b1f27
JB
1362 if (parse.p.cipher != WLAN_CIPHER_SUITE_WEP40 &&
1363 parse.p.cipher != WLAN_CIPHER_SUITE_WEP104) {
768075eb 1364 GENL_SET_ERR_MSG(info, "connect key must be WEP");
386b1f27
JB
1365 err = -EINVAL;
1366 goto error;
1367 }
fffd0934
JB
1368 result->params[parse.idx].cipher = parse.p.cipher;
1369 result->params[parse.idx].key_len = parse.p.key_len;
1370 result->params[parse.idx].key = result->data[parse.idx];
1371 memcpy(result->data[parse.idx], parse.p.key, parse.p.key_len);
de7044ee 1372
386b1f27
JB
1373 /* must be WEP key if we got here */
1374 if (no_ht)
1375 *no_ht = true;
fffd0934
JB
1376 }
1377
f1c1f17a
JB
1378 if (result->def < 0) {
1379 err = -EINVAL;
768075eb 1380 GENL_SET_ERR_MSG(info, "need a default/TX key");
f1c1f17a
JB
1381 goto error;
1382 }
1383
fffd0934
JB
1384 return result;
1385 error:
1386 kfree(result);
1387 return ERR_PTR(err);
1388}
1389
1390static int nl80211_key_allowed(struct wireless_dev *wdev)
1391{
1392 ASSERT_WDEV_LOCK(wdev);
1393
fffd0934
JB
1394 switch (wdev->iftype) {
1395 case NL80211_IFTYPE_AP:
1396 case NL80211_IFTYPE_AP_VLAN:
074ac8df 1397 case NL80211_IFTYPE_P2P_GO:
ff973af7 1398 case NL80211_IFTYPE_MESH_POINT:
fffd0934
JB
1399 break;
1400 case NL80211_IFTYPE_ADHOC:
fffd0934 1401 case NL80211_IFTYPE_STATION:
074ac8df 1402 case NL80211_IFTYPE_P2P_CLIENT:
ceca7b71 1403 if (!wdev->current_bss)
fffd0934
JB
1404 return -ENOLINK;
1405 break;
de4fcbad 1406 case NL80211_IFTYPE_UNSPECIFIED:
6e0bd6c3 1407 case NL80211_IFTYPE_OCB:
de4fcbad 1408 case NL80211_IFTYPE_MONITOR:
cb3b7d87 1409 case NL80211_IFTYPE_NAN:
de4fcbad
JB
1410 case NL80211_IFTYPE_P2P_DEVICE:
1411 case NL80211_IFTYPE_WDS:
1412 case NUM_NL80211_IFTYPES:
fffd0934
JB
1413 return -EINVAL;
1414 }
1415
1416 return 0;
1417}
1418
664834de 1419static struct ieee80211_channel *nl80211_get_valid_chan(struct wiphy *wiphy,
942ba88b 1420 u32 freq)
664834de
JM
1421{
1422 struct ieee80211_channel *chan;
1423
942ba88b 1424 chan = ieee80211_get_channel_khz(wiphy, freq);
664834de
JM
1425 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
1426 return NULL;
1427 return chan;
1428}
1429
7527a782
JB
1430static int nl80211_put_iftypes(struct sk_buff *msg, u32 attr, u16 ifmodes)
1431{
ae0be8de 1432 struct nlattr *nl_modes = nla_nest_start_noflag(msg, attr);
7527a782
JB
1433 int i;
1434
1435 if (!nl_modes)
1436 goto nla_put_failure;
1437
1438 i = 0;
1439 while (ifmodes) {
9360ffd1
DM
1440 if ((ifmodes & 1) && nla_put_flag(msg, i))
1441 goto nla_put_failure;
7527a782
JB
1442 ifmodes >>= 1;
1443 i++;
1444 }
1445
1446 nla_nest_end(msg, nl_modes);
1447 return 0;
1448
1449nla_put_failure:
1450 return -ENOBUFS;
1451}
1452
1453static int nl80211_put_iface_combinations(struct wiphy *wiphy,
cdc89b97
JB
1454 struct sk_buff *msg,
1455 bool large)
7527a782
JB
1456{
1457 struct nlattr *nl_combis;
1458 int i, j;
1459
ae0be8de
MK
1460 nl_combis = nla_nest_start_noflag(msg,
1461 NL80211_ATTR_INTERFACE_COMBINATIONS);
7527a782
JB
1462 if (!nl_combis)
1463 goto nla_put_failure;
1464
1465 for (i = 0; i < wiphy->n_iface_combinations; i++) {
1466 const struct ieee80211_iface_combination *c;
1467 struct nlattr *nl_combi, *nl_limits;
1468
1469 c = &wiphy->iface_combinations[i];
1470
ae0be8de 1471 nl_combi = nla_nest_start_noflag(msg, i + 1);
7527a782
JB
1472 if (!nl_combi)
1473 goto nla_put_failure;
1474
ae0be8de
MK
1475 nl_limits = nla_nest_start_noflag(msg,
1476 NL80211_IFACE_COMB_LIMITS);
7527a782
JB
1477 if (!nl_limits)
1478 goto nla_put_failure;
1479
1480 for (j = 0; j < c->n_limits; j++) {
1481 struct nlattr *nl_limit;
1482
ae0be8de 1483 nl_limit = nla_nest_start_noflag(msg, j + 1);
7527a782
JB
1484 if (!nl_limit)
1485 goto nla_put_failure;
9360ffd1
DM
1486 if (nla_put_u32(msg, NL80211_IFACE_LIMIT_MAX,
1487 c->limits[j].max))
1488 goto nla_put_failure;
7527a782
JB
1489 if (nl80211_put_iftypes(msg, NL80211_IFACE_LIMIT_TYPES,
1490 c->limits[j].types))
1491 goto nla_put_failure;
1492 nla_nest_end(msg, nl_limit);
1493 }
1494
1495 nla_nest_end(msg, nl_limits);
1496
9360ffd1
DM
1497 if (c->beacon_int_infra_match &&
1498 nla_put_flag(msg, NL80211_IFACE_COMB_STA_AP_BI_MATCH))
1499 goto nla_put_failure;
1500 if (nla_put_u32(msg, NL80211_IFACE_COMB_NUM_CHANNELS,
1501 c->num_different_channels) ||
1502 nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM,
1503 c->max_interfaces))
1504 goto nla_put_failure;
cdc89b97 1505 if (large &&
8c48b50a
FF
1506 (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
1507 c->radar_detect_widths) ||
1508 nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
1509 c->radar_detect_regions)))
cdc89b97 1510 goto nla_put_failure;
0c317a02
PK
1511 if (c->beacon_int_min_gcd &&
1512 nla_put_u32(msg, NL80211_IFACE_COMB_BI_MIN_GCD,
1513 c->beacon_int_min_gcd))
1514 goto nla_put_failure;
7527a782
JB
1515
1516 nla_nest_end(msg, nl_combi);
1517 }
1518
1519 nla_nest_end(msg, nl_combis);
1520
1521 return 0;
1522nla_put_failure:
1523 return -ENOBUFS;
1524}
1525
3713b4e3 1526#ifdef CONFIG_PM
b56cf720
JB
1527static int nl80211_send_wowlan_tcp_caps(struct cfg80211_registered_device *rdev,
1528 struct sk_buff *msg)
1529{
964dc9e2 1530 const struct wiphy_wowlan_tcp_support *tcp = rdev->wiphy.wowlan->tcp;
b56cf720
JB
1531 struct nlattr *nl_tcp;
1532
1533 if (!tcp)
1534 return 0;
1535
ae0be8de
MK
1536 nl_tcp = nla_nest_start_noflag(msg,
1537 NL80211_WOWLAN_TRIG_TCP_CONNECTION);
b56cf720
JB
1538 if (!nl_tcp)
1539 return -ENOBUFS;
1540
1541 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
1542 tcp->data_payload_max))
1543 return -ENOBUFS;
1544
1545 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
1546 tcp->data_payload_max))
1547 return -ENOBUFS;
1548
1549 if (tcp->seq && nla_put_flag(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ))
1550 return -ENOBUFS;
1551
1552 if (tcp->tok && nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
1553 sizeof(*tcp->tok), tcp->tok))
1554 return -ENOBUFS;
1555
1556 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
1557 tcp->data_interval_max))
1558 return -ENOBUFS;
1559
1560 if (nla_put_u32(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
1561 tcp->wake_payload_max))
1562 return -ENOBUFS;
1563
1564 nla_nest_end(msg, nl_tcp);
1565 return 0;
1566}
1567
3713b4e3 1568static int nl80211_send_wowlan(struct sk_buff *msg,
1b8ec87a 1569 struct cfg80211_registered_device *rdev,
b56cf720 1570 bool large)
55682965 1571{
3713b4e3 1572 struct nlattr *nl_wowlan;
55682965 1573
1b8ec87a 1574 if (!rdev->wiphy.wowlan)
3713b4e3 1575 return 0;
55682965 1576
ae0be8de
MK
1577 nl_wowlan = nla_nest_start_noflag(msg,
1578 NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED);
3713b4e3
JB
1579 if (!nl_wowlan)
1580 return -ENOBUFS;
9360ffd1 1581
1b8ec87a 1582 if (((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_ANY) &&
3713b4e3 1583 nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
1b8ec87a 1584 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_DISCONNECT) &&
3713b4e3 1585 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
1b8ec87a 1586 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT) &&
3713b4e3 1587 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
1b8ec87a 1588 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) &&
3713b4e3 1589 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED)) ||
1b8ec87a 1590 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
3713b4e3 1591 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
1b8ec87a 1592 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) &&
3713b4e3 1593 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
1b8ec87a 1594 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) &&
3713b4e3 1595 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
1b8ec87a 1596 ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE) &&
3713b4e3
JB
1597 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
1598 return -ENOBUFS;
9360ffd1 1599
1b8ec87a 1600 if (rdev->wiphy.wowlan->n_patterns) {
50ac6607 1601 struct nl80211_pattern_support pat = {
1b8ec87a
ZG
1602 .max_patterns = rdev->wiphy.wowlan->n_patterns,
1603 .min_pattern_len = rdev->wiphy.wowlan->pattern_min_len,
1604 .max_pattern_len = rdev->wiphy.wowlan->pattern_max_len,
1605 .max_pkt_offset = rdev->wiphy.wowlan->max_pkt_offset,
3713b4e3 1606 };
9360ffd1 1607
3713b4e3
JB
1608 if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
1609 sizeof(pat), &pat))
1610 return -ENOBUFS;
1611 }
9360ffd1 1612
75453ccb
LC
1613 if ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_NET_DETECT) &&
1614 nla_put_u32(msg, NL80211_WOWLAN_TRIG_NET_DETECT,
1615 rdev->wiphy.wowlan->max_nd_match_sets))
1616 return -ENOBUFS;
1617
1b8ec87a 1618 if (large && nl80211_send_wowlan_tcp_caps(rdev, msg))
b56cf720
JB
1619 return -ENOBUFS;
1620
3713b4e3 1621 nla_nest_end(msg, nl_wowlan);
9360ffd1 1622
3713b4e3
JB
1623 return 0;
1624}
1625#endif
9360ffd1 1626
be29b99a 1627static int nl80211_send_coalesce(struct sk_buff *msg,
1b8ec87a 1628 struct cfg80211_registered_device *rdev)
be29b99a
AK
1629{
1630 struct nl80211_coalesce_rule_support rule;
1631
1b8ec87a 1632 if (!rdev->wiphy.coalesce)
be29b99a
AK
1633 return 0;
1634
1b8ec87a
ZG
1635 rule.max_rules = rdev->wiphy.coalesce->n_rules;
1636 rule.max_delay = rdev->wiphy.coalesce->max_delay;
1637 rule.pat.max_patterns = rdev->wiphy.coalesce->n_patterns;
1638 rule.pat.min_pattern_len = rdev->wiphy.coalesce->pattern_min_len;
1639 rule.pat.max_pattern_len = rdev->wiphy.coalesce->pattern_max_len;
1640 rule.pat.max_pkt_offset = rdev->wiphy.coalesce->max_pkt_offset;
be29b99a
AK
1641
1642 if (nla_put(msg, NL80211_ATTR_COALESCE_RULE, sizeof(rule), &rule))
1643 return -ENOBUFS;
1644
1645 return 0;
1646}
1647
c4cbaf79
LC
1648static int
1649nl80211_send_iftype_data(struct sk_buff *msg,
22395217 1650 const struct ieee80211_supported_band *sband,
c4cbaf79
LC
1651 const struct ieee80211_sband_iftype_data *iftdata)
1652{
1653 const struct ieee80211_sta_he_cap *he_cap = &iftdata->he_cap;
1654
1655 if (nl80211_put_iftypes(msg, NL80211_BAND_IFTYPE_ATTR_IFTYPES,
1656 iftdata->types_mask))
1657 return -ENOBUFS;
1658
1659 if (he_cap->has_he) {
1660 if (nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC,
1661 sizeof(he_cap->he_cap_elem.mac_cap_info),
1662 he_cap->he_cap_elem.mac_cap_info) ||
1663 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY,
1664 sizeof(he_cap->he_cap_elem.phy_cap_info),
1665 he_cap->he_cap_elem.phy_cap_info) ||
1666 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET,
1667 sizeof(he_cap->he_mcs_nss_supp),
1668 &he_cap->he_mcs_nss_supp) ||
1669 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE,
1670 sizeof(he_cap->ppe_thres), he_cap->ppe_thres))
1671 return -ENOBUFS;
1672 }
1673
22395217
JB
1674 if (sband->band == NL80211_BAND_6GHZ &&
1675 nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA,
1676 sizeof(iftdata->he_6ghz_capa),
1677 &iftdata->he_6ghz_capa))
1678 return -ENOBUFS;
1679
c4cbaf79
LC
1680 return 0;
1681}
1682
3713b4e3 1683static int nl80211_send_band_rateinfo(struct sk_buff *msg,
f8d504ca
JB
1684 struct ieee80211_supported_band *sband,
1685 bool large)
3713b4e3
JB
1686{
1687 struct nlattr *nl_rates, *nl_rate;
1688 struct ieee80211_rate *rate;
1689 int i;
87bbbe22 1690
3713b4e3
JB
1691 /* add HT info */
1692 if (sband->ht_cap.ht_supported &&
1693 (nla_put(msg, NL80211_BAND_ATTR_HT_MCS_SET,
1694 sizeof(sband->ht_cap.mcs),
1695 &sband->ht_cap.mcs) ||
1696 nla_put_u16(msg, NL80211_BAND_ATTR_HT_CAPA,
1697 sband->ht_cap.cap) ||
1698 nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR,
1699 sband->ht_cap.ampdu_factor) ||
1700 nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
1701 sband->ht_cap.ampdu_density)))
1702 return -ENOBUFS;
afe0cbf8 1703
3713b4e3
JB
1704 /* add VHT info */
1705 if (sband->vht_cap.vht_supported &&
1706 (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET,
1707 sizeof(sband->vht_cap.vht_mcs),
1708 &sband->vht_cap.vht_mcs) ||
1709 nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA,
1710 sband->vht_cap.cap)))
1711 return -ENOBUFS;
f59ac048 1712
f8d504ca 1713 if (large && sband->n_iftype_data) {
c4cbaf79 1714 struct nlattr *nl_iftype_data =
ae0be8de
MK
1715 nla_nest_start_noflag(msg,
1716 NL80211_BAND_ATTR_IFTYPE_DATA);
c4cbaf79
LC
1717 int err;
1718
1719 if (!nl_iftype_data)
1720 return -ENOBUFS;
1721
1722 for (i = 0; i < sband->n_iftype_data; i++) {
1723 struct nlattr *iftdata;
1724
ae0be8de 1725 iftdata = nla_nest_start_noflag(msg, i + 1);
c4cbaf79
LC
1726 if (!iftdata)
1727 return -ENOBUFS;
1728
22395217 1729 err = nl80211_send_iftype_data(msg, sband,
c4cbaf79
LC
1730 &sband->iftype_data[i]);
1731 if (err)
1732 return err;
1733
1734 nla_nest_end(msg, iftdata);
1735 }
1736
1737 nla_nest_end(msg, nl_iftype_data);
1738 }
1739
2a38075c 1740 /* add EDMG info */
f8d504ca 1741 if (large && sband->edmg_cap.channels &&
2a38075c
AAL
1742 (nla_put_u8(msg, NL80211_BAND_ATTR_EDMG_CHANNELS,
1743 sband->edmg_cap.channels) ||
1744 nla_put_u8(msg, NL80211_BAND_ATTR_EDMG_BW_CONFIG,
1745 sband->edmg_cap.bw_config)))
1746
1747 return -ENOBUFS;
1748
3713b4e3 1749 /* add bitrates */
ae0be8de 1750 nl_rates = nla_nest_start_noflag(msg, NL80211_BAND_ATTR_RATES);
3713b4e3
JB
1751 if (!nl_rates)
1752 return -ENOBUFS;
ee688b00 1753
3713b4e3 1754 for (i = 0; i < sband->n_bitrates; i++) {
ae0be8de 1755 nl_rate = nla_nest_start_noflag(msg, i);
3713b4e3
JB
1756 if (!nl_rate)
1757 return -ENOBUFS;
ee688b00 1758
3713b4e3
JB
1759 rate = &sband->bitrates[i];
1760 if (nla_put_u32(msg, NL80211_BITRATE_ATTR_RATE,
1761 rate->bitrate))
1762 return -ENOBUFS;
1763 if ((rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) &&
1764 nla_put_flag(msg,
1765 NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE))
1766 return -ENOBUFS;
ee688b00 1767
3713b4e3
JB
1768 nla_nest_end(msg, nl_rate);
1769 }
d51626df 1770
3713b4e3 1771 nla_nest_end(msg, nl_rates);
bf0c111e 1772
3713b4e3
JB
1773 return 0;
1774}
ee688b00 1775
3713b4e3
JB
1776static int
1777nl80211_send_mgmt_stypes(struct sk_buff *msg,
1778 const struct ieee80211_txrx_stypes *mgmt_stypes)
1779{
1780 u16 stypes;
1781 struct nlattr *nl_ftypes, *nl_ifs;
1782 enum nl80211_iftype ift;
1783 int i;
ee688b00 1784
3713b4e3
JB
1785 if (!mgmt_stypes)
1786 return 0;
5dab3b8a 1787
ae0be8de 1788 nl_ifs = nla_nest_start_noflag(msg, NL80211_ATTR_TX_FRAME_TYPES);
3713b4e3
JB
1789 if (!nl_ifs)
1790 return -ENOBUFS;
e2f367f2 1791
3713b4e3 1792 for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
ae0be8de 1793 nl_ftypes = nla_nest_start_noflag(msg, ift);
3713b4e3
JB
1794 if (!nl_ftypes)
1795 return -ENOBUFS;
1796 i = 0;
1797 stypes = mgmt_stypes[ift].tx;
1798 while (stypes) {
1799 if ((stypes & 1) &&
1800 nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
1801 (i << 4) | IEEE80211_FTYPE_MGMT))
1802 return -ENOBUFS;
1803 stypes >>= 1;
1804 i++;
ee688b00 1805 }
3713b4e3
JB
1806 nla_nest_end(msg, nl_ftypes);
1807 }
ee688b00 1808
3713b4e3 1809 nla_nest_end(msg, nl_ifs);
ee688b00 1810
ae0be8de 1811 nl_ifs = nla_nest_start_noflag(msg, NL80211_ATTR_RX_FRAME_TYPES);
3713b4e3
JB
1812 if (!nl_ifs)
1813 return -ENOBUFS;
ee688b00 1814
3713b4e3 1815 for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
ae0be8de 1816 nl_ftypes = nla_nest_start_noflag(msg, ift);
3713b4e3
JB
1817 if (!nl_ftypes)
1818 return -ENOBUFS;
1819 i = 0;
1820 stypes = mgmt_stypes[ift].rx;
1821 while (stypes) {
1822 if ((stypes & 1) &&
1823 nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
1824 (i << 4) | IEEE80211_FTYPE_MGMT))
1825 return -ENOBUFS;
1826 stypes >>= 1;
1827 i++;
1828 }
1829 nla_nest_end(msg, nl_ftypes);
1830 }
1831 nla_nest_end(msg, nl_ifs);
ee688b00 1832
3713b4e3
JB
1833 return 0;
1834}
ee688b00 1835
1794899e
JB
1836#define CMD(op, n) \
1837 do { \
1838 if (rdev->ops->op) { \
1839 i++; \
1840 if (nla_put_u32(msg, i, NL80211_CMD_ ## n)) \
1841 goto nla_put_failure; \
1842 } \
1843 } while (0)
1844
1845static int nl80211_add_commands_unsplit(struct cfg80211_registered_device *rdev,
1846 struct sk_buff *msg)
1847{
1848 int i = 0;
1849
1850 /*
1851 * do *NOT* add anything into this function, new things need to be
1852 * advertised only to new versions of userspace that can deal with
1853 * the split (and they can't possibly care about new features...
1854 */
1855 CMD(add_virtual_intf, NEW_INTERFACE);
1856 CMD(change_virtual_intf, SET_INTERFACE);
1857 CMD(add_key, NEW_KEY);
1858 CMD(start_ap, START_AP);
1859 CMD(add_station, NEW_STATION);
1860 CMD(add_mpath, NEW_MPATH);
1861 CMD(update_mesh_config, SET_MESH_CONFIG);
1862 CMD(change_bss, SET_BSS);
1863 CMD(auth, AUTHENTICATE);
1864 CMD(assoc, ASSOCIATE);
1865 CMD(deauth, DEAUTHENTICATE);
1866 CMD(disassoc, DISASSOCIATE);
1867 CMD(join_ibss, JOIN_IBSS);
1868 CMD(join_mesh, JOIN_MESH);
1869 CMD(set_pmksa, SET_PMKSA);
1870 CMD(del_pmksa, DEL_PMKSA);
1871 CMD(flush_pmksa, FLUSH_PMKSA);
1872 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)
1873 CMD(remain_on_channel, REMAIN_ON_CHANNEL);
1874 CMD(set_bitrate_mask, SET_TX_BITRATE_MASK);
1875 CMD(mgmt_tx, FRAME);
1876 CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL);
1877 if (rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
1878 i++;
1879 if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS))
1880 goto nla_put_failure;
1881 }
1882 if (rdev->ops->set_monitor_channel || rdev->ops->start_ap ||
1883 rdev->ops->join_mesh) {
1884 i++;
1885 if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL))
1886 goto nla_put_failure;
1887 }
1888 CMD(set_wds_peer, SET_WDS_PEER);
1889 if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) {
1890 CMD(tdls_mgmt, TDLS_MGMT);
1891 CMD(tdls_oper, TDLS_OPER);
1892 }
ca986ad9 1893 if (rdev->wiphy.max_sched_scan_reqs)
1794899e
JB
1894 CMD(sched_scan_start, START_SCHED_SCAN);
1895 CMD(probe_client, PROBE_CLIENT);
1896 CMD(set_noack_map, SET_NOACK_MAP);
1897 if (rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) {
1898 i++;
1899 if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS))
1900 goto nla_put_failure;
1901 }
1902 CMD(start_p2p_device, START_P2P_DEVICE);
1903 CMD(set_mcast_rate, SET_MCAST_RATE);
1904#ifdef CONFIG_NL80211_TESTMODE
1905 CMD(testmode_cmd, TESTMODE);
1906#endif
1907
1908 if (rdev->ops->connect || rdev->ops->auth) {
1909 i++;
1910 if (nla_put_u32(msg, i, NL80211_CMD_CONNECT))
1911 goto nla_put_failure;
1912 }
1913
1914 if (rdev->ops->disconnect || rdev->ops->deauth) {
1915 i++;
1916 if (nla_put_u32(msg, i, NL80211_CMD_DISCONNECT))
1917 goto nla_put_failure;
1918 }
1919
1920 return i;
1921 nla_put_failure:
1922 return -ENOBUFS;
1923}
1924
9bb7e0f2
JB
1925static int
1926nl80211_send_pmsr_ftm_capa(const struct cfg80211_pmsr_capabilities *cap,
1927 struct sk_buff *msg)
1928{
1929 struct nlattr *ftm;
1930
1931 if (!cap->ftm.supported)
1932 return 0;
1933
ae0be8de 1934 ftm = nla_nest_start_noflag(msg, NL80211_PMSR_TYPE_FTM);
9bb7e0f2
JB
1935 if (!ftm)
1936 return -ENOBUFS;
1937
1938 if (cap->ftm.asap && nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_ASAP))
1939 return -ENOBUFS;
1940 if (cap->ftm.non_asap &&
1941 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_NON_ASAP))
1942 return -ENOBUFS;
1943 if (cap->ftm.request_lci &&
1944 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_REQ_LCI))
1945 return -ENOBUFS;
1946 if (cap->ftm.request_civicloc &&
1947 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_REQ_CIVICLOC))
1948 return -ENOBUFS;
1949 if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES,
1950 cap->ftm.preambles))
1951 return -ENOBUFS;
1952 if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS,
1953 cap->ftm.bandwidths))
1954 return -ENOBUFS;
1955 if (cap->ftm.max_bursts_exponent >= 0 &&
1956 nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT,
1957 cap->ftm.max_bursts_exponent))
1958 return -ENOBUFS;
1959 if (cap->ftm.max_ftms_per_burst &&
1960 nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST,
1961 cap->ftm.max_ftms_per_burst))
1962 return -ENOBUFS;
efb5520d
AS
1963 if (cap->ftm.trigger_based &&
1964 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED))
1965 return -ENOBUFS;
1966 if (cap->ftm.non_trigger_based &&
1967 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED))
1968 return -ENOBUFS;
9bb7e0f2
JB
1969
1970 nla_nest_end(msg, ftm);
1971 return 0;
1972}
1973
1974static int nl80211_send_pmsr_capa(struct cfg80211_registered_device *rdev,
1975 struct sk_buff *msg)
1976{
1977 const struct cfg80211_pmsr_capabilities *cap = rdev->wiphy.pmsr_capa;
1978 struct nlattr *pmsr, *caps;
1979
1980 if (!cap)
1981 return 0;
1982
1983 /*
1984 * we don't need to clean up anything here since the caller
1985 * will genlmsg_cancel() if we fail
1986 */
1987
ae0be8de 1988 pmsr = nla_nest_start_noflag(msg, NL80211_ATTR_PEER_MEASUREMENTS);
9bb7e0f2
JB
1989 if (!pmsr)
1990 return -ENOBUFS;
1991
1992 if (nla_put_u32(msg, NL80211_PMSR_ATTR_MAX_PEERS, cap->max_peers))
1993 return -ENOBUFS;
1994
1995 if (cap->report_ap_tsf &&
1996 nla_put_flag(msg, NL80211_PMSR_ATTR_REPORT_AP_TSF))
1997 return -ENOBUFS;
1998
1999 if (cap->randomize_mac_addr &&
2000 nla_put_flag(msg, NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR))
2001 return -ENOBUFS;
2002
ae0be8de 2003 caps = nla_nest_start_noflag(msg, NL80211_PMSR_ATTR_TYPE_CAPA);
9bb7e0f2
JB
2004 if (!caps)
2005 return -ENOBUFS;
2006
2007 if (nl80211_send_pmsr_ftm_capa(cap, msg))
2008 return -ENOBUFS;
2009
2010 nla_nest_end(msg, caps);
2011 nla_nest_end(msg, pmsr);
2012
2013 return 0;
2014}
2015
d6039a34
VJ
2016static int
2017nl80211_put_iftype_akm_suites(struct cfg80211_registered_device *rdev,
2018 struct sk_buff *msg)
2019{
2020 int i;
2021 struct nlattr *nested, *nested_akms;
2022 const struct wiphy_iftype_akm_suites *iftype_akms;
2023
2024 if (!rdev->wiphy.num_iftype_akm_suites ||
2025 !rdev->wiphy.iftype_akm_suites)
2026 return 0;
2027
2028 nested = nla_nest_start(msg, NL80211_ATTR_IFTYPE_AKM_SUITES);
2029 if (!nested)
2030 return -ENOBUFS;
2031
2032 for (i = 0; i < rdev->wiphy.num_iftype_akm_suites; i++) {
2033 nested_akms = nla_nest_start(msg, i + 1);
2034 if (!nested_akms)
2035 return -ENOBUFS;
2036
2037 iftype_akms = &rdev->wiphy.iftype_akm_suites[i];
2038
2039 if (nl80211_put_iftypes(msg, NL80211_IFTYPE_AKM_ATTR_IFTYPES,
2040 iftype_akms->iftypes_mask))
2041 return -ENOBUFS;
2042
2043 if (nla_put(msg, NL80211_IFTYPE_AKM_ATTR_SUITES,
2044 sizeof(u32) * iftype_akms->n_akm_suites,
2045 iftype_akms->akm_suites)) {
2046 return -ENOBUFS;
2047 }
2048 nla_nest_end(msg, nested_akms);
2049 }
2050
2051 nla_nest_end(msg, nested);
2052
2053 return 0;
2054}
2055
3710a8a6
JB
2056static int
2057nl80211_put_tid_config_support(struct cfg80211_registered_device *rdev,
2058 struct sk_buff *msg)
2059{
2060 struct nlattr *supp;
2061
2062 if (!rdev->wiphy.tid_config_support.vif &&
2063 !rdev->wiphy.tid_config_support.peer)
2064 return 0;
2065
2066 supp = nla_nest_start(msg, NL80211_ATTR_TID_CONFIG);
2067 if (!supp)
2068 return -ENOSPC;
2069
2070 if (rdev->wiphy.tid_config_support.vif &&
2071 nla_put_u64_64bit(msg, NL80211_TID_CONFIG_ATTR_VIF_SUPP,
2072 rdev->wiphy.tid_config_support.vif,
2073 NL80211_TID_CONFIG_ATTR_PAD))
2074 goto fail;
2075
2076 if (rdev->wiphy.tid_config_support.peer &&
2077 nla_put_u64_64bit(msg, NL80211_TID_CONFIG_ATTR_PEER_SUPP,
2078 rdev->wiphy.tid_config_support.peer,
2079 NL80211_TID_CONFIG_ATTR_PAD))
2080 goto fail;
2081
6a21d16c
T
2082 /* for now we just use the same value ... makes more sense */
2083 if (nla_put_u8(msg, NL80211_TID_CONFIG_ATTR_RETRY_SHORT,
2084 rdev->wiphy.tid_config_support.max_retry))
2085 goto fail;
2086 if (nla_put_u8(msg, NL80211_TID_CONFIG_ATTR_RETRY_LONG,
2087 rdev->wiphy.tid_config_support.max_retry))
2088 goto fail;
2089
3710a8a6
JB
2090 nla_nest_end(msg, supp);
2091
2092 return 0;
2093fail:
2094 nla_nest_cancel(msg, supp);
2095 return -ENOBUFS;
2096}
2097
86e8cf98
JB
2098struct nl80211_dump_wiphy_state {
2099 s64 filter_wiphy;
2100 long start;
019ae3a9 2101 long split_start, band_start, chan_start, capa_start;
86e8cf98
JB
2102 bool split;
2103};
2104
1b8ec87a 2105static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
3bb20556 2106 enum nl80211_commands cmd,
3713b4e3 2107 struct sk_buff *msg, u32 portid, u32 seq,
86e8cf98 2108 int flags, struct nl80211_dump_wiphy_state *state)
3713b4e3
JB
2109{
2110 void *hdr;
2111 struct nlattr *nl_bands, *nl_band;
2112 struct nlattr *nl_freqs, *nl_freq;
2113 struct nlattr *nl_cmds;
57fbcce3 2114 enum nl80211_band band;
3713b4e3
JB
2115 struct ieee80211_channel *chan;
2116 int i;
2117 const struct ieee80211_txrx_stypes *mgmt_stypes =
1b8ec87a 2118 rdev->wiphy.mgmt_stypes;
fe1abafd 2119 u32 features;
ee688b00 2120
3bb20556 2121 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
3713b4e3
JB
2122 if (!hdr)
2123 return -ENOBUFS;
ee688b00 2124
86e8cf98
JB
2125 if (WARN_ON(!state))
2126 return -EINVAL;
ee688b00 2127
1b8ec87a 2128 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
3713b4e3 2129 nla_put_string(msg, NL80211_ATTR_WIPHY_NAME,
1b8ec87a 2130 wiphy_name(&rdev->wiphy)) ||
3713b4e3
JB
2131 nla_put_u32(msg, NL80211_ATTR_GENERATION,
2132 cfg80211_rdev_list_generation))
8fdc621d
JB
2133 goto nla_put_failure;
2134
3bb20556
JB
2135 if (cmd != NL80211_CMD_NEW_WIPHY)
2136 goto finish;
2137
86e8cf98 2138 switch (state->split_start) {
3713b4e3
JB
2139 case 0:
2140 if (nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT,
1b8ec87a 2141 rdev->wiphy.retry_short) ||
3713b4e3 2142 nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_LONG,
1b8ec87a 2143 rdev->wiphy.retry_long) ||
3713b4e3 2144 nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
1b8ec87a 2145 rdev->wiphy.frag_threshold) ||
3713b4e3 2146 nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD,
1b8ec87a 2147 rdev->wiphy.rts_threshold) ||
3713b4e3 2148 nla_put_u8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS,
1b8ec87a 2149 rdev->wiphy.coverage_class) ||
3713b4e3 2150 nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
1b8ec87a 2151 rdev->wiphy.max_scan_ssids) ||
3713b4e3 2152 nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
1b8ec87a 2153 rdev->wiphy.max_sched_scan_ssids) ||
3713b4e3 2154 nla_put_u16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
1b8ec87a 2155 rdev->wiphy.max_scan_ie_len) ||
3713b4e3 2156 nla_put_u16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN,
1b8ec87a 2157 rdev->wiphy.max_sched_scan_ie_len) ||
3713b4e3 2158 nla_put_u8(msg, NL80211_ATTR_MAX_MATCH_SETS,
f8d504ca 2159 rdev->wiphy.max_match_sets))
9360ffd1 2160 goto nla_put_failure;
3713b4e3 2161
1b8ec87a 2162 if ((rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) &&
3713b4e3 2163 nla_put_flag(msg, NL80211_ATTR_SUPPORT_IBSS_RSN))
aa430da4 2164 goto nla_put_failure;
1b8ec87a 2165 if ((rdev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) &&
3713b4e3
JB
2166 nla_put_flag(msg, NL80211_ATTR_SUPPORT_MESH_AUTH))
2167 goto nla_put_failure;
1b8ec87a 2168 if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) &&
3713b4e3
JB
2169 nla_put_flag(msg, NL80211_ATTR_SUPPORT_AP_UAPSD))
2170 goto nla_put_failure;
1b8ec87a 2171 if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) &&
3713b4e3
JB
2172 nla_put_flag(msg, NL80211_ATTR_ROAM_SUPPORT))
2173 goto nla_put_failure;
1b8ec87a 2174 if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
3713b4e3
JB
2175 nla_put_flag(msg, NL80211_ATTR_TDLS_SUPPORT))
2176 goto nla_put_failure;
1b8ec87a 2177 if ((rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) &&
3713b4e3 2178 nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP))
9360ffd1 2179 goto nla_put_failure;
86e8cf98
JB
2180 state->split_start++;
2181 if (state->split)
3713b4e3 2182 break;
7b506ff6 2183 fallthrough;
3713b4e3
JB
2184 case 1:
2185 if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES,
1b8ec87a
ZG
2186 sizeof(u32) * rdev->wiphy.n_cipher_suites,
2187 rdev->wiphy.cipher_suites))
3713b4e3 2188 goto nla_put_failure;
4745fc09 2189
3713b4e3 2190 if (nla_put_u8(msg, NL80211_ATTR_MAX_NUM_PMKIDS,
1b8ec87a 2191 rdev->wiphy.max_num_pmkids))
3713b4e3 2192 goto nla_put_failure;
b23aa676 2193
1b8ec87a 2194 if ((rdev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) &&
3713b4e3 2195 nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE))
9360ffd1 2196 goto nla_put_failure;
b23aa676 2197
3713b4e3 2198 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX,
1b8ec87a 2199 rdev->wiphy.available_antennas_tx) ||
3713b4e3 2200 nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX,
1b8ec87a 2201 rdev->wiphy.available_antennas_rx))
9360ffd1 2202 goto nla_put_failure;
b23aa676 2203
1b8ec87a 2204 if ((rdev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) &&
3713b4e3 2205 nla_put_u32(msg, NL80211_ATTR_PROBE_RESP_OFFLOAD,
1b8ec87a 2206 rdev->wiphy.probe_resp_offload))
3713b4e3 2207 goto nla_put_failure;
8fdc621d 2208
1b8ec87a
ZG
2209 if ((rdev->wiphy.available_antennas_tx ||
2210 rdev->wiphy.available_antennas_rx) &&
2211 rdev->ops->get_antenna) {
3713b4e3
JB
2212 u32 tx_ant = 0, rx_ant = 0;
2213 int res;
7a087e74 2214
1b8ec87a 2215 res = rdev_get_antenna(rdev, &tx_ant, &rx_ant);
3713b4e3
JB
2216 if (!res) {
2217 if (nla_put_u32(msg,
2218 NL80211_ATTR_WIPHY_ANTENNA_TX,
2219 tx_ant) ||
2220 nla_put_u32(msg,
2221 NL80211_ATTR_WIPHY_ANTENNA_RX,
2222 rx_ant))
2223 goto nla_put_failure;
2224 }
2225 }
a293911d 2226
86e8cf98
JB
2227 state->split_start++;
2228 if (state->split)
3713b4e3 2229 break;
7b506ff6 2230 fallthrough;
3713b4e3
JB
2231 case 2:
2232 if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES,
1b8ec87a 2233 rdev->wiphy.interface_modes))
3713b4e3 2234 goto nla_put_failure;
86e8cf98
JB
2235 state->split_start++;
2236 if (state->split)
3713b4e3 2237 break;
7b506ff6 2238 fallthrough;
3713b4e3 2239 case 3:
ae0be8de
MK
2240 nl_bands = nla_nest_start_noflag(msg,
2241 NL80211_ATTR_WIPHY_BANDS);
3713b4e3
JB
2242 if (!nl_bands)
2243 goto nla_put_failure;
f7ca38df 2244
86e8cf98 2245 for (band = state->band_start;
57fbcce3 2246 band < NUM_NL80211_BANDS; band++) {
3713b4e3 2247 struct ieee80211_supported_band *sband;
2e161f78 2248
f8d504ca
JB
2249 /* omit higher bands for ancient software */
2250 if (band > NL80211_BAND_5GHZ && !state->split)
2251 break;
2252
1b8ec87a 2253 sband = rdev->wiphy.bands[band];
2e161f78 2254
3713b4e3
JB
2255 if (!sband)
2256 continue;
2257
ae0be8de 2258 nl_band = nla_nest_start_noflag(msg, band);
3713b4e3 2259 if (!nl_band)
2e161f78 2260 goto nla_put_failure;
3713b4e3 2261
86e8cf98 2262 switch (state->chan_start) {
3713b4e3 2263 case 0:
f8d504ca
JB
2264 if (nl80211_send_band_rateinfo(msg, sband,
2265 state->split))
9360ffd1 2266 goto nla_put_failure;
86e8cf98
JB
2267 state->chan_start++;
2268 if (state->split)
3713b4e3 2269 break;
7b506ff6 2270 fallthrough;
3713b4e3
JB
2271 default:
2272 /* add frequencies */
ae0be8de
MK
2273 nl_freqs = nla_nest_start_noflag(msg,
2274 NL80211_BAND_ATTR_FREQS);
3713b4e3
JB
2275 if (!nl_freqs)
2276 goto nla_put_failure;
2277
86e8cf98 2278 for (i = state->chan_start - 1;
3713b4e3
JB
2279 i < sband->n_channels;
2280 i++) {
ae0be8de
MK
2281 nl_freq = nla_nest_start_noflag(msg,
2282 i);
3713b4e3
JB
2283 if (!nl_freq)
2284 goto nla_put_failure;
2285
2286 chan = &sband->channels[i];
2287
86e8cf98 2288 if (nl80211_msg_put_channel(
50f32718 2289 msg, &rdev->wiphy, chan,
86e8cf98 2290 state->split))
3713b4e3
JB
2291 goto nla_put_failure;
2292
2293 nla_nest_end(msg, nl_freq);
86e8cf98 2294 if (state->split)
3713b4e3
JB
2295 break;
2296 }
2297 if (i < sband->n_channels)
86e8cf98 2298 state->chan_start = i + 2;
3713b4e3 2299 else
86e8cf98 2300 state->chan_start = 0;
3713b4e3
JB
2301 nla_nest_end(msg, nl_freqs);
2302 }
2303
2304 nla_nest_end(msg, nl_band);
2305
86e8cf98 2306 if (state->split) {
3713b4e3 2307 /* start again here */
86e8cf98 2308 if (state->chan_start)
3713b4e3
JB
2309 band--;
2310 break;
2e161f78 2311 }
2e161f78 2312 }
3713b4e3 2313 nla_nest_end(msg, nl_bands);
2e161f78 2314
57fbcce3 2315 if (band < NUM_NL80211_BANDS)
86e8cf98 2316 state->band_start = band + 1;
3713b4e3 2317 else
86e8cf98 2318 state->band_start = 0;
74b70a4e 2319
3713b4e3 2320 /* if bands & channels are done, continue outside */
86e8cf98
JB
2321 if (state->band_start == 0 && state->chan_start == 0)
2322 state->split_start++;
2323 if (state->split)
3713b4e3 2324 break;
7b506ff6 2325 fallthrough;
3713b4e3 2326 case 4:
ae0be8de
MK
2327 nl_cmds = nla_nest_start_noflag(msg,
2328 NL80211_ATTR_SUPPORTED_COMMANDS);
3713b4e3 2329 if (!nl_cmds)
2e161f78
JB
2330 goto nla_put_failure;
2331
1794899e
JB
2332 i = nl80211_add_commands_unsplit(rdev, msg);
2333 if (i < 0)
2334 goto nla_put_failure;
86e8cf98 2335 if (state->split) {
5de17984
AS
2336 CMD(crit_proto_start, CRIT_PROTOCOL_START);
2337 CMD(crit_proto_stop, CRIT_PROTOCOL_STOP);
1b8ec87a 2338 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)
16ef1fe2 2339 CMD(channel_switch, CHANNEL_SWITCH);
02df00eb 2340 CMD(set_qos_map, SET_QOS_MAP);
723e73ac
JB
2341 if (rdev->wiphy.features &
2342 NL80211_FEATURE_SUPPORTS_WMM_ADMISSION)
960d01ac 2343 CMD(add_tx_ts, ADD_TX_TS);
ce0ce13a 2344 CMD(set_multicast_to_unicast, SET_MULTICAST_TO_UNICAST);
088e8df8 2345 CMD(update_connect_params, UPDATE_CONNECT_PARAMS);
7010998c 2346 CMD(update_ft_ies, UPDATE_FT_IES);
5de17984 2347 }
3713b4e3 2348#undef CMD
ff1b6e69 2349
3713b4e3 2350 nla_nest_end(msg, nl_cmds);
86e8cf98
JB
2351 state->split_start++;
2352 if (state->split)
3713b4e3 2353 break;
7b506ff6 2354 fallthrough;
3713b4e3 2355 case 5:
1b8ec87a
ZG
2356 if (rdev->ops->remain_on_channel &&
2357 (rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) &&
3713b4e3
JB
2358 nla_put_u32(msg,
2359 NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION,
1b8ec87a 2360 rdev->wiphy.max_remain_on_channel_duration))
3713b4e3
JB
2361 goto nla_put_failure;
2362
1b8ec87a 2363 if ((rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX) &&
3713b4e3
JB
2364 nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK))
2365 goto nla_put_failure;
2366
86e8cf98
JB
2367 state->split_start++;
2368 if (state->split)
3713b4e3 2369 break;
7b506ff6 2370 fallthrough;
3713b4e3
JB
2371 case 6:
2372#ifdef CONFIG_PM
1b8ec87a 2373 if (nl80211_send_wowlan(msg, rdev, state->split))
3713b4e3 2374 goto nla_put_failure;
86e8cf98
JB
2375 state->split_start++;
2376 if (state->split)
3713b4e3
JB
2377 break;
2378#else
86e8cf98 2379 state->split_start++;
dfb89c56 2380#endif
7b506ff6 2381 fallthrough;
3713b4e3
JB
2382 case 7:
2383 if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES,
1b8ec87a 2384 rdev->wiphy.software_iftypes))
3713b4e3 2385 goto nla_put_failure;
ff1b6e69 2386
1b8ec87a 2387 if (nl80211_put_iface_combinations(&rdev->wiphy, msg,
86e8cf98 2388 state->split))
3713b4e3 2389 goto nla_put_failure;
7527a782 2390
86e8cf98
JB
2391 state->split_start++;
2392 if (state->split)
3713b4e3 2393 break;
7b506ff6 2394 fallthrough;
3713b4e3 2395 case 8:
1b8ec87a 2396 if ((rdev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) &&
3713b4e3 2397 nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME,
1b8ec87a 2398 rdev->wiphy.ap_sme_capa))
3713b4e3 2399 goto nla_put_failure;
7527a782 2400
1b8ec87a 2401 features = rdev->wiphy.features;
fe1abafd
JB
2402 /*
2403 * We can only add the per-channel limit information if the
2404 * dump is split, otherwise it makes it too big. Therefore
2405 * only advertise it in that case.
2406 */
86e8cf98 2407 if (state->split)
fe1abafd
JB
2408 features |= NL80211_FEATURE_ADVERTISE_CHAN_LIMITS;
2409 if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, features))
3713b4e3 2410 goto nla_put_failure;
562a7480 2411
1b8ec87a 2412 if (rdev->wiphy.ht_capa_mod_mask &&
3713b4e3 2413 nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK,
1b8ec87a
ZG
2414 sizeof(*rdev->wiphy.ht_capa_mod_mask),
2415 rdev->wiphy.ht_capa_mod_mask))
3713b4e3 2416 goto nla_put_failure;
1f074bd8 2417
1b8ec87a
ZG
2418 if (rdev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME &&
2419 rdev->wiphy.max_acl_mac_addrs &&
3713b4e3 2420 nla_put_u32(msg, NL80211_ATTR_MAC_ACL_MAX,
1b8ec87a 2421 rdev->wiphy.max_acl_mac_addrs))
3713b4e3 2422 goto nla_put_failure;
7e7c8926 2423
3713b4e3
JB
2424 /*
2425 * Any information below this point is only available to
2426 * applications that can deal with it being split. This
2427 * helps ensure that newly added capabilities don't break
2428 * older tools by overrunning their buffers.
2429 *
2430 * We still increment split_start so that in the split
2431 * case we'll continue with more data in the next round,
2432 * but break unconditionally so unsplit data stops here.
2433 */
ab10c22b
JB
2434 if (state->split)
2435 state->split_start++;
2436 else
2437 state->split_start = 0;
3713b4e3
JB
2438 break;
2439 case 9:
f8d504ca
JB
2440 if (nl80211_send_mgmt_stypes(msg, mgmt_stypes))
2441 goto nla_put_failure;
2442
2443 if (nla_put_u32(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS,
2444 rdev->wiphy.max_sched_scan_plans) ||
2445 nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL,
2446 rdev->wiphy.max_sched_scan_plan_interval) ||
2447 nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS,
2448 rdev->wiphy.max_sched_scan_plan_iterations))
2449 goto nla_put_failure;
2450
1b8ec87a 2451 if (rdev->wiphy.extended_capabilities &&
fe1abafd 2452 (nla_put(msg, NL80211_ATTR_EXT_CAPA,
1b8ec87a
ZG
2453 rdev->wiphy.extended_capabilities_len,
2454 rdev->wiphy.extended_capabilities) ||
fe1abafd 2455 nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK,
1b8ec87a
ZG
2456 rdev->wiphy.extended_capabilities_len,
2457 rdev->wiphy.extended_capabilities_mask)))
fe1abafd 2458 goto nla_put_failure;
a50df0c4 2459
1b8ec87a 2460 if (rdev->wiphy.vht_capa_mod_mask &&
ee2aca34 2461 nla_put(msg, NL80211_ATTR_VHT_CAPABILITY_MASK,
1b8ec87a
ZG
2462 sizeof(*rdev->wiphy.vht_capa_mod_mask),
2463 rdev->wiphy.vht_capa_mod_mask))
ee2aca34
JB
2464 goto nla_put_failure;
2465
ae6fa4d5
DK
2466 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
2467 rdev->wiphy.perm_addr))
2468 goto nla_put_failure;
2469
2470 if (!is_zero_ether_addr(rdev->wiphy.addr_mask) &&
2471 nla_put(msg, NL80211_ATTR_MAC_MASK, ETH_ALEN,
2472 rdev->wiphy.addr_mask))
2473 goto nla_put_failure;
2474
2475 if (rdev->wiphy.n_addresses > 1) {
2476 void *attr;
2477
2478 attr = nla_nest_start(msg, NL80211_ATTR_MAC_ADDRS);
2479 if (!attr)
2480 goto nla_put_failure;
2481
2482 for (i = 0; i < rdev->wiphy.n_addresses; i++)
2483 if (nla_put(msg, i + 1, ETH_ALEN,
2484 rdev->wiphy.addresses[i].addr))
2485 goto nla_put_failure;
2486
2487 nla_nest_end(msg, attr);
2488 }
2489
be29b99a
AK
2490 state->split_start++;
2491 break;
2492 case 10:
1b8ec87a 2493 if (nl80211_send_coalesce(msg, rdev))
be29b99a
AK
2494 goto nla_put_failure;
2495
1b8ec87a 2496 if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) &&
01e0daa4
FF
2497 (nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) ||
2498 nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ)))
2499 goto nla_put_failure;
b43504cf 2500
1b8ec87a 2501 if (rdev->wiphy.max_ap_assoc_sta &&
b43504cf 2502 nla_put_u32(msg, NL80211_ATTR_MAX_AP_ASSOC_STA,
1b8ec87a 2503 rdev->wiphy.max_ap_assoc_sta))
b43504cf
JM
2504 goto nla_put_failure;
2505
ad7e718c
JB
2506 state->split_start++;
2507 break;
2508 case 11:
1b8ec87a 2509 if (rdev->wiphy.n_vendor_commands) {
567ffc35
JB
2510 const struct nl80211_vendor_cmd_info *info;
2511 struct nlattr *nested;
2512
ae0be8de
MK
2513 nested = nla_nest_start_noflag(msg,
2514 NL80211_ATTR_VENDOR_DATA);
567ffc35
JB
2515 if (!nested)
2516 goto nla_put_failure;
2517
1b8ec87a
ZG
2518 for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) {
2519 info = &rdev->wiphy.vendor_commands[i].info;
567ffc35
JB
2520 if (nla_put(msg, i + 1, sizeof(*info), info))
2521 goto nla_put_failure;
2522 }
2523 nla_nest_end(msg, nested);
2524 }
2525
1b8ec87a 2526 if (rdev->wiphy.n_vendor_events) {
567ffc35
JB
2527 const struct nl80211_vendor_cmd_info *info;
2528 struct nlattr *nested;
ad7e718c 2529
ae0be8de
MK
2530 nested = nla_nest_start_noflag(msg,
2531 NL80211_ATTR_VENDOR_EVENTS);
567ffc35 2532 if (!nested)
ad7e718c 2533 goto nla_put_failure;
567ffc35 2534
1b8ec87a
ZG
2535 for (i = 0; i < rdev->wiphy.n_vendor_events; i++) {
2536 info = &rdev->wiphy.vendor_events[i];
567ffc35
JB
2537 if (nla_put(msg, i + 1, sizeof(*info), info))
2538 goto nla_put_failure;
2539 }
2540 nla_nest_end(msg, nested);
2541 }
9a774c78
AO
2542 state->split_start++;
2543 break;
2544 case 12:
2545 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH &&
2546 nla_put_u8(msg, NL80211_ATTR_MAX_CSA_COUNTERS,
2547 rdev->wiphy.max_num_csa_counters))
2548 goto nla_put_failure;
01e0daa4 2549
1bdd716c
AN
2550 if (rdev->wiphy.regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
2551 nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
2552 goto nla_put_failure;
2553
ca986ad9
AVS
2554 if (rdev->wiphy.max_sched_scan_reqs &&
2555 nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_MAX_REQS,
2556 rdev->wiphy.max_sched_scan_reqs))
2557 goto nla_put_failure;
2558
d75bb06b
GKS
2559 if (nla_put(msg, NL80211_ATTR_EXT_FEATURES,
2560 sizeof(rdev->wiphy.ext_features),
2561 rdev->wiphy.ext_features))
2562 goto nla_put_failure;
2563
38de03d2
AS
2564 if (rdev->wiphy.bss_select_support) {
2565 struct nlattr *nested;
2566 u32 bss_select_support = rdev->wiphy.bss_select_support;
2567
ae0be8de
MK
2568 nested = nla_nest_start_noflag(msg,
2569 NL80211_ATTR_BSS_SELECT);
38de03d2
AS
2570 if (!nested)
2571 goto nla_put_failure;
2572
2573 i = 0;
2574 while (bss_select_support) {
2575 if ((bss_select_support & 1) &&
2576 nla_put_flag(msg, i))
2577 goto nla_put_failure;
2578 i++;
2579 bss_select_support >>= 1;
2580 }
2581 nla_nest_end(msg, nested);
2582 }
2583
019ae3a9
KV
2584 state->split_start++;
2585 break;
2586 case 13:
2587 if (rdev->wiphy.num_iftype_ext_capab &&
2588 rdev->wiphy.iftype_ext_capab) {
2589 struct nlattr *nested_ext_capab, *nested;
2590
ae0be8de
MK
2591 nested = nla_nest_start_noflag(msg,
2592 NL80211_ATTR_IFTYPE_EXT_CAPA);
019ae3a9
KV
2593 if (!nested)
2594 goto nla_put_failure;
2595
2596 for (i = state->capa_start;
2597 i < rdev->wiphy.num_iftype_ext_capab; i++) {
2598 const struct wiphy_iftype_ext_capab *capab;
2599
2600 capab = &rdev->wiphy.iftype_ext_capab[i];
2601
ae0be8de
MK
2602 nested_ext_capab = nla_nest_start_noflag(msg,
2603 i);
019ae3a9
KV
2604 if (!nested_ext_capab ||
2605 nla_put_u32(msg, NL80211_ATTR_IFTYPE,
2606 capab->iftype) ||
2607 nla_put(msg, NL80211_ATTR_EXT_CAPA,
2608 capab->extended_capabilities_len,
2609 capab->extended_capabilities) ||
2610 nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK,
2611 capab->extended_capabilities_len,
2612 capab->extended_capabilities_mask))
2613 goto nla_put_failure;
2614
2615 nla_nest_end(msg, nested_ext_capab);
2616 if (state->split)
2617 break;
2618 }
2619 nla_nest_end(msg, nested);
2620 if (i < rdev->wiphy.num_iftype_ext_capab) {
2621 state->capa_start = i + 1;
2622 break;
2623 }
2624 }
2625
8585989d
LC
2626 if (nla_put_u32(msg, NL80211_ATTR_BANDS,
2627 rdev->wiphy.nan_supported_bands))
2628 goto nla_put_failure;
2629
52539ca8
THJ
2630 if (wiphy_ext_feature_isset(&rdev->wiphy,
2631 NL80211_EXT_FEATURE_TXQS)) {
2632 struct cfg80211_txq_stats txqstats = {};
2633 int res;
2634
2635 res = rdev_get_txq_stats(rdev, NULL, &txqstats);
2636 if (!res &&
2637 !nl80211_put_txq_stats(msg, &txqstats,
2638 NL80211_ATTR_TXQ_STATS))
2639 goto nla_put_failure;
2640
2641 if (nla_put_u32(msg, NL80211_ATTR_TXQ_LIMIT,
2642 rdev->wiphy.txq_limit))
2643 goto nla_put_failure;
2644 if (nla_put_u32(msg, NL80211_ATTR_TXQ_MEMORY_LIMIT,
2645 rdev->wiphy.txq_memory_limit))
2646 goto nla_put_failure;
2647 if (nla_put_u32(msg, NL80211_ATTR_TXQ_QUANTUM,
2648 rdev->wiphy.txq_quantum))
2649 goto nla_put_failure;
2650 }
2651
9bb7e0f2
JB
2652 state->split_start++;
2653 break;
2654 case 14:
2655 if (nl80211_send_pmsr_capa(rdev, msg))
2656 goto nla_put_failure;
2657
ab4dfa20
VJ
2658 state->split_start++;
2659 break;
2660 case 15:
2661 if (rdev->wiphy.akm_suites &&
2662 nla_put(msg, NL80211_ATTR_AKM_SUITES,
2663 sizeof(u32) * rdev->wiphy.n_akm_suites,
2664 rdev->wiphy.akm_suites))
2665 goto nla_put_failure;
2666
d6039a34
VJ
2667 if (nl80211_put_iftype_akm_suites(rdev, msg))
2668 goto nla_put_failure;
2669
3710a8a6
JB
2670 if (nl80211_put_tid_config_support(rdev, msg))
2671 goto nla_put_failure;
2672
3713b4e3 2673 /* done */
86e8cf98 2674 state->split_start = 0;
3713b4e3
JB
2675 break;
2676 }
3bb20556 2677 finish:
053c095a
JB
2678 genlmsg_end(msg, hdr);
2679 return 0;
55682965
JB
2680
2681 nla_put_failure:
bc3ed28c
TG
2682 genlmsg_cancel(msg, hdr);
2683 return -EMSGSIZE;
55682965
JB
2684}
2685
86e8cf98
JB
2686static int nl80211_dump_wiphy_parse(struct sk_buff *skb,
2687 struct netlink_callback *cb,
2688 struct nl80211_dump_wiphy_state *state)
2689{
50508d94
JB
2690 struct nlattr **tb = kcalloc(NUM_NL80211_ATTR, sizeof(*tb), GFP_KERNEL);
2691 int ret;
2692
2693 if (!tb)
2694 return -ENOMEM;
2695
2696 ret = nlmsg_parse_deprecated(cb->nlh,
2697 GENL_HDRLEN + nl80211_fam.hdrsize,
2698 tb, nl80211_fam.maxattr,
2699 nl80211_policy, NULL);
86e8cf98 2700 /* ignore parse errors for backward compatibility */
50508d94
JB
2701 if (ret) {
2702 ret = 0;
2703 goto out;
2704 }
86e8cf98
JB
2705
2706 state->split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP];
2707 if (tb[NL80211_ATTR_WIPHY])
2708 state->filter_wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
2709 if (tb[NL80211_ATTR_WDEV])
2710 state->filter_wiphy = nla_get_u64(tb[NL80211_ATTR_WDEV]) >> 32;
2711 if (tb[NL80211_ATTR_IFINDEX]) {
2712 struct net_device *netdev;
2713 struct cfg80211_registered_device *rdev;
2714 int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
2715
7f2b8562 2716 netdev = __dev_get_by_index(sock_net(skb->sk), ifidx);
50508d94
JB
2717 if (!netdev) {
2718 ret = -ENODEV;
2719 goto out;
2720 }
86e8cf98 2721 if (netdev->ieee80211_ptr) {
f26cbf40 2722 rdev = wiphy_to_rdev(
86e8cf98
JB
2723 netdev->ieee80211_ptr->wiphy);
2724 state->filter_wiphy = rdev->wiphy_idx;
2725 }
86e8cf98
JB
2726 }
2727
50508d94
JB
2728 ret = 0;
2729out:
2730 kfree(tb);
2731 return ret;
86e8cf98
JB
2732}
2733
55682965
JB
2734static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
2735{
645e77de 2736 int idx = 0, ret;
86e8cf98 2737 struct nl80211_dump_wiphy_state *state = (void *)cb->args[0];
1b8ec87a 2738 struct cfg80211_registered_device *rdev;
3a5a423b 2739
5fe231e8 2740 rtnl_lock();
86e8cf98
JB
2741 if (!state) {
2742 state = kzalloc(sizeof(*state), GFP_KERNEL);
57ed5cd6
JL
2743 if (!state) {
2744 rtnl_unlock();
86e8cf98 2745 return -ENOMEM;
3713b4e3 2746 }
86e8cf98
JB
2747 state->filter_wiphy = -1;
2748 ret = nl80211_dump_wiphy_parse(skb, cb, state);
2749 if (ret) {
2750 kfree(state);
2751 rtnl_unlock();
2752 return ret;
3713b4e3 2753 }
86e8cf98 2754 cb->args[0] = (long)state;
3713b4e3
JB
2755 }
2756
1b8ec87a
ZG
2757 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
2758 if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
463d0183 2759 continue;
86e8cf98 2760 if (++idx <= state->start)
55682965 2761 continue;
86e8cf98 2762 if (state->filter_wiphy != -1 &&
1b8ec87a 2763 state->filter_wiphy != rdev->wiphy_idx)
3713b4e3
JB
2764 continue;
2765 /* attempt to fit multiple wiphy data chunks into the skb */
2766 do {
3bb20556
JB
2767 ret = nl80211_send_wiphy(rdev, NL80211_CMD_NEW_WIPHY,
2768 skb,
3713b4e3
JB
2769 NETLINK_CB(cb->skb).portid,
2770 cb->nlh->nlmsg_seq,
86e8cf98 2771 NLM_F_MULTI, state);
3713b4e3
JB
2772 if (ret < 0) {
2773 /*
2774 * If sending the wiphy data didn't fit (ENOBUFS
2775 * or EMSGSIZE returned), this SKB is still
2776 * empty (so it's not too big because another
2777 * wiphy dataset is already in the skb) and
2778 * we've not tried to adjust the dump allocation
2779 * yet ... then adjust the alloc size to be
2780 * bigger, and return 1 but with the empty skb.
2781 * This results in an empty message being RX'ed
2782 * in userspace, but that is ignored.
2783 *
2784 * We can then retry with the larger buffer.
2785 */
2786 if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
f12cb289 2787 !skb->len && !state->split &&
3713b4e3
JB
2788 cb->min_dump_alloc < 4096) {
2789 cb->min_dump_alloc = 4096;
f12cb289 2790 state->split_start = 0;
d98cae64 2791 rtnl_unlock();
3713b4e3
JB
2792 return 1;
2793 }
2794 idx--;
2795 break;
645e77de 2796 }
86e8cf98 2797 } while (state->split_start > 0);
3713b4e3 2798 break;
55682965 2799 }
5fe231e8 2800 rtnl_unlock();
55682965 2801
86e8cf98 2802 state->start = idx;
55682965
JB
2803
2804 return skb->len;
2805}
2806
86e8cf98
JB
2807static int nl80211_dump_wiphy_done(struct netlink_callback *cb)
2808{
2809 kfree((void *)cb->args[0]);
2810 return 0;
2811}
2812
55682965
JB
2813static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
2814{
2815 struct sk_buff *msg;
1b8ec87a 2816 struct cfg80211_registered_device *rdev = info->user_ptr[0];
86e8cf98 2817 struct nl80211_dump_wiphy_state state = {};
55682965 2818
645e77de 2819 msg = nlmsg_new(4096, GFP_KERNEL);
55682965 2820 if (!msg)
4c476991 2821 return -ENOMEM;
55682965 2822
3bb20556
JB
2823 if (nl80211_send_wiphy(rdev, NL80211_CMD_NEW_WIPHY, msg,
2824 info->snd_portid, info->snd_seq, 0,
86e8cf98 2825 &state) < 0) {
4c476991
JB
2826 nlmsg_free(msg);
2827 return -ENOBUFS;
2828 }
55682965 2829
134e6375 2830 return genlmsg_reply(msg, info);
55682965
JB
2831}
2832
31888487
JM
2833static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = {
2834 [NL80211_TXQ_ATTR_QUEUE] = { .type = NLA_U8 },
2835 [NL80211_TXQ_ATTR_TXOP] = { .type = NLA_U16 },
2836 [NL80211_TXQ_ATTR_CWMIN] = { .type = NLA_U16 },
2837 [NL80211_TXQ_ATTR_CWMAX] = { .type = NLA_U16 },
2838 [NL80211_TXQ_ATTR_AIFS] = { .type = NLA_U8 },
2839};
2840
2841static int parse_txq_params(struct nlattr *tb[],
2842 struct ieee80211_txq_params *txq_params)
2843{
259d8c1e
DW
2844 u8 ac;
2845
a3304b0a 2846 if (!tb[NL80211_TXQ_ATTR_AC] || !tb[NL80211_TXQ_ATTR_TXOP] ||
31888487
JM
2847 !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] ||
2848 !tb[NL80211_TXQ_ATTR_AIFS])
2849 return -EINVAL;
2850
259d8c1e 2851 ac = nla_get_u8(tb[NL80211_TXQ_ATTR_AC]);
31888487
JM
2852 txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]);
2853 txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]);
2854 txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]);
2855 txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]);
2856
259d8c1e 2857 if (ac >= NL80211_NUM_ACS)
a3304b0a 2858 return -EINVAL;
259d8c1e 2859 txq_params->ac = array_index_nospec(ac, NL80211_NUM_ACS);
31888487
JM
2860 return 0;
2861}
2862
f444de05
JB
2863static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev)
2864{
2865 /*
cc1d2806
JB
2866 * You can only set the channel explicitly for WDS interfaces,
2867 * all others have their channel managed via their respective
2868 * "establish a connection" command (connect, join, ...)
2869 *
2870 * For AP/GO and mesh mode, the channel can be set with the
2871 * channel userspace API, but is only stored and passed to the
2872 * low-level driver when the AP starts or the mesh is joined.
2873 * This is for backward compatibility, userspace can also give
2874 * the channel in the start-ap or join-mesh commands instead.
f444de05
JB
2875 *
2876 * Monitors are special as they are normally slaved to
e8c9bd5b
JB
2877 * whatever else is going on, so they have their own special
2878 * operation to set the monitor channel if possible.
f444de05
JB
2879 */
2880 return !wdev ||
2881 wdev->iftype == NL80211_IFTYPE_AP ||
f444de05 2882 wdev->iftype == NL80211_IFTYPE_MESH_POINT ||
074ac8df
JB
2883 wdev->iftype == NL80211_IFTYPE_MONITOR ||
2884 wdev->iftype == NL80211_IFTYPE_P2P_GO;
f444de05
JB
2885}
2886
9bb7e0f2
JB
2887int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
2888 struct genl_info *info,
2889 struct cfg80211_chan_def *chandef)
683b6d3b 2890{
49f9cf0e
JB
2891 struct netlink_ext_ack *extack = info->extack;
2892 struct nlattr **attrs = info->attrs;
dbeca2ea 2893 u32 control_freq;
683b6d3b 2894
49f9cf0e 2895 if (!attrs[NL80211_ATTR_WIPHY_FREQ])
683b6d3b
JB
2896 return -EINVAL;
2897
942ba88b
TP
2898 control_freq = MHZ_TO_KHZ(
2899 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
2900 if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
2901 control_freq +=
2902 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
683b6d3b 2903
f43e5210 2904 memset(chandef, 0, sizeof(*chandef));
942ba88b 2905 chandef->chan = ieee80211_get_channel_khz(&rdev->wiphy, control_freq);
3d9d1d66 2906 chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
942ba88b
TP
2907 chandef->center_freq1 = KHZ_TO_MHZ(control_freq);
2908 chandef->freq1_offset = control_freq % 1000;
3d9d1d66 2909 chandef->center_freq2 = 0;
683b6d3b
JB
2910
2911 /* Primary channel not allowed */
49f9cf0e
JB
2912 if (!chandef->chan || chandef->chan->flags & IEEE80211_CHAN_DISABLED) {
2913 NL_SET_ERR_MSG_ATTR(extack, attrs[NL80211_ATTR_WIPHY_FREQ],
2914 "Channel is disabled");
683b6d3b 2915 return -EINVAL;
49f9cf0e 2916 }
683b6d3b 2917
49f9cf0e 2918 if (attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
3d9d1d66
JB
2919 enum nl80211_channel_type chantype;
2920
49f9cf0e 2921 chantype = nla_get_u32(attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
3d9d1d66
JB
2922
2923 switch (chantype) {
2924 case NL80211_CHAN_NO_HT:
2925 case NL80211_CHAN_HT20:
2926 case NL80211_CHAN_HT40PLUS:
2927 case NL80211_CHAN_HT40MINUS:
2928 cfg80211_chandef_create(chandef, chandef->chan,
2929 chantype);
ffa4629e 2930 /* user input for center_freq is incorrect */
49f9cf0e
JB
2931 if (attrs[NL80211_ATTR_CENTER_FREQ1] &&
2932 chandef->center_freq1 != nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1])) {
2933 NL_SET_ERR_MSG_ATTR(extack,
2934 attrs[NL80211_ATTR_CENTER_FREQ1],
2935 "bad center frequency 1");
ffa4629e 2936 return -EINVAL;
49f9cf0e 2937 }
ffa4629e 2938 /* center_freq2 must be zero */
49f9cf0e
JB
2939 if (attrs[NL80211_ATTR_CENTER_FREQ2] &&
2940 nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2])) {
2941 NL_SET_ERR_MSG_ATTR(extack,
2942 attrs[NL80211_ATTR_CENTER_FREQ2],
2943 "center frequency 2 can't be used");
ffa4629e 2944 return -EINVAL;
49f9cf0e 2945 }
3d9d1d66
JB
2946 break;
2947 default:
49f9cf0e
JB
2948 NL_SET_ERR_MSG_ATTR(extack,
2949 attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
2950 "invalid channel type");
3d9d1d66
JB
2951 return -EINVAL;
2952 }
49f9cf0e 2953 } else if (attrs[NL80211_ATTR_CHANNEL_WIDTH]) {
3d9d1d66 2954 chandef->width =
49f9cf0e 2955 nla_get_u32(attrs[NL80211_ATTR_CHANNEL_WIDTH]);
942ba88b 2956 if (attrs[NL80211_ATTR_CENTER_FREQ1]) {
3d9d1d66 2957 chandef->center_freq1 =
49f9cf0e 2958 nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1]);
942ba88b
TP
2959 if (attrs[NL80211_ATTR_CENTER_FREQ1_OFFSET])
2960 chandef->freq1_offset = nla_get_u32(
2961 attrs[NL80211_ATTR_CENTER_FREQ1_OFFSET]);
2962 else
2963 chandef->freq1_offset = 0;
2964 }
49f9cf0e 2965 if (attrs[NL80211_ATTR_CENTER_FREQ2])
3d9d1d66 2966 chandef->center_freq2 =
49f9cf0e 2967 nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2]);
3d9d1d66
JB
2968 }
2969
2a38075c
AAL
2970 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]) {
2971 chandef->edmg.channels =
2972 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]);
2973
2974 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG])
2975 chandef->edmg.bw_config =
2976 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]);
2977 } else {
2978 chandef->edmg.bw_config = 0;
2979 chandef->edmg.channels = 0;
2980 }
2981
49f9cf0e
JB
2982 if (!cfg80211_chandef_valid(chandef)) {
2983 NL_SET_ERR_MSG(extack, "invalid channel definition");
3d9d1d66 2984 return -EINVAL;
49f9cf0e 2985 }
3d9d1d66 2986
9f5e8f6e 2987 if (!cfg80211_chandef_usable(&rdev->wiphy, chandef,
49f9cf0e
JB
2988 IEEE80211_CHAN_DISABLED)) {
2989 NL_SET_ERR_MSG(extack, "(extension) channel is disabled");
3d9d1d66 2990 return -EINVAL;
49f9cf0e 2991 }
3d9d1d66 2992
2f301ab2
SW
2993 if ((chandef->width == NL80211_CHAN_WIDTH_5 ||
2994 chandef->width == NL80211_CHAN_WIDTH_10) &&
49f9cf0e
JB
2995 !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ)) {
2996 NL_SET_ERR_MSG(extack, "5/10 MHz not supported");
2f301ab2 2997 return -EINVAL;
49f9cf0e 2998 }
2f301ab2 2999
683b6d3b
JB
3000 return 0;
3001}
3002
f444de05 3003static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
e16821bc 3004 struct net_device *dev,
f444de05
JB
3005 struct genl_info *info)
3006{
683b6d3b 3007 struct cfg80211_chan_def chandef;
f444de05 3008 int result;
e8c9bd5b 3009 enum nl80211_iftype iftype = NL80211_IFTYPE_MONITOR;
e16821bc 3010 struct wireless_dev *wdev = NULL;
e8c9bd5b 3011
e16821bc
JM
3012 if (dev)
3013 wdev = dev->ieee80211_ptr;
f444de05
JB
3014 if (!nl80211_can_set_dev_channel(wdev))
3015 return -EOPNOTSUPP;
e16821bc
JM
3016 if (wdev)
3017 iftype = wdev->iftype;
f444de05 3018
683b6d3b
JB
3019 result = nl80211_parse_chandef(rdev, info, &chandef);
3020 if (result)
3021 return result;
f444de05 3022
e8c9bd5b 3023 switch (iftype) {
aa430da4
JB
3024 case NL80211_IFTYPE_AP:
3025 case NL80211_IFTYPE_P2P_GO:
923b352f
AN
3026 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
3027 iftype)) {
aa430da4
JB
3028 result = -EINVAL;
3029 break;
3030 }
e16821bc
JM
3031 if (wdev->beacon_interval) {
3032 if (!dev || !rdev->ops->set_ap_chanwidth ||
3033 !(rdev->wiphy.features &
3034 NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE)) {
3035 result = -EBUSY;
3036 break;
3037 }
3038
3039 /* Only allow dynamic channel width changes */
3040 if (chandef.chan != wdev->preset_chandef.chan) {
3041 result = -EBUSY;
3042 break;
3043 }
3044 result = rdev_set_ap_chanwidth(rdev, dev, &chandef);
3045 if (result)
3046 break;
3047 }
683b6d3b 3048 wdev->preset_chandef = chandef;
aa430da4
JB
3049 result = 0;
3050 break;
cc1d2806 3051 case NL80211_IFTYPE_MESH_POINT:
683b6d3b 3052 result = cfg80211_set_mesh_channel(rdev, wdev, &chandef);
cc1d2806 3053 break;
e8c9bd5b 3054 case NL80211_IFTYPE_MONITOR:
683b6d3b 3055 result = cfg80211_set_monitor_channel(rdev, &chandef);
e8c9bd5b 3056 break;
aa430da4 3057 default:
e8c9bd5b 3058 result = -EINVAL;
f444de05 3059 }
f444de05
JB
3060
3061 return result;
3062}
3063
3064static int nl80211_set_channel(struct sk_buff *skb, struct genl_info *info)
3065{
4c476991
JB
3066 struct cfg80211_registered_device *rdev = info->user_ptr[0];
3067 struct net_device *netdev = info->user_ptr[1];
f444de05 3068
e16821bc 3069 return __nl80211_set_channel(rdev, netdev, info);
f444de05
JB
3070}
3071
e8347eba
BJ
3072static int nl80211_set_wds_peer(struct sk_buff *skb, struct genl_info *info)
3073{
43b19952
JB
3074 struct cfg80211_registered_device *rdev = info->user_ptr[0];
3075 struct net_device *dev = info->user_ptr[1];
3076 struct wireless_dev *wdev = dev->ieee80211_ptr;
388ac775 3077 const u8 *bssid;
e8347eba
BJ
3078
3079 if (!info->attrs[NL80211_ATTR_MAC])
3080 return -EINVAL;
3081
43b19952
JB
3082 if (netif_running(dev))
3083 return -EBUSY;
e8347eba 3084
43b19952
JB
3085 if (!rdev->ops->set_wds_peer)
3086 return -EOPNOTSUPP;
e8347eba 3087
43b19952
JB
3088 if (wdev->iftype != NL80211_IFTYPE_WDS)
3089 return -EOPNOTSUPP;
e8347eba
BJ
3090
3091 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
e35e4d28 3092 return rdev_set_wds_peer(rdev, dev, bssid);
e8347eba
BJ
3093}
3094
55682965
JB
3095static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
3096{
3097 struct cfg80211_registered_device *rdev;
f444de05
JB
3098 struct net_device *netdev = NULL;
3099 struct wireless_dev *wdev;
a1e567c8 3100 int result = 0, rem_txq_params = 0;
31888487 3101 struct nlattr *nl_txq_params;
b9a5f8ca
JM
3102 u32 changed;
3103 u8 retry_short = 0, retry_long = 0;
3104 u32 frag_threshold = 0, rts_threshold = 0;
81077e82 3105 u8 coverage_class = 0;
52539ca8 3106 u32 txq_limit = 0, txq_memory_limit = 0, txq_quantum = 0;
55682965 3107
5fe231e8
JB
3108 ASSERT_RTNL();
3109
f444de05
JB
3110 /*
3111 * Try to find the wiphy and netdev. Normally this
3112 * function shouldn't need the netdev, but this is
3113 * done for backward compatibility -- previously
3114 * setting the channel was done per wiphy, but now
3115 * it is per netdev. Previous userland like hostapd
3116 * also passed a netdev to set_wiphy, so that it is
3117 * possible to let that go to the right netdev!
3118 */
4bbf4d56 3119
f444de05
JB
3120 if (info->attrs[NL80211_ATTR_IFINDEX]) {
3121 int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
3122
7f2b8562 3123 netdev = __dev_get_by_index(genl_info_net(info), ifindex);
5fe231e8 3124 if (netdev && netdev->ieee80211_ptr)
f26cbf40 3125 rdev = wiphy_to_rdev(netdev->ieee80211_ptr->wiphy);
5fe231e8 3126 else
f444de05 3127 netdev = NULL;
4bbf4d56
JB
3128 }
3129
f444de05 3130 if (!netdev) {
878d9ec7
JB
3131 rdev = __cfg80211_rdev_from_attrs(genl_info_net(info),
3132 info->attrs);
5fe231e8 3133 if (IS_ERR(rdev))
4c476991 3134 return PTR_ERR(rdev);
f444de05
JB
3135 wdev = NULL;
3136 netdev = NULL;
3137 result = 0;
71fe96bf 3138 } else
f444de05 3139 wdev = netdev->ieee80211_ptr;
f444de05
JB
3140
3141 /*
3142 * end workaround code, by now the rdev is available
3143 * and locked, and wdev may or may not be NULL.
3144 */
4bbf4d56
JB
3145
3146 if (info->attrs[NL80211_ATTR_WIPHY_NAME])
31888487
JM
3147 result = cfg80211_dev_rename(
3148 rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
4bbf4d56 3149
4bbf4d56 3150 if (result)
7f2b8562 3151 return result;
31888487
JM
3152
3153 if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) {
3154 struct ieee80211_txq_params txq_params;
3155 struct nlattr *tb[NL80211_TXQ_ATTR_MAX + 1];
3156
7f2b8562
YX
3157 if (!rdev->ops->set_txq_params)
3158 return -EOPNOTSUPP;
31888487 3159
7f2b8562
YX
3160 if (!netdev)
3161 return -EINVAL;
f70f01c2 3162
133a3ff2 3163 if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
7f2b8562
YX
3164 netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
3165 return -EINVAL;
133a3ff2 3166
7f2b8562
YX
3167 if (!netif_running(netdev))
3168 return -ENETDOWN;
2b5f8b0b 3169
31888487
JM
3170 nla_for_each_nested(nl_txq_params,
3171 info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
3172 rem_txq_params) {
8cb08174
JB
3173 result = nla_parse_nested_deprecated(tb,
3174 NL80211_TXQ_ATTR_MAX,
3175 nl_txq_params,
3176 txq_params_policy,
3177 info->extack);
ae811e21
JB
3178 if (result)
3179 return result;
31888487
JM
3180 result = parse_txq_params(tb, &txq_params);
3181 if (result)
7f2b8562 3182 return result;
31888487 3183
e35e4d28
HG
3184 result = rdev_set_txq_params(rdev, netdev,
3185 &txq_params);
31888487 3186 if (result)
7f2b8562 3187 return result;
31888487
JM
3188 }
3189 }
55682965 3190
72bdcf34 3191 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
e16821bc
JM
3192 result = __nl80211_set_channel(
3193 rdev,
3194 nl80211_can_set_dev_channel(wdev) ? netdev : NULL,
3195 info);
72bdcf34 3196 if (result)
7f2b8562 3197 return result;
72bdcf34
JM
3198 }
3199
98d2ff8b 3200 if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) {
c8442118 3201 struct wireless_dev *txp_wdev = wdev;
98d2ff8b
JO
3202 enum nl80211_tx_power_setting type;
3203 int idx, mbm = 0;
3204
c8442118
JB
3205 if (!(rdev->wiphy.features & NL80211_FEATURE_VIF_TXPOWER))
3206 txp_wdev = NULL;
3207
7f2b8562
YX
3208 if (!rdev->ops->set_tx_power)
3209 return -EOPNOTSUPP;
98d2ff8b
JO
3210
3211 idx = NL80211_ATTR_WIPHY_TX_POWER_SETTING;
3212 type = nla_get_u32(info->attrs[idx]);
3213
3214 if (!info->attrs[NL80211_ATTR_WIPHY_TX_POWER_LEVEL] &&
7f2b8562
YX
3215 (type != NL80211_TX_POWER_AUTOMATIC))
3216 return -EINVAL;
98d2ff8b
JO
3217
3218 if (type != NL80211_TX_POWER_AUTOMATIC) {
3219 idx = NL80211_ATTR_WIPHY_TX_POWER_LEVEL;
3220 mbm = nla_get_u32(info->attrs[idx]);
3221 }
3222
c8442118 3223 result = rdev_set_tx_power(rdev, txp_wdev, type, mbm);
98d2ff8b 3224 if (result)
7f2b8562 3225 return result;
98d2ff8b
JO
3226 }
3227
afe0cbf8
BR
3228 if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
3229 info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {
3230 u32 tx_ant, rx_ant;
7a087e74 3231
7f531e03
BR
3232 if ((!rdev->wiphy.available_antennas_tx &&
3233 !rdev->wiphy.available_antennas_rx) ||
7f2b8562
YX
3234 !rdev->ops->set_antenna)
3235 return -EOPNOTSUPP;
afe0cbf8
BR
3236
3237 tx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]);
3238 rx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]);
3239
a7ffac95 3240 /* reject antenna configurations which don't match the
7f531e03
BR
3241 * available antenna masks, except for the "all" mask */
3242 if ((~tx_ant && (tx_ant & ~rdev->wiphy.available_antennas_tx)) ||
7f2b8562
YX
3243 (~rx_ant && (rx_ant & ~rdev->wiphy.available_antennas_rx)))
3244 return -EINVAL;
a7ffac95 3245
7f531e03
BR
3246 tx_ant = tx_ant & rdev->wiphy.available_antennas_tx;
3247 rx_ant = rx_ant & rdev->wiphy.available_antennas_rx;
a7ffac95 3248
e35e4d28 3249 result = rdev_set_antenna(rdev, tx_ant, rx_ant);
afe0cbf8 3250 if (result)
7f2b8562 3251 return result;
afe0cbf8
BR
3252 }
3253
b9a5f8ca
JM
3254 changed = 0;
3255
3256 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {
3257 retry_short = nla_get_u8(
3258 info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]);
7f2b8562 3259
b9a5f8ca
JM
3260 changed |= WIPHY_PARAM_RETRY_SHORT;
3261 }
3262
3263 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]) {
3264 retry_long = nla_get_u8(
3265 info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]);
7f2b8562 3266
b9a5f8ca
JM
3267 changed |= WIPHY_PARAM_RETRY_LONG;
3268 }
3269
3270 if (info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) {
3271 frag_threshold = nla_get_u32(
3272 info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]);
7f2b8562
YX
3273 if (frag_threshold < 256)
3274 return -EINVAL;
3275
b9a5f8ca
JM
3276 if (frag_threshold != (u32) -1) {
3277 /*
3278 * Fragments (apart from the last one) are required to
3279 * have even length. Make the fragmentation code
3280 * simpler by stripping LSB should someone try to use
3281 * odd threshold value.
3282 */
3283 frag_threshold &= ~0x1;
3284 }
3285 changed |= WIPHY_PARAM_FRAG_THRESHOLD;
3286 }
3287
3288 if (info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]) {
3289 rts_threshold = nla_get_u32(
3290 info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]);
3291 changed |= WIPHY_PARAM_RTS_THRESHOLD;
3292 }
3293
81077e82 3294 if (info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) {
3057dbfd
LB
3295 if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK])
3296 return -EINVAL;
3297
81077e82
LT
3298 coverage_class = nla_get_u8(
3299 info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]);
3300 changed |= WIPHY_PARAM_COVERAGE_CLASS;
3301 }
3302
3057dbfd
LB
3303 if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) {
3304 if (!(rdev->wiphy.features & NL80211_FEATURE_ACKTO_ESTIMATION))
3305 return -EOPNOTSUPP;
3306
3307 changed |= WIPHY_PARAM_DYN_ACK;
81077e82
LT
3308 }
3309
52539ca8
THJ
3310 if (info->attrs[NL80211_ATTR_TXQ_LIMIT]) {
3311 if (!wiphy_ext_feature_isset(&rdev->wiphy,
3312 NL80211_EXT_FEATURE_TXQS))
3313 return -EOPNOTSUPP;
3314 txq_limit = nla_get_u32(
3315 info->attrs[NL80211_ATTR_TXQ_LIMIT]);
3316 changed |= WIPHY_PARAM_TXQ_LIMIT;
3317 }
3318
3319 if (info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]) {
3320 if (!wiphy_ext_feature_isset(&rdev->wiphy,
3321 NL80211_EXT_FEATURE_TXQS))
3322 return -EOPNOTSUPP;
3323 txq_memory_limit = nla_get_u32(
3324 info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]);
3325 changed |= WIPHY_PARAM_TXQ_MEMORY_LIMIT;
3326 }
3327
3328 if (info->attrs[NL80211_ATTR_TXQ_QUANTUM]) {
3329 if (!wiphy_ext_feature_isset(&rdev->wiphy,
3330 NL80211_EXT_FEATURE_TXQS))
3331 return -EOPNOTSUPP;
3332 txq_quantum = nla_get_u32(
3333 info->attrs[NL80211_ATTR_TXQ_QUANTUM]);
3334 changed |= WIPHY_PARAM_TXQ_QUANTUM;
3335 }
3336
b9a5f8ca
JM
3337 if (changed) {
3338 u8 old_retry_short, old_retry_long;
3339 u32 old_frag_threshold, old_rts_threshold;
81077e82 3340 u8 old_coverage_class;
52539ca8 3341 u32 old_txq_limit, old_txq_memory_limit, old_txq_quantum;
b9a5f8ca 3342
7f2b8562
YX
3343 if (!rdev->ops->set_wiphy_params)
3344 return -EOPNOTSUPP;
b9a5f8ca
JM
3345
3346 old_retry_short = rdev->wiphy.retry_short;
3347 old_retry_long = rdev->wiphy.retry_long;
3348 old_frag_threshold = rdev->wiphy.frag_threshold;
3349 old_rts_threshold = rdev->wiphy.rts_threshold;
81077e82 3350 old_coverage_class = rdev->wiphy.coverage_class;
52539ca8
THJ
3351 old_txq_limit = rdev->wiphy.txq_limit;
3352 old_txq_memory_limit = rdev->wiphy.txq_memory_limit;
3353 old_txq_quantum = rdev->wiphy.txq_quantum;
b9a5f8ca
JM
3354
3355 if (changed & WIPHY_PARAM_RETRY_SHORT)
3356 rdev->wiphy.retry_short = retry_short;
3357 if (changed & WIPHY_PARAM_RETRY_LONG)
3358 rdev->wiphy.retry_long = retry_long;
3359 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
3360 rdev->wiphy.frag_threshold = frag_threshold;
3361 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
3362 rdev->wiphy.rts_threshold = rts_threshold;
81077e82
LT
3363 if (changed & WIPHY_PARAM_COVERAGE_CLASS)
3364 rdev->wiphy.coverage_class = coverage_class;
52539ca8
THJ
3365 if (changed & WIPHY_PARAM_TXQ_LIMIT)
3366 rdev->wiphy.txq_limit = txq_limit;
3367 if (changed & WIPHY_PARAM_TXQ_MEMORY_LIMIT)
3368 rdev->wiphy.txq_memory_limit = txq_memory_limit;
3369 if (changed & WIPHY_PARAM_TXQ_QUANTUM)
3370 rdev->wiphy.txq_quantum = txq_quantum;
b9a5f8ca 3371
e35e4d28 3372 result = rdev_set_wiphy_params(rdev, changed);
b9a5f8ca
JM
3373 if (result) {
3374 rdev->wiphy.retry_short = old_retry_short;
3375 rdev->wiphy.retry_long = old_retry_long;
3376 rdev->wiphy.frag_threshold = old_frag_threshold;
3377 rdev->wiphy.rts_threshold = old_rts_threshold;
81077e82 3378 rdev->wiphy.coverage_class = old_coverage_class;
52539ca8
THJ
3379 rdev->wiphy.txq_limit = old_txq_limit;
3380 rdev->wiphy.txq_memory_limit = old_txq_memory_limit;
3381 rdev->wiphy.txq_quantum = old_txq_quantum;
9189ee31 3382 return result;
b9a5f8ca
JM
3383 }
3384 }
7f2b8562 3385 return 0;
55682965
JB
3386}
3387
683b6d3b 3388static int nl80211_send_chandef(struct sk_buff *msg,
d2859df5 3389 const struct cfg80211_chan_def *chandef)
683b6d3b 3390{
601555cd
JB
3391 if (WARN_ON(!cfg80211_chandef_valid(chandef)))
3392 return -EINVAL;
3d9d1d66 3393
683b6d3b
JB
3394 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
3395 chandef->chan->center_freq))
3396 return -ENOBUFS;
942ba88b
TP
3397 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
3398 chandef->chan->freq_offset))
3399 return -ENOBUFS;
3d9d1d66
JB
3400 switch (chandef->width) {
3401 case NL80211_CHAN_WIDTH_20_NOHT:
3402 case NL80211_CHAN_WIDTH_20:
3403 case NL80211_CHAN_WIDTH_40:
3404 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
3405 cfg80211_get_chandef_type(chandef)))
3406 return -ENOBUFS;
3407 break;
3408 default:
3409 break;
3410 }
3411 if (nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, chandef->width))
3412 return -ENOBUFS;
3413 if (nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ1, chandef->center_freq1))
3414 return -ENOBUFS;
3415 if (chandef->center_freq2 &&
3416 nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2, chandef->center_freq2))
683b6d3b
JB
3417 return -ENOBUFS;
3418 return 0;
3419}
3420
15e47304 3421static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags,
d726405a 3422 struct cfg80211_registered_device *rdev,
3d1a5bbf
AZ
3423 struct wireless_dev *wdev,
3424 enum nl80211_commands cmd)
55682965 3425{
72fb2abc 3426 struct net_device *dev = wdev->netdev;
55682965
JB
3427 void *hdr;
3428
3d1a5bbf
AZ
3429 WARN_ON(cmd != NL80211_CMD_NEW_INTERFACE &&
3430 cmd != NL80211_CMD_DEL_INTERFACE &&
3431 cmd != NL80211_CMD_SET_INTERFACE);
8f894be2
TB
3432
3433 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
55682965
JB
3434 if (!hdr)
3435 return -1;
3436
72fb2abc
JB
3437 if (dev &&
3438 (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
98104fde 3439 nla_put_string(msg, NL80211_ATTR_IFNAME, dev->name)))
72fb2abc
JB
3440 goto nla_put_failure;
3441
3442 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
3443 nla_put_u32(msg, NL80211_ATTR_IFTYPE, wdev->iftype) ||
2dad624e
ND
3444 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
3445 NL80211_ATTR_PAD) ||
98104fde 3446 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, wdev_address(wdev)) ||
9360ffd1
DM
3447 nla_put_u32(msg, NL80211_ATTR_GENERATION,
3448 rdev->devlist_generation ^
446faa15
AQ
3449 (cfg80211_rdev_list_generation << 2)) ||
3450 nla_put_u8(msg, NL80211_ATTR_4ADDR, wdev->use_4addr))
9360ffd1 3451 goto nla_put_failure;
f5ea9120 3452
5b7ccaf3 3453 if (rdev->ops->get_channel) {
683b6d3b 3454 int ret;
f43e5210 3455 struct cfg80211_chan_def chandef = {};
683b6d3b
JB
3456
3457 ret = rdev_get_channel(rdev, wdev, &chandef);
3458 if (ret == 0) {
3459 if (nl80211_send_chandef(msg, &chandef))
3460 goto nla_put_failure;
3461 }
d91df0e3
PF
3462 }
3463
d55d0d59
RM
3464 if (rdev->ops->get_tx_power) {
3465 int dbm, ret;
3466
3467 ret = rdev_get_tx_power(rdev, wdev, &dbm);
3468 if (ret == 0 &&
3469 nla_put_u32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL,
3470 DBM_TO_MBM(dbm)))
3471 goto nla_put_failure;
3472 }
3473
44905265
JB
3474 wdev_lock(wdev);
3475 switch (wdev->iftype) {
3476 case NL80211_IFTYPE_AP:
3477 if (wdev->ssid_len &&
3478 nla_put(msg, NL80211_ATTR_SSID, wdev->ssid_len, wdev->ssid))
4564b187 3479 goto nla_put_failure_locked;
44905265
JB
3480 break;
3481 case NL80211_IFTYPE_STATION:
3482 case NL80211_IFTYPE_P2P_CLIENT:
3483 case NL80211_IFTYPE_ADHOC: {
3484 const u8 *ssid_ie;
3485 if (!wdev->current_bss)
3486 break;
7a94b8c2 3487 rcu_read_lock();
44905265
JB
3488 ssid_ie = ieee80211_bss_get_ie(&wdev->current_bss->pub,
3489 WLAN_EID_SSID);
7a94b8c2
DB
3490 if (ssid_ie &&
3491 nla_put(msg, NL80211_ATTR_SSID, ssid_ie[1], ssid_ie + 2))
3492 goto nla_put_failure_rcu_locked;
3493 rcu_read_unlock();
44905265
JB
3494 break;
3495 }
3496 default:
3497 /* nothing */
3498 break;
b84e7a05 3499 }
44905265 3500 wdev_unlock(wdev);
b84e7a05 3501
52539ca8
THJ
3502 if (rdev->ops->get_txq_stats) {
3503 struct cfg80211_txq_stats txqstats = {};
3504 int ret = rdev_get_txq_stats(rdev, wdev, &txqstats);
3505
3506 if (ret == 0 &&
3507 !nl80211_put_txq_stats(msg, &txqstats,
3508 NL80211_ATTR_TXQ_STATS))
3509 goto nla_put_failure;
3510 }
3511
053c095a
JB
3512 genlmsg_end(msg, hdr);
3513 return 0;
55682965 3514
7a94b8c2
DB
3515 nla_put_failure_rcu_locked:
3516 rcu_read_unlock();
4564b187
JB
3517 nla_put_failure_locked:
3518 wdev_unlock(wdev);
55682965 3519 nla_put_failure:
bc3ed28c
TG
3520 genlmsg_cancel(msg, hdr);
3521 return -EMSGSIZE;
55682965
JB
3522}
3523
3524static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
3525{
3526 int wp_idx = 0;
3527 int if_idx = 0;
3528 int wp_start = cb->args[0];
3529 int if_start = cb->args[1];
b7fb44da 3530 int filter_wiphy = -1;
f5ea9120 3531 struct cfg80211_registered_device *rdev;
55682965 3532 struct wireless_dev *wdev;
ea90e0dc 3533 int ret;
55682965 3534
5fe231e8 3535 rtnl_lock();
b7fb44da
DK
3536 if (!cb->args[2]) {
3537 struct nl80211_dump_wiphy_state state = {
3538 .filter_wiphy = -1,
3539 };
b7fb44da
DK
3540
3541 ret = nl80211_dump_wiphy_parse(skb, cb, &state);
3542 if (ret)
ea90e0dc 3543 goto out_unlock;
b7fb44da
DK
3544
3545 filter_wiphy = state.filter_wiphy;
3546
3547 /*
3548 * if filtering, set cb->args[2] to +1 since 0 is the default
3549 * value needed to determine that parsing is necessary.
3550 */
3551 if (filter_wiphy >= 0)
3552 cb->args[2] = filter_wiphy + 1;
3553 else
3554 cb->args[2] = -1;
3555 } else if (cb->args[2] > 0) {
3556 filter_wiphy = cb->args[2] - 1;
3557 }
3558
f5ea9120
JB
3559 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
3560 if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
463d0183 3561 continue;
bba95fef
JB
3562 if (wp_idx < wp_start) {
3563 wp_idx++;
55682965 3564 continue;
bba95fef 3565 }
b7fb44da
DK
3566
3567 if (filter_wiphy >= 0 && filter_wiphy != rdev->wiphy_idx)
3568 continue;
3569
55682965
JB
3570 if_idx = 0;
3571
53873f13 3572 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
bba95fef
JB
3573 if (if_idx < if_start) {
3574 if_idx++;
55682965 3575 continue;
bba95fef 3576 }
15e47304 3577 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid,
55682965 3578 cb->nlh->nlmsg_seq, NLM_F_MULTI,
3d1a5bbf
AZ
3579 rdev, wdev,
3580 NL80211_CMD_NEW_INTERFACE) < 0) {
bba95fef
JB
3581 goto out;
3582 }
3583 if_idx++;
55682965 3584 }
bba95fef
JB
3585
3586 wp_idx++;
55682965 3587 }
bba95fef 3588 out:
55682965
JB
3589 cb->args[0] = wp_idx;
3590 cb->args[1] = if_idx;
3591
ea90e0dc
JB
3592 ret = skb->len;
3593 out_unlock:
3594 rtnl_unlock();
3595
3596 return ret;
55682965
JB
3597}
3598
3599static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
3600{
3601 struct sk_buff *msg;
1b8ec87a 3602 struct cfg80211_registered_device *rdev = info->user_ptr[0];
72fb2abc 3603 struct wireless_dev *wdev = info->user_ptr[1];
55682965 3604
fd2120ca 3605 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
55682965 3606 if (!msg)
4c476991 3607 return -ENOMEM;
55682965 3608
15e47304 3609 if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0,
3d1a5bbf 3610 rdev, wdev, NL80211_CMD_NEW_INTERFACE) < 0) {
4c476991
JB
3611 nlmsg_free(msg);
3612 return -ENOBUFS;
3613 }
55682965 3614
134e6375 3615 return genlmsg_reply(msg, info);
55682965
JB
3616}
3617
66f7ac50
MW
3618static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = {
3619 [NL80211_MNTR_FLAG_FCSFAIL] = { .type = NLA_FLAG },
3620 [NL80211_MNTR_FLAG_PLCPFAIL] = { .type = NLA_FLAG },
3621 [NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG },
3622 [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG },
3623 [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG },
e057d3c3 3624 [NL80211_MNTR_FLAG_ACTIVE] = { .type = NLA_FLAG },
66f7ac50
MW
3625};
3626
3627static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
3628{
3629 struct nlattr *flags[NL80211_MNTR_FLAG_MAX + 1];
3630 int flag;
3631
3632 *mntrflags = 0;
3633
3634 if (!nla)
3635 return -EINVAL;
3636
8cb08174 3637 if (nla_parse_nested_deprecated(flags, NL80211_MNTR_FLAG_MAX, nla, mntr_flags_policy, NULL))
66f7ac50
MW
3638 return -EINVAL;
3639
3640 for (flag = 1; flag <= NL80211_MNTR_FLAG_MAX; flag++)
3641 if (flags[flag])
3642 *mntrflags |= (1<<flag);
3643
818a986e
JB
3644 *mntrflags |= MONITOR_FLAG_CHANGED;
3645
66f7ac50
MW
3646 return 0;
3647}
3648
1db77596
JB
3649static int nl80211_parse_mon_options(struct cfg80211_registered_device *rdev,
3650 enum nl80211_iftype type,
3651 struct genl_info *info,
3652 struct vif_params *params)
3653{
3654 bool change = false;
3655 int err;
3656
3657 if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
3658 if (type != NL80211_IFTYPE_MONITOR)
3659 return -EINVAL;
3660
3661 err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS],
3662 &params->flags);
3663 if (err)
3664 return err;
3665
3666 change = true;
3667 }
3668
3669 if (params->flags & MONITOR_FLAG_ACTIVE &&
3670 !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR))
3671 return -EOPNOTSUPP;
3672
3673 if (info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]) {
3674 const u8 *mumimo_groups;
3675 u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
3676
3677 if (type != NL80211_IFTYPE_MONITOR)
3678 return -EINVAL;
3679
3680 if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
3681 return -EOPNOTSUPP;
3682
3683 mumimo_groups =
3684 nla_data(info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]);
3685
3686 /* bits 0 and 63 are reserved and must be zero */
4954601f
JB
3687 if ((mumimo_groups[0] & BIT(0)) ||
3688 (mumimo_groups[VHT_MUMIMO_GROUPS_DATA_LEN - 1] & BIT(7)))
1db77596
JB
3689 return -EINVAL;
3690
3691 params->vht_mumimo_groups = mumimo_groups;
3692 change = true;
3693 }
3694
3695 if (info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]) {
3696 u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
3697
3698 if (type != NL80211_IFTYPE_MONITOR)
3699 return -EINVAL;
3700
3701 if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
3702 return -EOPNOTSUPP;
3703
3704 params->vht_mumimo_follow_addr =
3705 nla_data(info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]);
3706 change = true;
3707 }
3708
3709 return change ? 1 : 0;
3710}
3711
9bc383de 3712static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev,
ad4bb6f8
JB
3713 struct net_device *netdev, u8 use_4addr,
3714 enum nl80211_iftype iftype)
9bc383de 3715{
ad4bb6f8 3716 if (!use_4addr) {
2e92a2d0 3717 if (netdev && netif_is_bridge_port(netdev))
ad4bb6f8 3718 return -EBUSY;
9bc383de 3719 return 0;
ad4bb6f8 3720 }
9bc383de
JB
3721
3722 switch (iftype) {
3723 case NL80211_IFTYPE_AP_VLAN:
3724 if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP)
3725 return 0;
3726 break;
3727 case NL80211_IFTYPE_STATION:
3728 if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_STATION)
3729 return 0;
3730 break;
3731 default:
3732 break;
3733 }
3734
3735 return -EOPNOTSUPP;
3736}
3737
55682965
JB
3738static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
3739{
4c476991 3740 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2ec600d6 3741 struct vif_params params;
e36d56b6 3742 int err;
04a773ad 3743 enum nl80211_iftype otype, ntype;
4c476991 3744 struct net_device *dev = info->user_ptr[1];
ac7f9cfa 3745 bool change = false;
55682965 3746
2ec600d6
LCC
3747 memset(&params, 0, sizeof(params));
3748
04a773ad 3749 otype = ntype = dev->ieee80211_ptr->iftype;
55682965 3750
723b038d 3751 if (info->attrs[NL80211_ATTR_IFTYPE]) {
ac7f9cfa 3752 ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
04a773ad 3753 if (otype != ntype)
ac7f9cfa 3754 change = true;
723b038d
JB
3755 }
3756
92ffe055 3757 if (info->attrs[NL80211_ATTR_MESH_ID]) {
29cbe68c
JB
3758 struct wireless_dev *wdev = dev->ieee80211_ptr;
3759
4c476991
JB
3760 if (ntype != NL80211_IFTYPE_MESH_POINT)
3761 return -EINVAL;
29cbe68c
JB
3762 if (netif_running(dev))
3763 return -EBUSY;
3764
3765 wdev_lock(wdev);
3766 BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN !=
3767 IEEE80211_MAX_MESH_ID_LEN);
3768 wdev->mesh_id_up_len =
3769 nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
3770 memcpy(wdev->ssid, nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
3771 wdev->mesh_id_up_len);
3772 wdev_unlock(wdev);
2ec600d6
LCC
3773 }
3774
8b787643
FF
3775 if (info->attrs[NL80211_ATTR_4ADDR]) {
3776 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
3777 change = true;
ad4bb6f8 3778 err = nl80211_valid_4addr(rdev, dev, params.use_4addr, ntype);
9bc383de 3779 if (err)
4c476991 3780 return err;
8b787643
FF
3781 } else {
3782 params.use_4addr = -1;
3783 }
3784
1db77596
JB
3785 err = nl80211_parse_mon_options(rdev, ntype, info, &params);
3786 if (err < 0)
3787 return err;
3788 if (err > 0)
c6e6a0c8 3789 change = true;
e057d3c3 3790
ac7f9cfa 3791 if (change)
818a986e 3792 err = cfg80211_change_iface(rdev, dev, ntype, &params);
ac7f9cfa
JB
3793 else
3794 err = 0;
60719ffd 3795
9bc383de
JB
3796 if (!err && params.use_4addr != -1)
3797 dev->ieee80211_ptr->use_4addr = params.use_4addr;
3798
3d1a5bbf
AZ
3799 if (change && !err) {
3800 struct wireless_dev *wdev = dev->ieee80211_ptr;
3801
3802 nl80211_notify_iface(rdev, wdev, NL80211_CMD_SET_INTERFACE);
3803 }
3804
55682965
JB
3805 return err;
3806}
3807
3808static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
3809{
4c476991 3810 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2ec600d6 3811 struct vif_params params;
84efbb84 3812 struct wireless_dev *wdev;
896ff063 3813 struct sk_buff *msg;
55682965
JB
3814 int err;
3815 enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
3816
78f22b6a
JB
3817 /* to avoid failing a new interface creation due to pending removal */
3818 cfg80211_destroy_ifaces(rdev);
3819
2ec600d6
LCC
3820 memset(&params, 0, sizeof(params));
3821
55682965
JB
3822 if (!info->attrs[NL80211_ATTR_IFNAME])
3823 return -EINVAL;
3824
ab0d76f6 3825 if (info->attrs[NL80211_ATTR_IFTYPE])
55682965 3826 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
55682965 3827
33d915d9 3828 if (!rdev->ops->add_virtual_intf)
4c476991 3829 return -EOPNOTSUPP;
55682965 3830
cb3b7d87 3831 if ((type == NL80211_IFTYPE_P2P_DEVICE || type == NL80211_IFTYPE_NAN ||
e8f479b1
BG
3832 rdev->wiphy.features & NL80211_FEATURE_MAC_ON_CREATE) &&
3833 info->attrs[NL80211_ATTR_MAC]) {
1c18f145
AS
3834 nla_memcpy(params.macaddr, info->attrs[NL80211_ATTR_MAC],
3835 ETH_ALEN);
3836 if (!is_valid_ether_addr(params.macaddr))
3837 return -EADDRNOTAVAIL;
3838 }
3839
9bc383de 3840 if (info->attrs[NL80211_ATTR_4ADDR]) {
8b787643 3841 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
ad4bb6f8 3842 err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type);
9bc383de 3843 if (err)
4c476991 3844 return err;
9bc383de 3845 }
8b787643 3846
e6f40511 3847 if (!cfg80211_iftype_allowed(&rdev->wiphy, type, params.use_4addr, 0))
33d915d9
MP
3848 return -EOPNOTSUPP;
3849
1db77596
JB
3850 err = nl80211_parse_mon_options(rdev, type, info, &params);
3851 if (err < 0)
3852 return err;
e057d3c3 3853
a18c7192
JB
3854 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3855 if (!msg)
3856 return -ENOMEM;
3857
e35e4d28
HG
3858 wdev = rdev_add_virtual_intf(rdev,
3859 nla_data(info->attrs[NL80211_ATTR_IFNAME]),
818a986e 3860 NET_NAME_USER, type, &params);
d687cbb7
RM
3861 if (WARN_ON(!wdev)) {
3862 nlmsg_free(msg);
3863 return -EPROTO;
3864 } else if (IS_ERR(wdev)) {
1c90f9d4 3865 nlmsg_free(msg);
84efbb84 3866 return PTR_ERR(wdev);
1c90f9d4 3867 }
2ec600d6 3868
18e5ca65 3869 if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
78f22b6a
JB
3870 wdev->owner_nlportid = info->snd_portid;
3871
98104fde
JB
3872 switch (type) {
3873 case NL80211_IFTYPE_MESH_POINT:
3874 if (!info->attrs[NL80211_ATTR_MESH_ID])
3875 break;
29cbe68c
JB
3876 wdev_lock(wdev);
3877 BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN !=
3878 IEEE80211_MAX_MESH_ID_LEN);
3879 wdev->mesh_id_up_len =
3880 nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
3881 memcpy(wdev->ssid, nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
3882 wdev->mesh_id_up_len);
3883 wdev_unlock(wdev);
98104fde 3884 break;
cb3b7d87 3885 case NL80211_IFTYPE_NAN:
98104fde
JB
3886 case NL80211_IFTYPE_P2P_DEVICE:
3887 /*
cb3b7d87 3888 * P2P Device and NAN do not have a netdev, so don't go
98104fde
JB
3889 * through the netdev notifier and must be added here
3890 */
e4d4216e 3891 cfg80211_init_wdev(rdev, wdev);
98104fde
JB
3892 break;
3893 default:
3894 break;
29cbe68c
JB
3895 }
3896
15e47304 3897 if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0,
3d1a5bbf 3898 rdev, wdev, NL80211_CMD_NEW_INTERFACE) < 0) {
1c90f9d4
JB
3899 nlmsg_free(msg);
3900 return -ENOBUFS;
3901 }
3902
3903 return genlmsg_reply(msg, info);
55682965
JB
3904}
3905
3906static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
3907{
4c476991 3908 struct cfg80211_registered_device *rdev = info->user_ptr[0];
84efbb84 3909 struct wireless_dev *wdev = info->user_ptr[1];
55682965 3910
4c476991
JB
3911 if (!rdev->ops->del_virtual_intf)
3912 return -EOPNOTSUPP;
55682965 3913
84efbb84
JB
3914 /*
3915 * If we remove a wireless device without a netdev then clear
3916 * user_ptr[1] so that nl80211_post_doit won't dereference it
3917 * to check if it needs to do dev_put(). Otherwise it crashes
3918 * since the wdev has been freed, unlike with a netdev where
3919 * we need the dev_put() for the netdev to really be freed.
3920 */
3921 if (!wdev->netdev)
3922 info->user_ptr[1] = NULL;
3923
7f8ed01e 3924 return rdev_del_virtual_intf(rdev, wdev);
55682965
JB
3925}
3926
1d9d9213
SW
3927static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info)
3928{
3929 struct cfg80211_registered_device *rdev = info->user_ptr[0];
3930 struct net_device *dev = info->user_ptr[1];
3931 u16 noack_map;
3932
3933 if (!info->attrs[NL80211_ATTR_NOACK_MAP])
3934 return -EINVAL;
3935
3936 if (!rdev->ops->set_noack_map)
3937 return -EOPNOTSUPP;
3938
3939 noack_map = nla_get_u16(info->attrs[NL80211_ATTR_NOACK_MAP]);
3940
e35e4d28 3941 return rdev_set_noack_map(rdev, dev, noack_map);
1d9d9213
SW
3942}
3943
41ade00f
JB
3944struct get_key_cookie {
3945 struct sk_buff *msg;
3946 int error;
b9454e83 3947 int idx;
41ade00f
JB
3948};
3949
3950static void get_key_callback(void *c, struct key_params *params)
3951{
b9454e83 3952 struct nlattr *key;
41ade00f
JB
3953 struct get_key_cookie *cookie = c;
3954
9360ffd1
DM
3955 if ((params->key &&
3956 nla_put(cookie->msg, NL80211_ATTR_KEY_DATA,
3957 params->key_len, params->key)) ||
3958 (params->seq &&
3959 nla_put(cookie->msg, NL80211_ATTR_KEY_SEQ,
3960 params->seq_len, params->seq)) ||
3961 (params->cipher &&
3962 nla_put_u32(cookie->msg, NL80211_ATTR_KEY_CIPHER,
3963 params->cipher)))
3964 goto nla_put_failure;
41ade00f 3965
ae0be8de 3966 key = nla_nest_start_noflag(cookie->msg, NL80211_ATTR_KEY);
b9454e83
JB
3967 if (!key)
3968 goto nla_put_failure;
3969
9360ffd1
DM
3970 if ((params->key &&
3971 nla_put(cookie->msg, NL80211_KEY_DATA,
3972 params->key_len, params->key)) ||
3973 (params->seq &&
3974 nla_put(cookie->msg, NL80211_KEY_SEQ,
3975 params->seq_len, params->seq)) ||
3976 (params->cipher &&
3977 nla_put_u32(cookie->msg, NL80211_KEY_CIPHER,
3978 params->cipher)))
3979 goto nla_put_failure;
b9454e83 3980
efdfce72 3981 if (nla_put_u8(cookie->msg, NL80211_KEY_IDX, cookie->idx))
9360ffd1 3982 goto nla_put_failure;
b9454e83
JB
3983
3984 nla_nest_end(cookie->msg, key);
3985
41ade00f
JB
3986 return;
3987 nla_put_failure:
3988 cookie->error = 1;
3989}
3990
3991static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
3992{
4c476991 3993 struct cfg80211_registered_device *rdev = info->user_ptr[0];
41ade00f 3994 int err;
4c476991 3995 struct net_device *dev = info->user_ptr[1];
41ade00f 3996 u8 key_idx = 0;
e31b8213
JB
3997 const u8 *mac_addr = NULL;
3998 bool pairwise;
41ade00f
JB
3999 struct get_key_cookie cookie = {
4000 .error = 0,
4001 };
4002 void *hdr;
4003 struct sk_buff *msg;
155d7c73
JB
4004 bool bigtk_support = false;
4005
4006 if (wiphy_ext_feature_isset(&rdev->wiphy,
4007 NL80211_EXT_FEATURE_BEACON_PROTECTION))
4008 bigtk_support = true;
4009
4010 if ((dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION ||
4011 dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
4012 wiphy_ext_feature_isset(&rdev->wiphy,
4013 NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT))
4014 bigtk_support = true;
41ade00f 4015
56be393f 4016 if (info->attrs[NL80211_ATTR_KEY_IDX]) {
41ade00f 4017 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
155d7c73
JB
4018
4019 if (key_idx >= 6 && key_idx <= 7 && !bigtk_support) {
4020 GENL_SET_ERR_MSG(info, "BIGTK not supported");
56be393f 4021 return -EINVAL;
155d7c73 4022 }
56be393f 4023 }
41ade00f 4024
41ade00f
JB
4025 if (info->attrs[NL80211_ATTR_MAC])
4026 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4027
e31b8213
JB
4028 pairwise = !!mac_addr;
4029 if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
4030 u32 kt = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
7a087e74 4031
e31b8213
JB
4032 if (kt != NL80211_KEYTYPE_GROUP &&
4033 kt != NL80211_KEYTYPE_PAIRWISE)
4034 return -EINVAL;
4035 pairwise = kt == NL80211_KEYTYPE_PAIRWISE;
4036 }
4037
4c476991
JB
4038 if (!rdev->ops->get_key)
4039 return -EOPNOTSUPP;
41ade00f 4040
0fa7b391
JB
4041 if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
4042 return -ENOENT;
4043
fd2120ca 4044 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
4045 if (!msg)
4046 return -ENOMEM;
41ade00f 4047
15e47304 4048 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
41ade00f 4049 NL80211_CMD_NEW_KEY);
cb35fba3 4050 if (!hdr)
9fe271af 4051 goto nla_put_failure;
41ade00f
JB
4052
4053 cookie.msg = msg;
b9454e83 4054 cookie.idx = key_idx;
41ade00f 4055
9360ffd1
DM
4056 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
4057 nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx))
4058 goto nla_put_failure;
4059 if (mac_addr &&
4060 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr))
4061 goto nla_put_failure;
41ade00f 4062
e35e4d28
HG
4063 err = rdev_get_key(rdev, dev, key_idx, pairwise, mac_addr, &cookie,
4064 get_key_callback);
41ade00f
JB
4065
4066 if (err)
6c95e2a2 4067 goto free_msg;
41ade00f
JB
4068
4069 if (cookie.error)
4070 goto nla_put_failure;
4071
4072 genlmsg_end(msg, hdr);
4c476991 4073 return genlmsg_reply(msg, info);
41ade00f
JB
4074
4075 nla_put_failure:
4076 err = -ENOBUFS;
6c95e2a2 4077 free_msg:
41ade00f 4078 nlmsg_free(msg);
41ade00f
JB
4079 return err;
4080}
4081
4082static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
4083{
4c476991 4084 struct cfg80211_registered_device *rdev = info->user_ptr[0];
b9454e83 4085 struct key_parse key;
41ade00f 4086 int err;
4c476991 4087 struct net_device *dev = info->user_ptr[1];
41ade00f 4088
b9454e83
JB
4089 err = nl80211_parse_key(info, &key);
4090 if (err)
4091 return err;
41ade00f 4092
b9454e83 4093 if (key.idx < 0)
41ade00f
JB
4094 return -EINVAL;
4095
6cdd3979
AW
4096 /* Only support setting default key and
4097 * Extended Key ID action NL80211_KEY_SET_TX.
4098 */
56be393f 4099 if (!key.def && !key.defmgmt && !key.defbeacon &&
6cdd3979 4100 !(key.p.mode == NL80211_KEY_SET_TX))
41ade00f
JB
4101 return -EINVAL;
4102
dbd2fd65 4103 wdev_lock(dev->ieee80211_ptr);
3cfcf6ac 4104
dbd2fd65
JB
4105 if (key.def) {
4106 if (!rdev->ops->set_default_key) {
4107 err = -EOPNOTSUPP;
4108 goto out;
4109 }
41ade00f 4110
dbd2fd65
JB
4111 err = nl80211_key_allowed(dev->ieee80211_ptr);
4112 if (err)
4113 goto out;
4114
e35e4d28 4115 err = rdev_set_default_key(rdev, dev, key.idx,
dbd2fd65
JB
4116 key.def_uni, key.def_multi);
4117
4118 if (err)
4119 goto out;
fffd0934 4120
3d23e349 4121#ifdef CONFIG_CFG80211_WEXT
dbd2fd65
JB
4122 dev->ieee80211_ptr->wext.default_key = key.idx;
4123#endif
6cdd3979 4124 } else if (key.defmgmt) {
dbd2fd65
JB
4125 if (key.def_uni || !key.def_multi) {
4126 err = -EINVAL;
4127 goto out;
4128 }
4129
4130 if (!rdev->ops->set_default_mgmt_key) {
4131 err = -EOPNOTSUPP;
4132 goto out;
4133 }
4134
4135 err = nl80211_key_allowed(dev->ieee80211_ptr);
4136 if (err)
4137 goto out;
4138
e35e4d28 4139 err = rdev_set_default_mgmt_key(rdev, dev, key.idx);
dbd2fd65
JB
4140 if (err)
4141 goto out;
4142
4143#ifdef CONFIG_CFG80211_WEXT
4144 dev->ieee80211_ptr->wext.default_mgmt_key = key.idx;
08645126 4145#endif
56be393f
JM
4146 } else if (key.defbeacon) {
4147 if (key.def_uni || !key.def_multi) {
4148 err = -EINVAL;
4149 goto out;
4150 }
4151
4152 if (!rdev->ops->set_default_beacon_key) {
4153 err = -EOPNOTSUPP;
4154 goto out;
4155 }
4156
4157 err = nl80211_key_allowed(dev->ieee80211_ptr);
4158 if (err)
4159 goto out;
4160
4161 err = rdev_set_default_beacon_key(rdev, dev, key.idx);
4162 if (err)
4163 goto out;
6cdd3979
AW
4164 } else if (key.p.mode == NL80211_KEY_SET_TX &&
4165 wiphy_ext_feature_isset(&rdev->wiphy,
4166 NL80211_EXT_FEATURE_EXT_KEY_ID)) {
4167 u8 *mac_addr = NULL;
4168
4169 if (info->attrs[NL80211_ATTR_MAC])
4170 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4171
4172 if (!mac_addr || key.idx < 0 || key.idx > 1) {
4173 err = -EINVAL;
4174 goto out;
4175 }
dbd2fd65 4176
6cdd3979
AW
4177 err = rdev_add_key(rdev, dev, key.idx,
4178 NL80211_KEYTYPE_PAIRWISE,
4179 mac_addr, &key.p);
4180 } else {
4181 err = -EINVAL;
4182 }
dbd2fd65 4183 out:
fffd0934 4184 wdev_unlock(dev->ieee80211_ptr);
41ade00f 4185
41ade00f
JB
4186 return err;
4187}
4188
4189static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
4190{
4c476991 4191 struct cfg80211_registered_device *rdev = info->user_ptr[0];
fffd0934 4192 int err;
4c476991 4193 struct net_device *dev = info->user_ptr[1];
b9454e83 4194 struct key_parse key;
e31b8213 4195 const u8 *mac_addr = NULL;
41ade00f 4196
b9454e83
JB
4197 err = nl80211_parse_key(info, &key);
4198 if (err)
4199 return err;
41ade00f 4200
f8af764b
JM
4201 if (!key.p.key) {
4202 GENL_SET_ERR_MSG(info, "no key");
41ade00f 4203 return -EINVAL;
f8af764b 4204 }
41ade00f 4205
41ade00f
JB
4206 if (info->attrs[NL80211_ATTR_MAC])
4207 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4208
e31b8213
JB
4209 if (key.type == -1) {
4210 if (mac_addr)
4211 key.type = NL80211_KEYTYPE_PAIRWISE;
4212 else
4213 key.type = NL80211_KEYTYPE_GROUP;
4214 }
4215
4216 /* for now */
4217 if (key.type != NL80211_KEYTYPE_PAIRWISE &&
f8af764b
JM
4218 key.type != NL80211_KEYTYPE_GROUP) {
4219 GENL_SET_ERR_MSG(info, "key type not pairwise or group");
e31b8213 4220 return -EINVAL;
f8af764b 4221 }
e31b8213 4222
14f34e36
GG
4223 if (key.type == NL80211_KEYTYPE_GROUP &&
4224 info->attrs[NL80211_ATTR_VLAN_ID])
4225 key.p.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
4226
4c476991
JB
4227 if (!rdev->ops->add_key)
4228 return -EOPNOTSUPP;
25e47c18 4229
e31b8213
JB
4230 if (cfg80211_validate_key_settings(rdev, &key.p, key.idx,
4231 key.type == NL80211_KEYTYPE_PAIRWISE,
f8af764b
JM
4232 mac_addr)) {
4233 GENL_SET_ERR_MSG(info, "key setting validation failed");
4c476991 4234 return -EINVAL;
f8af764b 4235 }
41ade00f 4236
fffd0934
JB
4237 wdev_lock(dev->ieee80211_ptr);
4238 err = nl80211_key_allowed(dev->ieee80211_ptr);
f8af764b
JM
4239 if (err)
4240 GENL_SET_ERR_MSG(info, "key not allowed");
4241 if (!err) {
e35e4d28
HG
4242 err = rdev_add_key(rdev, dev, key.idx,
4243 key.type == NL80211_KEYTYPE_PAIRWISE,
4244 mac_addr, &key.p);
f8af764b
JM
4245 if (err)
4246 GENL_SET_ERR_MSG(info, "key addition failed");
4247 }
fffd0934 4248 wdev_unlock(dev->ieee80211_ptr);
41ade00f 4249
41ade00f
JB
4250 return err;
4251}
4252
4253static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
4254{
4c476991 4255 struct cfg80211_registered_device *rdev = info->user_ptr[0];
41ade00f 4256 int err;
4c476991 4257 struct net_device *dev = info->user_ptr[1];
41ade00f 4258 u8 *mac_addr = NULL;
b9454e83 4259 struct key_parse key;
41ade00f 4260
b9454e83
JB
4261 err = nl80211_parse_key(info, &key);
4262 if (err)
4263 return err;
41ade00f 4264
3dc289f8
AT
4265 if (key.idx < 0)
4266 return -EINVAL;
4267
41ade00f
JB
4268 if (info->attrs[NL80211_ATTR_MAC])
4269 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4270
e31b8213
JB
4271 if (key.type == -1) {
4272 if (mac_addr)
4273 key.type = NL80211_KEYTYPE_PAIRWISE;
4274 else
4275 key.type = NL80211_KEYTYPE_GROUP;
4276 }
4277
4278 /* for now */
4279 if (key.type != NL80211_KEYTYPE_PAIRWISE &&
4280 key.type != NL80211_KEYTYPE_GROUP)
4281 return -EINVAL;
4282
4c476991
JB
4283 if (!rdev->ops->del_key)
4284 return -EOPNOTSUPP;
41ade00f 4285
fffd0934
JB
4286 wdev_lock(dev->ieee80211_ptr);
4287 err = nl80211_key_allowed(dev->ieee80211_ptr);
e31b8213 4288
0fa7b391 4289 if (key.type == NL80211_KEYTYPE_GROUP && mac_addr &&
e31b8213
JB
4290 !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
4291 err = -ENOENT;
4292
fffd0934 4293 if (!err)
e35e4d28
HG
4294 err = rdev_del_key(rdev, dev, key.idx,
4295 key.type == NL80211_KEYTYPE_PAIRWISE,
4296 mac_addr);
41ade00f 4297
3d23e349 4298#ifdef CONFIG_CFG80211_WEXT
08645126 4299 if (!err) {
b9454e83 4300 if (key.idx == dev->ieee80211_ptr->wext.default_key)
08645126 4301 dev->ieee80211_ptr->wext.default_key = -1;
b9454e83 4302 else if (key.idx == dev->ieee80211_ptr->wext.default_mgmt_key)
08645126
JB
4303 dev->ieee80211_ptr->wext.default_mgmt_key = -1;
4304 }
4305#endif
fffd0934 4306 wdev_unlock(dev->ieee80211_ptr);
08645126 4307
41ade00f
JB
4308 return err;
4309}
4310
77765eaf
VT
4311/* This function returns an error or the number of nested attributes */
4312static int validate_acl_mac_addrs(struct nlattr *nl_attr)
4313{
4314 struct nlattr *attr;
4315 int n_entries = 0, tmp;
4316
4317 nla_for_each_nested(attr, nl_attr, tmp) {
4318 if (nla_len(attr) != ETH_ALEN)
4319 return -EINVAL;
4320
4321 n_entries++;
4322 }
4323
4324 return n_entries;
4325}
4326
4327/*
4328 * This function parses ACL information and allocates memory for ACL data.
4329 * On successful return, the calling function is responsible to free the
4330 * ACL buffer returned by this function.
4331 */
4332static struct cfg80211_acl_data *parse_acl_data(struct wiphy *wiphy,
4333 struct genl_info *info)
4334{
4335 enum nl80211_acl_policy acl_policy;
4336 struct nlattr *attr;
4337 struct cfg80211_acl_data *acl;
4338 int i = 0, n_entries, tmp;
4339
4340 if (!wiphy->max_acl_mac_addrs)
4341 return ERR_PTR(-EOPNOTSUPP);
4342
4343 if (!info->attrs[NL80211_ATTR_ACL_POLICY])
4344 return ERR_PTR(-EINVAL);
4345
4346 acl_policy = nla_get_u32(info->attrs[NL80211_ATTR_ACL_POLICY]);
4347 if (acl_policy != NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED &&
4348 acl_policy != NL80211_ACL_POLICY_DENY_UNLESS_LISTED)
4349 return ERR_PTR(-EINVAL);
4350
4351 if (!info->attrs[NL80211_ATTR_MAC_ADDRS])
4352 return ERR_PTR(-EINVAL);
4353
4354 n_entries = validate_acl_mac_addrs(info->attrs[NL80211_ATTR_MAC_ADDRS]);
4355 if (n_entries < 0)
4356 return ERR_PTR(n_entries);
4357
4358 if (n_entries > wiphy->max_acl_mac_addrs)
4359 return ERR_PTR(-ENOTSUPP);
4360
391d132c 4361 acl = kzalloc(struct_size(acl, mac_addrs, n_entries), GFP_KERNEL);
77765eaf
VT
4362 if (!acl)
4363 return ERR_PTR(-ENOMEM);
4364
4365 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_MAC_ADDRS], tmp) {
4366 memcpy(acl->mac_addrs[i].addr, nla_data(attr), ETH_ALEN);
4367 i++;
4368 }
4369
4370 acl->n_acl_entries = n_entries;
4371 acl->acl_policy = acl_policy;
4372
4373 return acl;
4374}
4375
4376static int nl80211_set_mac_acl(struct sk_buff *skb, struct genl_info *info)
4377{
4378 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4379 struct net_device *dev = info->user_ptr[1];
4380 struct cfg80211_acl_data *acl;
4381 int err;
4382
4383 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
4384 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
4385 return -EOPNOTSUPP;
4386
4387 if (!dev->ieee80211_ptr->beacon_interval)
4388 return -EINVAL;
4389
4390 acl = parse_acl_data(&rdev->wiphy, info);
4391 if (IS_ERR(acl))
4392 return PTR_ERR(acl);
4393
4394 err = rdev_set_mac_acl(rdev, dev, acl);
4395
4396 kfree(acl);
4397
4398 return err;
4399}
4400
a7c7fbff
PK
4401static u32 rateset_to_mask(struct ieee80211_supported_band *sband,
4402 u8 *rates, u8 rates_len)
4403{
4404 u8 i;
4405 u32 mask = 0;
4406
4407 for (i = 0; i < rates_len; i++) {
4408 int rate = (rates[i] & 0x7f) * 5;
4409 int ridx;
4410
4411 for (ridx = 0; ridx < sband->n_bitrates; ridx++) {
4412 struct ieee80211_rate *srate =
4413 &sband->bitrates[ridx];
4414 if (rate == srate->bitrate) {
4415 mask |= 1 << ridx;
4416 break;
4417 }
4418 }
4419 if (ridx == sband->n_bitrates)
4420 return 0; /* rate not found */
4421 }
4422
4423 return mask;
4424}
4425
4426static bool ht_rateset_to_mask(struct ieee80211_supported_band *sband,
4427 u8 *rates, u8 rates_len,
4428 u8 mcs[IEEE80211_HT_MCS_MASK_LEN])
4429{
4430 u8 i;
4431
4432 memset(mcs, 0, IEEE80211_HT_MCS_MASK_LEN);
4433
4434 for (i = 0; i < rates_len; i++) {
4435 int ridx, rbit;
4436
4437 ridx = rates[i] / 8;
4438 rbit = BIT(rates[i] % 8);
4439
4440 /* check validity */
4441 if ((ridx < 0) || (ridx >= IEEE80211_HT_MCS_MASK_LEN))
4442 return false;
4443
4444 /* check availability */
30fe6d50 4445 ridx = array_index_nospec(ridx, IEEE80211_HT_MCS_MASK_LEN);
a7c7fbff
PK
4446 if (sband->ht_cap.mcs.rx_mask[ridx] & rbit)
4447 mcs[ridx] |= rbit;
4448 else
4449 return false;
4450 }
4451
4452 return true;
4453}
4454
4455static u16 vht_mcs_map_to_mcs_mask(u8 vht_mcs_map)
4456{
4457 u16 mcs_mask = 0;
4458
4459 switch (vht_mcs_map) {
4460 case IEEE80211_VHT_MCS_NOT_SUPPORTED:
4461 break;
4462 case IEEE80211_VHT_MCS_SUPPORT_0_7:
4463 mcs_mask = 0x00FF;
4464 break;
4465 case IEEE80211_VHT_MCS_SUPPORT_0_8:
4466 mcs_mask = 0x01FF;
4467 break;
4468 case IEEE80211_VHT_MCS_SUPPORT_0_9:
4469 mcs_mask = 0x03FF;
4470 break;
4471 default:
4472 break;
4473 }
4474
4475 return mcs_mask;
4476}
4477
4478static void vht_build_mcs_mask(u16 vht_mcs_map,
4479 u16 vht_mcs_mask[NL80211_VHT_NSS_MAX])
4480{
4481 u8 nss;
4482
4483 for (nss = 0; nss < NL80211_VHT_NSS_MAX; nss++) {
4484 vht_mcs_mask[nss] = vht_mcs_map_to_mcs_mask(vht_mcs_map & 0x03);
4485 vht_mcs_map >>= 2;
4486 }
4487}
4488
4489static bool vht_set_mcs_mask(struct ieee80211_supported_band *sband,
4490 struct nl80211_txrate_vht *txrate,
4491 u16 mcs[NL80211_VHT_NSS_MAX])
4492{
4493 u16 tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
4494 u16 tx_mcs_mask[NL80211_VHT_NSS_MAX] = {};
4495 u8 i;
4496
4497 if (!sband->vht_cap.vht_supported)
4498 return false;
4499
4500 memset(mcs, 0, sizeof(u16) * NL80211_VHT_NSS_MAX);
4501
4502 /* Build vht_mcs_mask from VHT capabilities */
4503 vht_build_mcs_mask(tx_mcs_map, tx_mcs_mask);
4504
4505 for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
4506 if ((tx_mcs_mask[i] & txrate->mcs[i]) == txrate->mcs[i])
4507 mcs[i] = txrate->mcs[i];
4508 else
4509 return false;
4510 }
4511
4512 return true;
4513}
4514
eb89a6a6
MH
4515static u16 he_mcs_map_to_mcs_mask(u8 he_mcs_map)
4516{
4517 switch (he_mcs_map) {
4518 case IEEE80211_HE_MCS_NOT_SUPPORTED:
4519 return 0;
4520 case IEEE80211_HE_MCS_SUPPORT_0_7:
4521 return 0x00FF;
4522 case IEEE80211_HE_MCS_SUPPORT_0_9:
4523 return 0x03FF;
4524 case IEEE80211_HE_MCS_SUPPORT_0_11:
4525 return 0xFFF;
4526 default:
4527 break;
4528 }
4529 return 0;
4530}
4531
4532static void he_build_mcs_mask(u16 he_mcs_map,
4533 u16 he_mcs_mask[NL80211_HE_NSS_MAX])
4534{
4535 u8 nss;
4536
4537 for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++) {
4538 he_mcs_mask[nss] = he_mcs_map_to_mcs_mask(he_mcs_map & 0x03);
4539 he_mcs_map >>= 2;
4540 }
4541}
4542
4543static u16 he_get_txmcsmap(struct genl_info *info,
4544 const struct ieee80211_sta_he_cap *he_cap)
4545{
4546 struct net_device *dev = info->user_ptr[1];
4547 struct wireless_dev *wdev = dev->ieee80211_ptr;
4548 __le16 tx_mcs;
4549
4550 switch (wdev->chandef.width) {
4551 case NL80211_CHAN_WIDTH_80P80:
4552 tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_80p80;
4553 break;
4554 case NL80211_CHAN_WIDTH_160:
4555 tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_160;
4556 break;
4557 default:
4558 tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_80;
4559 break;
4560 }
4561 return le16_to_cpu(tx_mcs);
4562}
4563
4564static bool he_set_mcs_mask(struct genl_info *info,
4565 struct wireless_dev *wdev,
4566 struct ieee80211_supported_band *sband,
4567 struct nl80211_txrate_he *txrate,
4568 u16 mcs[NL80211_HE_NSS_MAX])
4569{
4570 const struct ieee80211_sta_he_cap *he_cap;
4571 u16 tx_mcs_mask[NL80211_HE_NSS_MAX] = {};
4572 u16 tx_mcs_map = 0;
4573 u8 i;
4574
4575 he_cap = ieee80211_get_he_iftype_cap(sband, wdev->iftype);
4576 if (!he_cap)
4577 return false;
4578
4579 memset(mcs, 0, sizeof(u16) * NL80211_HE_NSS_MAX);
4580
4581 tx_mcs_map = he_get_txmcsmap(info, he_cap);
4582
4583 /* Build he_mcs_mask from HE capabilities */
4584 he_build_mcs_mask(tx_mcs_map, tx_mcs_mask);
4585
4586 for (i = 0; i < NL80211_HE_NSS_MAX; i++) {
4587 if ((tx_mcs_mask[i] & txrate->mcs[i]) == txrate->mcs[i])
4588 mcs[i] = txrate->mcs[i];
4589 else
4590 return false;
4591 }
4592
4593 return true;
4594}
4595
a7c7fbff 4596static int nl80211_parse_tx_bitrate_mask(struct genl_info *info,
9a5f6488
TC
4597 struct nlattr *attrs[],
4598 enum nl80211_attrs attr,
eb89a6a6 4599 struct cfg80211_bitrate_mask *mask,
857b34c4
RM
4600 struct net_device *dev,
4601 bool default_all_enabled)
a7c7fbff
PK
4602{
4603 struct nlattr *tb[NL80211_TXRATE_MAX + 1];
4604 struct cfg80211_registered_device *rdev = info->user_ptr[0];
eb89a6a6 4605 struct wireless_dev *wdev = dev->ieee80211_ptr;
a7c7fbff
PK
4606 int rem, i;
4607 struct nlattr *tx_rates;
4608 struct ieee80211_supported_band *sband;
eb89a6a6 4609 u16 vht_tx_mcs_map, he_tx_mcs_map;
a7c7fbff
PK
4610
4611 memset(mask, 0, sizeof(*mask));
4612 /* Default to all rates enabled */
4613 for (i = 0; i < NUM_NL80211_BANDS; i++) {
eb89a6a6
MH
4614 const struct ieee80211_sta_he_cap *he_cap;
4615
857b34c4
RM
4616 if (!default_all_enabled)
4617 break;
4618
a7c7fbff
PK
4619 sband = rdev->wiphy.bands[i];
4620
4621 if (!sband)
4622 continue;
4623
4624 mask->control[i].legacy = (1 << sband->n_bitrates) - 1;
4625 memcpy(mask->control[i].ht_mcs,
4626 sband->ht_cap.mcs.rx_mask,
4627 sizeof(mask->control[i].ht_mcs));
4628
4629 if (!sband->vht_cap.vht_supported)
4630 continue;
4631
4632 vht_tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
4633 vht_build_mcs_mask(vht_tx_mcs_map, mask->control[i].vht_mcs);
eb89a6a6
MH
4634
4635 he_cap = ieee80211_get_he_iftype_cap(sband, wdev->iftype);
4636 if (!he_cap)
4637 continue;
4638
4639 he_tx_mcs_map = he_get_txmcsmap(info, he_cap);
4640 he_build_mcs_mask(he_tx_mcs_map, mask->control[i].he_mcs);
4641
4642 mask->control[i].he_gi = 0xFF;
4643 mask->control[i].he_ltf = 0xFF;
a7c7fbff
PK
4644 }
4645
4646 /* if no rates are given set it back to the defaults */
9a5f6488 4647 if (!attrs[attr])
a7c7fbff
PK
4648 goto out;
4649
4650 /* The nested attribute uses enum nl80211_band as the index. This maps
4651 * directly to the enum nl80211_band values used in cfg80211.
4652 */
4653 BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8);
9a5f6488 4654 nla_for_each_nested(tx_rates, attrs[attr], rem) {
a7c7fbff
PK
4655 enum nl80211_band band = nla_type(tx_rates);
4656 int err;
4657
4658 if (band < 0 || band >= NUM_NL80211_BANDS)
4659 return -EINVAL;
4660 sband = rdev->wiphy.bands[band];
4661 if (sband == NULL)
4662 return -EINVAL;
8cb08174
JB
4663 err = nla_parse_nested_deprecated(tb, NL80211_TXRATE_MAX,
4664 tx_rates,
4665 nl80211_txattr_policy,
4666 info->extack);
a7c7fbff
PK
4667 if (err)
4668 return err;
4669 if (tb[NL80211_TXRATE_LEGACY]) {
4670 mask->control[band].legacy = rateset_to_mask(
4671 sband,
4672 nla_data(tb[NL80211_TXRATE_LEGACY]),
4673 nla_len(tb[NL80211_TXRATE_LEGACY]));
4674 if ((mask->control[band].legacy == 0) &&
4675 nla_len(tb[NL80211_TXRATE_LEGACY]))
4676 return -EINVAL;
4677 }
4678 if (tb[NL80211_TXRATE_HT]) {
4679 if (!ht_rateset_to_mask(
4680 sband,
4681 nla_data(tb[NL80211_TXRATE_HT]),
4682 nla_len(tb[NL80211_TXRATE_HT]),
4683 mask->control[band].ht_mcs))
4684 return -EINVAL;
4685 }
c4a30446 4686
a7c7fbff
PK
4687 if (tb[NL80211_TXRATE_VHT]) {
4688 if (!vht_set_mcs_mask(
4689 sband,
4690 nla_data(tb[NL80211_TXRATE_VHT]),
4691 mask->control[band].vht_mcs))
4692 return -EINVAL;
4693 }
c4a30446 4694
a7c7fbff
PK
4695 if (tb[NL80211_TXRATE_GI]) {
4696 mask->control[band].gi =
4697 nla_get_u8(tb[NL80211_TXRATE_GI]);
4698 if (mask->control[band].gi > NL80211_TXRATE_FORCE_LGI)
4699 return -EINVAL;
4700 }
eb89a6a6
MH
4701 if (tb[NL80211_TXRATE_HE] &&
4702 !he_set_mcs_mask(info, wdev, sband,
4703 nla_data(tb[NL80211_TXRATE_HE]),
4704 mask->control[band].he_mcs))
4705 return -EINVAL;
c4a30446 4706
eb89a6a6
MH
4707 if (tb[NL80211_TXRATE_HE_GI])
4708 mask->control[band].he_gi =
4709 nla_get_u8(tb[NL80211_TXRATE_HE_GI]);
4710 if (tb[NL80211_TXRATE_HE_LTF])
4711 mask->control[band].he_ltf =
4712 nla_get_u8(tb[NL80211_TXRATE_HE_LTF]);
a7c7fbff
PK
4713
4714 if (mask->control[band].legacy == 0) {
eb89a6a6 4715 /* don't allow empty legacy rates if HT, VHT or HE
a7c7fbff
PK
4716 * are not even supported.
4717 */
4718 if (!(rdev->wiphy.bands[band]->ht_cap.ht_supported ||
eb89a6a6
MH
4719 rdev->wiphy.bands[band]->vht_cap.vht_supported ||
4720 ieee80211_get_he_iftype_cap(sband, wdev->iftype)))
a7c7fbff
PK
4721 return -EINVAL;
4722
4723 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
4724 if (mask->control[band].ht_mcs[i])
4725 goto out;
4726
4727 for (i = 0; i < NL80211_VHT_NSS_MAX; i++)
4728 if (mask->control[band].vht_mcs[i])
4729 goto out;
4730
eb89a6a6
MH
4731 for (i = 0; i < NL80211_HE_NSS_MAX; i++)
4732 if (mask->control[band].he_mcs[i])
4733 goto out;
4734
a7c7fbff
PK
4735 /* legacy and mcs rates may not be both empty */
4736 return -EINVAL;
4737 }
4738 }
4739
4740out:
4741 return 0;
4742}
4743
8564e382
JB
4744static int validate_beacon_tx_rate(struct cfg80211_registered_device *rdev,
4745 enum nl80211_band band,
4746 struct cfg80211_bitrate_mask *beacon_rate)
a7c7fbff 4747{
c4a30446 4748 u32 count_ht, count_vht, count_he, i;
8564e382 4749 u32 rate = beacon_rate->control[band].legacy;
a7c7fbff
PK
4750
4751 /* Allow only one rate */
4752 if (hweight32(rate) > 1)
4753 return -EINVAL;
4754
4755 count_ht = 0;
4756 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
8564e382 4757 if (hweight8(beacon_rate->control[band].ht_mcs[i]) > 1) {
a7c7fbff 4758 return -EINVAL;
8564e382 4759 } else if (beacon_rate->control[band].ht_mcs[i]) {
a7c7fbff
PK
4760 count_ht++;
4761 if (count_ht > 1)
4762 return -EINVAL;
4763 }
4764 if (count_ht && rate)
4765 return -EINVAL;
4766 }
4767
4768 count_vht = 0;
4769 for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
8564e382 4770 if (hweight16(beacon_rate->control[band].vht_mcs[i]) > 1) {
a7c7fbff 4771 return -EINVAL;
8564e382 4772 } else if (beacon_rate->control[band].vht_mcs[i]) {
a7c7fbff
PK
4773 count_vht++;
4774 if (count_vht > 1)
4775 return -EINVAL;
4776 }
4777 if (count_vht && rate)
4778 return -EINVAL;
4779 }
4780
c4a30446
RM
4781 count_he = 0;
4782 for (i = 0; i < NL80211_HE_NSS_MAX; i++) {
4783 if (hweight16(beacon_rate->control[band].he_mcs[i]) > 1) {
4784 return -EINVAL;
4785 } else if (beacon_rate->control[band].he_mcs[i]) {
4786 count_he++;
4787 if (count_he > 1)
4788 return -EINVAL;
4789 }
4790 if (count_he && rate)
4791 return -EINVAL;
4792 }
4793
4794 if ((count_ht && count_vht && count_he) ||
4795 (!rate && !count_ht && !count_vht && !count_he))
a7c7fbff
PK
4796 return -EINVAL;
4797
8564e382
JB
4798 if (rate &&
4799 !wiphy_ext_feature_isset(&rdev->wiphy,
4800 NL80211_EXT_FEATURE_BEACON_RATE_LEGACY))
4801 return -EINVAL;
4802 if (count_ht &&
4803 !wiphy_ext_feature_isset(&rdev->wiphy,
4804 NL80211_EXT_FEATURE_BEACON_RATE_HT))
4805 return -EINVAL;
4806 if (count_vht &&
4807 !wiphy_ext_feature_isset(&rdev->wiphy,
4808 NL80211_EXT_FEATURE_BEACON_RATE_VHT))
4809 return -EINVAL;
c4a30446
RM
4810 if (count_he &&
4811 !wiphy_ext_feature_isset(&rdev->wiphy,
4812 NL80211_EXT_FEATURE_BEACON_RATE_HE))
4813 return -EINVAL;
8564e382 4814
a7c7fbff
PK
4815 return 0;
4816}
4817
81e54d08
PKC
4818static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
4819 struct nlattr *attrs[],
8860020e 4820 struct cfg80211_beacon_data *bcn)
ed1b6cc7 4821{
8860020e 4822 bool haveinfo = false;
81e54d08 4823 int err;
ed1b6cc7 4824
8860020e 4825 memset(bcn, 0, sizeof(*bcn));
ed1b6cc7 4826
a1193be8
SW
4827 if (attrs[NL80211_ATTR_BEACON_HEAD]) {
4828 bcn->head = nla_data(attrs[NL80211_ATTR_BEACON_HEAD]);
4829 bcn->head_len = nla_len(attrs[NL80211_ATTR_BEACON_HEAD]);
8860020e
JB
4830 if (!bcn->head_len)
4831 return -EINVAL;
4832 haveinfo = true;
ed1b6cc7
JB
4833 }
4834
a1193be8
SW
4835 if (attrs[NL80211_ATTR_BEACON_TAIL]) {
4836 bcn->tail = nla_data(attrs[NL80211_ATTR_BEACON_TAIL]);
4837 bcn->tail_len = nla_len(attrs[NL80211_ATTR_BEACON_TAIL]);
8860020e 4838 haveinfo = true;
ed1b6cc7
JB
4839 }
4840
4c476991
JB
4841 if (!haveinfo)
4842 return -EINVAL;
3b85875a 4843
a1193be8
SW
4844 if (attrs[NL80211_ATTR_IE]) {
4845 bcn->beacon_ies = nla_data(attrs[NL80211_ATTR_IE]);
4846 bcn->beacon_ies_len = nla_len(attrs[NL80211_ATTR_IE]);
9946ecfb
JM
4847 }
4848
a1193be8 4849 if (attrs[NL80211_ATTR_IE_PROBE_RESP]) {
8860020e 4850 bcn->proberesp_ies =
a1193be8 4851 nla_data(attrs[NL80211_ATTR_IE_PROBE_RESP]);
8860020e 4852 bcn->proberesp_ies_len =
a1193be8 4853 nla_len(attrs[NL80211_ATTR_IE_PROBE_RESP]);
9946ecfb
JM
4854 }
4855
a1193be8 4856 if (attrs[NL80211_ATTR_IE_ASSOC_RESP]) {
8860020e 4857 bcn->assocresp_ies =
a1193be8 4858 nla_data(attrs[NL80211_ATTR_IE_ASSOC_RESP]);
8860020e 4859 bcn->assocresp_ies_len =
a1193be8 4860 nla_len(attrs[NL80211_ATTR_IE_ASSOC_RESP]);
9946ecfb
JM
4861 }
4862
a1193be8
SW
4863 if (attrs[NL80211_ATTR_PROBE_RESP]) {
4864 bcn->probe_resp = nla_data(attrs[NL80211_ATTR_PROBE_RESP]);
4865 bcn->probe_resp_len = nla_len(attrs[NL80211_ATTR_PROBE_RESP]);
00f740e1
AN
4866 }
4867
81e54d08
PKC
4868 if (attrs[NL80211_ATTR_FTM_RESPONDER]) {
4869 struct nlattr *tb[NL80211_FTM_RESP_ATTR_MAX + 1];
4870
8cb08174
JB
4871 err = nla_parse_nested_deprecated(tb,
4872 NL80211_FTM_RESP_ATTR_MAX,
4873 attrs[NL80211_ATTR_FTM_RESPONDER],
4874 NULL, NULL);
81e54d08
PKC
4875 if (err)
4876 return err;
4877
4878 if (tb[NL80211_FTM_RESP_ATTR_ENABLED] &&
4879 wiphy_ext_feature_isset(&rdev->wiphy,
4880 NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER))
4881 bcn->ftm_responder = 1;
4882 else
4883 return -EOPNOTSUPP;
4884
4885 if (tb[NL80211_FTM_RESP_ATTR_LCI]) {
4886 bcn->lci = nla_data(tb[NL80211_FTM_RESP_ATTR_LCI]);
4887 bcn->lci_len = nla_len(tb[NL80211_FTM_RESP_ATTR_LCI]);
4888 }
4889
4890 if (tb[NL80211_FTM_RESP_ATTR_CIVICLOC]) {
4891 bcn->civicloc = nla_data(tb[NL80211_FTM_RESP_ATTR_CIVICLOC]);
4892 bcn->civicloc_len = nla_len(tb[NL80211_FTM_RESP_ATTR_CIVICLOC]);
4893 }
4894 } else {
4895 bcn->ftm_responder = -1;
4896 }
4897
8860020e
JB
4898 return 0;
4899}
4900
796e90f4
JC
4901static int nl80211_parse_he_obss_pd(struct nlattr *attrs,
4902 struct ieee80211_he_obss_pd *he_obss_pd)
4903{
4904 struct nlattr *tb[NL80211_HE_OBSS_PD_ATTR_MAX + 1];
4905 int err;
4906
4907 err = nla_parse_nested(tb, NL80211_HE_OBSS_PD_ATTR_MAX, attrs,
4908 he_obss_pd_policy, NULL);
4909 if (err)
4910 return err;
4911
f5bec330
RM
4912 if (!tb[NL80211_HE_OBSS_PD_ATTR_SR_CTRL])
4913 return -EINVAL;
4914
4915 he_obss_pd->sr_ctrl = nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_SR_CTRL]);
4916
6c8b6e4a
RM
4917 if (tb[NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET])
4918 he_obss_pd->min_offset =
4919 nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET]);
4920 if (tb[NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET])
4921 he_obss_pd->max_offset =
4922 nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET]);
f5bec330
RM
4923 if (tb[NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET])
4924 he_obss_pd->non_srg_max_offset =
4925 nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET]);
6c8b6e4a
RM
4926
4927 if (he_obss_pd->min_offset > he_obss_pd->max_offset)
796e90f4
JC
4928 return -EINVAL;
4929
f5bec330
RM
4930 if (tb[NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP])
4931 memcpy(he_obss_pd->bss_color_bitmap,
4932 nla_data(tb[NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP]),
4933 sizeof(he_obss_pd->bss_color_bitmap));
4934
4935 if (tb[NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP])
4936 memcpy(he_obss_pd->partial_bssid_bitmap,
4937 nla_data(tb[NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP]),
4938 sizeof(he_obss_pd->partial_bssid_bitmap));
4939
796e90f4
JC
4940 he_obss_pd->enable = true;
4941
4942 return 0;
4943}
4944
5c5e52d1
JC
4945static int nl80211_parse_he_bss_color(struct nlattr *attrs,
4946 struct cfg80211_he_bss_color *he_bss_color)
4947{
4948 struct nlattr *tb[NL80211_HE_BSS_COLOR_ATTR_MAX + 1];
4949 int err;
4950
4951 err = nla_parse_nested(tb, NL80211_HE_BSS_COLOR_ATTR_MAX, attrs,
4952 he_bss_color_policy, NULL);
4953 if (err)
4954 return err;
4955
4956 if (!tb[NL80211_HE_BSS_COLOR_ATTR_COLOR])
4957 return -EINVAL;
4958
4959 he_bss_color->color =
4960 nla_get_u8(tb[NL80211_HE_BSS_COLOR_ATTR_COLOR]);
75e6b594
JB
4961 he_bss_color->enabled =
4962 !nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_DISABLED]);
5c5e52d1
JC
4963 he_bss_color->partial =
4964 nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_PARTIAL]);
4965
4966 return 0;
4967}
4968
291c49de
AD
4969static int nl80211_parse_fils_discovery(struct cfg80211_registered_device *rdev,
4970 struct nlattr *attrs,
4971 struct cfg80211_ap_settings *params)
4972{
4973 struct nlattr *tb[NL80211_FILS_DISCOVERY_ATTR_MAX + 1];
4974 int ret;
4975 struct cfg80211_fils_discovery *fd = &params->fils_discovery;
4976
4977 if (!wiphy_ext_feature_isset(&rdev->wiphy,
4978 NL80211_EXT_FEATURE_FILS_DISCOVERY))
4979 return -EINVAL;
4980
4981 ret = nla_parse_nested(tb, NL80211_FILS_DISCOVERY_ATTR_MAX, attrs,
4982 NULL, NULL);
4983 if (ret)
4984 return ret;
4985
4986 if (!tb[NL80211_FILS_DISCOVERY_ATTR_INT_MIN] ||
4987 !tb[NL80211_FILS_DISCOVERY_ATTR_INT_MAX] ||
4988 !tb[NL80211_FILS_DISCOVERY_ATTR_TMPL])
4989 return -EINVAL;
4990
4991 fd->tmpl_len = nla_len(tb[NL80211_FILS_DISCOVERY_ATTR_TMPL]);
4992 fd->tmpl = nla_data(tb[NL80211_FILS_DISCOVERY_ATTR_TMPL]);
4993 fd->min_interval = nla_get_u32(tb[NL80211_FILS_DISCOVERY_ATTR_INT_MIN]);
4994 fd->max_interval = nla_get_u32(tb[NL80211_FILS_DISCOVERY_ATTR_INT_MAX]);
4995
4996 return 0;
4997}
4998
7443dcd1
AD
4999static int
5000nl80211_parse_unsol_bcast_probe_resp(struct cfg80211_registered_device *rdev,
5001 struct nlattr *attrs,
5002 struct cfg80211_ap_settings *params)
5003{
5004 struct nlattr *tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX + 1];
5005 int ret;
5006 struct cfg80211_unsol_bcast_probe_resp *presp =
5007 &params->unsol_bcast_probe_resp;
5008
5009 if (!wiphy_ext_feature_isset(&rdev->wiphy,
5010 NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP))
5011 return -EINVAL;
5012
5013 ret = nla_parse_nested(tb, NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX,
5014 attrs, NULL, NULL);
5015 if (ret)
5016 return ret;
5017
5018 if (!tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT] ||
5019 !tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL])
5020 return -EINVAL;
5021
5022 presp->tmpl = nla_data(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL]);
5023 presp->tmpl_len = nla_len(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL]);
5024 presp->interval = nla_get_u32(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT]);
5025 return 0;
5026}
5027
66cd794e
JB
5028static void nl80211_check_ap_rate_selectors(struct cfg80211_ap_settings *params,
5029 const u8 *rates)
5030{
5031 int i;
5032
5033 if (!rates)
5034 return;
5035
5036 for (i = 0; i < rates[1]; i++) {
5037 if (rates[2 + i] == BSS_MEMBERSHIP_SELECTOR_HT_PHY)
5038 params->ht_required = true;
5039 if (rates[2 + i] == BSS_MEMBERSHIP_SELECTOR_VHT_PHY)
5040 params->vht_required = true;
2a392596
IP
5041 if (rates[2 + i] == BSS_MEMBERSHIP_SELECTOR_HE_PHY)
5042 params->he_required = true;
66cd794e
JB
5043 }
5044}
5045
5046/*
5047 * Since the nl80211 API didn't include, from the beginning, attributes about
5048 * HT/VHT requirements/capabilities, we parse them out of the IEs for the
5049 * benefit of drivers that rebuild IEs in the firmware.
5050 */
5051static void nl80211_calculate_ap_params(struct cfg80211_ap_settings *params)
5052{
5053 const struct cfg80211_beacon_data *bcn = &params->beacon;
ba83bfb1
IM
5054 size_t ies_len = bcn->tail_len;
5055 const u8 *ies = bcn->tail;
66cd794e
JB
5056 const u8 *rates;
5057 const u8 *cap;
5058
5059 rates = cfg80211_find_ie(WLAN_EID_SUPP_RATES, ies, ies_len);
5060 nl80211_check_ap_rate_selectors(params, rates);
5061
5062 rates = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, ies, ies_len);
5063 nl80211_check_ap_rate_selectors(params, rates);
5064
5065 cap = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies, ies_len);
5066 if (cap && cap[1] >= sizeof(*params->ht_cap))
5067 params->ht_cap = (void *)(cap + 2);
5068 cap = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, ies, ies_len);
5069 if (cap && cap[1] >= sizeof(*params->vht_cap))
5070 params->vht_cap = (void *)(cap + 2);
244eb9ae
ST
5071 cap = cfg80211_find_ext_ie(WLAN_EID_EXT_HE_CAPABILITY, ies, ies_len);
5072 if (cap && cap[1] >= sizeof(*params->he_cap) + 1)
5073 params->he_cap = (void *)(cap + 3);
7e8d6f12
ST
5074 cap = cfg80211_find_ext_ie(WLAN_EID_EXT_HE_OPERATION, ies, ies_len);
5075 if (cap && cap[1] >= sizeof(*params->he_oper) + 1)
5076 params->he_oper = (void *)(cap + 3);
66cd794e
JB
5077}
5078
46c1dd0c
FF
5079static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
5080 struct cfg80211_ap_settings *params)
5081{
5082 struct wireless_dev *wdev;
5083 bool ret = false;
5084
53873f13 5085 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
46c1dd0c
FF
5086 if (wdev->iftype != NL80211_IFTYPE_AP &&
5087 wdev->iftype != NL80211_IFTYPE_P2P_GO)
5088 continue;
5089
683b6d3b 5090 if (!wdev->preset_chandef.chan)
46c1dd0c
FF
5091 continue;
5092
683b6d3b 5093 params->chandef = wdev->preset_chandef;
46c1dd0c
FF
5094 ret = true;
5095 break;
5096 }
5097
46c1dd0c
FF
5098 return ret;
5099}
5100
e39e5b5e
JM
5101static bool nl80211_valid_auth_type(struct cfg80211_registered_device *rdev,
5102 enum nl80211_auth_type auth_type,
5103 enum nl80211_commands cmd)
5104{
5105 if (auth_type > NL80211_AUTHTYPE_MAX)
5106 return false;
5107
5108 switch (cmd) {
5109 case NL80211_CMD_AUTHENTICATE:
5110 if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) &&
5111 auth_type == NL80211_AUTHTYPE_SAE)
5112 return false;
63181060
JM
5113 if (!wiphy_ext_feature_isset(&rdev->wiphy,
5114 NL80211_EXT_FEATURE_FILS_STA) &&
5115 (auth_type == NL80211_AUTHTYPE_FILS_SK ||
5116 auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
5117 auth_type == NL80211_AUTHTYPE_FILS_PK))
5118 return false;
e39e5b5e
JM
5119 return true;
5120 case NL80211_CMD_CONNECT:
10773a7c 5121 if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) &&
26f7044e
CHH
5122 !wiphy_ext_feature_isset(&rdev->wiphy,
5123 NL80211_EXT_FEATURE_SAE_OFFLOAD) &&
10773a7c 5124 auth_type == NL80211_AUTHTYPE_SAE)
a3caf744 5125 return false;
10773a7c 5126
a3caf744
VK
5127 /* FILS with SK PFS or PK not supported yet */
5128 if (auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
5129 auth_type == NL80211_AUTHTYPE_FILS_PK)
5130 return false;
5131 if (!wiphy_ext_feature_isset(
5132 &rdev->wiphy,
5133 NL80211_EXT_FEATURE_FILS_SK_OFFLOAD) &&
5134 auth_type == NL80211_AUTHTYPE_FILS_SK)
5135 return false;
5136 return true;
e39e5b5e 5137 case NL80211_CMD_START_AP:
2831a631
CHH
5138 if (!wiphy_ext_feature_isset(&rdev->wiphy,
5139 NL80211_EXT_FEATURE_SAE_OFFLOAD_AP) &&
5140 auth_type == NL80211_AUTHTYPE_SAE)
e39e5b5e 5141 return false;
63181060
JM
5142 /* FILS not supported yet */
5143 if (auth_type == NL80211_AUTHTYPE_FILS_SK ||
5144 auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
5145 auth_type == NL80211_AUTHTYPE_FILS_PK)
5146 return false;
e39e5b5e
JM
5147 return true;
5148 default:
5149 return false;
5150 }
5151}
5152
8860020e
JB
5153static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
5154{
5155 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5156 struct net_device *dev = info->user_ptr[1];
5157 struct wireless_dev *wdev = dev->ieee80211_ptr;
5158 struct cfg80211_ap_settings params;
5159 int err;
5160
5161 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
5162 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
5163 return -EOPNOTSUPP;
5164
5165 if (!rdev->ops->start_ap)
5166 return -EOPNOTSUPP;
5167
5168 if (wdev->beacon_interval)
5169 return -EALREADY;
5170
5171 memset(&params, 0, sizeof(params));
5172
5173 /* these are required for START_AP */
5174 if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
5175 !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
5176 !info->attrs[NL80211_ATTR_BEACON_HEAD])
5177 return -EINVAL;
5178
81e54d08 5179 err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon);
8860020e
JB
5180 if (err)
5181 return err;
5182
5183 params.beacon_interval =
5184 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
5185 params.dtim_period =
5186 nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
5187
0c317a02
PK
5188 err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype,
5189 params.beacon_interval);
8860020e
JB
5190 if (err)
5191 return err;
5192
5193 /*
5194 * In theory, some of these attributes should be required here
5195 * but since they were not used when the command was originally
5196 * added, keep them optional for old user space programs to let
5197 * them continue to work with drivers that do not need the
5198 * additional information -- drivers must check!
5199 */
5200 if (info->attrs[NL80211_ATTR_SSID]) {
5201 params.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
5202 params.ssid_len =
5203 nla_len(info->attrs[NL80211_ATTR_SSID]);
cb9abd48 5204 if (params.ssid_len == 0)
8860020e
JB
5205 return -EINVAL;
5206 }
5207
ab0d76f6 5208 if (info->attrs[NL80211_ATTR_HIDDEN_SSID])
8860020e
JB
5209 params.hidden_ssid = nla_get_u32(
5210 info->attrs[NL80211_ATTR_HIDDEN_SSID]);
8860020e
JB
5211
5212 params.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
5213
5214 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
5215 params.auth_type = nla_get_u32(
5216 info->attrs[NL80211_ATTR_AUTH_TYPE]);
e39e5b5e
JM
5217 if (!nl80211_valid_auth_type(rdev, params.auth_type,
5218 NL80211_CMD_START_AP))
8860020e
JB
5219 return -EINVAL;
5220 } else
5221 params.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
5222
5223 err = nl80211_crypto_settings(rdev, info, &params.crypto,
5224 NL80211_MAX_NR_CIPHER_SUITES);
5225 if (err)
5226 return err;
5227
1b658f11
VT
5228 if (info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]) {
5229 if (!(rdev->wiphy.features & NL80211_FEATURE_INACTIVITY_TIMER))
5230 return -EOPNOTSUPP;
5231 params.inactivity_timeout = nla_get_u16(
5232 info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
5233 }
5234
53cabad7
JB
5235 if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
5236 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
5237 return -EINVAL;
5238 params.p2p_ctwindow =
5239 nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
53cabad7
JB
5240 if (params.p2p_ctwindow != 0 &&
5241 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
5242 return -EINVAL;
5243 }
5244
5245 if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
5246 u8 tmp;
5247
5248 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
5249 return -EINVAL;
5250 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
53cabad7
JB
5251 params.p2p_opp_ps = tmp;
5252 if (params.p2p_opp_ps != 0 &&
5253 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
5254 return -EINVAL;
5255 }
5256
aa430da4 5257 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
683b6d3b
JB
5258 err = nl80211_parse_chandef(rdev, info, &params.chandef);
5259 if (err)
5260 return err;
5261 } else if (wdev->preset_chandef.chan) {
5262 params.chandef = wdev->preset_chandef;
46c1dd0c 5263 } else if (!nl80211_get_ap_channel(rdev, &params))
aa430da4
JB
5264 return -EINVAL;
5265
923b352f
AN
5266 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params.chandef,
5267 wdev->iftype))
aa430da4
JB
5268 return -EINVAL;
5269
a7c7fbff 5270 if (info->attrs[NL80211_ATTR_TX_RATES]) {
9a5f6488
TC
5271 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
5272 NL80211_ATTR_TX_RATES,
eb89a6a6 5273 &params.beacon_rate,
857b34c4 5274 dev, false);
a7c7fbff
PK
5275 if (err)
5276 return err;
5277
8564e382
JB
5278 err = validate_beacon_tx_rate(rdev, params.chandef.chan->band,
5279 &params.beacon_rate);
a7c7fbff
PK
5280 if (err)
5281 return err;
5282 }
5283
18998c38
EP
5284 if (info->attrs[NL80211_ATTR_SMPS_MODE]) {
5285 params.smps_mode =
5286 nla_get_u8(info->attrs[NL80211_ATTR_SMPS_MODE]);
5287 switch (params.smps_mode) {
5288 case NL80211_SMPS_OFF:
5289 break;
5290 case NL80211_SMPS_STATIC:
5291 if (!(rdev->wiphy.features &
5292 NL80211_FEATURE_STATIC_SMPS))
5293 return -EINVAL;
5294 break;
5295 case NL80211_SMPS_DYNAMIC:
5296 if (!(rdev->wiphy.features &
5297 NL80211_FEATURE_DYNAMIC_SMPS))
5298 return -EINVAL;
5299 break;
5300 default:
5301 return -EINVAL;
5302 }
5303 } else {
5304 params.smps_mode = NL80211_SMPS_OFF;
5305 }
5306
6e8ef842
PK
5307 params.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
5308 if (params.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ])
5309 return -EOPNOTSUPP;
5310
4baf6bea
OO
5311 if (info->attrs[NL80211_ATTR_ACL_POLICY]) {
5312 params.acl = parse_acl_data(&rdev->wiphy, info);
5313 if (IS_ERR(params.acl))
5314 return PTR_ERR(params.acl);
5315 }
5316
a0de1ca3
JC
5317 params.twt_responder =
5318 nla_get_flag(info->attrs[NL80211_ATTR_TWT_RESPONDER]);
5319
796e90f4
JC
5320 if (info->attrs[NL80211_ATTR_HE_OBSS_PD]) {
5321 err = nl80211_parse_he_obss_pd(
5322 info->attrs[NL80211_ATTR_HE_OBSS_PD],
5323 &params.he_obss_pd);
bc7a39b4
LC
5324 if (err)
5325 goto out;
796e90f4
JC
5326 }
5327
5c5e52d1
JC
5328 if (info->attrs[NL80211_ATTR_HE_BSS_COLOR]) {
5329 err = nl80211_parse_he_bss_color(
5330 info->attrs[NL80211_ATTR_HE_BSS_COLOR],
5331 &params.he_bss_color);
5332 if (err)
60a0121f 5333 goto out;
5c5e52d1
JC
5334 }
5335
291c49de
AD
5336 if (info->attrs[NL80211_ATTR_FILS_DISCOVERY]) {
5337 err = nl80211_parse_fils_discovery(rdev,
5338 info->attrs[NL80211_ATTR_FILS_DISCOVERY],
5339 &params);
5340 if (err)
5341 goto out;
5342 }
5343
7443dcd1
AD
5344 if (info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP]) {
5345 err = nl80211_parse_unsol_bcast_probe_resp(
5346 rdev, info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP],
5347 &params);
5348 if (err)
5349 return err;
5350 }
5351
66cd794e
JB
5352 nl80211_calculate_ap_params(&params);
5353
fe494370
SD
5354 if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
5355 params.flags |= AP_SETTINGS_EXTERNAL_AUTH_SUPPORT;
5356
c56589ed 5357 wdev_lock(wdev);
e35e4d28 5358 err = rdev_start_ap(rdev, dev, &params);
46c1dd0c 5359 if (!err) {
683b6d3b 5360 wdev->preset_chandef = params.chandef;
8860020e 5361 wdev->beacon_interval = params.beacon_interval;
9e0e2961 5362 wdev->chandef = params.chandef;
06e191e2
AQ
5363 wdev->ssid_len = params.ssid_len;
5364 memcpy(wdev->ssid, params.ssid, wdev->ssid_len);
466a3061
DK
5365
5366 if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
5367 wdev->conn_owner_nlportid = info->snd_portid;
46c1dd0c 5368 }
c56589ed 5369 wdev_unlock(wdev);
77765eaf 5370
9951ebfc 5371out:
77765eaf
VT
5372 kfree(params.acl);
5373
56d1893d 5374 return err;
ed1b6cc7
JB
5375}
5376
8860020e
JB
5377static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info)
5378{
5379 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5380 struct net_device *dev = info->user_ptr[1];
5381 struct wireless_dev *wdev = dev->ieee80211_ptr;
5382 struct cfg80211_beacon_data params;
5383 int err;
5384
5385 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
5386 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
5387 return -EOPNOTSUPP;
5388
5389 if (!rdev->ops->change_beacon)
5390 return -EOPNOTSUPP;
5391
5392 if (!wdev->beacon_interval)
5393 return -EINVAL;
5394
81e54d08 5395 err = nl80211_parse_beacon(rdev, info->attrs, &params);
8860020e
JB
5396 if (err)
5397 return err;
5398
c56589ed
SW
5399 wdev_lock(wdev);
5400 err = rdev_change_beacon(rdev, dev, &params);
5401 wdev_unlock(wdev);
5402
5403 return err;
8860020e
JB
5404}
5405
5406static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info)
ed1b6cc7 5407{
4c476991
JB
5408 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5409 struct net_device *dev = info->user_ptr[1];
ed1b6cc7 5410
7c8d5e03 5411 return cfg80211_stop_ap(rdev, dev, false);
ed1b6cc7
JB
5412}
5413
5727ef1b
JB
5414static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
5415 [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG },
5416 [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG },
5417 [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG },
0e46724a 5418 [NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG },
b39c48fa 5419 [NL80211_STA_FLAG_AUTHENTICATED] = { .type = NLA_FLAG },
d83023da 5420 [NL80211_STA_FLAG_TDLS_PEER] = { .type = NLA_FLAG },
5727ef1b
JB
5421};
5422
eccb8e8f 5423static int parse_station_flags(struct genl_info *info,
bdd3ae3d 5424 enum nl80211_iftype iftype,
eccb8e8f 5425 struct station_parameters *params)
5727ef1b
JB
5426{
5427 struct nlattr *flags[NL80211_STA_FLAG_MAX + 1];
eccb8e8f 5428 struct nlattr *nla;
5727ef1b
JB
5429 int flag;
5430
eccb8e8f
JB
5431 /*
5432 * Try parsing the new attribute first so userspace
5433 * can specify both for older kernels.
5434 */
5435 nla = info->attrs[NL80211_ATTR_STA_FLAGS2];
5436 if (nla) {
5437 struct nl80211_sta_flag_update *sta_flags;
5438
5439 sta_flags = nla_data(nla);
5440 params->sta_flags_mask = sta_flags->mask;
5441 params->sta_flags_set = sta_flags->set;
77ee7c89 5442 params->sta_flags_set &= params->sta_flags_mask;
eccb8e8f
JB
5443 if ((params->sta_flags_mask |
5444 params->sta_flags_set) & BIT(__NL80211_STA_FLAG_INVALID))
5445 return -EINVAL;
5446 return 0;
5447 }
5448
5449 /* if present, parse the old attribute */
5727ef1b 5450
eccb8e8f 5451 nla = info->attrs[NL80211_ATTR_STA_FLAGS];
5727ef1b
JB
5452 if (!nla)
5453 return 0;
5454
8cb08174 5455 if (nla_parse_nested_deprecated(flags, NL80211_STA_FLAG_MAX, nla, sta_flags_policy, info->extack))
5727ef1b
JB
5456 return -EINVAL;
5457
bdd3ae3d
JB
5458 /*
5459 * Only allow certain flags for interface types so that
5460 * other attributes are silently ignored. Remember that
5461 * this is backward compatibility code with old userspace
5462 * and shouldn't be hit in other cases anyway.
5463 */
5464 switch (iftype) {
5465 case NL80211_IFTYPE_AP:
5466 case NL80211_IFTYPE_AP_VLAN:
5467 case NL80211_IFTYPE_P2P_GO:
5468 params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
5469 BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
5470 BIT(NL80211_STA_FLAG_WME) |
5471 BIT(NL80211_STA_FLAG_MFP);
5472 break;
5473 case NL80211_IFTYPE_P2P_CLIENT:
5474 case NL80211_IFTYPE_STATION:
5475 params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
5476 BIT(NL80211_STA_FLAG_TDLS_PEER);
5477 break;
5478 case NL80211_IFTYPE_MESH_POINT:
5479 params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHENTICATED) |
5480 BIT(NL80211_STA_FLAG_MFP) |
5481 BIT(NL80211_STA_FLAG_AUTHORIZED);
5cf3006c 5482 break;
bdd3ae3d
JB
5483 default:
5484 return -EINVAL;
5485 }
5727ef1b 5486
3383b5a6
JB
5487 for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++) {
5488 if (flags[flag]) {
eccb8e8f 5489 params->sta_flags_set |= (1<<flag);
5727ef1b 5490
3383b5a6
JB
5491 /* no longer support new API additions in old API */
5492 if (flag > NL80211_STA_FLAG_MAX_OLD_API)
5493 return -EINVAL;
5494 }
5495 }
5496
5727ef1b
JB
5497 return 0;
5498}
5499
9bb7e0f2 5500bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr)
c8dcfd8a
FF
5501{
5502 struct nlattr *rate;
8eb41c8d
VK
5503 u32 bitrate;
5504 u16 bitrate_compat;
bbf67e45 5505 enum nl80211_rate_info rate_flg;
c8dcfd8a 5506
ae0be8de 5507 rate = nla_nest_start_noflag(msg, attr);
c8dcfd8a 5508 if (!rate)
db9c64cf 5509 return false;
c8dcfd8a
FF
5510
5511 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
5512 bitrate = cfg80211_calculate_bitrate(info);
8eb41c8d
VK
5513 /* report 16-bit bitrate only if we can */
5514 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
db9c64cf
JB
5515 if (bitrate > 0 &&
5516 nla_put_u32(msg, NL80211_RATE_INFO_BITRATE32, bitrate))
5517 return false;
5518 if (bitrate_compat > 0 &&
5519 nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat))
5520 return false;
5521
b51f3bee
JB
5522 switch (info->bw) {
5523 case RATE_INFO_BW_5:
5524 rate_flg = NL80211_RATE_INFO_5_MHZ_WIDTH;
5525 break;
5526 case RATE_INFO_BW_10:
5527 rate_flg = NL80211_RATE_INFO_10_MHZ_WIDTH;
5528 break;
5529 default:
5530 WARN_ON(1);
7b506ff6 5531 fallthrough;
b51f3bee
JB
5532 case RATE_INFO_BW_20:
5533 rate_flg = 0;
5534 break;
5535 case RATE_INFO_BW_40:
5536 rate_flg = NL80211_RATE_INFO_40_MHZ_WIDTH;
5537 break;
5538 case RATE_INFO_BW_80:
5539 rate_flg = NL80211_RATE_INFO_80_MHZ_WIDTH;
5540 break;
5541 case RATE_INFO_BW_160:
5542 rate_flg = NL80211_RATE_INFO_160_MHZ_WIDTH;
5543 break;
c4cbaf79
LC
5544 case RATE_INFO_BW_HE_RU:
5545 rate_flg = 0;
5546 WARN_ON(!(info->flags & RATE_INFO_FLAGS_HE_MCS));
b51f3bee
JB
5547 }
5548
5549 if (rate_flg && nla_put_flag(msg, rate_flg))
5550 return false;
5551
db9c64cf
JB
5552 if (info->flags & RATE_INFO_FLAGS_MCS) {
5553 if (nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs))
5554 return false;
db9c64cf
JB
5555 if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
5556 nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
5557 return false;
5558 } else if (info->flags & RATE_INFO_FLAGS_VHT_MCS) {
5559 if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_MCS, info->mcs))
5560 return false;
5561 if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_NSS, info->nss))
5562 return false;
db9c64cf
JB
5563 if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
5564 nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
5565 return false;
c4cbaf79
LC
5566 } else if (info->flags & RATE_INFO_FLAGS_HE_MCS) {
5567 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_MCS, info->mcs))
5568 return false;
5569 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_NSS, info->nss))
5570 return false;
5571 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_GI, info->he_gi))
5572 return false;
5573 if (nla_put_u8(msg, NL80211_RATE_INFO_HE_DCM, info->he_dcm))
5574 return false;
5575 if (info->bw == RATE_INFO_BW_HE_RU &&
5576 nla_put_u8(msg, NL80211_RATE_INFO_HE_RU_ALLOC,
5577 info->he_ru_alloc))
5578 return false;
db9c64cf 5579 }
c8dcfd8a
FF
5580
5581 nla_nest_end(msg, rate);
5582 return true;
c8dcfd8a
FF
5583}
5584
119363c7
FF
5585static bool nl80211_put_signal(struct sk_buff *msg, u8 mask, s8 *signal,
5586 int id)
5587{
5588 void *attr;
5589 int i = 0;
5590
5591 if (!mask)
5592 return true;
5593
ae0be8de 5594 attr = nla_nest_start_noflag(msg, id);
119363c7
FF
5595 if (!attr)
5596 return false;
5597
5598 for (i = 0; i < IEEE80211_MAX_CHAINS; i++) {
5599 if (!(mask & BIT(i)))
5600 continue;
5601
5602 if (nla_put_u8(msg, i, signal[i]))
5603 return false;
5604 }
5605
5606 nla_nest_end(msg, attr);
5607
5608 return true;
5609}
5610
cf5ead82
JB
5611static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
5612 u32 seq, int flags,
66266b3a
JL
5613 struct cfg80211_registered_device *rdev,
5614 struct net_device *dev,
98b62183 5615 const u8 *mac_addr, struct station_info *sinfo)
fd5b74dc
JB
5616{
5617 void *hdr;
f4263c98 5618 struct nlattr *sinfoattr, *bss_param;
fd5b74dc 5619
cf5ead82 5620 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
f77bf486
AS
5621 if (!hdr) {
5622 cfg80211_sinfo_release_content(sinfo);
fd5b74dc 5623 return -1;
f77bf486 5624 }
fd5b74dc 5625
9360ffd1
DM
5626 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
5627 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) ||
5628 nla_put_u32(msg, NL80211_ATTR_GENERATION, sinfo->generation))
5629 goto nla_put_failure;
f5ea9120 5630
ae0be8de 5631 sinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_STA_INFO);
2ec600d6 5632 if (!sinfoattr)
fd5b74dc 5633 goto nla_put_failure;
319090bf
JB
5634
5635#define PUT_SINFO(attr, memb, type) do { \
d686b920 5636 BUILD_BUG_ON(sizeof(type) == sizeof(u64)); \
397c657a 5637 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
319090bf
JB
5638 nla_put_ ## type(msg, NL80211_STA_INFO_ ## attr, \
5639 sinfo->memb)) \
5640 goto nla_put_failure; \
5641 } while (0)
d686b920 5642#define PUT_SINFO_U64(attr, memb) do { \
397c657a 5643 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
d686b920
JB
5644 nla_put_u64_64bit(msg, NL80211_STA_INFO_ ## attr, \
5645 sinfo->memb, NL80211_STA_INFO_PAD)) \
5646 goto nla_put_failure; \
5647 } while (0)
319090bf
JB
5648
5649 PUT_SINFO(CONNECTED_TIME, connected_time, u32);
5650 PUT_SINFO(INACTIVE_TIME, inactive_time, u32);
6c7a0033 5651 PUT_SINFO_U64(ASSOC_AT_BOOTTIME, assoc_at);
319090bf 5652
397c657a
OE
5653 if (sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES) |
5654 BIT_ULL(NL80211_STA_INFO_RX_BYTES64)) &&
9360ffd1 5655 nla_put_u32(msg, NL80211_STA_INFO_RX_BYTES,
42745e03 5656 (u32)sinfo->rx_bytes))
9360ffd1 5657 goto nla_put_failure;
319090bf 5658
397c657a
OE
5659 if (sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES) |
5660 BIT_ULL(NL80211_STA_INFO_TX_BYTES64)) &&
9360ffd1 5661 nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES,
42745e03
VK
5662 (u32)sinfo->tx_bytes))
5663 goto nla_put_failure;
319090bf 5664
d686b920
JB
5665 PUT_SINFO_U64(RX_BYTES64, rx_bytes);
5666 PUT_SINFO_U64(TX_BYTES64, tx_bytes);
319090bf
JB
5667 PUT_SINFO(LLID, llid, u16);
5668 PUT_SINFO(PLID, plid, u16);
5669 PUT_SINFO(PLINK_STATE, plink_state, u8);
d686b920 5670 PUT_SINFO_U64(RX_DURATION, rx_duration);
36647055
THJ
5671 PUT_SINFO_U64(TX_DURATION, tx_duration);
5672
5673 if (wiphy_ext_feature_isset(&rdev->wiphy,
5674 NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
5675 PUT_SINFO(AIRTIME_WEIGHT, airtime_weight, u16);
319090bf 5676
66266b3a
JL
5677 switch (rdev->wiphy.signal_type) {
5678 case CFG80211_SIGNAL_TYPE_MBM:
319090bf
JB
5679 PUT_SINFO(SIGNAL, signal, u8);
5680 PUT_SINFO(SIGNAL_AVG, signal_avg, u8);
66266b3a
JL
5681 break;
5682 default:
5683 break;
5684 }
397c657a 5685 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) {
119363c7
FF
5686 if (!nl80211_put_signal(msg, sinfo->chains,
5687 sinfo->chain_signal,
5688 NL80211_STA_INFO_CHAIN_SIGNAL))
5689 goto nla_put_failure;
5690 }
397c657a 5691 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) {
119363c7
FF
5692 if (!nl80211_put_signal(msg, sinfo->chains,
5693 sinfo->chain_signal_avg,
5694 NL80211_STA_INFO_CHAIN_SIGNAL_AVG))
5695 goto nla_put_failure;
5696 }
397c657a 5697 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) {
c8dcfd8a
FF
5698 if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
5699 NL80211_STA_INFO_TX_BITRATE))
5700 goto nla_put_failure;
5701 }
397c657a 5702 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) {
c8dcfd8a
FF
5703 if (!nl80211_put_sta_rate(msg, &sinfo->rxrate,
5704 NL80211_STA_INFO_RX_BITRATE))
420e7fab 5705 goto nla_put_failure;
420e7fab 5706 }
319090bf
JB
5707
5708 PUT_SINFO(RX_PACKETS, rx_packets, u32);
5709 PUT_SINFO(TX_PACKETS, tx_packets, u32);
5710 PUT_SINFO(TX_RETRIES, tx_retries, u32);
5711 PUT_SINFO(TX_FAILED, tx_failed, u32);
5712 PUT_SINFO(EXPECTED_THROUGHPUT, expected_throughput, u32);
ab60633c 5713 PUT_SINFO(AIRTIME_LINK_METRIC, airtime_link_metric, u32);
319090bf
JB
5714 PUT_SINFO(BEACON_LOSS, beacon_loss_count, u32);
5715 PUT_SINFO(LOCAL_PM, local_pm, u32);
5716 PUT_SINFO(PEER_PM, peer_pm, u32);
5717 PUT_SINFO(NONPEER_PM, nonpeer_pm, u32);
dbdaee7a 5718 PUT_SINFO(CONNECTED_TO_GATE, connected_to_gate, u8);
1303a51c 5719 PUT_SINFO(CONNECTED_TO_AS, connected_to_as, u8);
319090bf 5720
397c657a 5721 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_BSS_PARAM)) {
ae0be8de
MK
5722 bss_param = nla_nest_start_noflag(msg,
5723 NL80211_STA_INFO_BSS_PARAM);
f4263c98
PS
5724 if (!bss_param)
5725 goto nla_put_failure;
5726
9360ffd1
DM
5727 if (((sinfo->bss_param.flags & BSS_PARAM_FLAGS_CTS_PROT) &&
5728 nla_put_flag(msg, NL80211_STA_BSS_PARAM_CTS_PROT)) ||
5729 ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_PREAMBLE) &&
5730 nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_PREAMBLE)) ||
5731 ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_SLOT_TIME) &&
5732 nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME)) ||
5733 nla_put_u8(msg, NL80211_STA_BSS_PARAM_DTIM_PERIOD,
5734 sinfo->bss_param.dtim_period) ||
5735 nla_put_u16(msg, NL80211_STA_BSS_PARAM_BEACON_INTERVAL,
5736 sinfo->bss_param.beacon_interval))
5737 goto nla_put_failure;
f4263c98
PS
5738
5739 nla_nest_end(msg, bss_param);
5740 }
397c657a 5741 if ((sinfo->filled & BIT_ULL(NL80211_STA_INFO_STA_FLAGS)) &&
9360ffd1
DM
5742 nla_put(msg, NL80211_STA_INFO_STA_FLAGS,
5743 sizeof(struct nl80211_sta_flag_update),
5744 &sinfo->sta_flags))
5745 goto nla_put_failure;
319090bf 5746
d686b920
JB
5747 PUT_SINFO_U64(T_OFFSET, t_offset);
5748 PUT_SINFO_U64(RX_DROP_MISC, rx_dropped_misc);
5749 PUT_SINFO_U64(BEACON_RX, rx_beacon);
a76b1942 5750 PUT_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8);
0d4e14a3
AB
5751 PUT_SINFO(RX_MPDUS, rx_mpdu_count, u32);
5752 PUT_SINFO(FCS_ERROR_COUNT, fcs_err_count, u32);
81d5439d 5753 if (wiphy_ext_feature_isset(&rdev->wiphy,
9c06602b
BP
5754 NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT)) {
5755 PUT_SINFO(ACK_SIGNAL, ack_signal, u8);
5756 PUT_SINFO(ACK_SIGNAL_AVG, avg_ack_signal, s8);
5757 }
319090bf
JB
5758
5759#undef PUT_SINFO
d686b920 5760#undef PUT_SINFO_U64
6de39808 5761
8689c051 5762 if (sinfo->pertid) {
6de39808
JB
5763 struct nlattr *tidsattr;
5764 int tid;
5765
ae0be8de
MK
5766 tidsattr = nla_nest_start_noflag(msg,
5767 NL80211_STA_INFO_TID_STATS);
6de39808
JB
5768 if (!tidsattr)
5769 goto nla_put_failure;
5770
5771 for (tid = 0; tid < IEEE80211_NUM_TIDS + 1; tid++) {
5772 struct cfg80211_tid_stats *tidstats;
5773 struct nlattr *tidattr;
5774
5775 tidstats = &sinfo->pertid[tid];
5776
5777 if (!tidstats->filled)
5778 continue;
5779
ae0be8de 5780 tidattr = nla_nest_start_noflag(msg, tid + 1);
6de39808
JB
5781 if (!tidattr)
5782 goto nla_put_failure;
5783
d686b920 5784#define PUT_TIDVAL_U64(attr, memb) do { \
6de39808 5785 if (tidstats->filled & BIT(NL80211_TID_STATS_ ## attr) && \
d686b920
JB
5786 nla_put_u64_64bit(msg, NL80211_TID_STATS_ ## attr, \
5787 tidstats->memb, NL80211_TID_STATS_PAD)) \
6de39808
JB
5788 goto nla_put_failure; \
5789 } while (0)
5790
d686b920
JB
5791 PUT_TIDVAL_U64(RX_MSDU, rx_msdu);
5792 PUT_TIDVAL_U64(TX_MSDU, tx_msdu);
5793 PUT_TIDVAL_U64(TX_MSDU_RETRIES, tx_msdu_retries);
5794 PUT_TIDVAL_U64(TX_MSDU_FAILED, tx_msdu_failed);
6de39808 5795
d686b920 5796#undef PUT_TIDVAL_U64
52539ca8
THJ
5797 if ((tidstats->filled &
5798 BIT(NL80211_TID_STATS_TXQ_STATS)) &&
5799 !nl80211_put_txq_stats(msg, &tidstats->txq_stats,
5800 NL80211_TID_STATS_TXQ_STATS))
5801 goto nla_put_failure;
5802
6de39808
JB
5803 nla_nest_end(msg, tidattr);
5804 }
5805
5806 nla_nest_end(msg, tidsattr);
5807 }
5808
2ec600d6 5809 nla_nest_end(msg, sinfoattr);
fd5b74dc 5810
319090bf 5811 if (sinfo->assoc_req_ies_len &&
9360ffd1
DM
5812 nla_put(msg, NL80211_ATTR_IE, sinfo->assoc_req_ies_len,
5813 sinfo->assoc_req_ies))
5814 goto nla_put_failure;
50d3dfb7 5815
7ea3e110 5816 cfg80211_sinfo_release_content(sinfo);
053c095a
JB
5817 genlmsg_end(msg, hdr);
5818 return 0;
fd5b74dc
JB
5819
5820 nla_put_failure:
7ea3e110 5821 cfg80211_sinfo_release_content(sinfo);
bc3ed28c
TG
5822 genlmsg_cancel(msg, hdr);
5823 return -EMSGSIZE;
fd5b74dc
JB
5824}
5825
2ec600d6 5826static int nl80211_dump_station(struct sk_buff *skb,
bba95fef 5827 struct netlink_callback *cb)
2ec600d6 5828{
73887fd9 5829 struct station_info sinfo;
1b8ec87a 5830 struct cfg80211_registered_device *rdev;
97990a06 5831 struct wireless_dev *wdev;
2ec600d6 5832 u8 mac_addr[ETH_ALEN];
97990a06 5833 int sta_idx = cb->args[2];
2ec600d6 5834 int err;
2ec600d6 5835
ea90e0dc 5836 rtnl_lock();
5297c65c 5837 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
67748893 5838 if (err)
ea90e0dc 5839 goto out_err;
bba95fef 5840
97990a06
JB
5841 if (!wdev->netdev) {
5842 err = -EINVAL;
5843 goto out_err;
5844 }
5845
1b8ec87a 5846 if (!rdev->ops->dump_station) {
eec60b03 5847 err = -EOPNOTSUPP;
bba95fef
JB
5848 goto out_err;
5849 }
5850
bba95fef 5851 while (1) {
73887fd9 5852 memset(&sinfo, 0, sizeof(sinfo));
1b8ec87a 5853 err = rdev_dump_station(rdev, wdev->netdev, sta_idx,
73887fd9 5854 mac_addr, &sinfo);
bba95fef
JB
5855 if (err == -ENOENT)
5856 break;
5857 if (err)
3b85875a 5858 goto out_err;
bba95fef 5859
cf5ead82 5860 if (nl80211_send_station(skb, NL80211_CMD_NEW_STATION,
15e47304 5861 NETLINK_CB(cb->skb).portid,
bba95fef 5862 cb->nlh->nlmsg_seq, NLM_F_MULTI,
1b8ec87a 5863 rdev, wdev->netdev, mac_addr,
73887fd9 5864 &sinfo) < 0)
bba95fef
JB
5865 goto out;
5866
5867 sta_idx++;
5868 }
5869
bba95fef 5870 out:
97990a06 5871 cb->args[2] = sta_idx;
bba95fef 5872 err = skb->len;
bba95fef 5873 out_err:
ea90e0dc 5874 rtnl_unlock();
bba95fef
JB
5875
5876 return err;
2ec600d6 5877}
fd5b74dc 5878
5727ef1b
JB
5879static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
5880{
4c476991
JB
5881 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5882 struct net_device *dev = info->user_ptr[1];
73887fd9 5883 struct station_info sinfo;
fd5b74dc
JB
5884 struct sk_buff *msg;
5885 u8 *mac_addr = NULL;
4c476991 5886 int err;
fd5b74dc 5887
73887fd9 5888 memset(&sinfo, 0, sizeof(sinfo));
fd5b74dc 5889
73887fd9
JB
5890 if (!info->attrs[NL80211_ATTR_MAC])
5891 return -EINVAL;
fd5b74dc
JB
5892
5893 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
5894
73887fd9
JB
5895 if (!rdev->ops->get_station)
5896 return -EOPNOTSUPP;
3b85875a 5897
73887fd9 5898 err = rdev_get_station(rdev, dev, mac_addr, &sinfo);
fd5b74dc 5899 if (err)
73887fd9 5900 return err;
2ec600d6 5901
fd2120ca 5902 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7ea3e110 5903 if (!msg) {
ba8f566a 5904 cfg80211_sinfo_release_content(&sinfo);
73887fd9 5905 return -ENOMEM;
7ea3e110 5906 }
fd5b74dc 5907
cf5ead82
JB
5908 if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION,
5909 info->snd_portid, info->snd_seq, 0,
73887fd9 5910 rdev, dev, mac_addr, &sinfo) < 0) {
4c476991 5911 nlmsg_free(msg);
73887fd9 5912 return -ENOBUFS;
4c476991 5913 }
3b85875a 5914
73887fd9 5915 return genlmsg_reply(msg, info);
5727ef1b
JB
5916}
5917
77ee7c89
JB
5918int cfg80211_check_station_change(struct wiphy *wiphy,
5919 struct station_parameters *params,
5920 enum cfg80211_station_type statype)
5921{
e4208427
AB
5922 if (params->listen_interval != -1 &&
5923 statype != CFG80211_STA_AP_CLIENT_UNASSOC)
77ee7c89 5924 return -EINVAL;
e4208427 5925
17b94247
AB
5926 if (params->support_p2p_ps != -1 &&
5927 statype != CFG80211_STA_AP_CLIENT_UNASSOC)
5928 return -EINVAL;
5929
c72e1140 5930 if (params->aid &&
e4208427
AB
5931 !(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
5932 statype != CFG80211_STA_AP_CLIENT_UNASSOC)
77ee7c89
JB
5933 return -EINVAL;
5934
5935 /* When you run into this, adjust the code below for the new flag */
5936 BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7);
5937
5938 switch (statype) {
eef941e6
TP
5939 case CFG80211_STA_MESH_PEER_KERNEL:
5940 case CFG80211_STA_MESH_PEER_USER:
77ee7c89
JB
5941 /*
5942 * No ignoring the TDLS flag here -- the userspace mesh
5943 * code doesn't have the bug of including TDLS in the
5944 * mask everywhere.
5945 */
5946 if (params->sta_flags_mask &
5947 ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) |
5948 BIT(NL80211_STA_FLAG_MFP) |
5949 BIT(NL80211_STA_FLAG_AUTHORIZED)))
5950 return -EINVAL;
5951 break;
5952 case CFG80211_STA_TDLS_PEER_SETUP:
5953 case CFG80211_STA_TDLS_PEER_ACTIVE:
5954 if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
5955 return -EINVAL;
5956 /* ignore since it can't change */
5957 params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
5958 break;
5959 default:
5960 /* disallow mesh-specific things */
5961 if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION)
5962 return -EINVAL;
5963 if (params->local_pm)
5964 return -EINVAL;
5965 if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)
5966 return -EINVAL;
5967 }
5968
5969 if (statype != CFG80211_STA_TDLS_PEER_SETUP &&
5970 statype != CFG80211_STA_TDLS_PEER_ACTIVE) {
5971 /* TDLS can't be set, ... */
5972 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
5973 return -EINVAL;
5974 /*
5975 * ... but don't bother the driver with it. This works around
5976 * a hostapd/wpa_supplicant issue -- it always includes the
5977 * TLDS_PEER flag in the mask even for AP mode.
5978 */
5979 params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
5980 }
5981
47edb11b
AB
5982 if (statype != CFG80211_STA_TDLS_PEER_SETUP &&
5983 statype != CFG80211_STA_AP_CLIENT_UNASSOC) {
77ee7c89
JB
5984 /* reject other things that can't change */
5985 if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD)
5986 return -EINVAL;
5987 if (params->sta_modify_mask & STATION_PARAM_APPLY_CAPABILITY)
5988 return -EINVAL;
5989 if (params->supported_rates)
5990 return -EINVAL;
c4cbaf79
LC
5991 if (params->ext_capab || params->ht_capa || params->vht_capa ||
5992 params->he_capa)
77ee7c89
JB
5993 return -EINVAL;
5994 }
5995
47edb11b
AB
5996 if (statype != CFG80211_STA_AP_CLIENT &&
5997 statype != CFG80211_STA_AP_CLIENT_UNASSOC) {
77ee7c89
JB
5998 if (params->vlan)
5999 return -EINVAL;
6000 }
6001
6002 switch (statype) {
6003 case CFG80211_STA_AP_MLME_CLIENT:
6004 /* Use this only for authorizing/unauthorizing a station */
6005 if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))
6006 return -EOPNOTSUPP;
6007 break;
6008 case CFG80211_STA_AP_CLIENT:
47edb11b 6009 case CFG80211_STA_AP_CLIENT_UNASSOC:
77ee7c89
JB
6010 /* accept only the listed bits */
6011 if (params->sta_flags_mask &
6012 ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
6013 BIT(NL80211_STA_FLAG_AUTHENTICATED) |
6014 BIT(NL80211_STA_FLAG_ASSOCIATED) |
6015 BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
6016 BIT(NL80211_STA_FLAG_WME) |
6017 BIT(NL80211_STA_FLAG_MFP)))
6018 return -EINVAL;
6019
6020 /* but authenticated/associated only if driver handles it */
6021 if (!(wiphy->features & NL80211_FEATURE_FULL_AP_CLIENT_STATE) &&
6022 params->sta_flags_mask &
6023 (BIT(NL80211_STA_FLAG_AUTHENTICATED) |
6024 BIT(NL80211_STA_FLAG_ASSOCIATED)))
6025 return -EINVAL;
6026 break;
6027 case CFG80211_STA_IBSS:
6028 case CFG80211_STA_AP_STA:
6029 /* reject any changes other than AUTHORIZED */
6030 if (params->sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED))
6031 return -EINVAL;
6032 break;
6033 case CFG80211_STA_TDLS_PEER_SETUP:
6034 /* reject any changes other than AUTHORIZED or WME */
6035 if (params->sta_flags_mask & ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
6036 BIT(NL80211_STA_FLAG_WME)))
6037 return -EINVAL;
6038 /* force (at least) rates when authorizing */
6039 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED) &&
6040 !params->supported_rates)
6041 return -EINVAL;
6042 break;
6043 case CFG80211_STA_TDLS_PEER_ACTIVE:
6044 /* reject any changes */
6045 return -EINVAL;
eef941e6 6046 case CFG80211_STA_MESH_PEER_KERNEL:
77ee7c89
JB
6047 if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)
6048 return -EINVAL;
6049 break;
eef941e6 6050 case CFG80211_STA_MESH_PEER_USER:
42925040
CYY
6051 if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION &&
6052 params->plink_action != NL80211_PLINK_ACTION_BLOCK)
77ee7c89
JB
6053 return -EINVAL;
6054 break;
6055 }
6056
06f7c88c
BL
6057 /*
6058 * Older kernel versions ignored this attribute entirely, so don't
6059 * reject attempts to update it but mark it as unused instead so the
6060 * driver won't look at the data.
6061 */
6062 if (statype != CFG80211_STA_AP_CLIENT_UNASSOC &&
6063 statype != CFG80211_STA_TDLS_PEER_SETUP)
6064 params->opmode_notif_used = false;
6065
77ee7c89
JB
6066 return 0;
6067}
6068EXPORT_SYMBOL(cfg80211_check_station_change);
6069
5727ef1b 6070/*
c258d2de 6071 * Get vlan interface making sure it is running and on the right wiphy.
5727ef1b 6072 */
80b99899
JB
6073static struct net_device *get_vlan(struct genl_info *info,
6074 struct cfg80211_registered_device *rdev)
5727ef1b 6075{
463d0183 6076 struct nlattr *vlanattr = info->attrs[NL80211_ATTR_STA_VLAN];
80b99899
JB
6077 struct net_device *v;
6078 int ret;
6079
6080 if (!vlanattr)
6081 return NULL;
6082
6083 v = dev_get_by_index(genl_info_net(info), nla_get_u32(vlanattr));
6084 if (!v)
6085 return ERR_PTR(-ENODEV);
6086
6087 if (!v->ieee80211_ptr || v->ieee80211_ptr->wiphy != &rdev->wiphy) {
6088 ret = -EINVAL;
6089 goto error;
5727ef1b 6090 }
80b99899 6091
77ee7c89
JB
6092 if (v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
6093 v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
6094 v->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
6095 ret = -EINVAL;
6096 goto error;
6097 }
6098
80b99899
JB
6099 if (!netif_running(v)) {
6100 ret = -ENETDOWN;
6101 goto error;
6102 }
6103
6104 return v;
6105 error:
6106 dev_put(v);
6107 return ERR_PTR(ret);
5727ef1b
JB
6108}
6109
94e860f1
JB
6110static const struct nla_policy
6111nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] = {
df881293
JM
6112 [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 },
6113 [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 },
6114};
6115
ff276691
JB
6116static int nl80211_parse_sta_wme(struct genl_info *info,
6117 struct station_parameters *params)
df881293 6118{
df881293
JM
6119 struct nlattr *tb[NL80211_STA_WME_MAX + 1];
6120 struct nlattr *nla;
6121 int err;
6122
df881293
JM
6123 /* parse WME attributes if present */
6124 if (!info->attrs[NL80211_ATTR_STA_WME])
6125 return 0;
6126
6127 nla = info->attrs[NL80211_ATTR_STA_WME];
8cb08174
JB
6128 err = nla_parse_nested_deprecated(tb, NL80211_STA_WME_MAX, nla,
6129 nl80211_sta_wme_policy,
6130 info->extack);
df881293
JM
6131 if (err)
6132 return err;
6133
6134 if (tb[NL80211_STA_WME_UAPSD_QUEUES])
6135 params->uapsd_queues = nla_get_u8(
6136 tb[NL80211_STA_WME_UAPSD_QUEUES]);
6137 if (params->uapsd_queues & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
6138 return -EINVAL;
6139
6140 if (tb[NL80211_STA_WME_MAX_SP])
6141 params->max_sp = nla_get_u8(tb[NL80211_STA_WME_MAX_SP]);
6142
6143 if (params->max_sp & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
6144 return -EINVAL;
6145
6146 params->sta_modify_mask |= STATION_PARAM_APPLY_UAPSD;
6147
6148 return 0;
6149}
6150
c01fc9ad
SD
6151static int nl80211_parse_sta_channel_info(struct genl_info *info,
6152 struct station_parameters *params)
6153{
6154 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]) {
6155 params->supported_channels =
6156 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
6157 params->supported_channels_len =
6158 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
6159 /*
6160 * Need to include at least one (first channel, number of
cb9abd48
JB
6161 * channels) tuple for each subband (checked in policy),
6162 * and must have proper tuples for the rest of the data as well.
c01fc9ad 6163 */
c01fc9ad
SD
6164 if (params->supported_channels_len % 2)
6165 return -EINVAL;
6166 }
6167
6168 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]) {
6169 params->supported_oper_classes =
6170 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
6171 params->supported_oper_classes_len =
6172 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
c01fc9ad
SD
6173 }
6174 return 0;
6175}
6176
ff276691
JB
6177static int nl80211_set_station_tdls(struct genl_info *info,
6178 struct station_parameters *params)
6179{
c01fc9ad 6180 int err;
ff276691 6181 /* Dummy STA entry gets updated once the peer capabilities are known */
5e4b6f56
JM
6182 if (info->attrs[NL80211_ATTR_PEER_AID])
6183 params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
ff276691
JB
6184 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
6185 params->ht_capa =
6186 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
6187 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
6188 params->vht_capa =
6189 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
c4cbaf79
LC
6190 if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
6191 params->he_capa =
6192 nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
6193 params->he_capa_len =
6194 nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
c4cbaf79 6195 }
ff276691 6196
c01fc9ad
SD
6197 err = nl80211_parse_sta_channel_info(info, params);
6198 if (err)
6199 return err;
6200
ff276691
JB
6201 return nl80211_parse_sta_wme(info, params);
6202}
6203
e96d1cd2
ARN
6204static int nl80211_parse_sta_txpower_setting(struct genl_info *info,
6205 struct station_parameters *params)
6206{
6207 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6208 int idx;
6209
6210 if (info->attrs[NL80211_ATTR_STA_TX_POWER_SETTING]) {
6211 if (!rdev->ops->set_tx_power ||
6212 !wiphy_ext_feature_isset(&rdev->wiphy,
6213 NL80211_EXT_FEATURE_STA_TX_PWR))
6214 return -EOPNOTSUPP;
6215
6216 idx = NL80211_ATTR_STA_TX_POWER_SETTING;
6217 params->txpwr.type = nla_get_u8(info->attrs[idx]);
6218
6219 if (params->txpwr.type == NL80211_TX_POWER_LIMITED) {
6220 idx = NL80211_ATTR_STA_TX_POWER;
6221
6222 if (info->attrs[idx])
6223 params->txpwr.power =
6224 nla_get_s16(info->attrs[idx]);
6225 else
6226 return -EINVAL;
6227 }
6228 params->sta_modify_mask |= STATION_PARAM_APPLY_STA_TXPOWER;
6229 }
6230
6231 return 0;
6232}
6233
5727ef1b
JB
6234static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
6235{
4c476991 6236 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 6237 struct net_device *dev = info->user_ptr[1];
5727ef1b 6238 struct station_parameters params;
77ee7c89
JB
6239 u8 *mac_addr;
6240 int err;
5727ef1b
JB
6241
6242 memset(&params, 0, sizeof(params));
6243
77ee7c89
JB
6244 if (!rdev->ops->change_station)
6245 return -EOPNOTSUPP;
6246
e4208427
AB
6247 /*
6248 * AID and listen_interval properties can be set only for unassociated
6249 * station. Include these parameters here and will check them in
6250 * cfg80211_check_station_change().
6251 */
a9bc31e4
AB
6252 if (info->attrs[NL80211_ATTR_STA_AID])
6253 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
e4208427 6254
14f34e36
GG
6255 if (info->attrs[NL80211_ATTR_VLAN_ID])
6256 params.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
6257
e4208427
AB
6258 if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
6259 params.listen_interval =
6260 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
6261 else
6262 params.listen_interval = -1;
5727ef1b 6263
ab0d76f6
JB
6264 if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS])
6265 params.support_p2p_ps =
6266 nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
6267 else
17b94247 6268 params.support_p2p_ps = -1;
17b94247 6269
5727ef1b
JB
6270 if (!info->attrs[NL80211_ATTR_MAC])
6271 return -EINVAL;
6272
6273 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
6274
6275 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
6276 params.supported_rates =
6277 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
6278 params.supported_rates_len =
6279 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
6280 }
6281
9d62a986
JM
6282 if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
6283 params.capability =
6284 nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]);
6285 params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY;
6286 }
6287
6288 if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) {
6289 params.ext_capab =
6290 nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
6291 params.ext_capab_len =
6292 nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
6293 }
6294
bdd3ae3d 6295 if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
5727ef1b
JB
6296 return -EINVAL;
6297
ab0d76f6 6298 if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
2ec600d6 6299 params.plink_action =
f8bacc21 6300 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
2ec600d6 6301
f8bacc21 6302 if (info->attrs[NL80211_ATTR_STA_PLINK_STATE]) {
9c3990aa 6303 params.plink_state =
f8bacc21 6304 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]);
ab0d76f6 6305 if (info->attrs[NL80211_ATTR_MESH_PEER_AID])
7d27a0ba
MH
6306 params.peer_aid = nla_get_u16(
6307 info->attrs[NL80211_ATTR_MESH_PEER_AID]);
f8bacc21
JB
6308 params.sta_modify_mask |= STATION_PARAM_APPLY_PLINK_STATE;
6309 }
9c3990aa 6310
ab0d76f6
JB
6311 if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE])
6312 params.local_pm = nla_get_u32(
3b1c5a53
MP
6313 info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]);
6314
06f7c88c
BL
6315 if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
6316 params.opmode_notif_used = true;
6317 params.opmode_notif =
6318 nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
6319 }
6320
43e64bf3
RM
6321 if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
6322 params.he_6ghz_capa =
fce2ff72 6323 nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
43e64bf3 6324
36647055
THJ
6325 if (info->attrs[NL80211_ATTR_AIRTIME_WEIGHT])
6326 params.airtime_weight =
6327 nla_get_u16(info->attrs[NL80211_ATTR_AIRTIME_WEIGHT]);
6328
6329 if (params.airtime_weight &&
6330 !wiphy_ext_feature_isset(&rdev->wiphy,
6331 NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
6332 return -EOPNOTSUPP;
6333
e96d1cd2
ARN
6334 err = nl80211_parse_sta_txpower_setting(info, &params);
6335 if (err)
6336 return err;
6337
77ee7c89
JB
6338 /* Include parameters for TDLS peer (will check later) */
6339 err = nl80211_set_station_tdls(info, &params);
6340 if (err)
6341 return err;
6342
6343 params.vlan = get_vlan(info, rdev);
6344 if (IS_ERR(params.vlan))
6345 return PTR_ERR(params.vlan);
6346
a97f4424
JB
6347 switch (dev->ieee80211_ptr->iftype) {
6348 case NL80211_IFTYPE_AP:
6349 case NL80211_IFTYPE_AP_VLAN:
074ac8df 6350 case NL80211_IFTYPE_P2P_GO:
074ac8df 6351 case NL80211_IFTYPE_P2P_CLIENT:
a97f4424 6352 case NL80211_IFTYPE_STATION:
267335d6 6353 case NL80211_IFTYPE_ADHOC:
a97f4424 6354 case NL80211_IFTYPE_MESH_POINT:
a97f4424
JB
6355 break;
6356 default:
77ee7c89
JB
6357 err = -EOPNOTSUPP;
6358 goto out_put_vlan;
034d655e
JB
6359 }
6360
77ee7c89 6361 /* driver will call cfg80211_check_station_change() */
e35e4d28 6362 err = rdev_change_station(rdev, dev, mac_addr, &params);
5727ef1b 6363
77ee7c89 6364 out_put_vlan:
5727ef1b
JB
6365 if (params.vlan)
6366 dev_put(params.vlan);
3b85875a 6367
5727ef1b
JB
6368 return err;
6369}
6370
6371static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
6372{
4c476991 6373 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5727ef1b 6374 int err;
4c476991 6375 struct net_device *dev = info->user_ptr[1];
5727ef1b
JB
6376 struct station_parameters params;
6377 u8 *mac_addr = NULL;
bda95eb1
JB
6378 u32 auth_assoc = BIT(NL80211_STA_FLAG_AUTHENTICATED) |
6379 BIT(NL80211_STA_FLAG_ASSOCIATED);
5727ef1b
JB
6380
6381 memset(&params, 0, sizeof(params));
6382
984c311b
JB
6383 if (!rdev->ops->add_station)
6384 return -EOPNOTSUPP;
6385
5727ef1b
JB
6386 if (!info->attrs[NL80211_ATTR_MAC])
6387 return -EINVAL;
6388
5727ef1b
JB
6389 if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
6390 return -EINVAL;
6391
6392 if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
6393 return -EINVAL;
6394
5e4b6f56
JM
6395 if (!info->attrs[NL80211_ATTR_STA_AID] &&
6396 !info->attrs[NL80211_ATTR_PEER_AID])
0e956c13
TLSC
6397 return -EINVAL;
6398
5727ef1b
JB
6399 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
6400 params.supported_rates =
6401 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
6402 params.supported_rates_len =
6403 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
6404 params.listen_interval =
6405 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
51b50fbe 6406
14f34e36
GG
6407 if (info->attrs[NL80211_ATTR_VLAN_ID])
6408 params.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
6409
17b94247 6410 if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) {
ab0d76f6
JB
6411 params.support_p2p_ps =
6412 nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
17b94247
AB
6413 } else {
6414 /*
6415 * if not specified, assume it's supported for P2P GO interface,
6416 * and is NOT supported for AP interface
6417 */
6418 params.support_p2p_ps =
6419 dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO;
6420 }
6421
3d124ea2 6422 if (info->attrs[NL80211_ATTR_PEER_AID])
5e4b6f56 6423 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
3d124ea2
JM
6424 else
6425 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
51b50fbe 6426
9d62a986
JM
6427 if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
6428 params.capability =
6429 nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]);
6430 params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY;
6431 }
6432
6433 if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) {
6434 params.ext_capab =
6435 nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
6436 params.ext_capab_len =
6437 nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
6438 }
6439
36aedc90
JM
6440 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
6441 params.ht_capa =
6442 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
5727ef1b 6443
f461be3e
MP
6444 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
6445 params.vht_capa =
6446 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
6447
c4cbaf79
LC
6448 if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
6449 params.he_capa =
6450 nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
6451 params.he_capa_len =
6452 nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
c4cbaf79
LC
6453 }
6454
43e64bf3
RM
6455 if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
6456 params.he_6ghz_capa =
6457 nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
6458
60f4a7b1
MK
6459 if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
6460 params.opmode_notif_used = true;
6461 params.opmode_notif =
6462 nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
6463 }
6464
ab0d76f6 6465 if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
96b78dff 6466 params.plink_action =
f8bacc21 6467 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
96b78dff 6468
36647055
THJ
6469 if (info->attrs[NL80211_ATTR_AIRTIME_WEIGHT])
6470 params.airtime_weight =
6471 nla_get_u16(info->attrs[NL80211_ATTR_AIRTIME_WEIGHT]);
6472
6473 if (params.airtime_weight &&
6474 !wiphy_ext_feature_isset(&rdev->wiphy,
6475 NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
6476 return -EOPNOTSUPP;
6477
e96d1cd2
ARN
6478 err = nl80211_parse_sta_txpower_setting(info, &params);
6479 if (err)
6480 return err;
6481
c01fc9ad
SD
6482 err = nl80211_parse_sta_channel_info(info, &params);
6483 if (err)
6484 return err;
6485
ff276691
JB
6486 err = nl80211_parse_sta_wme(info, &params);
6487 if (err)
6488 return err;
bdd90d5e 6489
bdd3ae3d 6490 if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
5727ef1b
JB
6491 return -EINVAL;
6492
496fcc29
JB
6493 /* HT/VHT requires QoS, but if we don't have that just ignore HT/VHT
6494 * as userspace might just pass through the capabilities from the IEs
6495 * directly, rather than enforcing this restriction and returning an
6496 * error in this case.
6497 */
6498 if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME))) {
6499 params.ht_capa = NULL;
6500 params.vht_capa = NULL;
c4cbaf79
LC
6501
6502 /* HE requires WME */
43e64bf3 6503 if (params.he_capa_len || params.he_6ghz_capa)
c4cbaf79 6504 return -EINVAL;
496fcc29
JB
6505 }
6506
43e64bf3
RM
6507 /* Ensure that HT/VHT capabilities are not set for 6 GHz HE STA */
6508 if (params.he_6ghz_capa && (params.ht_capa || params.vht_capa))
6509 return -EINVAL;
6510
77ee7c89
JB
6511 /* When you run into this, adjust the code below for the new flag */
6512 BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7);
6513
bdd90d5e
JB
6514 switch (dev->ieee80211_ptr->iftype) {
6515 case NL80211_IFTYPE_AP:
6516 case NL80211_IFTYPE_AP_VLAN:
6517 case NL80211_IFTYPE_P2P_GO:
984c311b
JB
6518 /* ignore WME attributes if iface/sta is not capable */
6519 if (!(rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) ||
6520 !(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)))
6521 params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
c75786c9 6522
bdd90d5e 6523 /* TDLS peers cannot be added */
3d124ea2
JM
6524 if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ||
6525 info->attrs[NL80211_ATTR_PEER_AID])
4319e193 6526 return -EINVAL;
bdd90d5e
JB
6527 /* but don't bother the driver with it */
6528 params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
3b9ce80c 6529
d582cffb
JB
6530 /* allow authenticated/associated only if driver handles it */
6531 if (!(rdev->wiphy.features &
6532 NL80211_FEATURE_FULL_AP_CLIENT_STATE) &&
bda95eb1 6533 params.sta_flags_mask & auth_assoc)
d582cffb
JB
6534 return -EINVAL;
6535
bda95eb1
JB
6536 /* Older userspace, or userspace wanting to be compatible with
6537 * !NL80211_FEATURE_FULL_AP_CLIENT_STATE, will not set the auth
6538 * and assoc flags in the mask, but assumes the station will be
6539 * added as associated anyway since this was the required driver
6540 * behaviour before NL80211_FEATURE_FULL_AP_CLIENT_STATE was
6541 * introduced.
6542 * In order to not bother drivers with this quirk in the API
6543 * set the flags in both the mask and set for new stations in
6544 * this case.
6545 */
6546 if (!(params.sta_flags_mask & auth_assoc)) {
6547 params.sta_flags_mask |= auth_assoc;
6548 params.sta_flags_set |= auth_assoc;
6549 }
6550
bdd90d5e
JB
6551 /* must be last in here for error handling */
6552 params.vlan = get_vlan(info, rdev);
6553 if (IS_ERR(params.vlan))
6554 return PTR_ERR(params.vlan);
6555 break;
6556 case NL80211_IFTYPE_MESH_POINT:
984c311b
JB
6557 /* ignore uAPSD data */
6558 params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
6559
d582cffb
JB
6560 /* associated is disallowed */
6561 if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED))
6562 return -EINVAL;
bdd90d5e 6563 /* TDLS peers cannot be added */
3d124ea2
JM
6564 if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ||
6565 info->attrs[NL80211_ATTR_PEER_AID])
bdd90d5e
JB
6566 return -EINVAL;
6567 break;
6568 case NL80211_IFTYPE_STATION:
93d08f0b 6569 case NL80211_IFTYPE_P2P_CLIENT:
984c311b
JB
6570 /* ignore uAPSD data */
6571 params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
6572
77ee7c89
JB
6573 /* these are disallowed */
6574 if (params.sta_flags_mask &
6575 (BIT(NL80211_STA_FLAG_ASSOCIATED) |
6576 BIT(NL80211_STA_FLAG_AUTHENTICATED)))
d582cffb 6577 return -EINVAL;
bdd90d5e
JB
6578 /* Only TDLS peers can be added */
6579 if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
6580 return -EINVAL;
6581 /* Can only add if TDLS ... */
6582 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS))
6583 return -EOPNOTSUPP;
6584 /* ... with external setup is supported */
6585 if (!(rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP))
6586 return -EOPNOTSUPP;
77ee7c89
JB
6587 /*
6588 * Older wpa_supplicant versions always mark the TDLS peer
6589 * as authorized, but it shouldn't yet be.
6590 */
6591 params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_AUTHORIZED);
bdd90d5e
JB
6592 break;
6593 default:
6594 return -EOPNOTSUPP;
c75786c9
EP
6595 }
6596
bdd90d5e 6597 /* be aware of params.vlan when changing code here */
5727ef1b 6598
e35e4d28 6599 err = rdev_add_station(rdev, dev, mac_addr, &params);
5727ef1b 6600
5727ef1b
JB
6601 if (params.vlan)
6602 dev_put(params.vlan);
5727ef1b
JB
6603 return err;
6604}
6605
6606static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
6607{
4c476991
JB
6608 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6609 struct net_device *dev = info->user_ptr[1];
89c771e5
JM
6610 struct station_del_parameters params;
6611
6612 memset(&params, 0, sizeof(params));
5727ef1b
JB
6613
6614 if (info->attrs[NL80211_ATTR_MAC])
89c771e5 6615 params.mac = nla_data(info->attrs[NL80211_ATTR_MAC]);
5727ef1b 6616
306b79ea
JB
6617 switch (dev->ieee80211_ptr->iftype) {
6618 case NL80211_IFTYPE_AP:
6619 case NL80211_IFTYPE_AP_VLAN:
6620 case NL80211_IFTYPE_MESH_POINT:
6621 case NL80211_IFTYPE_P2P_GO:
6622 /* always accept these */
6623 break;
6624 case NL80211_IFTYPE_ADHOC:
6625 /* conditionally accept */
6626 if (wiphy_ext_feature_isset(&rdev->wiphy,
6627 NL80211_EXT_FEATURE_DEL_IBSS_STA))
6628 break;
edafcf42 6629 return -EINVAL;
306b79ea 6630 default:
4c476991 6631 return -EINVAL;
306b79ea 6632 }
5727ef1b 6633
4c476991
JB
6634 if (!rdev->ops->del_station)
6635 return -EOPNOTSUPP;
3b85875a 6636
98856866
JM
6637 if (info->attrs[NL80211_ATTR_MGMT_SUBTYPE]) {
6638 params.subtype =
6639 nla_get_u8(info->attrs[NL80211_ATTR_MGMT_SUBTYPE]);
6640 if (params.subtype != IEEE80211_STYPE_DISASSOC >> 4 &&
6641 params.subtype != IEEE80211_STYPE_DEAUTH >> 4)
6642 return -EINVAL;
6643 } else {
6644 /* Default to Deauthentication frame */
6645 params.subtype = IEEE80211_STYPE_DEAUTH >> 4;
6646 }
6647
6648 if (info->attrs[NL80211_ATTR_REASON_CODE]) {
6649 params.reason_code =
6650 nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
6651 if (params.reason_code == 0)
6652 return -EINVAL; /* 0 is reserved */
6653 } else {
6654 /* Default to reason code 2 */
6655 params.reason_code = WLAN_REASON_PREV_AUTH_NOT_VALID;
6656 }
6657
89c771e5 6658 return rdev_del_station(rdev, dev, &params);
5727ef1b
JB
6659}
6660
15e47304 6661static int nl80211_send_mpath(struct sk_buff *msg, u32 portid, u32 seq,
2ec600d6
LCC
6662 int flags, struct net_device *dev,
6663 u8 *dst, u8 *next_hop,
6664 struct mpath_info *pinfo)
6665{
6666 void *hdr;
6667 struct nlattr *pinfoattr;
6668
1ef4c850 6669 hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_MPATH);
2ec600d6
LCC
6670 if (!hdr)
6671 return -1;
6672
9360ffd1
DM
6673 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
6674 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, dst) ||
6675 nla_put(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop) ||
6676 nla_put_u32(msg, NL80211_ATTR_GENERATION, pinfo->generation))
6677 goto nla_put_failure;
f5ea9120 6678
ae0be8de 6679 pinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_MPATH_INFO);
2ec600d6
LCC
6680 if (!pinfoattr)
6681 goto nla_put_failure;
9360ffd1
DM
6682 if ((pinfo->filled & MPATH_INFO_FRAME_QLEN) &&
6683 nla_put_u32(msg, NL80211_MPATH_INFO_FRAME_QLEN,
6684 pinfo->frame_qlen))
6685 goto nla_put_failure;
6686 if (((pinfo->filled & MPATH_INFO_SN) &&
6687 nla_put_u32(msg, NL80211_MPATH_INFO_SN, pinfo->sn)) ||
6688 ((pinfo->filled & MPATH_INFO_METRIC) &&
6689 nla_put_u32(msg, NL80211_MPATH_INFO_METRIC,
6690 pinfo->metric)) ||
6691 ((pinfo->filled & MPATH_INFO_EXPTIME) &&
6692 nla_put_u32(msg, NL80211_MPATH_INFO_EXPTIME,
6693 pinfo->exptime)) ||
6694 ((pinfo->filled & MPATH_INFO_FLAGS) &&
6695 nla_put_u8(msg, NL80211_MPATH_INFO_FLAGS,
6696 pinfo->flags)) ||
6697 ((pinfo->filled & MPATH_INFO_DISCOVERY_TIMEOUT) &&
6698 nla_put_u32(msg, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT,
6699 pinfo->discovery_timeout)) ||
6700 ((pinfo->filled & MPATH_INFO_DISCOVERY_RETRIES) &&
6701 nla_put_u8(msg, NL80211_MPATH_INFO_DISCOVERY_RETRIES,
cc241636
JH
6702 pinfo->discovery_retries)) ||
6703 ((pinfo->filled & MPATH_INFO_HOP_COUNT) &&
6704 nla_put_u8(msg, NL80211_MPATH_INFO_HOP_COUNT,
540bbcb9
JH
6705 pinfo->hop_count)) ||
6706 ((pinfo->filled & MPATH_INFO_PATH_CHANGE) &&
6707 nla_put_u32(msg, NL80211_MPATH_INFO_PATH_CHANGE,
6708 pinfo->path_change_count)))
9360ffd1 6709 goto nla_put_failure;
2ec600d6
LCC
6710
6711 nla_nest_end(msg, pinfoattr);
6712
053c095a
JB
6713 genlmsg_end(msg, hdr);
6714 return 0;
2ec600d6
LCC
6715
6716 nla_put_failure:
bc3ed28c
TG
6717 genlmsg_cancel(msg, hdr);
6718 return -EMSGSIZE;
2ec600d6
LCC
6719}
6720
6721static int nl80211_dump_mpath(struct sk_buff *skb,
bba95fef 6722 struct netlink_callback *cb)
2ec600d6 6723{
2ec600d6 6724 struct mpath_info pinfo;
1b8ec87a 6725 struct cfg80211_registered_device *rdev;
97990a06 6726 struct wireless_dev *wdev;
2ec600d6
LCC
6727 u8 dst[ETH_ALEN];
6728 u8 next_hop[ETH_ALEN];
97990a06 6729 int path_idx = cb->args[2];
2ec600d6 6730 int err;
2ec600d6 6731
ea90e0dc 6732 rtnl_lock();
5297c65c 6733 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
67748893 6734 if (err)
ea90e0dc 6735 goto out_err;
bba95fef 6736
1b8ec87a 6737 if (!rdev->ops->dump_mpath) {
eec60b03 6738 err = -EOPNOTSUPP;
bba95fef
JB
6739 goto out_err;
6740 }
6741
97990a06 6742 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
eec60b03 6743 err = -EOPNOTSUPP;
0448b5fc 6744 goto out_err;
eec60b03
JM
6745 }
6746
bba95fef 6747 while (1) {
1b8ec87a 6748 err = rdev_dump_mpath(rdev, wdev->netdev, path_idx, dst,
97990a06 6749 next_hop, &pinfo);
bba95fef 6750 if (err == -ENOENT)
2ec600d6 6751 break;
bba95fef 6752 if (err)
3b85875a 6753 goto out_err;
2ec600d6 6754
15e47304 6755 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid,
bba95fef 6756 cb->nlh->nlmsg_seq, NLM_F_MULTI,
97990a06 6757 wdev->netdev, dst, next_hop,
bba95fef
JB
6758 &pinfo) < 0)
6759 goto out;
2ec600d6 6760
bba95fef 6761 path_idx++;
2ec600d6 6762 }
2ec600d6 6763
bba95fef 6764 out:
97990a06 6765 cb->args[2] = path_idx;
bba95fef 6766 err = skb->len;
bba95fef 6767 out_err:
ea90e0dc 6768 rtnl_unlock();
bba95fef 6769 return err;
2ec600d6
LCC
6770}
6771
6772static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
6773{
4c476991 6774 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2ec600d6 6775 int err;
4c476991 6776 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
6777 struct mpath_info pinfo;
6778 struct sk_buff *msg;
6779 u8 *dst = NULL;
6780 u8 next_hop[ETH_ALEN];
6781
6782 memset(&pinfo, 0, sizeof(pinfo));
6783
6784 if (!info->attrs[NL80211_ATTR_MAC])
6785 return -EINVAL;
6786
6787 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
6788
4c476991
JB
6789 if (!rdev->ops->get_mpath)
6790 return -EOPNOTSUPP;
2ec600d6 6791
4c476991
JB
6792 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
6793 return -EOPNOTSUPP;
eec60b03 6794
e35e4d28 6795 err = rdev_get_mpath(rdev, dev, dst, next_hop, &pinfo);
2ec600d6 6796 if (err)
4c476991 6797 return err;
2ec600d6 6798
fd2120ca 6799 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2ec600d6 6800 if (!msg)
4c476991 6801 return -ENOMEM;
2ec600d6 6802
15e47304 6803 if (nl80211_send_mpath(msg, info->snd_portid, info->snd_seq, 0,
4c476991
JB
6804 dev, dst, next_hop, &pinfo) < 0) {
6805 nlmsg_free(msg);
6806 return -ENOBUFS;
6807 }
3b85875a 6808
4c476991 6809 return genlmsg_reply(msg, info);
2ec600d6
LCC
6810}
6811
6812static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
6813{
4c476991
JB
6814 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6815 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
6816 u8 *dst = NULL;
6817 u8 *next_hop = NULL;
6818
6819 if (!info->attrs[NL80211_ATTR_MAC])
6820 return -EINVAL;
6821
6822 if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
6823 return -EINVAL;
6824
6825 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
6826 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
6827
4c476991
JB
6828 if (!rdev->ops->change_mpath)
6829 return -EOPNOTSUPP;
35a8efe1 6830
4c476991
JB
6831 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
6832 return -EOPNOTSUPP;
2ec600d6 6833
e35e4d28 6834 return rdev_change_mpath(rdev, dev, dst, next_hop);
2ec600d6 6835}
4c476991 6836
2ec600d6
LCC
6837static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
6838{
4c476991
JB
6839 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6840 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
6841 u8 *dst = NULL;
6842 u8 *next_hop = NULL;
6843
6844 if (!info->attrs[NL80211_ATTR_MAC])
6845 return -EINVAL;
6846
6847 if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
6848 return -EINVAL;
6849
6850 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
6851 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
6852
4c476991
JB
6853 if (!rdev->ops->add_mpath)
6854 return -EOPNOTSUPP;
35a8efe1 6855
4c476991
JB
6856 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
6857 return -EOPNOTSUPP;
2ec600d6 6858
e35e4d28 6859 return rdev_add_mpath(rdev, dev, dst, next_hop);
2ec600d6
LCC
6860}
6861
6862static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
6863{
4c476991
JB
6864 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6865 struct net_device *dev = info->user_ptr[1];
2ec600d6
LCC
6866 u8 *dst = NULL;
6867
6868 if (info->attrs[NL80211_ATTR_MAC])
6869 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
6870
4c476991
JB
6871 if (!rdev->ops->del_mpath)
6872 return -EOPNOTSUPP;
3b85875a 6873
b501426c
MP
6874 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
6875 return -EOPNOTSUPP;
6876
e35e4d28 6877 return rdev_del_mpath(rdev, dev, dst);
2ec600d6
LCC
6878}
6879
66be7d2b
HR
6880static int nl80211_get_mpp(struct sk_buff *skb, struct genl_info *info)
6881{
6882 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6883 int err;
6884 struct net_device *dev = info->user_ptr[1];
6885 struct mpath_info pinfo;
6886 struct sk_buff *msg;
6887 u8 *dst = NULL;
6888 u8 mpp[ETH_ALEN];
6889
6890 memset(&pinfo, 0, sizeof(pinfo));
6891
6892 if (!info->attrs[NL80211_ATTR_MAC])
6893 return -EINVAL;
6894
6895 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
6896
6897 if (!rdev->ops->get_mpp)
6898 return -EOPNOTSUPP;
6899
6900 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
6901 return -EOPNOTSUPP;
6902
6903 err = rdev_get_mpp(rdev, dev, dst, mpp, &pinfo);
6904 if (err)
6905 return err;
6906
6907 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
6908 if (!msg)
6909 return -ENOMEM;
6910
6911 if (nl80211_send_mpath(msg, info->snd_portid, info->snd_seq, 0,
6912 dev, dst, mpp, &pinfo) < 0) {
6913 nlmsg_free(msg);
6914 return -ENOBUFS;
6915 }
6916
6917 return genlmsg_reply(msg, info);
6918}
6919
6920static int nl80211_dump_mpp(struct sk_buff *skb,
6921 struct netlink_callback *cb)
6922{
6923 struct mpath_info pinfo;
6924 struct cfg80211_registered_device *rdev;
6925 struct wireless_dev *wdev;
6926 u8 dst[ETH_ALEN];
6927 u8 mpp[ETH_ALEN];
6928 int path_idx = cb->args[2];
6929 int err;
6930
ea90e0dc 6931 rtnl_lock();
5297c65c 6932 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
66be7d2b 6933 if (err)
ea90e0dc 6934 goto out_err;
66be7d2b
HR
6935
6936 if (!rdev->ops->dump_mpp) {
6937 err = -EOPNOTSUPP;
6938 goto out_err;
6939 }
6940
6941 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
6942 err = -EOPNOTSUPP;
6943 goto out_err;
6944 }
6945
6946 while (1) {
6947 err = rdev_dump_mpp(rdev, wdev->netdev, path_idx, dst,
6948 mpp, &pinfo);
6949 if (err == -ENOENT)
6950 break;
6951 if (err)
6952 goto out_err;
6953
6954 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid,
6955 cb->nlh->nlmsg_seq, NLM_F_MULTI,
6956 wdev->netdev, dst, mpp,
6957 &pinfo) < 0)
6958 goto out;
6959
6960 path_idx++;
6961 }
6962
6963 out:
6964 cb->args[2] = path_idx;
6965 err = skb->len;
6966 out_err:
ea90e0dc 6967 rtnl_unlock();
66be7d2b
HR
6968 return err;
6969}
6970
9f1ba906
JM
6971static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
6972{
4c476991
JB
6973 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6974 struct net_device *dev = info->user_ptr[1];
c56589ed 6975 struct wireless_dev *wdev = dev->ieee80211_ptr;
9f1ba906 6976 struct bss_parameters params;
c56589ed 6977 int err;
9f1ba906
JM
6978
6979 memset(&params, 0, sizeof(params));
6980 /* default to not changing parameters */
6981 params.use_cts_prot = -1;
6982 params.use_short_preamble = -1;
6983 params.use_short_slot_time = -1;
fd8aaaf3 6984 params.ap_isolate = -1;
50b12f59 6985 params.ht_opmode = -1;
53cabad7
JB
6986 params.p2p_ctwindow = -1;
6987 params.p2p_opp_ps = -1;
9f1ba906
JM
6988
6989 if (info->attrs[NL80211_ATTR_BSS_CTS_PROT])
6990 params.use_cts_prot =
6991 nla_get_u8(info->attrs[NL80211_ATTR_BSS_CTS_PROT]);
6992 if (info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE])
6993 params.use_short_preamble =
6994 nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]);
6995 if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME])
6996 params.use_short_slot_time =
6997 nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]);
90c97a04
JM
6998 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
6999 params.basic_rates =
7000 nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
7001 params.basic_rates_len =
7002 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
7003 }
fd8aaaf3
FF
7004 if (info->attrs[NL80211_ATTR_AP_ISOLATE])
7005 params.ap_isolate = !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]);
50b12f59
HS
7006 if (info->attrs[NL80211_ATTR_BSS_HT_OPMODE])
7007 params.ht_opmode =
7008 nla_get_u16(info->attrs[NL80211_ATTR_BSS_HT_OPMODE]);
9f1ba906 7009
53cabad7
JB
7010 if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
7011 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
7012 return -EINVAL;
7013 params.p2p_ctwindow =
ab0d76f6 7014 nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
53cabad7
JB
7015 if (params.p2p_ctwindow != 0 &&
7016 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
7017 return -EINVAL;
7018 }
7019
7020 if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
7021 u8 tmp;
7022
7023 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
7024 return -EINVAL;
7025 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
53cabad7
JB
7026 params.p2p_opp_ps = tmp;
7027 if (params.p2p_opp_ps &&
7028 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
7029 return -EINVAL;
7030 }
7031
4c476991
JB
7032 if (!rdev->ops->change_bss)
7033 return -EOPNOTSUPP;
9f1ba906 7034
074ac8df 7035 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
4c476991
JB
7036 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
7037 return -EOPNOTSUPP;
3b85875a 7038
c56589ed
SW
7039 wdev_lock(wdev);
7040 err = rdev_change_bss(rdev, dev, &params);
7041 wdev_unlock(wdev);
7042
7043 return err;
9f1ba906
JM
7044}
7045
b2e1b302
LR
7046static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
7047{
b2e1b302 7048 char *data = NULL;
05050753 7049 bool is_indoor;
57b5ce07 7050 enum nl80211_user_reg_hint_type user_reg_hint_type;
05050753
I
7051 u32 owner_nlportid;
7052
80778f18
LR
7053 /*
7054 * You should only get this when cfg80211 hasn't yet initialized
7055 * completely when built-in to the kernel right between the time
7056 * window between nl80211_init() and regulatory_init(), if that is
7057 * even possible.
7058 */
458f4f9e 7059 if (unlikely(!rcu_access_pointer(cfg80211_regdomain)))
fe33eb39 7060 return -EINPROGRESS;
80778f18 7061
57b5ce07
LR
7062 if (info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE])
7063 user_reg_hint_type =
7064 nla_get_u32(info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE]);
7065 else
7066 user_reg_hint_type = NL80211_USER_REG_HINT_USER;
7067
7068 switch (user_reg_hint_type) {
7069 case NL80211_USER_REG_HINT_USER:
7070 case NL80211_USER_REG_HINT_CELL_BASE:
52616f2b
IP
7071 if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
7072 return -EINVAL;
7073
7074 data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
7075 return regulatory_hint_user(data, user_reg_hint_type);
7076 case NL80211_USER_REG_HINT_INDOOR:
05050753
I
7077 if (info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
7078 owner_nlportid = info->snd_portid;
7079 is_indoor = !!info->attrs[NL80211_ATTR_REG_INDOOR];
7080 } else {
7081 owner_nlportid = 0;
7082 is_indoor = true;
7083 }
7084
7085 return regulatory_hint_indoor(is_indoor, owner_nlportid);
57b5ce07
LR
7086 default:
7087 return -EINVAL;
7088 }
b2e1b302
LR
7089}
7090
1ea4ff3e
JB
7091static int nl80211_reload_regdb(struct sk_buff *skb, struct genl_info *info)
7092{
7093 return reg_reload_regdb();
7094}
7095
24bdd9f4 7096static int nl80211_get_mesh_config(struct sk_buff *skb,
29cbe68c 7097 struct genl_info *info)
93da9cc1 7098{
4c476991 7099 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 7100 struct net_device *dev = info->user_ptr[1];
29cbe68c
JB
7101 struct wireless_dev *wdev = dev->ieee80211_ptr;
7102 struct mesh_config cur_params;
7103 int err = 0;
93da9cc1 7104 void *hdr;
7105 struct nlattr *pinfoattr;
7106 struct sk_buff *msg;
7107
29cbe68c
JB
7108 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
7109 return -EOPNOTSUPP;
7110
24bdd9f4 7111 if (!rdev->ops->get_mesh_config)
4c476991 7112 return -EOPNOTSUPP;
f3f92586 7113
29cbe68c
JB
7114 wdev_lock(wdev);
7115 /* If not connected, get default parameters */
7116 if (!wdev->mesh_id_len)
7117 memcpy(&cur_params, &default_mesh_config, sizeof(cur_params));
7118 else
e35e4d28 7119 err = rdev_get_mesh_config(rdev, dev, &cur_params);
29cbe68c
JB
7120 wdev_unlock(wdev);
7121
93da9cc1 7122 if (err)
4c476991 7123 return err;
93da9cc1 7124
7125 /* Draw up a netlink message to send back */
fd2120ca 7126 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
7127 if (!msg)
7128 return -ENOMEM;
15e47304 7129 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
24bdd9f4 7130 NL80211_CMD_GET_MESH_CONFIG);
93da9cc1 7131 if (!hdr)
efe1cf0c 7132 goto out;
ae0be8de 7133 pinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_MESH_CONFIG);
93da9cc1 7134 if (!pinfoattr)
7135 goto nla_put_failure;
9360ffd1
DM
7136 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
7137 nla_put_u16(msg, NL80211_MESHCONF_RETRY_TIMEOUT,
7138 cur_params.dot11MeshRetryTimeout) ||
7139 nla_put_u16(msg, NL80211_MESHCONF_CONFIRM_TIMEOUT,
7140 cur_params.dot11MeshConfirmTimeout) ||
7141 nla_put_u16(msg, NL80211_MESHCONF_HOLDING_TIMEOUT,
7142 cur_params.dot11MeshHoldingTimeout) ||
7143 nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS,
7144 cur_params.dot11MeshMaxPeerLinks) ||
7145 nla_put_u8(msg, NL80211_MESHCONF_MAX_RETRIES,
7146 cur_params.dot11MeshMaxRetries) ||
7147 nla_put_u8(msg, NL80211_MESHCONF_TTL,
7148 cur_params.dot11MeshTTL) ||
7149 nla_put_u8(msg, NL80211_MESHCONF_ELEMENT_TTL,
7150 cur_params.element_ttl) ||
7151 nla_put_u8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
7152 cur_params.auto_open_plinks) ||
7eab0f64
JL
7153 nla_put_u32(msg, NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
7154 cur_params.dot11MeshNbrOffsetMaxNeighbor) ||
9360ffd1
DM
7155 nla_put_u8(msg, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
7156 cur_params.dot11MeshHWMPmaxPREQretries) ||
7157 nla_put_u32(msg, NL80211_MESHCONF_PATH_REFRESH_TIME,
7158 cur_params.path_refresh_time) ||
7159 nla_put_u16(msg, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
7160 cur_params.min_discovery_timeout) ||
7161 nla_put_u32(msg, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
7162 cur_params.dot11MeshHWMPactivePathTimeout) ||
7163 nla_put_u16(msg, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
7164 cur_params.dot11MeshHWMPpreqMinInterval) ||
7165 nla_put_u16(msg, NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
7166 cur_params.dot11MeshHWMPperrMinInterval) ||
7167 nla_put_u16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
7168 cur_params.dot11MeshHWMPnetDiameterTraversalTime) ||
7169 nla_put_u8(msg, NL80211_MESHCONF_HWMP_ROOTMODE,
7170 cur_params.dot11MeshHWMPRootMode) ||
7171 nla_put_u16(msg, NL80211_MESHCONF_HWMP_RANN_INTERVAL,
7172 cur_params.dot11MeshHWMPRannInterval) ||
7173 nla_put_u8(msg, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
7174 cur_params.dot11MeshGateAnnouncementProtocol) ||
7175 nla_put_u8(msg, NL80211_MESHCONF_FORWARDING,
7176 cur_params.dot11MeshForwarding) ||
335d5349 7177 nla_put_s32(msg, NL80211_MESHCONF_RSSI_THRESHOLD,
70c33eaa
AN
7178 cur_params.rssi_threshold) ||
7179 nla_put_u32(msg, NL80211_MESHCONF_HT_OPMODE,
ac1073a6
CYY
7180 cur_params.ht_opmode) ||
7181 nla_put_u32(msg, NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
7182 cur_params.dot11MeshHWMPactivePathToRootTimeout) ||
7183 nla_put_u16(msg, NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
728b19e5
CYY
7184 cur_params.dot11MeshHWMProotInterval) ||
7185 nla_put_u16(msg, NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
3b1c5a53
MP
7186 cur_params.dot11MeshHWMPconfirmationInterval) ||
7187 nla_put_u32(msg, NL80211_MESHCONF_POWER_MODE,
7188 cur_params.power_mode) ||
7189 nla_put_u16(msg, NL80211_MESHCONF_AWAKE_WINDOW,
8e7c0538
CT
7190 cur_params.dot11MeshAwakeWindowDuration) ||
7191 nla_put_u32(msg, NL80211_MESHCONF_PLINK_TIMEOUT,
01d66fbd
BC
7192 cur_params.plink_timeout) ||
7193 nla_put_u8(msg, NL80211_MESHCONF_CONNECTED_TO_GATE,
e3718a61
LL
7194 cur_params.dot11MeshConnectedToMeshGate) ||
7195 nla_put_u8(msg, NL80211_MESHCONF_NOLEARN,
184eebe6
MT
7196 cur_params.dot11MeshNolearn) ||
7197 nla_put_u8(msg, NL80211_MESHCONF_CONNECTED_TO_AS,
7198 cur_params.dot11MeshConnectedToAuthServer))
9360ffd1 7199 goto nla_put_failure;
93da9cc1 7200 nla_nest_end(msg, pinfoattr);
7201 genlmsg_end(msg, hdr);
4c476991 7202 return genlmsg_reply(msg, info);
93da9cc1 7203
3b85875a 7204 nla_put_failure:
efe1cf0c 7205 out:
d080e275 7206 nlmsg_free(msg);
4c476991 7207 return -ENOBUFS;
93da9cc1 7208}
7209
ab0d76f6
JB
7210static const struct nla_policy
7211nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] = {
7212 [NL80211_MESHCONF_RETRY_TIMEOUT] =
7213 NLA_POLICY_RANGE(NLA_U16, 1, 255),
7214 [NL80211_MESHCONF_CONFIRM_TIMEOUT] =
7215 NLA_POLICY_RANGE(NLA_U16, 1, 255),
7216 [NL80211_MESHCONF_HOLDING_TIMEOUT] =
7217 NLA_POLICY_RANGE(NLA_U16, 1, 255),
7218 [NL80211_MESHCONF_MAX_PEER_LINKS] =
7219 NLA_POLICY_RANGE(NLA_U16, 0, 255),
7220 [NL80211_MESHCONF_MAX_RETRIES] = NLA_POLICY_MAX(NLA_U8, 16),
7221 [NL80211_MESHCONF_TTL] = NLA_POLICY_MIN(NLA_U8, 1),
7222 [NL80211_MESHCONF_ELEMENT_TTL] = NLA_POLICY_MIN(NLA_U8, 1),
7223 [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = NLA_POLICY_MAX(NLA_U8, 1),
7224 [NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR] =
7225 NLA_POLICY_RANGE(NLA_U32, 1, 255),
93da9cc1 7226 [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 },
7227 [NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 },
ab0d76f6 7228 [NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = NLA_POLICY_MIN(NLA_U16, 1),
93da9cc1 7229 [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 },
ab0d76f6
JB
7230 [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] =
7231 NLA_POLICY_MIN(NLA_U16, 1),
7232 [NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL] =
7233 NLA_POLICY_MIN(NLA_U16, 1),
7234 [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] =
7235 NLA_POLICY_MIN(NLA_U16, 1),
7236 [NL80211_MESHCONF_HWMP_ROOTMODE] = NLA_POLICY_MAX(NLA_U8, 4),
7237 [NL80211_MESHCONF_HWMP_RANN_INTERVAL] =
7238 NLA_POLICY_MIN(NLA_U16, 1),
7239 [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = NLA_POLICY_MAX(NLA_U8, 1),
7240 [NL80211_MESHCONF_FORWARDING] = NLA_POLICY_MAX(NLA_U8, 1),
7241 [NL80211_MESHCONF_RSSI_THRESHOLD] =
7242 NLA_POLICY_RANGE(NLA_S32, -255, 0),
a4f606ea 7243 [NL80211_MESHCONF_HT_OPMODE] = { .type = NLA_U16 },
ac1073a6 7244 [NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT] = { .type = NLA_U32 },
ab0d76f6
JB
7245 [NL80211_MESHCONF_HWMP_ROOT_INTERVAL] =
7246 NLA_POLICY_MIN(NLA_U16, 1),
7247 [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] =
7248 NLA_POLICY_MIN(NLA_U16, 1),
7249 [NL80211_MESHCONF_POWER_MODE] =
7250 NLA_POLICY_RANGE(NLA_U32,
7251 NL80211_MESH_POWER_ACTIVE,
7252 NL80211_MESH_POWER_MAX),
3b1c5a53 7253 [NL80211_MESHCONF_AWAKE_WINDOW] = { .type = NLA_U16 },
8e7c0538 7254 [NL80211_MESHCONF_PLINK_TIMEOUT] = { .type = NLA_U32 },
01d66fbd 7255 [NL80211_MESHCONF_CONNECTED_TO_GATE] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
e3718a61 7256 [NL80211_MESHCONF_NOLEARN] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
184eebe6 7257 [NL80211_MESHCONF_CONNECTED_TO_AS] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
93da9cc1 7258};
7259
c80d545d
JC
7260static const struct nla_policy
7261 nl80211_mesh_setup_params_policy[NL80211_MESH_SETUP_ATTR_MAX+1] = {
d299a1f2 7262 [NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC] = { .type = NLA_U8 },
c80d545d
JC
7263 [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 },
7264 [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 },
15d5dda6 7265 [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG },
6e16d90b 7266 [NL80211_MESH_SETUP_AUTH_PROTOCOL] = { .type = NLA_U8 },
bb2798d4 7267 [NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG },
3d7af878
JB
7268 [NL80211_MESH_SETUP_IE] =
7269 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
7270 IEEE80211_MAX_DATA_LEN),
b130e5ce 7271 [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG },
c80d545d
JC
7272};
7273
24bdd9f4 7274static int nl80211_parse_mesh_config(struct genl_info *info,
bd90fdcc
JB
7275 struct mesh_config *cfg,
7276 u32 *mask_out)
93da9cc1 7277{
93da9cc1 7278 struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1];
bd90fdcc 7279 u32 mask = 0;
9757235f 7280 u16 ht_opmode;
93da9cc1 7281
ab0d76f6
JB
7282#define FILL_IN_MESH_PARAM_IF_SET(tb, cfg, param, mask, attr, fn) \
7283do { \
7284 if (tb[attr]) { \
7285 cfg->param = fn(tb[attr]); \
7286 mask |= BIT((attr) - 1); \
7287 } \
ea54fba2 7288} while (0)
bd90fdcc 7289
24bdd9f4 7290 if (!info->attrs[NL80211_ATTR_MESH_CONFIG])
93da9cc1 7291 return -EINVAL;
8cb08174 7292 if (nla_parse_nested_deprecated(tb, NL80211_MESHCONF_ATTR_MAX, info->attrs[NL80211_ATTR_MESH_CONFIG], nl80211_meshconf_params_policy, info->extack))
93da9cc1 7293 return -EINVAL;
7294
93da9cc1 7295 /* This makes sure that there aren't more than 32 mesh config
7296 * parameters (otherwise our bitfield scheme would not work.) */
7297 BUILD_BUG_ON(NL80211_MESHCONF_ATTR_MAX > 32);
7298
7299 /* Fill in the params struct */
ab0d76f6
JB
7300 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, mask,
7301 NL80211_MESHCONF_RETRY_TIMEOUT, nla_get_u16);
7302 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, mask,
7303 NL80211_MESHCONF_CONFIRM_TIMEOUT,
7304 nla_get_u16);
7305 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, mask,
7306 NL80211_MESHCONF_HOLDING_TIMEOUT,
7307 nla_get_u16);
7308 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, mask,
7309 NL80211_MESHCONF_MAX_PEER_LINKS,
7310 nla_get_u16);
7311 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, mask,
7312 NL80211_MESHCONF_MAX_RETRIES, nla_get_u8);
7313 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, mask,
7314 NL80211_MESHCONF_TTL, nla_get_u8);
7315 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, mask,
7316 NL80211_MESHCONF_ELEMENT_TTL, nla_get_u8);
7317 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, mask,
7318 NL80211_MESHCONF_AUTO_OPEN_PLINKS,
7319 nla_get_u8);
ea54fba2 7320 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor,
ab0d76f6 7321 mask,
a4f606ea 7322 NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
ab0d76f6
JB
7323 nla_get_u32);
7324 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, mask,
7325 NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
7326 nla_get_u8);
7327 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, mask,
7328 NL80211_MESHCONF_PATH_REFRESH_TIME,
7329 nla_get_u32);
7330 if (mask & BIT(NL80211_MESHCONF_PATH_REFRESH_TIME) &&
7331 (cfg->path_refresh_time < 1 || cfg->path_refresh_time > 65535))
7332 return -EINVAL;
7333 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, mask,
7334 NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
7335 nla_get_u16);
ea54fba2 7336 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout,
ab0d76f6 7337 mask,
a4f606ea 7338 NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
ab0d76f6
JB
7339 nla_get_u32);
7340 if (mask & BIT(NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT) &&
7341 (cfg->dot11MeshHWMPactivePathTimeout < 1 ||
7342 cfg->dot11MeshHWMPactivePathTimeout > 65535))
7343 return -EINVAL;
7344 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval, mask,
ea54fba2 7345 NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
ab0d76f6
JB
7346 nla_get_u16);
7347 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval, mask,
ea54fba2 7348 NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
ab0d76f6 7349 nla_get_u16);
93da9cc1 7350 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
ab0d76f6 7351 dot11MeshHWMPnetDiameterTraversalTime, mask,
a4f606ea 7352 NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
ab0d76f6
JB
7353 nla_get_u16);
7354 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, mask,
7355 NL80211_MESHCONF_HWMP_ROOTMODE, nla_get_u8);
7356 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, mask,
7357 NL80211_MESHCONF_HWMP_RANN_INTERVAL,
7358 nla_get_u16);
7359 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshGateAnnouncementProtocol,
ea54fba2 7360 mask, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
ab0d76f6
JB
7361 nla_get_u8);
7362 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, mask,
7363 NL80211_MESHCONF_FORWARDING, nla_get_u8);
7364 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, mask,
7365 NL80211_MESHCONF_RSSI_THRESHOLD,
7366 nla_get_s32);
01d66fbd
BC
7367 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConnectedToMeshGate, mask,
7368 NL80211_MESHCONF_CONNECTED_TO_GATE,
7369 nla_get_u8);
184eebe6
MT
7370 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConnectedToAuthServer, mask,
7371 NL80211_MESHCONF_CONNECTED_TO_AS,
7372 nla_get_u8);
9757235f
MH
7373 /*
7374 * Check HT operation mode based on
188f60ab 7375 * IEEE 802.11-2016 9.4.2.57 HT Operation element.
9757235f
MH
7376 */
7377 if (tb[NL80211_MESHCONF_HT_OPMODE]) {
7378 ht_opmode = nla_get_u16(tb[NL80211_MESHCONF_HT_OPMODE]);
7379
7380 if (ht_opmode & ~(IEEE80211_HT_OP_MODE_PROTECTION |
7381 IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT |
7382 IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT))
7383 return -EINVAL;
7384
188f60ab
BC
7385 /* NON_HT_STA bit is reserved, but some programs set it */
7386 ht_opmode &= ~IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT;
9757235f 7387
9757235f 7388 cfg->ht_opmode = ht_opmode;
fd551bac 7389 mask |= (1 << (NL80211_MESHCONF_HT_OPMODE - 1));
9757235f 7390 }
728b19e5 7391 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
ab0d76f6
JB
7392 dot11MeshHWMPactivePathToRootTimeout, mask,
7393 NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
7394 nla_get_u32);
7395 if (mask & BIT(NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT) &&
7396 (cfg->dot11MeshHWMPactivePathToRootTimeout < 1 ||
7397 cfg->dot11MeshHWMPactivePathToRootTimeout > 65535))
7398 return -EINVAL;
7399 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMProotInterval, mask,
7400 NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
7401 nla_get_u16);
7402 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPconfirmationInterval,
7403 mask,
728b19e5 7404 NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
ab0d76f6
JB
7405 nla_get_u16);
7406 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode, mask,
7407 NL80211_MESHCONF_POWER_MODE, nla_get_u32);
7408 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration, mask,
7409 NL80211_MESHCONF_AWAKE_WINDOW, nla_get_u16);
7410 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, mask,
7411 NL80211_MESHCONF_PLINK_TIMEOUT, nla_get_u32);
e3718a61
LL
7412 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNolearn, mask,
7413 NL80211_MESHCONF_NOLEARN, nla_get_u8);
bd90fdcc
JB
7414 if (mask_out)
7415 *mask_out = mask;
c80d545d 7416
bd90fdcc
JB
7417 return 0;
7418
7419#undef FILL_IN_MESH_PARAM_IF_SET
7420}
7421
c80d545d
JC
7422static int nl80211_parse_mesh_setup(struct genl_info *info,
7423 struct mesh_setup *setup)
7424{
bb2798d4 7425 struct cfg80211_registered_device *rdev = info->user_ptr[0];
c80d545d
JC
7426 struct nlattr *tb[NL80211_MESH_SETUP_ATTR_MAX + 1];
7427
7428 if (!info->attrs[NL80211_ATTR_MESH_SETUP])
7429 return -EINVAL;
8cb08174 7430 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
7431 return -EINVAL;
7432
d299a1f2
JC
7433 if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC])
7434 setup->sync_method =
7435 (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC])) ?
7436 IEEE80211_SYNC_METHOD_VENDOR :
7437 IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET;
7438
c80d545d
JC
7439 if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])
7440 setup->path_sel_proto =
7441 (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])) ?
7442 IEEE80211_PATH_PROTOCOL_VENDOR :
7443 IEEE80211_PATH_PROTOCOL_HWMP;
7444
7445 if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC])
7446 setup->path_metric =
7447 (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC])) ?
7448 IEEE80211_PATH_METRIC_VENDOR :
7449 IEEE80211_PATH_METRIC_AIRTIME;
7450
581a8b0f 7451 if (tb[NL80211_MESH_SETUP_IE]) {
c80d545d 7452 struct nlattr *ieattr =
581a8b0f 7453 tb[NL80211_MESH_SETUP_IE];
581a8b0f
JC
7454 setup->ie = nla_data(ieattr);
7455 setup->ie_len = nla_len(ieattr);
c80d545d 7456 }
bb2798d4
TP
7457 if (tb[NL80211_MESH_SETUP_USERSPACE_MPM] &&
7458 !(rdev->wiphy.features & NL80211_FEATURE_USERSPACE_MPM))
7459 return -EINVAL;
7460 setup->user_mpm = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_MPM]);
b130e5ce
JC
7461 setup->is_authenticated = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]);
7462 setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AMPE]);
bb2798d4
TP
7463 if (setup->is_secure)
7464 setup->user_mpm = true;
c80d545d 7465
6e16d90b
CT
7466 if (tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]) {
7467 if (!setup->user_mpm)
7468 return -EINVAL;
7469 setup->auth_id =
7470 nla_get_u8(tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]);
7471 }
7472
c80d545d
JC
7473 return 0;
7474}
7475
24bdd9f4 7476static int nl80211_update_mesh_config(struct sk_buff *skb,
29cbe68c 7477 struct genl_info *info)
bd90fdcc
JB
7478{
7479 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7480 struct net_device *dev = info->user_ptr[1];
29cbe68c 7481 struct wireless_dev *wdev = dev->ieee80211_ptr;
bd90fdcc
JB
7482 struct mesh_config cfg;
7483 u32 mask;
7484 int err;
7485
29cbe68c
JB
7486 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
7487 return -EOPNOTSUPP;
7488
24bdd9f4 7489 if (!rdev->ops->update_mesh_config)
bd90fdcc
JB
7490 return -EOPNOTSUPP;
7491
24bdd9f4 7492 err = nl80211_parse_mesh_config(info, &cfg, &mask);
bd90fdcc
JB
7493 if (err)
7494 return err;
7495
29cbe68c
JB
7496 wdev_lock(wdev);
7497 if (!wdev->mesh_id_len)
7498 err = -ENOLINK;
7499
7500 if (!err)
e35e4d28 7501 err = rdev_update_mesh_config(rdev, dev, mask, &cfg);
29cbe68c
JB
7502
7503 wdev_unlock(wdev);
7504
7505 return err;
93da9cc1 7506}
7507
ad30ca2c
AN
7508static int nl80211_put_regdom(const struct ieee80211_regdomain *regdom,
7509 struct sk_buff *msg)
f130347c 7510{
f130347c
LR
7511 struct nlattr *nl_reg_rules;
7512 unsigned int i;
f130347c 7513
458f4f9e
JB
7514 if (nla_put_string(msg, NL80211_ATTR_REG_ALPHA2, regdom->alpha2) ||
7515 (regdom->dfs_region &&
7516 nla_put_u8(msg, NL80211_ATTR_DFS_REGION, regdom->dfs_region)))
ad30ca2c 7517 goto nla_put_failure;
458f4f9e 7518
ae0be8de 7519 nl_reg_rules = nla_nest_start_noflag(msg, NL80211_ATTR_REG_RULES);
f130347c 7520 if (!nl_reg_rules)
ad30ca2c 7521 goto nla_put_failure;
f130347c 7522
458f4f9e 7523 for (i = 0; i < regdom->n_reg_rules; i++) {
f130347c
LR
7524 struct nlattr *nl_reg_rule;
7525 const struct ieee80211_reg_rule *reg_rule;
7526 const struct ieee80211_freq_range *freq_range;
7527 const struct ieee80211_power_rule *power_rule;
97524820 7528 unsigned int max_bandwidth_khz;
f130347c 7529
458f4f9e 7530 reg_rule = &regdom->reg_rules[i];
f130347c
LR
7531 freq_range = &reg_rule->freq_range;
7532 power_rule = &reg_rule->power_rule;
7533
ae0be8de 7534 nl_reg_rule = nla_nest_start_noflag(msg, i);
f130347c 7535 if (!nl_reg_rule)
ad30ca2c 7536 goto nla_put_failure;
f130347c 7537
97524820
JD
7538 max_bandwidth_khz = freq_range->max_bandwidth_khz;
7539 if (!max_bandwidth_khz)
7540 max_bandwidth_khz = reg_get_max_bandwidth(regdom,
7541 reg_rule);
7542
9360ffd1
DM
7543 if (nla_put_u32(msg, NL80211_ATTR_REG_RULE_FLAGS,
7544 reg_rule->flags) ||
7545 nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_START,
7546 freq_range->start_freq_khz) ||
7547 nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_END,
7548 freq_range->end_freq_khz) ||
7549 nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW,
97524820 7550 max_bandwidth_khz) ||
9360ffd1
DM
7551 nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
7552 power_rule->max_antenna_gain) ||
7553 nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP,
089027e5
JD
7554 power_rule->max_eirp) ||
7555 nla_put_u32(msg, NL80211_ATTR_DFS_CAC_TIME,
7556 reg_rule->dfs_cac_ms))
ad30ca2c 7557 goto nla_put_failure;
f130347c
LR
7558
7559 nla_nest_end(msg, nl_reg_rule);
7560 }
7561
7562 nla_nest_end(msg, nl_reg_rules);
ad30ca2c
AN
7563 return 0;
7564
7565nla_put_failure:
7566 return -EMSGSIZE;
7567}
7568
7569static int nl80211_get_reg_do(struct sk_buff *skb, struct genl_info *info)
7570{
7571 const struct ieee80211_regdomain *regdom = NULL;
7572 struct cfg80211_registered_device *rdev;
7573 struct wiphy *wiphy = NULL;
7574 struct sk_buff *msg;
7575 void *hdr;
7576
7577 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7578 if (!msg)
7579 return -ENOBUFS;
7580
7581 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
7582 NL80211_CMD_GET_REG);
7583 if (!hdr)
7584 goto put_failure;
7585
7586 if (info->attrs[NL80211_ATTR_WIPHY]) {
1bdd716c
AN
7587 bool self_managed;
7588
ad30ca2c
AN
7589 rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
7590 if (IS_ERR(rdev)) {
7591 nlmsg_free(msg);
7592 return PTR_ERR(rdev);
7593 }
7594
7595 wiphy = &rdev->wiphy;
1bdd716c
AN
7596 self_managed = wiphy->regulatory_flags &
7597 REGULATORY_WIPHY_SELF_MANAGED;
ad30ca2c
AN
7598 regdom = get_wiphy_regdom(wiphy);
7599
1bdd716c
AN
7600 /* a self-managed-reg device must have a private regdom */
7601 if (WARN_ON(!regdom && self_managed)) {
7602 nlmsg_free(msg);
7603 return -EINVAL;
7604 }
7605
ad30ca2c
AN
7606 if (regdom &&
7607 nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
7608 goto nla_put_failure;
7609 }
7610
7611 if (!wiphy && reg_last_request_cell_base() &&
7612 nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
7613 NL80211_USER_REG_HINT_CELL_BASE))
7614 goto nla_put_failure;
7615
7616 rcu_read_lock();
7617
7618 if (!regdom)
7619 regdom = rcu_dereference(cfg80211_regdomain);
7620
7621 if (nl80211_put_regdom(regdom, msg))
7622 goto nla_put_failure_rcu;
7623
7624 rcu_read_unlock();
f130347c
LR
7625
7626 genlmsg_end(msg, hdr);
5fe231e8 7627 return genlmsg_reply(msg, info);
f130347c 7628
458f4f9e
JB
7629nla_put_failure_rcu:
7630 rcu_read_unlock();
f130347c 7631nla_put_failure:
efe1cf0c 7632put_failure:
d080e275 7633 nlmsg_free(msg);
5fe231e8 7634 return -EMSGSIZE;
f130347c
LR
7635}
7636
ad30ca2c
AN
7637static int nl80211_send_regdom(struct sk_buff *msg, struct netlink_callback *cb,
7638 u32 seq, int flags, struct wiphy *wiphy,
7639 const struct ieee80211_regdomain *regdom)
7640{
7641 void *hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).portid, seq, flags,
7642 NL80211_CMD_GET_REG);
7643
7644 if (!hdr)
7645 return -1;
7646
0a833c29 7647 genl_dump_check_consistent(cb, hdr);
ad30ca2c
AN
7648
7649 if (nl80211_put_regdom(regdom, msg))
7650 goto nla_put_failure;
7651
7652 if (!wiphy && reg_last_request_cell_base() &&
7653 nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
7654 NL80211_USER_REG_HINT_CELL_BASE))
7655 goto nla_put_failure;
7656
7657 if (wiphy &&
7658 nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
7659 goto nla_put_failure;
7660
1bdd716c
AN
7661 if (wiphy && wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
7662 nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
7663 goto nla_put_failure;
7664
053c095a
JB
7665 genlmsg_end(msg, hdr);
7666 return 0;
ad30ca2c
AN
7667
7668nla_put_failure:
7669 genlmsg_cancel(msg, hdr);
7670 return -EMSGSIZE;
7671}
7672
7673static int nl80211_get_reg_dump(struct sk_buff *skb,
7674 struct netlink_callback *cb)
7675{
7676 const struct ieee80211_regdomain *regdom = NULL;
7677 struct cfg80211_registered_device *rdev;
7678 int err, reg_idx, start = cb->args[2];
7679
7680 rtnl_lock();
7681
7682 if (cfg80211_regdomain && start == 0) {
7683 err = nl80211_send_regdom(skb, cb, cb->nlh->nlmsg_seq,
7684 NLM_F_MULTI, NULL,
7685 rtnl_dereference(cfg80211_regdomain));
7686 if (err < 0)
7687 goto out_err;
7688 }
7689
7690 /* the global regdom is idx 0 */
7691 reg_idx = 1;
7692 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
7693 regdom = get_wiphy_regdom(&rdev->wiphy);
7694 if (!regdom)
7695 continue;
7696
7697 if (++reg_idx <= start)
7698 continue;
7699
7700 err = nl80211_send_regdom(skb, cb, cb->nlh->nlmsg_seq,
7701 NLM_F_MULTI, &rdev->wiphy, regdom);
7702 if (err < 0) {
7703 reg_idx--;
7704 break;
7705 }
7706 }
7707
7708 cb->args[2] = reg_idx;
7709 err = skb->len;
7710out_err:
7711 rtnl_unlock();
7712 return err;
7713}
7714
b6863036
JB
7715#ifdef CONFIG_CFG80211_CRDA_SUPPORT
7716static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = {
7717 [NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 },
7718 [NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 },
7719 [NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 },
7720 [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 },
7721 [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 },
7722 [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 },
7723 [NL80211_ATTR_DFS_CAC_TIME] = { .type = NLA_U32 },
7724};
7725
7726static int parse_reg_rule(struct nlattr *tb[],
7727 struct ieee80211_reg_rule *reg_rule)
7728{
7729 struct ieee80211_freq_range *freq_range = &reg_rule->freq_range;
7730 struct ieee80211_power_rule *power_rule = &reg_rule->power_rule;
7731
7732 if (!tb[NL80211_ATTR_REG_RULE_FLAGS])
7733 return -EINVAL;
7734 if (!tb[NL80211_ATTR_FREQ_RANGE_START])
7735 return -EINVAL;
7736 if (!tb[NL80211_ATTR_FREQ_RANGE_END])
7737 return -EINVAL;
7738 if (!tb[NL80211_ATTR_FREQ_RANGE_MAX_BW])
7739 return -EINVAL;
7740 if (!tb[NL80211_ATTR_POWER_RULE_MAX_EIRP])
7741 return -EINVAL;
7742
7743 reg_rule->flags = nla_get_u32(tb[NL80211_ATTR_REG_RULE_FLAGS]);
7744
7745 freq_range->start_freq_khz =
7746 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]);
7747 freq_range->end_freq_khz =
7748 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]);
7749 freq_range->max_bandwidth_khz =
7750 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]);
7751
7752 power_rule->max_eirp =
7753 nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]);
7754
7755 if (tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN])
7756 power_rule->max_antenna_gain =
7757 nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]);
7758
7759 if (tb[NL80211_ATTR_DFS_CAC_TIME])
7760 reg_rule->dfs_cac_ms =
7761 nla_get_u32(tb[NL80211_ATTR_DFS_CAC_TIME]);
7762
7763 return 0;
7764}
7765
b2e1b302
LR
7766static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
7767{
7768 struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1];
7769 struct nlattr *nl_reg_rule;
ea372c54
JB
7770 char *alpha2;
7771 int rem_reg_rules, r;
391d132c 7772 u32 num_rules = 0, rule_idx = 0;
4c7d3982 7773 enum nl80211_dfs_regions dfs_region = NL80211_DFS_UNSET;
ea372c54 7774 struct ieee80211_regdomain *rd;
b2e1b302
LR
7775
7776 if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
7777 return -EINVAL;
7778
7779 if (!info->attrs[NL80211_ATTR_REG_RULES])
7780 return -EINVAL;
7781
7782 alpha2 = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
7783
8b60b078
LR
7784 if (info->attrs[NL80211_ATTR_DFS_REGION])
7785 dfs_region = nla_get_u8(info->attrs[NL80211_ATTR_DFS_REGION]);
7786
b2e1b302 7787 nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
1a919318 7788 rem_reg_rules) {
b2e1b302
LR
7789 num_rules++;
7790 if (num_rules > NL80211_MAX_SUPP_REG_RULES)
4776c6e7 7791 return -EINVAL;
b2e1b302
LR
7792 }
7793
e438768f
LR
7794 if (!reg_is_valid_request(alpha2))
7795 return -EINVAL;
7796
391d132c 7797 rd = kzalloc(struct_size(rd, reg_rules, num_rules), GFP_KERNEL);
6913b49a
JB
7798 if (!rd)
7799 return -ENOMEM;
b2e1b302
LR
7800
7801 rd->n_reg_rules = num_rules;
7802 rd->alpha2[0] = alpha2[0];
7803 rd->alpha2[1] = alpha2[1];
7804
8b60b078
LR
7805 /*
7806 * Disable DFS master mode if the DFS region was
7807 * not supported or known on this kernel.
7808 */
7809 if (reg_supported_dfs_region(dfs_region))
7810 rd->dfs_region = dfs_region;
7811
b2e1b302 7812 nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
1a919318 7813 rem_reg_rules) {
8cb08174
JB
7814 r = nla_parse_nested_deprecated(tb, NL80211_REG_RULE_ATTR_MAX,
7815 nl_reg_rule, reg_rule_policy,
7816 info->extack);
ae811e21
JB
7817 if (r)
7818 goto bad_reg;
b2e1b302
LR
7819 r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]);
7820 if (r)
7821 goto bad_reg;
7822
7823 rule_idx++;
7824
d0e18f83
LR
7825 if (rule_idx > NL80211_MAX_SUPP_REG_RULES) {
7826 r = -EINVAL;
b2e1b302 7827 goto bad_reg;
d0e18f83 7828 }
b2e1b302
LR
7829 }
7830
06627990
JB
7831 /* set_regdom takes ownership of rd */
7832 return set_regdom(rd, REGD_SOURCE_CRDA);
d2372b31 7833 bad_reg:
b2e1b302 7834 kfree(rd);
d0e18f83 7835 return r;
b2e1b302 7836}
b6863036 7837#endif /* CONFIG_CFG80211_CRDA_SUPPORT */
b2e1b302 7838
83f5e2cf
JB
7839static int validate_scan_freqs(struct nlattr *freqs)
7840{
7841 struct nlattr *attr1, *attr2;
7842 int n_channels = 0, tmp1, tmp2;
7843
d7f13f74
SD
7844 nla_for_each_nested(attr1, freqs, tmp1)
7845 if (nla_len(attr1) != sizeof(u32))
7846 return 0;
7847
83f5e2cf
JB
7848 nla_for_each_nested(attr1, freqs, tmp1) {
7849 n_channels++;
7850 /*
7851 * Some hardware has a limited channel list for
7852 * scanning, and it is pretty much nonsensical
7853 * to scan for a channel twice, so disallow that
7854 * and don't require drivers to check that the
7855 * channel list they get isn't longer than what
7856 * they can scan, as long as they can scan all
7857 * the channels they registered at once.
7858 */
7859 nla_for_each_nested(attr2, freqs, tmp2)
7860 if (attr1 != attr2 &&
7861 nla_get_u32(attr1) == nla_get_u32(attr2))
7862 return 0;
7863 }
7864
7865 return n_channels;
7866}
7867
57fbcce3 7868static bool is_band_valid(struct wiphy *wiphy, enum nl80211_band b)
38de03d2 7869{
57fbcce3 7870 return b < NUM_NL80211_BANDS && wiphy->bands[b];
38de03d2
AS
7871}
7872
7873static int parse_bss_select(struct nlattr *nla, struct wiphy *wiphy,
7874 struct cfg80211_bss_selection *bss_select)
7875{
7876 struct nlattr *attr[NL80211_BSS_SELECT_ATTR_MAX + 1];
7877 struct nlattr *nest;
7878 int err;
7879 bool found = false;
7880 int i;
7881
7882 /* only process one nested attribute */
7883 nest = nla_data(nla);
7884 if (!nla_ok(nest, nla_len(nest)))
7885 return -EINVAL;
7886
8cb08174
JB
7887 err = nla_parse_nested_deprecated(attr, NL80211_BSS_SELECT_ATTR_MAX,
7888 nest, nl80211_bss_select_policy,
7889 NULL);
38de03d2
AS
7890 if (err)
7891 return err;
7892
7893 /* only one attribute may be given */
7894 for (i = 0; i <= NL80211_BSS_SELECT_ATTR_MAX; i++) {
7895 if (attr[i]) {
7896 if (found)
7897 return -EINVAL;
7898 found = true;
7899 }
7900 }
7901
7902 bss_select->behaviour = __NL80211_BSS_SELECT_ATTR_INVALID;
7903
7904 if (attr[NL80211_BSS_SELECT_ATTR_RSSI])
7905 bss_select->behaviour = NL80211_BSS_SELECT_ATTR_RSSI;
7906
7907 if (attr[NL80211_BSS_SELECT_ATTR_BAND_PREF]) {
7908 bss_select->behaviour = NL80211_BSS_SELECT_ATTR_BAND_PREF;
7909 bss_select->param.band_pref =
7910 nla_get_u32(attr[NL80211_BSS_SELECT_ATTR_BAND_PREF]);
7911 if (!is_band_valid(wiphy, bss_select->param.band_pref))
7912 return -EINVAL;
7913 }
7914
7915 if (attr[NL80211_BSS_SELECT_ATTR_RSSI_ADJUST]) {
7916 struct nl80211_bss_select_rssi_adjust *adj_param;
7917
7918 adj_param = nla_data(attr[NL80211_BSS_SELECT_ATTR_RSSI_ADJUST]);
7919 bss_select->behaviour = NL80211_BSS_SELECT_ATTR_RSSI_ADJUST;
7920 bss_select->param.adjust.band = adj_param->band;
7921 bss_select->param.adjust.delta = adj_param->delta;
7922 if (!is_band_valid(wiphy, bss_select->param.adjust.band))
7923 return -EINVAL;
7924 }
7925
7926 /* user-space did not provide behaviour attribute */
7927 if (bss_select->behaviour == __NL80211_BSS_SELECT_ATTR_INVALID)
7928 return -EINVAL;
7929
7930 if (!(wiphy->bss_select_support & BIT(bss_select->behaviour)))
7931 return -EINVAL;
7932
7933 return 0;
7934}
7935
9bb7e0f2
JB
7936int nl80211_parse_random_mac(struct nlattr **attrs,
7937 u8 *mac_addr, u8 *mac_addr_mask)
ad2b26ab
JB
7938{
7939 int i;
7940
7941 if (!attrs[NL80211_ATTR_MAC] && !attrs[NL80211_ATTR_MAC_MASK]) {
d2beae10
JP
7942 eth_zero_addr(mac_addr);
7943 eth_zero_addr(mac_addr_mask);
ad2b26ab
JB
7944 mac_addr[0] = 0x2;
7945 mac_addr_mask[0] = 0x3;
7946
7947 return 0;
7948 }
7949
7950 /* need both or none */
7951 if (!attrs[NL80211_ATTR_MAC] || !attrs[NL80211_ATTR_MAC_MASK])
7952 return -EINVAL;
7953
7954 memcpy(mac_addr, nla_data(attrs[NL80211_ATTR_MAC]), ETH_ALEN);
7955 memcpy(mac_addr_mask, nla_data(attrs[NL80211_ATTR_MAC_MASK]), ETH_ALEN);
7956
7957 /* don't allow or configure an mcast address */
7958 if (!is_multicast_ether_addr(mac_addr_mask) ||
7959 is_multicast_ether_addr(mac_addr))
7960 return -EINVAL;
7961
7962 /*
7963 * allow users to pass a MAC address that has bits set outside
7964 * of the mask, but don't bother drivers with having to deal
7965 * with such bits
7966 */
7967 for (i = 0; i < ETH_ALEN; i++)
7968 mac_addr[i] &= mac_addr_mask[i];
7969
7970 return 0;
7971}
7972
34373d12
VT
7973static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev)
7974{
7975 ASSERT_WDEV_LOCK(wdev);
7976
7977 if (!cfg80211_beaconing_iface_active(wdev))
7978 return true;
7979
7980 if (!(wdev->chandef.chan->flags & IEEE80211_CHAN_RADAR))
7981 return true;
7982
7983 return regulatory_pre_cac_allowed(wdev->wiphy);
7984}
7985
db0a4ad8
JB
7986static bool nl80211_check_scan_feat(struct wiphy *wiphy, u32 flags, u32 flag,
7987 enum nl80211_ext_feature_index feat)
7988{
7989 if (!(flags & flag))
7990 return true;
7991 if (wiphy_ext_feature_isset(wiphy, feat))
7992 return true;
7993 return false;
7994}
7995
2d23d073
RZ
7996static int
7997nl80211_check_scan_flags(struct wiphy *wiphy, struct wireless_dev *wdev,
7998 void *request, struct nlattr **attrs,
7999 bool is_sched_scan)
8000{
8001 u8 *mac_addr, *mac_addr_mask;
8002 u32 *flags;
8003 enum nl80211_feature_flags randomness_flag;
8004
8005 if (!attrs[NL80211_ATTR_SCAN_FLAGS])
8006 return 0;
8007
8008 if (is_sched_scan) {
8009 struct cfg80211_sched_scan_request *req = request;
8010
8011 randomness_flag = wdev ?
8012 NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR :
8013 NL80211_FEATURE_ND_RANDOM_MAC_ADDR;
8014 flags = &req->flags;
8015 mac_addr = req->mac_addr;
8016 mac_addr_mask = req->mac_addr_mask;
8017 } else {
8018 struct cfg80211_scan_request *req = request;
8019
8020 randomness_flag = NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
8021 flags = &req->flags;
8022 mac_addr = req->mac_addr;
8023 mac_addr_mask = req->mac_addr_mask;
8024 }
8025
8026 *flags = nla_get_u32(attrs[NL80211_ATTR_SCAN_FLAGS]);
8027
5037a009
SD
8028 if (((*flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
8029 !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) ||
db0a4ad8
JB
8030 !nl80211_check_scan_feat(wiphy, *flags,
8031 NL80211_SCAN_FLAG_LOW_SPAN,
8032 NL80211_EXT_FEATURE_LOW_SPAN_SCAN) ||
8033 !nl80211_check_scan_feat(wiphy, *flags,
8034 NL80211_SCAN_FLAG_LOW_POWER,
8035 NL80211_EXT_FEATURE_LOW_POWER_SCAN) ||
8036 !nl80211_check_scan_feat(wiphy, *flags,
8037 NL80211_SCAN_FLAG_HIGH_ACCURACY,
8038 NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN) ||
8039 !nl80211_check_scan_feat(wiphy, *flags,
8040 NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME,
8041 NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME) ||
8042 !nl80211_check_scan_feat(wiphy, *flags,
8043 NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP,
8044 NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP) ||
8045 !nl80211_check_scan_feat(wiphy, *flags,
8046 NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION,
8047 NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION) ||
8048 !nl80211_check_scan_feat(wiphy, *flags,
8049 NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE,
2e076f19
JB
8050 NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE) ||
8051 !nl80211_check_scan_feat(wiphy, *flags,
8052 NL80211_SCAN_FLAG_RANDOM_SN,
8053 NL80211_EXT_FEATURE_SCAN_RANDOM_SN) ||
8054 !nl80211_check_scan_feat(wiphy, *flags,
8055 NL80211_SCAN_FLAG_MIN_PREQ_CONTENT,
8056 NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT))
2d23d073
RZ
8057 return -EOPNOTSUPP;
8058
8059 if (*flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
8060 int err;
8061
8062 if (!(wiphy->features & randomness_flag) ||
8063 (wdev && wdev->current_bss))
8064 return -EOPNOTSUPP;
8065
8066 err = nl80211_parse_random_mac(attrs, mac_addr, mac_addr_mask);
8067 if (err)
8068 return err;
8069 }
8070
2d23d073
RZ
8071 return 0;
8072}
8073
2a519311
JB
8074static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
8075{
4c476991 8076 struct cfg80211_registered_device *rdev = info->user_ptr[0];
fd014284 8077 struct wireless_dev *wdev = info->user_ptr[1];
2a519311 8078 struct cfg80211_scan_request *request;
2032f3b2
TP
8079 struct nlattr *scan_freqs = NULL;
8080 bool scan_freqs_khz = false;
2a519311
JB
8081 struct nlattr *attr;
8082 struct wiphy *wiphy;
83f5e2cf 8083 int err, tmp, n_ssids = 0, n_channels, i;
70692ad2 8084 size_t ie_len;
2a519311 8085
79c97e97 8086 wiphy = &rdev->wiphy;
2a519311 8087
cb3b7d87
AB
8088 if (wdev->iftype == NL80211_IFTYPE_NAN)
8089 return -EOPNOTSUPP;
8090
4c476991
JB
8091 if (!rdev->ops->scan)
8092 return -EOPNOTSUPP;
2a519311 8093
83286856
CJ
8094 if (rdev->scan_req || rdev->scan_msg)
8095 return -EBUSY;
2a519311 8096
2032f3b2
TP
8097 if (info->attrs[NL80211_ATTR_SCAN_FREQ_KHZ]) {
8098 if (!wiphy_ext_feature_isset(wiphy,
8099 NL80211_EXT_FEATURE_SCAN_FREQ_KHZ))
8100 return -EOPNOTSUPP;
8101 scan_freqs = info->attrs[NL80211_ATTR_SCAN_FREQ_KHZ];
8102 scan_freqs_khz = true;
8103 } else if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES])
8104 scan_freqs = info->attrs[NL80211_ATTR_SCAN_FREQUENCIES];
8105
8106 if (scan_freqs) {
8107 n_channels = validate_scan_freqs(scan_freqs);
83286856
CJ
8108 if (!n_channels)
8109 return -EINVAL;
2a519311 8110 } else {
bdfbec2d 8111 n_channels = ieee80211_get_num_supported_channels(wiphy);
2a519311
JB
8112 }
8113
8114 if (info->attrs[NL80211_ATTR_SCAN_SSIDS])
8115 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp)
8116 n_ssids++;
8117
83286856
CJ
8118 if (n_ssids > wiphy->max_scan_ssids)
8119 return -EINVAL;
2a519311 8120
70692ad2
JM
8121 if (info->attrs[NL80211_ATTR_IE])
8122 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
8123 else
8124 ie_len = 0;
8125
83286856
CJ
8126 if (ie_len > wiphy->max_scan_ie_len)
8127 return -EINVAL;
18a83659 8128
2a519311 8129 request = kzalloc(sizeof(*request)
a2cd43c5
LC
8130 + sizeof(*request->ssids) * n_ssids
8131 + sizeof(*request->channels) * n_channels
70692ad2 8132 + ie_len, GFP_KERNEL);
83286856
CJ
8133 if (!request)
8134 return -ENOMEM;
2a519311 8135
2a519311 8136 if (n_ssids)
5ba63533 8137 request->ssids = (void *)&request->channels[n_channels];
2a519311 8138 request->n_ssids = n_ssids;
70692ad2 8139 if (ie_len) {
13874e4b 8140 if (n_ssids)
70692ad2
JM
8141 request->ie = (void *)(request->ssids + n_ssids);
8142 else
8143 request->ie = (void *)(request->channels + n_channels);
8144 }
2a519311 8145
584991dc 8146 i = 0;
2032f3b2 8147 if (scan_freqs) {
2a519311 8148 /* user specified, bail out if channel not found */
2032f3b2 8149 nla_for_each_nested(attr, scan_freqs, tmp) {
584991dc 8150 struct ieee80211_channel *chan;
2032f3b2 8151 int freq = nla_get_u32(attr);
584991dc 8152
2032f3b2
TP
8153 if (!scan_freqs_khz)
8154 freq = MHZ_TO_KHZ(freq);
584991dc 8155
2032f3b2 8156 chan = ieee80211_get_channel_khz(wiphy, freq);
584991dc 8157 if (!chan) {
2a519311
JB
8158 err = -EINVAL;
8159 goto out_free;
8160 }
584991dc
JB
8161
8162 /* ignore disabled channels */
8163 if (chan->flags & IEEE80211_CHAN_DISABLED)
8164 continue;
8165
8166 request->channels[i] = chan;
2a519311
JB
8167 i++;
8168 }
8169 } else {
57fbcce3 8170 enum nl80211_band band;
34850ab2 8171
2a519311 8172 /* all channels */
57fbcce3 8173 for (band = 0; band < NUM_NL80211_BANDS; band++) {
2a519311 8174 int j;
7a087e74 8175
2a519311
JB
8176 if (!wiphy->bands[band])
8177 continue;
8178 for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
584991dc
JB
8179 struct ieee80211_channel *chan;
8180
8181 chan = &wiphy->bands[band]->channels[j];
8182
8183 if (chan->flags & IEEE80211_CHAN_DISABLED)
8184 continue;
8185
8186 request->channels[i] = chan;
2a519311
JB
8187 i++;
8188 }
8189 }
8190 }
8191
584991dc
JB
8192 if (!i) {
8193 err = -EINVAL;
8194 goto out_free;
8195 }
8196
8197 request->n_channels = i;
8198
34373d12
VT
8199 wdev_lock(wdev);
8200 if (!cfg80211_off_channel_oper_allowed(wdev)) {
8201 struct ieee80211_channel *chan;
8202
8203 if (request->n_channels != 1) {
8204 wdev_unlock(wdev);
8205 err = -EBUSY;
8206 goto out_free;
8207 }
8208
8209 chan = request->channels[0];
8210 if (chan->center_freq != wdev->chandef.chan->center_freq) {
8211 wdev_unlock(wdev);
8212 err = -EBUSY;
8213 goto out_free;
8214 }
8215 }
8216 wdev_unlock(wdev);
8217
2a519311 8218 i = 0;
13874e4b 8219 if (n_ssids) {
2a519311 8220 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) {
57a27e1d 8221 if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) {
2a519311
JB
8222 err = -EINVAL;
8223 goto out_free;
8224 }
57a27e1d 8225 request->ssids[i].ssid_len = nla_len(attr);
2a519311 8226 memcpy(request->ssids[i].ssid, nla_data(attr), nla_len(attr));
2a519311
JB
8227 i++;
8228 }
8229 }
8230
70692ad2
JM
8231 if (info->attrs[NL80211_ATTR_IE]) {
8232 request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
de95a54b
JB
8233 memcpy((void *)request->ie,
8234 nla_data(info->attrs[NL80211_ATTR_IE]),
70692ad2
JM
8235 request->ie_len);
8236 }
8237
57fbcce3 8238 for (i = 0; i < NUM_NL80211_BANDS; i++)
a401d2bb
JB
8239 if (wiphy->bands[i])
8240 request->rates[i] =
8241 (1 << wiphy->bands[i]->n_bitrates) - 1;
34850ab2
JB
8242
8243 if (info->attrs[NL80211_ATTR_SCAN_SUPP_RATES]) {
8244 nla_for_each_nested(attr,
8245 info->attrs[NL80211_ATTR_SCAN_SUPP_RATES],
8246 tmp) {
57fbcce3 8247 enum nl80211_band band = nla_type(attr);
34850ab2 8248
57fbcce3 8249 if (band < 0 || band >= NUM_NL80211_BANDS) {
34850ab2
JB
8250 err = -EINVAL;
8251 goto out_free;
8252 }
1b09cd82
FF
8253
8254 if (!wiphy->bands[band])
8255 continue;
8256
34850ab2
JB
8257 err = ieee80211_get_ratemask(wiphy->bands[band],
8258 nla_data(attr),
8259 nla_len(attr),
8260 &request->rates[band]);
8261 if (err)
8262 goto out_free;
8263 }
8264 }
8265
1d76250b
AS
8266 if (info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]) {
8267 if (!wiphy_ext_feature_isset(wiphy,
8268 NL80211_EXT_FEATURE_SET_SCAN_DWELL)) {
8269 err = -EOPNOTSUPP;
8270 goto out_free;
8271 }
8272
8273 request->duration =
8274 nla_get_u16(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]);
8275 request->duration_mandatory =
8276 nla_get_flag(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY]);
8277 }
8278
2d23d073
RZ
8279 err = nl80211_check_scan_flags(wiphy, wdev, request, info->attrs,
8280 false);
8281 if (err)
8282 goto out_free;
ed473771 8283
e9f935e3
RM
8284 request->no_cck =
8285 nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
8286
2fa436b3
VK
8287 /* Initial implementation used NL80211_ATTR_MAC to set the specific
8288 * BSSID to scan for. This was problematic because that same attribute
8289 * was already used for another purpose (local random MAC address). The
8290 * NL80211_ATTR_BSSID attribute was added to fix this. For backwards
8291 * compatibility with older userspace components, also use the
8292 * NL80211_ATTR_MAC value here if it can be determined to be used for
8293 * the specific BSSID use case instead of the random MAC address
8294 * (NL80211_ATTR_SCAN_FLAGS is used to enable random MAC address use).
8295 */
8296 if (info->attrs[NL80211_ATTR_BSSID])
8297 memcpy(request->bssid,
8298 nla_data(info->attrs[NL80211_ATTR_BSSID]), ETH_ALEN);
8299 else if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) &&
8300 info->attrs[NL80211_ATTR_MAC])
818965d3
JM
8301 memcpy(request->bssid, nla_data(info->attrs[NL80211_ATTR_MAC]),
8302 ETH_ALEN);
8303 else
8304 eth_broadcast_addr(request->bssid);
8305
fd014284 8306 request->wdev = wdev;
79c97e97 8307 request->wiphy = &rdev->wiphy;
15d6030b 8308 request->scan_start = jiffies;
2a519311 8309
79c97e97 8310 rdev->scan_req = request;
c8cb5b85 8311 err = cfg80211_scan(rdev);
2a519311 8312
504776be
CJ
8313 if (err)
8314 goto out_free;
8315
8316 nl80211_send_scan_start(rdev, wdev);
8317 if (wdev->netdev)
8318 dev_hold(wdev->netdev);
8319
8320 return 0;
8321
2a519311 8322 out_free:
504776be
CJ
8323 rdev->scan_req = NULL;
8324 kfree(request);
3b85875a 8325
2a519311
JB
8326 return err;
8327}
8328
91d3ab46
VK
8329static int nl80211_abort_scan(struct sk_buff *skb, struct genl_info *info)
8330{
8331 struct cfg80211_registered_device *rdev = info->user_ptr[0];
8332 struct wireless_dev *wdev = info->user_ptr[1];
8333
8334 if (!rdev->ops->abort_scan)
8335 return -EOPNOTSUPP;
8336
8337 if (rdev->scan_msg)
8338 return 0;
8339
8340 if (!rdev->scan_req)
8341 return -ENOENT;
8342
8343 rdev_abort_scan(rdev, wdev);
8344 return 0;
8345}
8346
3b06d277
AS
8347static int
8348nl80211_parse_sched_scan_plans(struct wiphy *wiphy, int n_plans,
8349 struct cfg80211_sched_scan_request *request,
8350 struct nlattr **attrs)
8351{
8352 int tmp, err, i = 0;
8353 struct nlattr *attr;
8354
8355 if (!attrs[NL80211_ATTR_SCHED_SCAN_PLANS]) {
8356 u32 interval;
8357
8358 /*
8359 * If scan plans are not specified,
5a88de53 8360 * %NL80211_ATTR_SCHED_SCAN_INTERVAL will be specified. In this
3b06d277
AS
8361 * case one scan plan will be set with the specified scan
8362 * interval and infinite number of iterations.
8363 */
3b06d277
AS
8364 interval = nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]);
8365 if (!interval)
8366 return -EINVAL;
8367
8368 request->scan_plans[0].interval =
8369 DIV_ROUND_UP(interval, MSEC_PER_SEC);
8370 if (!request->scan_plans[0].interval)
8371 return -EINVAL;
8372
8373 if (request->scan_plans[0].interval >
8374 wiphy->max_sched_scan_plan_interval)
8375 request->scan_plans[0].interval =
8376 wiphy->max_sched_scan_plan_interval;
8377
8378 return 0;
8379 }
8380
8381 nla_for_each_nested(attr, attrs[NL80211_ATTR_SCHED_SCAN_PLANS], tmp) {
8382 struct nlattr *plan[NL80211_SCHED_SCAN_PLAN_MAX + 1];
8383
8384 if (WARN_ON(i >= n_plans))
8385 return -EINVAL;
8386
8cb08174
JB
8387 err = nla_parse_nested_deprecated(plan,
8388 NL80211_SCHED_SCAN_PLAN_MAX,
8389 attr, nl80211_plan_policy,
8390 NULL);
3b06d277
AS
8391 if (err)
8392 return err;
8393
8394 if (!plan[NL80211_SCHED_SCAN_PLAN_INTERVAL])
8395 return -EINVAL;
8396
8397 request->scan_plans[i].interval =
8398 nla_get_u32(plan[NL80211_SCHED_SCAN_PLAN_INTERVAL]);
8399 if (!request->scan_plans[i].interval ||
8400 request->scan_plans[i].interval >
8401 wiphy->max_sched_scan_plan_interval)
8402 return -EINVAL;
8403
8404 if (plan[NL80211_SCHED_SCAN_PLAN_ITERATIONS]) {
8405 request->scan_plans[i].iterations =
8406 nla_get_u32(plan[NL80211_SCHED_SCAN_PLAN_ITERATIONS]);
8407 if (!request->scan_plans[i].iterations ||
8408 (request->scan_plans[i].iterations >
8409 wiphy->max_sched_scan_plan_iterations))
8410 return -EINVAL;
8411 } else if (i < n_plans - 1) {
8412 /*
8413 * All scan plans but the last one must specify
8414 * a finite number of iterations
8415 */
8416 return -EINVAL;
8417 }
8418
8419 i++;
8420 }
8421
8422 /*
8423 * The last scan plan must not specify the number of
8424 * iterations, it is supposed to run infinitely
8425 */
8426 if (request->scan_plans[n_plans - 1].iterations)
8427 return -EINVAL;
8428
8429 return 0;
8430}
8431
1e1b11b6 8432static int
8433nl80211_parse_sched_scan_per_band_rssi(struct wiphy *wiphy,
8434 struct cfg80211_match_set *match_sets,
8435 struct nlattr *tb_band_rssi,
8436 s32 rssi_thold)
8437{
8438 struct nlattr *attr;
8439 int i, tmp, ret = 0;
8440
8441 if (!wiphy_ext_feature_isset(wiphy,
8442 NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD)) {
8443 if (tb_band_rssi)
8444 ret = -EOPNOTSUPP;
8445 else
8446 for (i = 0; i < NUM_NL80211_BANDS; i++)
8447 match_sets->per_band_rssi_thold[i] =
8448 NL80211_SCAN_RSSI_THOLD_OFF;
8449 return ret;
8450 }
8451
8452 for (i = 0; i < NUM_NL80211_BANDS; i++)
8453 match_sets->per_band_rssi_thold[i] = rssi_thold;
8454
8455 nla_for_each_nested(attr, tb_band_rssi, tmp) {
8456 enum nl80211_band band = nla_type(attr);
8457
8458 if (band < 0 || band >= NUM_NL80211_BANDS)
8459 return -EINVAL;
8460
8461 match_sets->per_band_rssi_thold[band] = nla_get_s32(attr);
8462 }
8463
8464 return 0;
8465}
8466
256da02d 8467static struct cfg80211_sched_scan_request *
ad2b26ab 8468nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
aad1e812 8469 struct nlattr **attrs, int max_match_sets)
807f8a8c
LC
8470{
8471 struct cfg80211_sched_scan_request *request;
807f8a8c 8472 struct nlattr *attr;
3b06d277 8473 int err, tmp, n_ssids = 0, n_match_sets = 0, n_channels, i, n_plans = 0;
57fbcce3 8474 enum nl80211_band band;
807f8a8c 8475 size_t ie_len;
a1f1c21c 8476 struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
ea73cbce 8477 s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
807f8a8c 8478
256da02d 8479 if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
807f8a8c 8480 n_channels = validate_scan_freqs(
256da02d 8481 attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
807f8a8c 8482 if (!n_channels)
256da02d 8483 return ERR_PTR(-EINVAL);
807f8a8c 8484 } else {
bdfbec2d 8485 n_channels = ieee80211_get_num_supported_channels(wiphy);
807f8a8c
LC
8486 }
8487
256da02d
LC
8488 if (attrs[NL80211_ATTR_SCAN_SSIDS])
8489 nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
807f8a8c
LC
8490 tmp)
8491 n_ssids++;
8492
93b6aa69 8493 if (n_ssids > wiphy->max_sched_scan_ssids)
256da02d 8494 return ERR_PTR(-EINVAL);
807f8a8c 8495
ea73cbce
JB
8496 /*
8497 * First, count the number of 'real' matchsets. Due to an issue with
8498 * the old implementation, matchsets containing only the RSSI attribute
8499 * (NL80211_SCHED_SCAN_MATCH_ATTR_RSSI) are considered as the 'default'
8500 * RSSI for all matchsets, rather than their own matchset for reporting
8501 * all APs with a strong RSSI. This is needed to be compatible with
8502 * older userspace that treated a matchset with only the RSSI as the
8503 * global RSSI for all other matchsets - if there are other matchsets.
8504 */
256da02d 8505 if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
a1f1c21c 8506 nla_for_each_nested(attr,
256da02d 8507 attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
ea73cbce
JB
8508 tmp) {
8509 struct nlattr *rssi;
8510
8cb08174
JB
8511 err = nla_parse_nested_deprecated(tb,
8512 NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
8513 attr,
8514 nl80211_match_policy,
8515 NULL);
ea73cbce 8516 if (err)
256da02d 8517 return ERR_PTR(err);
3007e352
AVS
8518
8519 /* SSID and BSSID are mutually exclusive */
8520 if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID] &&
8521 tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID])
8522 return ERR_PTR(-EINVAL);
8523
ea73cbce 8524 /* add other standalone attributes here */
3007e352
AVS
8525 if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID] ||
8526 tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID]) {
ea73cbce
JB
8527 n_match_sets++;
8528 continue;
8529 }
8530 rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
8531 if (rssi)
8532 default_match_rssi = nla_get_s32(rssi);
8533 }
8534 }
8535
8536 /* However, if there's no other matchset, add the RSSI one */
8537 if (!n_match_sets && default_match_rssi != NL80211_SCAN_RSSI_THOLD_OFF)
8538 n_match_sets = 1;
a1f1c21c 8539
aad1e812 8540 if (n_match_sets > max_match_sets)
256da02d 8541 return ERR_PTR(-EINVAL);
a1f1c21c 8542
256da02d
LC
8543 if (attrs[NL80211_ATTR_IE])
8544 ie_len = nla_len(attrs[NL80211_ATTR_IE]);
807f8a8c
LC
8545 else
8546 ie_len = 0;
8547
5a865bad 8548 if (ie_len > wiphy->max_sched_scan_ie_len)
256da02d 8549 return ERR_PTR(-EINVAL);
c10841ca 8550
3b06d277
AS
8551 if (attrs[NL80211_ATTR_SCHED_SCAN_PLANS]) {
8552 /*
8553 * NL80211_ATTR_SCHED_SCAN_INTERVAL must not be specified since
8554 * each scan plan already specifies its own interval
8555 */
8556 if (attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
8557 return ERR_PTR(-EINVAL);
8558
8559 nla_for_each_nested(attr,
8560 attrs[NL80211_ATTR_SCHED_SCAN_PLANS], tmp)
8561 n_plans++;
8562 } else {
8563 /*
8564 * The scan interval attribute is kept for backward
8565 * compatibility. If no scan plans are specified and sched scan
8566 * interval is specified, one scan plan will be set with this
8567 * scan interval and infinite number of iterations.
8568 */
8569 if (!attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
8570 return ERR_PTR(-EINVAL);
8571
8572 n_plans = 1;
8573 }
8574
8575 if (!n_plans || n_plans > wiphy->max_sched_scan_plans)
8576 return ERR_PTR(-EINVAL);
8577
bf95ecdb 8578 if (!wiphy_ext_feature_isset(
8579 wiphy, NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI) &&
8580 (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] ||
8581 attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]))
8582 return ERR_PTR(-EINVAL);
8583
807f8a8c 8584 request = kzalloc(sizeof(*request)
a2cd43c5 8585 + sizeof(*request->ssids) * n_ssids
a1f1c21c 8586 + sizeof(*request->match_sets) * n_match_sets
3b06d277 8587 + sizeof(*request->scan_plans) * n_plans
a2cd43c5 8588 + sizeof(*request->channels) * n_channels
807f8a8c 8589 + ie_len, GFP_KERNEL);
256da02d
LC
8590 if (!request)
8591 return ERR_PTR(-ENOMEM);
807f8a8c
LC
8592
8593 if (n_ssids)
8594 request->ssids = (void *)&request->channels[n_channels];
8595 request->n_ssids = n_ssids;
8596 if (ie_len) {
13874e4b 8597 if (n_ssids)
807f8a8c
LC
8598 request->ie = (void *)(request->ssids + n_ssids);
8599 else
8600 request->ie = (void *)(request->channels + n_channels);
8601 }
8602
a1f1c21c
LC
8603 if (n_match_sets) {
8604 if (request->ie)
8605 request->match_sets = (void *)(request->ie + ie_len);
13874e4b 8606 else if (n_ssids)
a1f1c21c
LC
8607 request->match_sets =
8608 (void *)(request->ssids + n_ssids);
8609 else
8610 request->match_sets =
8611 (void *)(request->channels + n_channels);
8612 }
8613 request->n_match_sets = n_match_sets;
8614
3b06d277
AS
8615 if (n_match_sets)
8616 request->scan_plans = (void *)(request->match_sets +
8617 n_match_sets);
8618 else if (request->ie)
8619 request->scan_plans = (void *)(request->ie + ie_len);
8620 else if (n_ssids)
8621 request->scan_plans = (void *)(request->ssids + n_ssids);
8622 else
8623 request->scan_plans = (void *)(request->channels + n_channels);
8624
8625 request->n_scan_plans = n_plans;
8626
807f8a8c 8627 i = 0;
256da02d 8628 if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
807f8a8c
LC
8629 /* user specified, bail out if channel not found */
8630 nla_for_each_nested(attr,
256da02d 8631 attrs[NL80211_ATTR_SCAN_FREQUENCIES],
807f8a8c
LC
8632 tmp) {
8633 struct ieee80211_channel *chan;
8634
8635 chan = ieee80211_get_channel(wiphy, nla_get_u32(attr));
8636
8637 if (!chan) {
8638 err = -EINVAL;
8639 goto out_free;
8640 }
8641
8642 /* ignore disabled channels */
8643 if (chan->flags & IEEE80211_CHAN_DISABLED)
8644 continue;
8645
8646 request->channels[i] = chan;
8647 i++;
8648 }
8649 } else {
8650 /* all channels */
57fbcce3 8651 for (band = 0; band < NUM_NL80211_BANDS; band++) {
807f8a8c 8652 int j;
7a087e74 8653
807f8a8c
LC
8654 if (!wiphy->bands[band])
8655 continue;
8656 for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
8657 struct ieee80211_channel *chan;
8658
8659 chan = &wiphy->bands[band]->channels[j];
8660
8661 if (chan->flags & IEEE80211_CHAN_DISABLED)
8662 continue;
8663
8664 request->channels[i] = chan;
8665 i++;
8666 }
8667 }
8668 }
8669
8670 if (!i) {
8671 err = -EINVAL;
8672 goto out_free;
8673 }
8674
8675 request->n_channels = i;
8676
8677 i = 0;
13874e4b 8678 if (n_ssids) {
256da02d 8679 nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
807f8a8c 8680 tmp) {
57a27e1d 8681 if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) {
807f8a8c
LC
8682 err = -EINVAL;
8683 goto out_free;
8684 }
57a27e1d 8685 request->ssids[i].ssid_len = nla_len(attr);
807f8a8c
LC
8686 memcpy(request->ssids[i].ssid, nla_data(attr),
8687 nla_len(attr));
807f8a8c
LC
8688 i++;
8689 }
8690 }
8691
a1f1c21c 8692 i = 0;
256da02d 8693 if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
a1f1c21c 8694 nla_for_each_nested(attr,
256da02d 8695 attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
a1f1c21c 8696 tmp) {
3007e352 8697 struct nlattr *ssid, *bssid, *rssi;
a1f1c21c 8698
8cb08174
JB
8699 err = nla_parse_nested_deprecated(tb,
8700 NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
8701 attr,
8702 nl80211_match_policy,
8703 NULL);
ae811e21
JB
8704 if (err)
8705 goto out_free;
4a4ab0d7 8706 ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID];
3007e352 8707 bssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID];
d39f3b4f
JB
8708
8709 if (!ssid && !bssid) {
8710 i++;
8711 continue;
8712 }
8713
8714 if (WARN_ON(i >= n_match_sets)) {
8715 /* this indicates a programming error,
8716 * the loop above should have verified
8717 * things properly
8718 */
8719 err = -EINVAL;
8720 goto out_free;
8721 }
8722
8723 if (ssid) {
d39f3b4f
JB
8724 memcpy(request->match_sets[i].ssid.ssid,
8725 nla_data(ssid), nla_len(ssid));
8726 request->match_sets[i].ssid.ssid_len =
8727 nla_len(ssid);
8728 }
cb9abd48 8729 if (bssid)
d39f3b4f
JB
8730 memcpy(request->match_sets[i].bssid,
8731 nla_data(bssid), ETH_ALEN);
3007e352 8732
d39f3b4f
JB
8733 /* special attribute - old implementation w/a */
8734 request->match_sets[i].rssi_thold = default_match_rssi;
8735 rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
8736 if (rssi)
ea73cbce 8737 request->match_sets[i].rssi_thold =
d39f3b4f 8738 nla_get_s32(rssi);
1e1b11b6 8739
8740 /* Parse per band RSSI attribute */
8741 err = nl80211_parse_sched_scan_per_band_rssi(wiphy,
8742 &request->match_sets[i],
8743 tb[NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI],
8744 request->match_sets[i].rssi_thold);
8745 if (err)
8746 goto out_free;
8747
a1f1c21c
LC
8748 i++;
8749 }
ea73cbce
JB
8750
8751 /* there was no other matchset, so the RSSI one is alone */
f89f46cf 8752 if (i == 0 && n_match_sets)
ea73cbce
JB
8753 request->match_sets[0].rssi_thold = default_match_rssi;
8754
8755 request->min_rssi_thold = INT_MAX;
8756 for (i = 0; i < n_match_sets; i++)
8757 request->min_rssi_thold =
8758 min(request->match_sets[i].rssi_thold,
8759 request->min_rssi_thold);
8760 } else {
8761 request->min_rssi_thold = NL80211_SCAN_RSSI_THOLD_OFF;
a1f1c21c
LC
8762 }
8763
9900e484
JB
8764 if (ie_len) {
8765 request->ie_len = ie_len;
807f8a8c 8766 memcpy((void *)request->ie,
256da02d 8767 nla_data(attrs[NL80211_ATTR_IE]),
807f8a8c
LC
8768 request->ie_len);
8769 }
8770
2d23d073
RZ
8771 err = nl80211_check_scan_flags(wiphy, wdev, request, attrs, true);
8772 if (err)
8773 goto out_free;
ed473771 8774
9c748934
LC
8775 if (attrs[NL80211_ATTR_SCHED_SCAN_DELAY])
8776 request->delay =
8777 nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_DELAY]);
8778
bf95ecdb 8779 if (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI]) {
8780 request->relative_rssi = nla_get_s8(
8781 attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI]);
8782 request->relative_rssi_set = true;
8783 }
8784
8785 if (request->relative_rssi_set &&
8786 attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]) {
8787 struct nl80211_bss_select_rssi_adjust *rssi_adjust;
8788
8789 rssi_adjust = nla_data(
8790 attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]);
8791 request->rssi_adjust.band = rssi_adjust->band;
8792 request->rssi_adjust.delta = rssi_adjust->delta;
8793 if (!is_band_valid(wiphy, request->rssi_adjust.band)) {
8794 err = -EINVAL;
8795 goto out_free;
8796 }
8797 }
8798
3b06d277
AS
8799 err = nl80211_parse_sched_scan_plans(wiphy, n_plans, request, attrs);
8800 if (err)
8801 goto out_free;
8802
15d6030b 8803 request->scan_start = jiffies;
807f8a8c 8804
256da02d 8805 return request;
807f8a8c
LC
8806
8807out_free:
8808 kfree(request);
256da02d
LC
8809 return ERR_PTR(err);
8810}
8811
8812static int nl80211_start_sched_scan(struct sk_buff *skb,
8813 struct genl_info *info)
8814{
8815 struct cfg80211_registered_device *rdev = info->user_ptr[0];
8816 struct net_device *dev = info->user_ptr[1];
ad2b26ab 8817 struct wireless_dev *wdev = dev->ieee80211_ptr;
31a60ed1 8818 struct cfg80211_sched_scan_request *sched_scan_req;
ca986ad9 8819 bool want_multi;
256da02d
LC
8820 int err;
8821
ca986ad9 8822 if (!rdev->wiphy.max_sched_scan_reqs || !rdev->ops->sched_scan_start)
256da02d
LC
8823 return -EOPNOTSUPP;
8824
ca986ad9
AVS
8825 want_multi = info->attrs[NL80211_ATTR_SCHED_SCAN_MULTI];
8826 err = cfg80211_sched_scan_req_possible(rdev, want_multi);
8827 if (err)
8828 return err;
256da02d 8829
31a60ed1 8830 sched_scan_req = nl80211_parse_sched_scan(&rdev->wiphy, wdev,
aad1e812
AVS
8831 info->attrs,
8832 rdev->wiphy.max_match_sets);
31a60ed1
JR
8833
8834 err = PTR_ERR_OR_ZERO(sched_scan_req);
256da02d
LC
8835 if (err)
8836 goto out_err;
8837
ca986ad9
AVS
8838 /* leave request id zero for legacy request
8839 * or if driver does not support multi-scheduled scan
8840 */
2fd351a8
DK
8841 if (want_multi && rdev->wiphy.max_sched_scan_reqs > 1)
8842 sched_scan_req->reqid = cfg80211_assign_cookie(rdev);
ca986ad9 8843
31a60ed1 8844 err = rdev_sched_scan_start(rdev, dev, sched_scan_req);
256da02d
LC
8845 if (err)
8846 goto out_free;
8847
31a60ed1
JR
8848 sched_scan_req->dev = dev;
8849 sched_scan_req->wiphy = &rdev->wiphy;
8850
93a1e86c
JR
8851 if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
8852 sched_scan_req->owner_nlportid = info->snd_portid;
8853
ca986ad9 8854 cfg80211_add_sched_scan_req(rdev, sched_scan_req);
256da02d 8855
96b08fd6 8856 nl80211_send_sched_scan(sched_scan_req, NL80211_CMD_START_SCHED_SCAN);
256da02d
LC
8857 return 0;
8858
8859out_free:
31a60ed1 8860 kfree(sched_scan_req);
256da02d 8861out_err:
807f8a8c
LC
8862 return err;
8863}
8864
8865static int nl80211_stop_sched_scan(struct sk_buff *skb,
8866 struct genl_info *info)
8867{
ca986ad9 8868 struct cfg80211_sched_scan_request *req;
807f8a8c 8869 struct cfg80211_registered_device *rdev = info->user_ptr[0];
ca986ad9 8870 u64 cookie;
807f8a8c 8871
ca986ad9 8872 if (!rdev->wiphy.max_sched_scan_reqs || !rdev->ops->sched_scan_stop)
807f8a8c
LC
8873 return -EOPNOTSUPP;
8874
ca986ad9
AVS
8875 if (info->attrs[NL80211_ATTR_COOKIE]) {
8876 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
8877 return __cfg80211_stop_sched_scan(rdev, cookie, false);
8878 }
8879
8880 req = list_first_or_null_rcu(&rdev->sched_scan_req_list,
8881 struct cfg80211_sched_scan_request,
8882 list);
8883 if (!req || req->reqid ||
8884 (req->owner_nlportid &&
8885 req->owner_nlportid != info->snd_portid))
8886 return -ENOENT;
8887
8888 return cfg80211_stop_sched_scan_req(rdev, req, false);
807f8a8c
LC
8889}
8890
04f39047
SW
8891static int nl80211_start_radar_detection(struct sk_buff *skb,
8892 struct genl_info *info)
8893{
8894 struct cfg80211_registered_device *rdev = info->user_ptr[0];
8895 struct net_device *dev = info->user_ptr[1];
8896 struct wireless_dev *wdev = dev->ieee80211_ptr;
13cf6dec 8897 struct wiphy *wiphy = wdev->wiphy;
04f39047 8898 struct cfg80211_chan_def chandef;
55f7435c 8899 enum nl80211_dfs_regions dfs_region;
31559f35 8900 unsigned int cac_time_ms;
04f39047
SW
8901 int err;
8902
13cf6dec 8903 dfs_region = reg_get_dfs_region(wiphy);
55f7435c
LR
8904 if (dfs_region == NL80211_DFS_UNSET)
8905 return -EINVAL;
8906
04f39047
SW
8907 err = nl80211_parse_chandef(rdev, info, &chandef);
8908 if (err)
8909 return err;
8910
ff311bc1
SW
8911 if (netif_carrier_ok(dev))
8912 return -EBUSY;
8913
04f39047
SW
8914 if (wdev->cac_started)
8915 return -EBUSY;
8916
13cf6dec 8917 err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype);
04f39047
SW
8918 if (err < 0)
8919 return err;
8920
8921 if (err == 0)
8922 return -EINVAL;
8923
13cf6dec 8924 if (!cfg80211_chandef_dfs_usable(wiphy, &chandef))
04f39047
SW
8925 return -EINVAL;
8926
13cf6dec
DL
8927 /* CAC start is offloaded to HW and can't be started manually */
8928 if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD))
8929 return -EOPNOTSUPP;
8930
04f39047
SW
8931 if (!rdev->ops->start_radar_detection)
8932 return -EOPNOTSUPP;
8933
31559f35
JD
8934 cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef);
8935 if (WARN_ON(!cac_time_ms))
8936 cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
8937
a1056b1b 8938 err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms);
04f39047 8939 if (!err) {
9e0e2961 8940 wdev->chandef = chandef;
04f39047
SW
8941 wdev->cac_started = true;
8942 wdev->cac_start_time = jiffies;
31559f35 8943 wdev->cac_time_ms = cac_time_ms;
04f39047 8944 }
04f39047
SW
8945 return err;
8946}
8947
30c63115
S
8948static int nl80211_notify_radar_detection(struct sk_buff *skb,
8949 struct genl_info *info)
8950{
8951 struct cfg80211_registered_device *rdev = info->user_ptr[0];
8952 struct net_device *dev = info->user_ptr[1];
8953 struct wireless_dev *wdev = dev->ieee80211_ptr;
8954 struct wiphy *wiphy = wdev->wiphy;
8955 struct cfg80211_chan_def chandef;
8956 enum nl80211_dfs_regions dfs_region;
8957 int err;
8958
8959 dfs_region = reg_get_dfs_region(wiphy);
8960 if (dfs_region == NL80211_DFS_UNSET) {
8961 GENL_SET_ERR_MSG(info,
8962 "DFS Region is not set. Unexpected Radar indication");
8963 return -EINVAL;
8964 }
8965
8966 err = nl80211_parse_chandef(rdev, info, &chandef);
8967 if (err) {
8968 GENL_SET_ERR_MSG(info, "Unable to extract chandef info");
8969 return err;
8970 }
8971
8972 err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype);
8973 if (err < 0) {
8974 GENL_SET_ERR_MSG(info, "chandef is invalid");
8975 return err;
8976 }
8977
8978 if (err == 0) {
8979 GENL_SET_ERR_MSG(info,
8980 "Unexpected Radar indication for chandef/iftype");
8981 return -EINVAL;
8982 }
8983
8984 /* Do not process this notification if radar is already detected
8985 * by kernel on this channel, and return success.
8986 */
8987 if (chandef.chan->dfs_state == NL80211_DFS_UNAVAILABLE)
8988 return 0;
8989
8990 cfg80211_set_dfs_state(wiphy, &chandef, NL80211_DFS_UNAVAILABLE);
8991
8992 cfg80211_sched_dfs_chan_update(rdev);
8993
a680fe46 8994 rdev->radar_chandef = chandef;
30c63115
S
8995
8996 /* Propagate this notification to other radios as well */
8997 queue_work(cfg80211_wq, &rdev->propagate_radar_detect_wk);
8998
8999 return 0;
9000}
9001
16ef1fe2
SW
9002static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
9003{
9004 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9005 struct net_device *dev = info->user_ptr[1];
9006 struct wireless_dev *wdev = dev->ieee80211_ptr;
9007 struct cfg80211_csa_settings params;
9008 /* csa_attrs is defined static to avoid waste of stack size - this
9009 * function is called under RTNL lock, so this should not be a problem.
9010 */
9011 static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1];
16ef1fe2 9012 int err;
ee4bc9e7 9013 bool need_new_beacon = false;
8d9de16f 9014 bool need_handle_dfs_flag = true;
9a774c78 9015 int len, i;
252e07ca 9016 u32 cs_count;
16ef1fe2
SW
9017
9018 if (!rdev->ops->channel_switch ||
9019 !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
9020 return -EOPNOTSUPP;
9021
ee4bc9e7
SW
9022 switch (dev->ieee80211_ptr->iftype) {
9023 case NL80211_IFTYPE_AP:
9024 case NL80211_IFTYPE_P2P_GO:
9025 need_new_beacon = true;
8d9de16f
BB
9026 /* For all modes except AP the handle_dfs flag needs to be
9027 * supplied to tell the kernel that userspace will handle radar
9028 * events when they happen. Otherwise a switch to a channel
9029 * requiring DFS will be rejected.
9030 */
9031 need_handle_dfs_flag = false;
ee4bc9e7
SW
9032
9033 /* useless if AP is not running */
9034 if (!wdev->beacon_interval)
1ff79dfa 9035 return -ENOTCONN;
ee4bc9e7
SW
9036 break;
9037 case NL80211_IFTYPE_ADHOC:
1ff79dfa
JB
9038 if (!wdev->ssid_len)
9039 return -ENOTCONN;
9040 break;
c6da674a 9041 case NL80211_IFTYPE_MESH_POINT:
1ff79dfa
JB
9042 if (!wdev->mesh_id_len)
9043 return -ENOTCONN;
ee4bc9e7
SW
9044 break;
9045 default:
16ef1fe2 9046 return -EOPNOTSUPP;
ee4bc9e7 9047 }
16ef1fe2
SW
9048
9049 memset(&params, 0, sizeof(params));
c177db2d 9050 params.beacon_csa.ftm_responder = -1;
16ef1fe2
SW
9051
9052 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
9053 !info->attrs[NL80211_ATTR_CH_SWITCH_COUNT])
9054 return -EINVAL;
9055
9056 /* only important for AP, IBSS and mesh create IEs internally */
d0a361a5 9057 if (need_new_beacon && !info->attrs[NL80211_ATTR_CSA_IES])
16ef1fe2
SW
9058 return -EINVAL;
9059
252e07ca
LC
9060 /* Even though the attribute is u32, the specification says
9061 * u8, so let's make sure we don't overflow.
9062 */
9063 cs_count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
9064 if (cs_count > 255)
9065 return -EINVAL;
9066
9067 params.count = cs_count;
16ef1fe2 9068
ee4bc9e7
SW
9069 if (!need_new_beacon)
9070 goto skip_beacons;
9071
81e54d08 9072 err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon_after);
16ef1fe2
SW
9073 if (err)
9074 return err;
9075
8cb08174
JB
9076 err = nla_parse_nested_deprecated(csa_attrs, NL80211_ATTR_MAX,
9077 info->attrs[NL80211_ATTR_CSA_IES],
9078 nl80211_policy, info->extack);
16ef1fe2
SW
9079 if (err)
9080 return err;
9081
81e54d08 9082 err = nl80211_parse_beacon(rdev, csa_attrs, &params.beacon_csa);
16ef1fe2
SW
9083 if (err)
9084 return err;
9085
00c207ed 9086 if (!csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON])
16ef1fe2
SW
9087 return -EINVAL;
9088
00c207ed 9089 len = nla_len(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
9a774c78 9090 if (!len || (len % sizeof(u16)))
16ef1fe2
SW
9091 return -EINVAL;
9092
9a774c78
AO
9093 params.n_counter_offsets_beacon = len / sizeof(u16);
9094 if (rdev->wiphy.max_num_csa_counters &&
9095 (params.n_counter_offsets_beacon >
9096 rdev->wiphy.max_num_csa_counters))
16ef1fe2
SW
9097 return -EINVAL;
9098
9a774c78 9099 params.counter_offsets_beacon =
00c207ed 9100 nla_data(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
9a774c78
AO
9101
9102 /* sanity checks - counters should fit and be the same */
9103 for (i = 0; i < params.n_counter_offsets_beacon; i++) {
9104 u16 offset = params.counter_offsets_beacon[i];
9105
9106 if (offset >= params.beacon_csa.tail_len)
9107 return -EINVAL;
9108
9109 if (params.beacon_csa.tail[offset] != params.count)
9110 return -EINVAL;
9111 }
9112
00c207ed
JC
9113 if (csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]) {
9114 len = nla_len(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
9a774c78 9115 if (!len || (len % sizeof(u16)))
16ef1fe2
SW
9116 return -EINVAL;
9117
9a774c78
AO
9118 params.n_counter_offsets_presp = len / sizeof(u16);
9119 if (rdev->wiphy.max_num_csa_counters &&
ad5987b4 9120 (params.n_counter_offsets_presp >
9a774c78 9121 rdev->wiphy.max_num_csa_counters))
16ef1fe2 9122 return -EINVAL;
9a774c78
AO
9123
9124 params.counter_offsets_presp =
00c207ed 9125 nla_data(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
9a774c78
AO
9126
9127 /* sanity checks - counters should fit and be the same */
9128 for (i = 0; i < params.n_counter_offsets_presp; i++) {
9129 u16 offset = params.counter_offsets_presp[i];
9130
9131 if (offset >= params.beacon_csa.probe_resp_len)
9132 return -EINVAL;
9133
9134 if (params.beacon_csa.probe_resp[offset] !=
9135 params.count)
9136 return -EINVAL;
9137 }
16ef1fe2
SW
9138 }
9139
ee4bc9e7 9140skip_beacons:
16ef1fe2
SW
9141 err = nl80211_parse_chandef(rdev, info, &params.chandef);
9142 if (err)
9143 return err;
9144
923b352f
AN
9145 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params.chandef,
9146 wdev->iftype))
16ef1fe2
SW
9147 return -EINVAL;
9148
2beb6dab
LC
9149 err = cfg80211_chandef_dfs_required(wdev->wiphy,
9150 &params.chandef,
9151 wdev->iftype);
9152 if (err < 0)
9153 return err;
9154
8d9de16f 9155 if (err > 0) {
2beb6dab 9156 params.radar_required = true;
8d9de16f
BB
9157 if (need_handle_dfs_flag &&
9158 !nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS])) {
9159 return -EINVAL;
9160 }
9161 }
16ef1fe2 9162
16ef1fe2
SW
9163 if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
9164 params.block_tx = true;
9165
c56589ed
SW
9166 wdev_lock(wdev);
9167 err = rdev_channel_switch(rdev, dev, &params);
9168 wdev_unlock(wdev);
9169
9170 return err;
16ef1fe2
SW
9171}
9172
9720bb3a
JB
9173static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
9174 u32 seq, int flags,
2a519311 9175 struct cfg80211_registered_device *rdev,
48ab905d
JB
9176 struct wireless_dev *wdev,
9177 struct cfg80211_internal_bss *intbss)
2a519311 9178{
48ab905d 9179 struct cfg80211_bss *res = &intbss->pub;
9caf0364 9180 const struct cfg80211_bss_ies *ies;
2a519311
JB
9181 void *hdr;
9182 struct nlattr *bss;
48ab905d
JB
9183
9184 ASSERT_WDEV_LOCK(wdev);
2a519311 9185
15e47304 9186 hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).portid, seq, flags,
2a519311
JB
9187 NL80211_CMD_NEW_SCAN_RESULTS);
9188 if (!hdr)
9189 return -1;
9190
0a833c29 9191 genl_dump_check_consistent(cb, hdr);
9720bb3a 9192
97990a06
JB
9193 if (nla_put_u32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation))
9194 goto nla_put_failure;
9195 if (wdev->netdev &&
9360ffd1
DM
9196 nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex))
9197 goto nla_put_failure;
2dad624e
ND
9198 if (nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
9199 NL80211_ATTR_PAD))
97990a06 9200 goto nla_put_failure;
2a519311 9201
ae0be8de 9202 bss = nla_nest_start_noflag(msg, NL80211_ATTR_BSS);
2a519311
JB
9203 if (!bss)
9204 goto nla_put_failure;
9360ffd1 9205 if ((!is_zero_ether_addr(res->bssid) &&
9caf0364 9206 nla_put(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid)))
9360ffd1 9207 goto nla_put_failure;
9caf0364
JB
9208
9209 rcu_read_lock();
0e227084
JB
9210 /* indicate whether we have probe response data or not */
9211 if (rcu_access_pointer(res->proberesp_ies) &&
9212 nla_put_flag(msg, NL80211_BSS_PRESP_DATA))
9213 goto fail_unlock_rcu;
9214
9215 /* this pointer prefers to be pointed to probe response data
9216 * but is always valid
9217 */
9caf0364 9218 ies = rcu_dereference(res->ies);
8cef2c9d 9219 if (ies) {
2dad624e
ND
9220 if (nla_put_u64_64bit(msg, NL80211_BSS_TSF, ies->tsf,
9221 NL80211_BSS_PAD))
8cef2c9d 9222 goto fail_unlock_rcu;
8cef2c9d
JB
9223 if (ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS,
9224 ies->len, ies->data))
9225 goto fail_unlock_rcu;
9caf0364 9226 }
0e227084
JB
9227
9228 /* and this pointer is always (unless driver didn't know) beacon data */
9caf0364 9229 ies = rcu_dereference(res->beacon_ies);
0e227084 9230 if (ies && ies->from_beacon) {
2dad624e
ND
9231 if (nla_put_u64_64bit(msg, NL80211_BSS_BEACON_TSF, ies->tsf,
9232 NL80211_BSS_PAD))
8cef2c9d
JB
9233 goto fail_unlock_rcu;
9234 if (ies->len && nla_put(msg, NL80211_BSS_BEACON_IES,
9235 ies->len, ies->data))
9236 goto fail_unlock_rcu;
9caf0364
JB
9237 }
9238 rcu_read_unlock();
9239
9360ffd1
DM
9240 if (res->beacon_interval &&
9241 nla_put_u16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval))
9242 goto nla_put_failure;
9243 if (nla_put_u16(msg, NL80211_BSS_CAPABILITY, res->capability) ||
9244 nla_put_u32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq) ||
942ba88b
TP
9245 nla_put_u32(msg, NL80211_BSS_FREQUENCY_OFFSET,
9246 res->channel->freq_offset) ||
dcd6eac1 9247 nla_put_u32(msg, NL80211_BSS_CHAN_WIDTH, res->scan_width) ||
9360ffd1
DM
9248 nla_put_u32(msg, NL80211_BSS_SEEN_MS_AGO,
9249 jiffies_to_msecs(jiffies - intbss->ts)))
9250 goto nla_put_failure;
2a519311 9251
1d76250b
AS
9252 if (intbss->parent_tsf &&
9253 (nla_put_u64_64bit(msg, NL80211_BSS_PARENT_TSF,
9254 intbss->parent_tsf, NL80211_BSS_PAD) ||
9255 nla_put(msg, NL80211_BSS_PARENT_BSSID, ETH_ALEN,
9256 intbss->parent_bssid)))
9257 goto nla_put_failure;
9258
6e19bc4b 9259 if (intbss->ts_boottime &&
2dad624e
ND
9260 nla_put_u64_64bit(msg, NL80211_BSS_LAST_SEEN_BOOTTIME,
9261 intbss->ts_boottime, NL80211_BSS_PAD))
6e19bc4b
DS
9262 goto nla_put_failure;
9263
983dafaa
SD
9264 if (!nl80211_put_signal(msg, intbss->pub.chains,
9265 intbss->pub.chain_signal,
9266 NL80211_BSS_CHAIN_SIGNAL))
9267 goto nla_put_failure;
9268
77965c97 9269 switch (rdev->wiphy.signal_type) {
2a519311 9270 case CFG80211_SIGNAL_TYPE_MBM:
9360ffd1
DM
9271 if (nla_put_u32(msg, NL80211_BSS_SIGNAL_MBM, res->signal))
9272 goto nla_put_failure;
2a519311
JB
9273 break;
9274 case CFG80211_SIGNAL_TYPE_UNSPEC:
9360ffd1
DM
9275 if (nla_put_u8(msg, NL80211_BSS_SIGNAL_UNSPEC, res->signal))
9276 goto nla_put_failure;
2a519311
JB
9277 break;
9278 default:
9279 break;
9280 }
9281
48ab905d 9282 switch (wdev->iftype) {
074ac8df 9283 case NL80211_IFTYPE_P2P_CLIENT:
48ab905d 9284 case NL80211_IFTYPE_STATION:
9360ffd1
DM
9285 if (intbss == wdev->current_bss &&
9286 nla_put_u32(msg, NL80211_BSS_STATUS,
9287 NL80211_BSS_STATUS_ASSOCIATED))
9288 goto nla_put_failure;
48ab905d
JB
9289 break;
9290 case NL80211_IFTYPE_ADHOC:
9360ffd1
DM
9291 if (intbss == wdev->current_bss &&
9292 nla_put_u32(msg, NL80211_BSS_STATUS,
9293 NL80211_BSS_STATUS_IBSS_JOINED))
9294 goto nla_put_failure;
48ab905d
JB
9295 break;
9296 default:
9297 break;
9298 }
9299
2a519311
JB
9300 nla_nest_end(msg, bss);
9301
053c095a
JB
9302 genlmsg_end(msg, hdr);
9303 return 0;
2a519311 9304
8cef2c9d
JB
9305 fail_unlock_rcu:
9306 rcu_read_unlock();
2a519311
JB
9307 nla_put_failure:
9308 genlmsg_cancel(msg, hdr);
9309 return -EMSGSIZE;
9310}
9311
97990a06 9312static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb)
2a519311 9313{
48ab905d 9314 struct cfg80211_registered_device *rdev;
2a519311 9315 struct cfg80211_internal_bss *scan;
48ab905d 9316 struct wireless_dev *wdev;
97990a06 9317 int start = cb->args[2], idx = 0;
2a519311
JB
9318 int err;
9319
ea90e0dc 9320 rtnl_lock();
5297c65c 9321 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
ea90e0dc
JB
9322 if (err) {
9323 rtnl_unlock();
67748893 9324 return err;
ea90e0dc 9325 }
2a519311 9326
48ab905d
JB
9327 wdev_lock(wdev);
9328 spin_lock_bh(&rdev->bss_lock);
d1e23c94
DK
9329
9330 /*
9331 * dump_scan will be called multiple times to break up the scan results
9332 * into multiple messages. It is unlikely that any more bss-es will be
9333 * expired after the first call, so only call only call this on the
9334 * first dump_scan invocation.
9335 */
9336 if (start == 0)
9337 cfg80211_bss_expire(rdev);
48ab905d 9338
9720bb3a
JB
9339 cb->seq = rdev->bss_generation;
9340
48ab905d 9341 list_for_each_entry(scan, &rdev->bss_list, list) {
2a519311
JB
9342 if (++idx <= start)
9343 continue;
9720bb3a 9344 if (nl80211_send_bss(skb, cb,
2a519311 9345 cb->nlh->nlmsg_seq, NLM_F_MULTI,
48ab905d 9346 rdev, wdev, scan) < 0) {
2a519311 9347 idx--;
67748893 9348 break;
2a519311
JB
9349 }
9350 }
9351
48ab905d
JB
9352 spin_unlock_bh(&rdev->bss_lock);
9353 wdev_unlock(wdev);
2a519311 9354
97990a06 9355 cb->args[2] = idx;
ea90e0dc 9356 rtnl_unlock();
2a519311 9357
67748893 9358 return skb->len;
2a519311
JB
9359}
9360
15e47304 9361static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq,
11f78ac3
JB
9362 int flags, struct net_device *dev,
9363 bool allow_radio_stats,
9364 struct survey_info *survey)
61fa713c
HS
9365{
9366 void *hdr;
9367 struct nlattr *infoattr;
9368
11f78ac3
JB
9369 /* skip radio stats if userspace didn't request them */
9370 if (!survey->channel && !allow_radio_stats)
9371 return 0;
9372
15e47304 9373 hdr = nl80211hdr_put(msg, portid, seq, flags,
61fa713c
HS
9374 NL80211_CMD_NEW_SURVEY_RESULTS);
9375 if (!hdr)
9376 return -ENOMEM;
9377
9360ffd1
DM
9378 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
9379 goto nla_put_failure;
61fa713c 9380
ae0be8de 9381 infoattr = nla_nest_start_noflag(msg, NL80211_ATTR_SURVEY_INFO);
61fa713c
HS
9382 if (!infoattr)
9383 goto nla_put_failure;
9384
11f78ac3
JB
9385 if (survey->channel &&
9386 nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY,
9360ffd1
DM
9387 survey->channel->center_freq))
9388 goto nla_put_failure;
58ef7c1b
TP
9389
9390 if (survey->channel && survey->channel->freq_offset &&
9391 nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY_OFFSET,
9392 survey->channel->freq_offset))
9393 goto nla_put_failure;
9360ffd1
DM
9394
9395 if ((survey->filled & SURVEY_INFO_NOISE_DBM) &&
9396 nla_put_u8(msg, NL80211_SURVEY_INFO_NOISE, survey->noise))
9397 goto nla_put_failure;
9398 if ((survey->filled & SURVEY_INFO_IN_USE) &&
9399 nla_put_flag(msg, NL80211_SURVEY_INFO_IN_USE))
9400 goto nla_put_failure;
4ed20beb 9401 if ((survey->filled & SURVEY_INFO_TIME) &&
2dad624e
ND
9402 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME,
9403 survey->time, NL80211_SURVEY_INFO_PAD))
9360ffd1 9404 goto nla_put_failure;
4ed20beb 9405 if ((survey->filled & SURVEY_INFO_TIME_BUSY) &&
2dad624e
ND
9406 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_BUSY,
9407 survey->time_busy, NL80211_SURVEY_INFO_PAD))
9360ffd1 9408 goto nla_put_failure;
4ed20beb 9409 if ((survey->filled & SURVEY_INFO_TIME_EXT_BUSY) &&
2dad624e
ND
9410 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_EXT_BUSY,
9411 survey->time_ext_busy, NL80211_SURVEY_INFO_PAD))
9360ffd1 9412 goto nla_put_failure;
4ed20beb 9413 if ((survey->filled & SURVEY_INFO_TIME_RX) &&
2dad624e
ND
9414 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_RX,
9415 survey->time_rx, NL80211_SURVEY_INFO_PAD))
9360ffd1 9416 goto nla_put_failure;
4ed20beb 9417 if ((survey->filled & SURVEY_INFO_TIME_TX) &&
2dad624e
ND
9418 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_TX,
9419 survey->time_tx, NL80211_SURVEY_INFO_PAD))
9360ffd1 9420 goto nla_put_failure;
052536ab 9421 if ((survey->filled & SURVEY_INFO_TIME_SCAN) &&
2dad624e
ND
9422 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_SCAN,
9423 survey->time_scan, NL80211_SURVEY_INFO_PAD))
052536ab 9424 goto nla_put_failure;
c8cd6e7f
FF
9425 if ((survey->filled & SURVEY_INFO_TIME_BSS_RX) &&
9426 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_BSS_RX,
9427 survey->time_bss_rx, NL80211_SURVEY_INFO_PAD))
9428 goto nla_put_failure;
61fa713c
HS
9429
9430 nla_nest_end(msg, infoattr);
9431
053c095a
JB
9432 genlmsg_end(msg, hdr);
9433 return 0;
61fa713c
HS
9434
9435 nla_put_failure:
9436 genlmsg_cancel(msg, hdr);
9437 return -EMSGSIZE;
9438}
9439
11f78ac3 9440static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
61fa713c 9441{
50508d94 9442 struct nlattr **attrbuf;
61fa713c 9443 struct survey_info survey;
1b8ec87a 9444 struct cfg80211_registered_device *rdev;
97990a06
JB
9445 struct wireless_dev *wdev;
9446 int survey_idx = cb->args[2];
61fa713c 9447 int res;
11f78ac3 9448 bool radio_stats;
61fa713c 9449
50508d94
JB
9450 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), GFP_KERNEL);
9451 if (!attrbuf)
9452 return -ENOMEM;
9453
ea90e0dc 9454 rtnl_lock();
5297c65c 9455 res = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
67748893 9456 if (res)
ea90e0dc 9457 goto out_err;
61fa713c 9458
11f78ac3 9459 /* prepare_wdev_dump parsed the attributes */
c90c39da 9460 radio_stats = attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS];
11f78ac3 9461
97990a06
JB
9462 if (!wdev->netdev) {
9463 res = -EINVAL;
9464 goto out_err;
9465 }
9466
1b8ec87a 9467 if (!rdev->ops->dump_survey) {
61fa713c
HS
9468 res = -EOPNOTSUPP;
9469 goto out_err;
9470 }
9471
9472 while (1) {
1b8ec87a 9473 res = rdev_dump_survey(rdev, wdev->netdev, survey_idx, &survey);
61fa713c
HS
9474 if (res == -ENOENT)
9475 break;
9476 if (res)
9477 goto out_err;
9478
11f78ac3
JB
9479 /* don't send disabled channels, but do send non-channel data */
9480 if (survey.channel &&
9481 survey.channel->flags & IEEE80211_CHAN_DISABLED) {
180cdc79
LR
9482 survey_idx++;
9483 continue;
9484 }
9485
61fa713c 9486 if (nl80211_send_survey(skb,
15e47304 9487 NETLINK_CB(cb->skb).portid,
61fa713c 9488 cb->nlh->nlmsg_seq, NLM_F_MULTI,
11f78ac3 9489 wdev->netdev, radio_stats, &survey) < 0)
61fa713c
HS
9490 goto out;
9491 survey_idx++;
9492 }
9493
9494 out:
97990a06 9495 cb->args[2] = survey_idx;
61fa713c
HS
9496 res = skb->len;
9497 out_err:
50508d94 9498 kfree(attrbuf);
ea90e0dc 9499 rtnl_unlock();
61fa713c
HS
9500 return res;
9501}
9502
b23aa676
SO
9503static bool nl80211_valid_wpa_versions(u32 wpa_versions)
9504{
9505 return !(wpa_versions & ~(NL80211_WPA_VERSION_1 |
cc3e14c2
CHH
9506 NL80211_WPA_VERSION_2 |
9507 NL80211_WPA_VERSION_3));
b23aa676
SO
9508}
9509
636a5d36
JM
9510static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
9511{
4c476991
JB
9512 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9513 struct net_device *dev = info->user_ptr[1];
19957bb3 9514 struct ieee80211_channel *chan;
11b6b5a4
JM
9515 const u8 *bssid, *ssid, *ie = NULL, *auth_data = NULL;
9516 int err, ssid_len, ie_len = 0, auth_data_len = 0;
19957bb3 9517 enum nl80211_auth_type auth_type;
fffd0934 9518 struct key_parse key;
d5cdfacb 9519 bool local_state_change;
942ba88b 9520 u32 freq;
636a5d36 9521
f4a11bb0
JB
9522 if (!info->attrs[NL80211_ATTR_MAC])
9523 return -EINVAL;
9524
1778092e
JM
9525 if (!info->attrs[NL80211_ATTR_AUTH_TYPE])
9526 return -EINVAL;
9527
19957bb3
JB
9528 if (!info->attrs[NL80211_ATTR_SSID])
9529 return -EINVAL;
9530
9531 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
9532 return -EINVAL;
9533
fffd0934
JB
9534 err = nl80211_parse_key(info, &key);
9535 if (err)
9536 return err;
9537
9538 if (key.idx >= 0) {
e31b8213
JB
9539 if (key.type != -1 && key.type != NL80211_KEYTYPE_GROUP)
9540 return -EINVAL;
fffd0934
JB
9541 if (!key.p.key || !key.p.key_len)
9542 return -EINVAL;
9543 if ((key.p.cipher != WLAN_CIPHER_SUITE_WEP40 ||
9544 key.p.key_len != WLAN_KEY_LEN_WEP40) &&
9545 (key.p.cipher != WLAN_CIPHER_SUITE_WEP104 ||
9546 key.p.key_len != WLAN_KEY_LEN_WEP104))
9547 return -EINVAL;
b6b5555b 9548 if (key.idx > 3)
fffd0934
JB
9549 return -EINVAL;
9550 } else {
9551 key.p.key_len = 0;
9552 key.p.key = NULL;
9553 }
9554
afea0b7a
JB
9555 if (key.idx >= 0) {
9556 int i;
9557 bool ok = false;
7a087e74 9558
afea0b7a
JB
9559 for (i = 0; i < rdev->wiphy.n_cipher_suites; i++) {
9560 if (key.p.cipher == rdev->wiphy.cipher_suites[i]) {
9561 ok = true;
9562 break;
9563 }
9564 }
4c476991
JB
9565 if (!ok)
9566 return -EINVAL;
afea0b7a
JB
9567 }
9568
4c476991
JB
9569 if (!rdev->ops->auth)
9570 return -EOPNOTSUPP;
636a5d36 9571
074ac8df 9572 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
9573 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
9574 return -EOPNOTSUPP;
eec60b03 9575
19957bb3 9576 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
942ba88b
TP
9577 freq = MHZ_TO_KHZ(nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
9578 if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
9579 freq +=
9580 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
9581
9582 chan = nl80211_get_valid_chan(&rdev->wiphy, freq);
664834de 9583 if (!chan)
4c476991 9584 return -EINVAL;
636a5d36 9585
19957bb3
JB
9586 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
9587 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
636a5d36
JM
9588
9589 if (info->attrs[NL80211_ATTR_IE]) {
19957bb3
JB
9590 ie = nla_data(info->attrs[NL80211_ATTR_IE]);
9591 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
9592 }
9593
19957bb3 9594 auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
e39e5b5e 9595 if (!nl80211_valid_auth_type(rdev, auth_type, NL80211_CMD_AUTHENTICATE))
4c476991 9596 return -EINVAL;
636a5d36 9597
63181060
JM
9598 if ((auth_type == NL80211_AUTHTYPE_SAE ||
9599 auth_type == NL80211_AUTHTYPE_FILS_SK ||
9600 auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
9601 auth_type == NL80211_AUTHTYPE_FILS_PK) &&
11b6b5a4 9602 !info->attrs[NL80211_ATTR_AUTH_DATA])
e39e5b5e
JM
9603 return -EINVAL;
9604
11b6b5a4 9605 if (info->attrs[NL80211_ATTR_AUTH_DATA]) {
63181060
JM
9606 if (auth_type != NL80211_AUTHTYPE_SAE &&
9607 auth_type != NL80211_AUTHTYPE_FILS_SK &&
9608 auth_type != NL80211_AUTHTYPE_FILS_SK_PFS &&
9609 auth_type != NL80211_AUTHTYPE_FILS_PK)
e39e5b5e 9610 return -EINVAL;
11b6b5a4
JM
9611 auth_data = nla_data(info->attrs[NL80211_ATTR_AUTH_DATA]);
9612 auth_data_len = nla_len(info->attrs[NL80211_ATTR_AUTH_DATA]);
e39e5b5e
JM
9613 }
9614
d5cdfacb
JM
9615 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
9616
95de817b
JB
9617 /*
9618 * Since we no longer track auth state, ignore
9619 * requests to only change local state.
9620 */
9621 if (local_state_change)
9622 return 0;
9623
91bf9b26
JB
9624 wdev_lock(dev->ieee80211_ptr);
9625 err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
9626 ssid, ssid_len, ie, ie_len,
9627 key.p.key, key.p.key_len, key.idx,
11b6b5a4 9628 auth_data, auth_data_len);
91bf9b26
JB
9629 wdev_unlock(dev->ieee80211_ptr);
9630 return err;
636a5d36
JM
9631}
9632
64bf3d4b
DK
9633static int validate_pae_over_nl80211(struct cfg80211_registered_device *rdev,
9634 struct genl_info *info)
9635{
9636 if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
9637 GENL_SET_ERR_MSG(info, "SOCKET_OWNER not set");
9638 return -EINVAL;
9639 }
9640
9641 if (!rdev->ops->tx_control_port ||
9642 !wiphy_ext_feature_isset(&rdev->wiphy,
9643 NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211))
9644 return -EOPNOTSUPP;
9645
9646 return 0;
9647}
9648
c0692b8f
JB
9649static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
9650 struct genl_info *info,
3dc27d25
JB
9651 struct cfg80211_crypto_settings *settings,
9652 int cipher_limit)
b23aa676 9653{
c0b2bbd8
JB
9654 memset(settings, 0, sizeof(*settings));
9655
b23aa676
SO
9656 settings->control_port = info->attrs[NL80211_ATTR_CONTROL_PORT];
9657
c0692b8f
JB
9658 if (info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) {
9659 u16 proto;
7a087e74 9660
c0692b8f
JB
9661 proto = nla_get_u16(
9662 info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]);
9663 settings->control_port_ethertype = cpu_to_be16(proto);
9664 if (!(rdev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) &&
9665 proto != ETH_P_PAE)
9666 return -EINVAL;
9667 if (info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT])
9668 settings->control_port_no_encrypt = true;
9669 } else
9670 settings->control_port_ethertype = cpu_to_be16(ETH_P_PAE);
9671
64bf3d4b
DK
9672 if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) {
9673 int r = validate_pae_over_nl80211(rdev, info);
9674
9675 if (r < 0)
9676 return r;
9677
9678 settings->control_port_over_nl80211 = true;
7f3f96ce
MT
9679
9680 if (info->attrs[NL80211_ATTR_CONTROL_PORT_NO_PREAUTH])
9681 settings->control_port_no_preauth = true;
64bf3d4b
DK
9682 }
9683
b23aa676
SO
9684 if (info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]) {
9685 void *data;
9686 int len, i;
9687
9688 data = nla_data(info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]);
9689 len = nla_len(info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]);
9690 settings->n_ciphers_pairwise = len / sizeof(u32);
9691
9692 if (len % sizeof(u32))
9693 return -EINVAL;
9694
3dc27d25 9695 if (settings->n_ciphers_pairwise > cipher_limit)
b23aa676
SO
9696 return -EINVAL;
9697
9698 memcpy(settings->ciphers_pairwise, data, len);
9699
9700 for (i = 0; i < settings->n_ciphers_pairwise; i++)
38ba3c57
JM
9701 if (!cfg80211_supported_cipher_suite(
9702 &rdev->wiphy,
b23aa676
SO
9703 settings->ciphers_pairwise[i]))
9704 return -EINVAL;
9705 }
9706
9707 if (info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]) {
9708 settings->cipher_group =
9709 nla_get_u32(info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]);
38ba3c57
JM
9710 if (!cfg80211_supported_cipher_suite(&rdev->wiphy,
9711 settings->cipher_group))
b23aa676
SO
9712 return -EINVAL;
9713 }
9714
9715 if (info->attrs[NL80211_ATTR_WPA_VERSIONS]) {
9716 settings->wpa_versions =
9717 nla_get_u32(info->attrs[NL80211_ATTR_WPA_VERSIONS]);
9718 if (!nl80211_valid_wpa_versions(settings->wpa_versions))
9719 return -EINVAL;
9720 }
9721
9722 if (info->attrs[NL80211_ATTR_AKM_SUITES]) {
9723 void *data;
6d30240e 9724 int len;
b23aa676
SO
9725
9726 data = nla_data(info->attrs[NL80211_ATTR_AKM_SUITES]);
9727 len = nla_len(info->attrs[NL80211_ATTR_AKM_SUITES]);
9728 settings->n_akm_suites = len / sizeof(u32);
9729
9730 if (len % sizeof(u32))
9731 return -EINVAL;
9732
1b9ca027
JM
9733 if (settings->n_akm_suites > NL80211_MAX_NR_AKM_SUITES)
9734 return -EINVAL;
9735
b23aa676 9736 memcpy(settings->akm_suites, data, len);
b23aa676
SO
9737 }
9738
91b5ab62
EP
9739 if (info->attrs[NL80211_ATTR_PMK]) {
9740 if (nla_len(info->attrs[NL80211_ATTR_PMK]) != WLAN_PMK_LEN)
9741 return -EINVAL;
9742 if (!wiphy_ext_feature_isset(&rdev->wiphy,
f9662274
CHH
9743 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK) &&
9744 !wiphy_ext_feature_isset(&rdev->wiphy,
9745 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK))
91b5ab62
EP
9746 return -EINVAL;
9747 settings->psk = nla_data(info->attrs[NL80211_ATTR_PMK]);
9748 }
9749
26f7044e
CHH
9750 if (info->attrs[NL80211_ATTR_SAE_PASSWORD]) {
9751 if (!wiphy_ext_feature_isset(&rdev->wiphy,
2831a631
CHH
9752 NL80211_EXT_FEATURE_SAE_OFFLOAD) &&
9753 !wiphy_ext_feature_isset(&rdev->wiphy,
9754 NL80211_EXT_FEATURE_SAE_OFFLOAD_AP))
26f7044e
CHH
9755 return -EINVAL;
9756 settings->sae_pwd =
9757 nla_data(info->attrs[NL80211_ATTR_SAE_PASSWORD]);
9758 settings->sae_pwd_len =
9759 nla_len(info->attrs[NL80211_ATTR_SAE_PASSWORD]);
9760 }
9761
9f0ffa41
RD
9762 if (info->attrs[NL80211_ATTR_SAE_PWE])
9763 settings->sae_pwe =
9764 nla_get_u8(info->attrs[NL80211_ATTR_SAE_PWE]);
9765 else
9766 settings->sae_pwe = NL80211_SAE_PWE_UNSPECIFIED;
9767
b23aa676
SO
9768 return 0;
9769}
9770
636a5d36
JM
9771static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
9772{
4c476991
JB
9773 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9774 struct net_device *dev = info->user_ptr[1];
f444de05 9775 struct ieee80211_channel *chan;
f62fab73
JB
9776 struct cfg80211_assoc_request req = {};
9777 const u8 *bssid, *ssid;
9778 int err, ssid_len = 0;
942ba88b 9779 u32 freq;
636a5d36 9780
bad29297
AZ
9781 if (dev->ieee80211_ptr->conn_owner_nlportid &&
9782 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
9783 return -EPERM;
9784
f4a11bb0 9785 if (!info->attrs[NL80211_ATTR_MAC] ||
19957bb3
JB
9786 !info->attrs[NL80211_ATTR_SSID] ||
9787 !info->attrs[NL80211_ATTR_WIPHY_FREQ])
f4a11bb0
JB
9788 return -EINVAL;
9789
4c476991
JB
9790 if (!rdev->ops->assoc)
9791 return -EOPNOTSUPP;
636a5d36 9792
074ac8df 9793 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
9794 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
9795 return -EOPNOTSUPP;
eec60b03 9796
19957bb3 9797 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
636a5d36 9798
942ba88b
TP
9799 freq = MHZ_TO_KHZ(nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
9800 if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
9801 freq +=
9802 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
9803 chan = nl80211_get_valid_chan(&rdev->wiphy, freq);
664834de 9804 if (!chan)
4c476991 9805 return -EINVAL;
636a5d36 9806
19957bb3
JB
9807 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
9808 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
636a5d36
JM
9809
9810 if (info->attrs[NL80211_ATTR_IE]) {
f62fab73
JB
9811 req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
9812 req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
9813 }
9814
dc6382ce 9815 if (info->attrs[NL80211_ATTR_USE_MFP]) {
4f5dadce 9816 enum nl80211_mfp mfp =
dc6382ce 9817 nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
4f5dadce 9818 if (mfp == NL80211_MFP_REQUIRED)
f62fab73 9819 req.use_mfp = true;
4c476991
JB
9820 else if (mfp != NL80211_MFP_NO)
9821 return -EINVAL;
dc6382ce
JM
9822 }
9823
3e5d7649 9824 if (info->attrs[NL80211_ATTR_PREV_BSSID])
f62fab73 9825 req.prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
3e5d7649 9826
7e7c8926 9827 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
f62fab73 9828 req.flags |= ASSOC_REQ_DISABLE_HT;
7e7c8926
BG
9829
9830 if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
f62fab73
JB
9831 memcpy(&req.ht_capa_mask,
9832 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
9833 sizeof(req.ht_capa_mask));
7e7c8926
BG
9834
9835 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
f62fab73 9836 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
7e7c8926 9837 return -EINVAL;
f62fab73
JB
9838 memcpy(&req.ht_capa,
9839 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
9840 sizeof(req.ht_capa));
7e7c8926
BG
9841 }
9842
ee2aca34 9843 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT]))
f62fab73 9844 req.flags |= ASSOC_REQ_DISABLE_VHT;
ee2aca34
JB
9845
9846 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
f62fab73
JB
9847 memcpy(&req.vht_capa_mask,
9848 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
9849 sizeof(req.vht_capa_mask));
ee2aca34
JB
9850
9851 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) {
f62fab73 9852 if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
ee2aca34 9853 return -EINVAL;
f62fab73
JB
9854 memcpy(&req.vht_capa,
9855 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]),
9856 sizeof(req.vht_capa));
ee2aca34
JB
9857 }
9858
bab5ab7d 9859 if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
0c9ca11b
BL
9860 if (!((rdev->wiphy.features &
9861 NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) &&
9862 (rdev->wiphy.features & NL80211_FEATURE_QUIET)) &&
9863 !wiphy_ext_feature_isset(&rdev->wiphy,
9864 NL80211_EXT_FEATURE_RRM))
bab5ab7d
AK
9865 return -EINVAL;
9866 req.flags |= ASSOC_REQ_USE_RRM;
9867 }
9868
348bd456
JM
9869 if (info->attrs[NL80211_ATTR_FILS_KEK]) {
9870 req.fils_kek = nla_data(info->attrs[NL80211_ATTR_FILS_KEK]);
9871 req.fils_kek_len = nla_len(info->attrs[NL80211_ATTR_FILS_KEK]);
9872 if (!info->attrs[NL80211_ATTR_FILS_NONCES])
9873 return -EINVAL;
9874 req.fils_nonces =
9875 nla_data(info->attrs[NL80211_ATTR_FILS_NONCES]);
9876 }
9877
d2b7588a
TP
9878 if (info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK]) {
9879 if (!info->attrs[NL80211_ATTR_S1G_CAPABILITY])
9880 return -EINVAL;
9881 memcpy(&req.s1g_capa_mask,
9882 nla_data(info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK]),
9883 sizeof(req.s1g_capa_mask));
9884 }
9885
9886 if (info->attrs[NL80211_ATTR_S1G_CAPABILITY]) {
9887 if (!info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK])
9888 return -EINVAL;
9889 memcpy(&req.s1g_capa,
9890 nla_data(info->attrs[NL80211_ATTR_S1G_CAPABILITY]),
9891 sizeof(req.s1g_capa));
9892 }
9893
f62fab73 9894 err = nl80211_crypto_settings(rdev, info, &req.crypto, 1);
91bf9b26
JB
9895 if (!err) {
9896 wdev_lock(dev->ieee80211_ptr);
bd2522b1 9897
f62fab73
JB
9898 err = cfg80211_mlme_assoc(rdev, dev, chan, bssid,
9899 ssid, ssid_len, &req);
bd2522b1
AZ
9900
9901 if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
9902 dev->ieee80211_ptr->conn_owner_nlportid =
9903 info->snd_portid;
9904 memcpy(dev->ieee80211_ptr->disconnect_bssid,
9905 bssid, ETH_ALEN);
9906 }
9907
91bf9b26
JB
9908 wdev_unlock(dev->ieee80211_ptr);
9909 }
636a5d36 9910
636a5d36
JM
9911 return err;
9912}
9913
9914static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
9915{
4c476991
JB
9916 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9917 struct net_device *dev = info->user_ptr[1];
19957bb3 9918 const u8 *ie = NULL, *bssid;
91bf9b26 9919 int ie_len = 0, err;
19957bb3 9920 u16 reason_code;
d5cdfacb 9921 bool local_state_change;
636a5d36 9922
bad29297
AZ
9923 if (dev->ieee80211_ptr->conn_owner_nlportid &&
9924 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
9925 return -EPERM;
9926
f4a11bb0
JB
9927 if (!info->attrs[NL80211_ATTR_MAC])
9928 return -EINVAL;
9929
9930 if (!info->attrs[NL80211_ATTR_REASON_CODE])
9931 return -EINVAL;
9932
4c476991
JB
9933 if (!rdev->ops->deauth)
9934 return -EOPNOTSUPP;
636a5d36 9935
074ac8df 9936 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
9937 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
9938 return -EOPNOTSUPP;
eec60b03 9939
19957bb3 9940 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
636a5d36 9941
19957bb3
JB
9942 reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
9943 if (reason_code == 0) {
f4a11bb0 9944 /* Reason Code 0 is reserved */
4c476991 9945 return -EINVAL;
255e737e 9946 }
636a5d36
JM
9947
9948 if (info->attrs[NL80211_ATTR_IE]) {
19957bb3
JB
9949 ie = nla_data(info->attrs[NL80211_ATTR_IE]);
9950 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
9951 }
9952
d5cdfacb
JM
9953 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
9954
91bf9b26
JB
9955 wdev_lock(dev->ieee80211_ptr);
9956 err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code,
9957 local_state_change);
9958 wdev_unlock(dev->ieee80211_ptr);
9959 return err;
636a5d36
JM
9960}
9961
9962static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
9963{
4c476991
JB
9964 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9965 struct net_device *dev = info->user_ptr[1];
19957bb3 9966 const u8 *ie = NULL, *bssid;
91bf9b26 9967 int ie_len = 0, err;
19957bb3 9968 u16 reason_code;
d5cdfacb 9969 bool local_state_change;
636a5d36 9970
bad29297
AZ
9971 if (dev->ieee80211_ptr->conn_owner_nlportid &&
9972 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
9973 return -EPERM;
9974
f4a11bb0
JB
9975 if (!info->attrs[NL80211_ATTR_MAC])
9976 return -EINVAL;
9977
9978 if (!info->attrs[NL80211_ATTR_REASON_CODE])
9979 return -EINVAL;
9980
4c476991
JB
9981 if (!rdev->ops->disassoc)
9982 return -EOPNOTSUPP;
636a5d36 9983
074ac8df 9984 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
9985 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
9986 return -EOPNOTSUPP;
eec60b03 9987
19957bb3 9988 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
636a5d36 9989
19957bb3
JB
9990 reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
9991 if (reason_code == 0) {
f4a11bb0 9992 /* Reason Code 0 is reserved */
4c476991 9993 return -EINVAL;
255e737e 9994 }
636a5d36
JM
9995
9996 if (info->attrs[NL80211_ATTR_IE]) {
19957bb3
JB
9997 ie = nla_data(info->attrs[NL80211_ATTR_IE]);
9998 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
9999 }
10000
d5cdfacb
JM
10001 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
10002
91bf9b26
JB
10003 wdev_lock(dev->ieee80211_ptr);
10004 err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code,
10005 local_state_change);
10006 wdev_unlock(dev->ieee80211_ptr);
10007 return err;
636a5d36
JM
10008}
10009
dd5b4cc7
FF
10010static bool
10011nl80211_parse_mcast_rate(struct cfg80211_registered_device *rdev,
57fbcce3 10012 int mcast_rate[NUM_NL80211_BANDS],
dd5b4cc7
FF
10013 int rateval)
10014{
10015 struct wiphy *wiphy = &rdev->wiphy;
10016 bool found = false;
10017 int band, i;
10018
57fbcce3 10019 for (band = 0; band < NUM_NL80211_BANDS; band++) {
dd5b4cc7
FF
10020 struct ieee80211_supported_band *sband;
10021
10022 sband = wiphy->bands[band];
10023 if (!sband)
10024 continue;
10025
10026 for (i = 0; i < sband->n_bitrates; i++) {
10027 if (sband->bitrates[i].bitrate == rateval) {
10028 mcast_rate[band] = i + 1;
10029 found = true;
10030 break;
10031 }
10032 }
10033 }
10034
10035 return found;
10036}
10037
04a773ad
JB
10038static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
10039{
4c476991
JB
10040 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10041 struct net_device *dev = info->user_ptr[1];
04a773ad
JB
10042 struct cfg80211_ibss_params ibss;
10043 struct wiphy *wiphy;
fffd0934 10044 struct cfg80211_cached_keys *connkeys = NULL;
04a773ad
JB
10045 int err;
10046
8e30bc55
JB
10047 memset(&ibss, 0, sizeof(ibss));
10048
683b6d3b 10049 if (!info->attrs[NL80211_ATTR_SSID] ||
04a773ad
JB
10050 !nla_len(info->attrs[NL80211_ATTR_SSID]))
10051 return -EINVAL;
10052
8e30bc55
JB
10053 ibss.beacon_interval = 100;
10054
12d20fc9 10055 if (info->attrs[NL80211_ATTR_BEACON_INTERVAL])
8e30bc55
JB
10056 ibss.beacon_interval =
10057 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
12d20fc9 10058
0c317a02
PK
10059 err = cfg80211_validate_beacon_int(rdev, NL80211_IFTYPE_ADHOC,
10060 ibss.beacon_interval);
12d20fc9
PK
10061 if (err)
10062 return err;
8e30bc55 10063
4c476991
JB
10064 if (!rdev->ops->join_ibss)
10065 return -EOPNOTSUPP;
04a773ad 10066
4c476991
JB
10067 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
10068 return -EOPNOTSUPP;
04a773ad 10069
79c97e97 10070 wiphy = &rdev->wiphy;
04a773ad 10071
39193498 10072 if (info->attrs[NL80211_ATTR_MAC]) {
04a773ad 10073 ibss.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
39193498
JB
10074
10075 if (!is_valid_ether_addr(ibss.bssid))
10076 return -EINVAL;
10077 }
04a773ad
JB
10078 ibss.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
10079 ibss.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
10080
10081 if (info->attrs[NL80211_ATTR_IE]) {
10082 ibss.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
10083 ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
10084 }
10085
683b6d3b
JB
10086 err = nl80211_parse_chandef(rdev, info, &ibss.chandef);
10087 if (err)
10088 return err;
04a773ad 10089
174e0cd2
IP
10090 if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef,
10091 NL80211_IFTYPE_ADHOC))
54858ee5
AS
10092 return -EINVAL;
10093
2f301ab2 10094 switch (ibss.chandef.width) {
bf372645
SW
10095 case NL80211_CHAN_WIDTH_5:
10096 case NL80211_CHAN_WIDTH_10:
2f301ab2
SW
10097 case NL80211_CHAN_WIDTH_20_NOHT:
10098 break;
10099 case NL80211_CHAN_WIDTH_20:
10100 case NL80211_CHAN_WIDTH_40:
ffc11991
JD
10101 if (!(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS))
10102 return -EINVAL;
10103 break;
10104 case NL80211_CHAN_WIDTH_80:
10105 case NL80211_CHAN_WIDTH_80P80:
10106 case NL80211_CHAN_WIDTH_160:
10107 if (!(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS))
10108 return -EINVAL;
10109 if (!wiphy_ext_feature_isset(&rdev->wiphy,
10110 NL80211_EXT_FEATURE_VHT_IBSS))
10111 return -EINVAL;
10112 break;
2f301ab2 10113 default:
c04d6150 10114 return -EINVAL;
2f301ab2 10115 }
db9c64cf 10116
04a773ad 10117 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
fffd0934
JB
10118 ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
10119
fbd2c8dc
TP
10120 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
10121 u8 *rates =
10122 nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
10123 int n_rates =
10124 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
10125 struct ieee80211_supported_band *sband =
683b6d3b 10126 wiphy->bands[ibss.chandef.chan->band];
fbd2c8dc 10127
34850ab2
JB
10128 err = ieee80211_get_ratemask(sband, rates, n_rates,
10129 &ibss.basic_rates);
10130 if (err)
10131 return err;
fbd2c8dc 10132 }
dd5b4cc7 10133
803768f5
SW
10134 if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
10135 memcpy(&ibss.ht_capa_mask,
10136 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
10137 sizeof(ibss.ht_capa_mask));
10138
10139 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
10140 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
10141 return -EINVAL;
10142 memcpy(&ibss.ht_capa,
10143 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
10144 sizeof(ibss.ht_capa));
10145 }
10146
dd5b4cc7
FF
10147 if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
10148 !nl80211_parse_mcast_rate(rdev, ibss.mcast_rate,
10149 nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE])))
10150 return -EINVAL;
fbd2c8dc 10151
4c476991 10152 if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
de7044ee
SM
10153 bool no_ht = false;
10154
768075eb 10155 connkeys = nl80211_parse_connkeys(rdev, info, &no_ht);
4c476991
JB
10156 if (IS_ERR(connkeys))
10157 return PTR_ERR(connkeys);
de7044ee 10158
3d9d1d66
JB
10159 if ((ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) &&
10160 no_ht) {
453431a5 10161 kfree_sensitive(connkeys);
de7044ee
SM
10162 return -EINVAL;
10163 }
4c476991 10164 }
04a773ad 10165
267335d6
AQ
10166 ibss.control_port =
10167 nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT]);
10168
c3bfe1f6
DK
10169 if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) {
10170 int r = validate_pae_over_nl80211(rdev, info);
10171
d350a0f4 10172 if (r < 0) {
453431a5 10173 kfree_sensitive(connkeys);
c3bfe1f6 10174 return r;
d350a0f4 10175 }
c3bfe1f6
DK
10176
10177 ibss.control_port_over_nl80211 = true;
10178 }
10179
5336fa88
SW
10180 ibss.userspace_handles_dfs =
10181 nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]);
10182
f8d16d3e
DK
10183 wdev_lock(dev->ieee80211_ptr);
10184 err = __cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
fffd0934 10185 if (err)
453431a5 10186 kfree_sensitive(connkeys);
f8d16d3e
DK
10187 else if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
10188 dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
10189 wdev_unlock(dev->ieee80211_ptr);
10190
04a773ad
JB
10191 return err;
10192}
10193
10194static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info)
10195{
4c476991
JB
10196 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10197 struct net_device *dev = info->user_ptr[1];
04a773ad 10198
4c476991
JB
10199 if (!rdev->ops->leave_ibss)
10200 return -EOPNOTSUPP;
04a773ad 10201
4c476991
JB
10202 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
10203 return -EOPNOTSUPP;
04a773ad 10204
4c476991 10205 return cfg80211_leave_ibss(rdev, dev, false);
04a773ad
JB
10206}
10207
f4e583c8
AQ
10208static int nl80211_set_mcast_rate(struct sk_buff *skb, struct genl_info *info)
10209{
10210 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10211 struct net_device *dev = info->user_ptr[1];
57fbcce3 10212 int mcast_rate[NUM_NL80211_BANDS];
f4e583c8
AQ
10213 u32 nla_rate;
10214 int err;
10215
10216 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
876dc930
BVB
10217 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
10218 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_OCB)
f4e583c8
AQ
10219 return -EOPNOTSUPP;
10220
10221 if (!rdev->ops->set_mcast_rate)
10222 return -EOPNOTSUPP;
10223
10224 memset(mcast_rate, 0, sizeof(mcast_rate));
10225
10226 if (!info->attrs[NL80211_ATTR_MCAST_RATE])
10227 return -EINVAL;
10228
10229 nla_rate = nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE]);
10230 if (!nl80211_parse_mcast_rate(rdev, mcast_rate, nla_rate))
10231 return -EINVAL;
10232
a1056b1b 10233 err = rdev_set_mcast_rate(rdev, dev, mcast_rate);
f4e583c8
AQ
10234
10235 return err;
10236}
10237
ad7e718c
JB
10238static struct sk_buff *
10239__cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev,
6c09e791
AK
10240 struct wireless_dev *wdev, int approxlen,
10241 u32 portid, u32 seq, enum nl80211_commands cmd,
567ffc35
JB
10242 enum nl80211_attrs attr,
10243 const struct nl80211_vendor_cmd_info *info,
10244 gfp_t gfp)
ad7e718c
JB
10245{
10246 struct sk_buff *skb;
10247 void *hdr;
10248 struct nlattr *data;
10249
10250 skb = nlmsg_new(approxlen + 100, gfp);
10251 if (!skb)
10252 return NULL;
10253
10254 hdr = nl80211hdr_put(skb, portid, seq, 0, cmd);
10255 if (!hdr) {
10256 kfree_skb(skb);
10257 return NULL;
10258 }
10259
10260 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
10261 goto nla_put_failure;
567ffc35
JB
10262
10263 if (info) {
10264 if (nla_put_u32(skb, NL80211_ATTR_VENDOR_ID,
10265 info->vendor_id))
10266 goto nla_put_failure;
10267 if (nla_put_u32(skb, NL80211_ATTR_VENDOR_SUBCMD,
10268 info->subcmd))
10269 goto nla_put_failure;
10270 }
10271
6c09e791 10272 if (wdev) {
2dad624e
ND
10273 if (nla_put_u64_64bit(skb, NL80211_ATTR_WDEV,
10274 wdev_id(wdev), NL80211_ATTR_PAD))
6c09e791
AK
10275 goto nla_put_failure;
10276 if (wdev->netdev &&
10277 nla_put_u32(skb, NL80211_ATTR_IFINDEX,
10278 wdev->netdev->ifindex))
10279 goto nla_put_failure;
10280 }
10281
ae0be8de 10282 data = nla_nest_start_noflag(skb, attr);
76e1fb4b
JB
10283 if (!data)
10284 goto nla_put_failure;
ad7e718c
JB
10285
10286 ((void **)skb->cb)[0] = rdev;
10287 ((void **)skb->cb)[1] = hdr;
10288 ((void **)skb->cb)[2] = data;
10289
10290 return skb;
10291
10292 nla_put_failure:
10293 kfree_skb(skb);
10294 return NULL;
10295}
f4e583c8 10296
e03ad6ea 10297struct sk_buff *__cfg80211_alloc_event_skb(struct wiphy *wiphy,
6c09e791 10298 struct wireless_dev *wdev,
e03ad6ea
JB
10299 enum nl80211_commands cmd,
10300 enum nl80211_attrs attr,
55c1fdf0 10301 unsigned int portid,
e03ad6ea
JB
10302 int vendor_event_idx,
10303 int approxlen, gfp_t gfp)
10304{
f26cbf40 10305 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
e03ad6ea
JB
10306 const struct nl80211_vendor_cmd_info *info;
10307
10308 switch (cmd) {
10309 case NL80211_CMD_TESTMODE:
10310 if (WARN_ON(vendor_event_idx != -1))
10311 return NULL;
10312 info = NULL;
10313 break;
10314 case NL80211_CMD_VENDOR:
10315 if (WARN_ON(vendor_event_idx < 0 ||
10316 vendor_event_idx >= wiphy->n_vendor_events))
10317 return NULL;
10318 info = &wiphy->vendor_events[vendor_event_idx];
10319 break;
10320 default:
10321 WARN_ON(1);
10322 return NULL;
10323 }
10324
55c1fdf0 10325 return __cfg80211_alloc_vendor_skb(rdev, wdev, approxlen, portid, 0,
e03ad6ea
JB
10326 cmd, attr, info, gfp);
10327}
10328EXPORT_SYMBOL(__cfg80211_alloc_event_skb);
10329
10330void __cfg80211_send_event_skb(struct sk_buff *skb, gfp_t gfp)
10331{
10332 struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
10333 void *hdr = ((void **)skb->cb)[1];
55c1fdf0 10334 struct nlmsghdr *nlhdr = nlmsg_hdr(skb);
e03ad6ea
JB
10335 struct nlattr *data = ((void **)skb->cb)[2];
10336 enum nl80211_multicast_groups mcgrp = NL80211_MCGRP_TESTMODE;
10337
bd8c78e7
JB
10338 /* clear CB data for netlink core to own from now on */
10339 memset(skb->cb, 0, sizeof(skb->cb));
10340
e03ad6ea
JB
10341 nla_nest_end(skb, data);
10342 genlmsg_end(skb, hdr);
10343
55c1fdf0
JB
10344 if (nlhdr->nlmsg_pid) {
10345 genlmsg_unicast(wiphy_net(&rdev->wiphy), skb,
10346 nlhdr->nlmsg_pid);
10347 } else {
10348 if (data->nla_type == NL80211_ATTR_VENDOR_DATA)
10349 mcgrp = NL80211_MCGRP_VENDOR;
e03ad6ea 10350
55c1fdf0
JB
10351 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
10352 skb, 0, mcgrp, gfp);
10353 }
e03ad6ea
JB
10354}
10355EXPORT_SYMBOL(__cfg80211_send_event_skb);
10356
aff89a9b 10357#ifdef CONFIG_NL80211_TESTMODE
aff89a9b
JB
10358static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
10359{
4c476991 10360 struct cfg80211_registered_device *rdev = info->user_ptr[0];
fc73f11f
DS
10361 struct wireless_dev *wdev =
10362 __cfg80211_wdev_from_attrs(genl_info_net(info), info->attrs);
aff89a9b
JB
10363 int err;
10364
fc73f11f
DS
10365 if (!rdev->ops->testmode_cmd)
10366 return -EOPNOTSUPP;
10367
10368 if (IS_ERR(wdev)) {
10369 err = PTR_ERR(wdev);
10370 if (err != -EINVAL)
10371 return err;
10372 wdev = NULL;
10373 } else if (wdev->wiphy != &rdev->wiphy) {
10374 return -EINVAL;
10375 }
10376
aff89a9b
JB
10377 if (!info->attrs[NL80211_ATTR_TESTDATA])
10378 return -EINVAL;
10379
ad7e718c 10380 rdev->cur_cmd_info = info;
fc73f11f 10381 err = rdev_testmode_cmd(rdev, wdev,
aff89a9b
JB
10382 nla_data(info->attrs[NL80211_ATTR_TESTDATA]),
10383 nla_len(info->attrs[NL80211_ATTR_TESTDATA]));
ad7e718c 10384 rdev->cur_cmd_info = NULL;
aff89a9b 10385
aff89a9b
JB
10386 return err;
10387}
10388
71063f0e
WYG
10389static int nl80211_testmode_dump(struct sk_buff *skb,
10390 struct netlink_callback *cb)
10391{
00918d33 10392 struct cfg80211_registered_device *rdev;
50508d94 10393 struct nlattr **attrbuf = NULL;
71063f0e
WYG
10394 int err;
10395 long phy_idx;
10396 void *data = NULL;
10397 int data_len = 0;
10398
5fe231e8
JB
10399 rtnl_lock();
10400
71063f0e
WYG
10401 if (cb->args[0]) {
10402 /*
10403 * 0 is a valid index, but not valid for args[0],
10404 * so we need to offset by 1.
10405 */
10406 phy_idx = cb->args[0] - 1;
a4956dca
LC
10407
10408 rdev = cfg80211_rdev_by_wiphy_idx(phy_idx);
10409 if (!rdev) {
10410 err = -ENOENT;
10411 goto out_err;
10412 }
71063f0e 10413 } else {
50508d94
JB
10414 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf),
10415 GFP_KERNEL);
10416 if (!attrbuf) {
10417 err = -ENOMEM;
10418 goto out_err;
10419 }
c90c39da 10420
8cb08174
JB
10421 err = nlmsg_parse_deprecated(cb->nlh,
10422 GENL_HDRLEN + nl80211_fam.hdrsize,
10423 attrbuf, nl80211_fam.maxattr,
10424 nl80211_policy, NULL);
71063f0e 10425 if (err)
5fe231e8 10426 goto out_err;
00918d33 10427
c90c39da 10428 rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
2bd7e35d 10429 if (IS_ERR(rdev)) {
5fe231e8
JB
10430 err = PTR_ERR(rdev);
10431 goto out_err;
00918d33 10432 }
2bd7e35d 10433 phy_idx = rdev->wiphy_idx;
2bd7e35d 10434
c90c39da
JB
10435 if (attrbuf[NL80211_ATTR_TESTDATA])
10436 cb->args[1] = (long)attrbuf[NL80211_ATTR_TESTDATA];
71063f0e
WYG
10437 }
10438
10439 if (cb->args[1]) {
10440 data = nla_data((void *)cb->args[1]);
10441 data_len = nla_len((void *)cb->args[1]);
10442 }
10443
00918d33 10444 if (!rdev->ops->testmode_dump) {
71063f0e
WYG
10445 err = -EOPNOTSUPP;
10446 goto out_err;
10447 }
10448
10449 while (1) {
15e47304 10450 void *hdr = nl80211hdr_put(skb, NETLINK_CB(cb->skb).portid,
71063f0e
WYG
10451 cb->nlh->nlmsg_seq, NLM_F_MULTI,
10452 NL80211_CMD_TESTMODE);
10453 struct nlattr *tmdata;
10454
cb35fba3
DC
10455 if (!hdr)
10456 break;
10457
9360ffd1 10458 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, phy_idx)) {
71063f0e
WYG
10459 genlmsg_cancel(skb, hdr);
10460 break;
10461 }
10462
ae0be8de 10463 tmdata = nla_nest_start_noflag(skb, NL80211_ATTR_TESTDATA);
71063f0e
WYG
10464 if (!tmdata) {
10465 genlmsg_cancel(skb, hdr);
10466 break;
10467 }
e35e4d28 10468 err = rdev_testmode_dump(rdev, skb, cb, data, data_len);
71063f0e
WYG
10469 nla_nest_end(skb, tmdata);
10470
10471 if (err == -ENOBUFS || err == -ENOENT) {
10472 genlmsg_cancel(skb, hdr);
10473 break;
10474 } else if (err) {
10475 genlmsg_cancel(skb, hdr);
10476 goto out_err;
10477 }
10478
10479 genlmsg_end(skb, hdr);
10480 }
10481
10482 err = skb->len;
10483 /* see above */
10484 cb->args[0] = phy_idx + 1;
10485 out_err:
50508d94 10486 kfree(attrbuf);
5fe231e8 10487 rtnl_unlock();
71063f0e
WYG
10488 return err;
10489}
aff89a9b
JB
10490#endif
10491
b23aa676
SO
10492static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
10493{
4c476991
JB
10494 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10495 struct net_device *dev = info->user_ptr[1];
b23aa676
SO
10496 struct cfg80211_connect_params connect;
10497 struct wiphy *wiphy;
fffd0934 10498 struct cfg80211_cached_keys *connkeys = NULL;
942ba88b 10499 u32 freq = 0;
b23aa676
SO
10500 int err;
10501
10502 memset(&connect, 0, sizeof(connect));
10503
b23aa676
SO
10504 if (!info->attrs[NL80211_ATTR_SSID] ||
10505 !nla_len(info->attrs[NL80211_ATTR_SSID]))
10506 return -EINVAL;
10507
10508 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
10509 connect.auth_type =
10510 nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
e39e5b5e
JM
10511 if (!nl80211_valid_auth_type(rdev, connect.auth_type,
10512 NL80211_CMD_CONNECT))
b23aa676
SO
10513 return -EINVAL;
10514 } else
10515 connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
10516
10517 connect.privacy = info->attrs[NL80211_ATTR_PRIVACY];
10518
3a00df57
AS
10519 if (info->attrs[NL80211_ATTR_WANT_1X_4WAY_HS] &&
10520 !wiphy_ext_feature_isset(&rdev->wiphy,
10521 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
10522 return -EINVAL;
10523 connect.want_1x = info->attrs[NL80211_ATTR_WANT_1X_4WAY_HS];
10524
c0692b8f 10525 err = nl80211_crypto_settings(rdev, info, &connect.crypto,
3dc27d25 10526 NL80211_MAX_NR_CIPHER_SUITES);
b23aa676
SO
10527 if (err)
10528 return err;
b23aa676 10529
074ac8df 10530 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
10531 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
10532 return -EOPNOTSUPP;
b23aa676 10533
79c97e97 10534 wiphy = &rdev->wiphy;
b23aa676 10535
4486ea98
BS
10536 connect.bg_scan_period = -1;
10537 if (info->attrs[NL80211_ATTR_BG_SCAN_PERIOD] &&
10538 (wiphy->flags & WIPHY_FLAG_SUPPORTS_FW_ROAM)) {
10539 connect.bg_scan_period =
10540 nla_get_u16(info->attrs[NL80211_ATTR_BG_SCAN_PERIOD]);
10541 }
10542
b23aa676
SO
10543 if (info->attrs[NL80211_ATTR_MAC])
10544 connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
1df4a510
JM
10545 else if (info->attrs[NL80211_ATTR_MAC_HINT])
10546 connect.bssid_hint =
10547 nla_data(info->attrs[NL80211_ATTR_MAC_HINT]);
b23aa676
SO
10548 connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
10549 connect.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
10550
10551 if (info->attrs[NL80211_ATTR_IE]) {
10552 connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
10553 connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
10554 }
10555
cee00a95
JM
10556 if (info->attrs[NL80211_ATTR_USE_MFP]) {
10557 connect.mfp = nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
65026002
EG
10558 if (connect.mfp == NL80211_MFP_OPTIONAL &&
10559 !wiphy_ext_feature_isset(&rdev->wiphy,
10560 NL80211_EXT_FEATURE_MFP_OPTIONAL))
10561 return -EOPNOTSUPP;
cee00a95
JM
10562 } else {
10563 connect.mfp = NL80211_MFP_NO;
10564 }
10565
ba6fbacf
JM
10566 if (info->attrs[NL80211_ATTR_PREV_BSSID])
10567 connect.prev_bssid =
10568 nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
10569
942ba88b
TP
10570 if (info->attrs[NL80211_ATTR_WIPHY_FREQ])
10571 freq = MHZ_TO_KHZ(nla_get_u32(
10572 info->attrs[NL80211_ATTR_WIPHY_FREQ]));
10573 if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
10574 freq +=
10575 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
10576
10577 if (freq) {
10578 connect.channel = nl80211_get_valid_chan(wiphy, freq);
664834de 10579 if (!connect.channel)
1df4a510
JM
10580 return -EINVAL;
10581 } else if (info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]) {
942ba88b
TP
10582 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]);
10583 freq = MHZ_TO_KHZ(freq);
10584 connect.channel_hint = nl80211_get_valid_chan(wiphy, freq);
664834de 10585 if (!connect.channel_hint)
4c476991 10586 return -EINVAL;
b23aa676
SO
10587 }
10588
2a38075c
AAL
10589 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]) {
10590 connect.edmg.channels =
10591 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]);
10592
10593 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG])
10594 connect.edmg.bw_config =
10595 nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]);
10596 }
10597
fffd0934 10598 if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) {
768075eb 10599 connkeys = nl80211_parse_connkeys(rdev, info, NULL);
4c476991
JB
10600 if (IS_ERR(connkeys))
10601 return PTR_ERR(connkeys);
fffd0934
JB
10602 }
10603
7e7c8926
BG
10604 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
10605 connect.flags |= ASSOC_REQ_DISABLE_HT;
10606
10607 if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
10608 memcpy(&connect.ht_capa_mask,
10609 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
10610 sizeof(connect.ht_capa_mask));
10611
10612 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
b4e4f47e 10613 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) {
453431a5 10614 kfree_sensitive(connkeys);
7e7c8926 10615 return -EINVAL;
b4e4f47e 10616 }
7e7c8926
BG
10617 memcpy(&connect.ht_capa,
10618 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
10619 sizeof(connect.ht_capa));
10620 }
10621
ee2aca34
JB
10622 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT]))
10623 connect.flags |= ASSOC_REQ_DISABLE_VHT;
10624
10625 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
10626 memcpy(&connect.vht_capa_mask,
10627 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
10628 sizeof(connect.vht_capa_mask));
10629
10630 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) {
10631 if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) {
453431a5 10632 kfree_sensitive(connkeys);
ee2aca34
JB
10633 return -EINVAL;
10634 }
10635 memcpy(&connect.vht_capa,
10636 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]),
10637 sizeof(connect.vht_capa));
10638 }
10639
bab5ab7d 10640 if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
0c9ca11b
BL
10641 if (!((rdev->wiphy.features &
10642 NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) &&
10643 (rdev->wiphy.features & NL80211_FEATURE_QUIET)) &&
10644 !wiphy_ext_feature_isset(&rdev->wiphy,
10645 NL80211_EXT_FEATURE_RRM)) {
453431a5 10646 kfree_sensitive(connkeys);
bab5ab7d 10647 return -EINVAL;
707554b4 10648 }
bab5ab7d
AK
10649 connect.flags |= ASSOC_REQ_USE_RRM;
10650 }
10651
34d50519 10652 connect.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
57fbcce3 10653 if (connect.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) {
453431a5 10654 kfree_sensitive(connkeys);
34d50519
LD
10655 return -EOPNOTSUPP;
10656 }
10657
38de03d2
AS
10658 if (info->attrs[NL80211_ATTR_BSS_SELECT]) {
10659 /* bss selection makes no sense if bssid is set */
10660 if (connect.bssid) {
453431a5 10661 kfree_sensitive(connkeys);
38de03d2
AS
10662 return -EINVAL;
10663 }
10664
10665 err = parse_bss_select(info->attrs[NL80211_ATTR_BSS_SELECT],
10666 wiphy, &connect.bss_select);
10667 if (err) {
453431a5 10668 kfree_sensitive(connkeys);
38de03d2
AS
10669 return err;
10670 }
10671 }
10672
a3caf744
VK
10673 if (wiphy_ext_feature_isset(&rdev->wiphy,
10674 NL80211_EXT_FEATURE_FILS_SK_OFFLOAD) &&
10675 info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] &&
10676 info->attrs[NL80211_ATTR_FILS_ERP_REALM] &&
10677 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] &&
10678 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
10679 connect.fils_erp_username =
10680 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
10681 connect.fils_erp_username_len =
10682 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
10683 connect.fils_erp_realm =
10684 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
10685 connect.fils_erp_realm_len =
10686 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
10687 connect.fils_erp_next_seq_num =
10688 nla_get_u16(
10689 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM]);
10690 connect.fils_erp_rrk =
10691 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
10692 connect.fils_erp_rrk_len =
10693 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
10694 } else if (info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] ||
10695 info->attrs[NL80211_ATTR_FILS_ERP_REALM] ||
10696 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] ||
10697 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
453431a5 10698 kfree_sensitive(connkeys);
a3caf744
VK
10699 return -EINVAL;
10700 }
10701
40cbfa90
SD
10702 if (nla_get_flag(info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])) {
10703 if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
453431a5 10704 kfree_sensitive(connkeys);
40cbfa90
SD
10705 GENL_SET_ERR_MSG(info,
10706 "external auth requires connection ownership");
10707 return -EINVAL;
10708 }
10709 connect.flags |= CONNECT_REQ_EXTERNAL_AUTH_SUPPORT;
10710 }
10711
83739b03 10712 wdev_lock(dev->ieee80211_ptr);
bd2522b1 10713
4ce2bd9c
JM
10714 err = cfg80211_connect(rdev, dev, &connect, connkeys,
10715 connect.prev_bssid);
fffd0934 10716 if (err)
453431a5 10717 kfree_sensitive(connkeys);
bd2522b1
AZ
10718
10719 if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
10720 dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
10721 if (connect.bssid)
10722 memcpy(dev->ieee80211_ptr->disconnect_bssid,
10723 connect.bssid, ETH_ALEN);
10724 else
3b1648f1 10725 eth_zero_addr(dev->ieee80211_ptr->disconnect_bssid);
bd2522b1
AZ
10726 }
10727
10728 wdev_unlock(dev->ieee80211_ptr);
10729
b23aa676
SO
10730 return err;
10731}
10732
088e8df8 10733static int nl80211_update_connect_params(struct sk_buff *skb,
10734 struct genl_info *info)
10735{
10736 struct cfg80211_connect_params connect = {};
10737 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10738 struct net_device *dev = info->user_ptr[1];
10739 struct wireless_dev *wdev = dev->ieee80211_ptr;
7f9a3e15
VK
10740 bool fils_sk_offload;
10741 u32 auth_type;
088e8df8 10742 u32 changed = 0;
10743 int ret;
10744
10745 if (!rdev->ops->update_connect_params)
10746 return -EOPNOTSUPP;
10747
10748 if (info->attrs[NL80211_ATTR_IE]) {
088e8df8 10749 connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
10750 connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
10751 changed |= UPDATE_ASSOC_IES;
10752 }
10753
7f9a3e15
VK
10754 fils_sk_offload = wiphy_ext_feature_isset(&rdev->wiphy,
10755 NL80211_EXT_FEATURE_FILS_SK_OFFLOAD);
10756
10757 /*
10758 * when driver supports fils-sk offload all attributes must be
10759 * provided. So the else covers "fils-sk-not-all" and
10760 * "no-fils-sk-any".
10761 */
10762 if (fils_sk_offload &&
10763 info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] &&
10764 info->attrs[NL80211_ATTR_FILS_ERP_REALM] &&
10765 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] &&
10766 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
10767 connect.fils_erp_username =
10768 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
10769 connect.fils_erp_username_len =
10770 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
10771 connect.fils_erp_realm =
10772 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
10773 connect.fils_erp_realm_len =
10774 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
10775 connect.fils_erp_next_seq_num =
10776 nla_get_u16(
10777 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM]);
10778 connect.fils_erp_rrk =
10779 nla_data(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
10780 connect.fils_erp_rrk_len =
10781 nla_len(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
10782 changed |= UPDATE_FILS_ERP_INFO;
10783 } else if (info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] ||
10784 info->attrs[NL80211_ATTR_FILS_ERP_REALM] ||
10785 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] ||
10786 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
10787 return -EINVAL;
10788 }
10789
10790 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
10791 auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
10792 if (!nl80211_valid_auth_type(rdev, auth_type,
10793 NL80211_CMD_CONNECT))
10794 return -EINVAL;
10795
10796 if (auth_type == NL80211_AUTHTYPE_FILS_SK &&
10797 fils_sk_offload && !(changed & UPDATE_FILS_ERP_INFO))
10798 return -EINVAL;
10799
10800 connect.auth_type = auth_type;
10801 changed |= UPDATE_AUTH_TYPE;
10802 }
10803
088e8df8 10804 wdev_lock(dev->ieee80211_ptr);
10805 if (!wdev->current_bss)
10806 ret = -ENOLINK;
10807 else
10808 ret = rdev_update_connect_params(rdev, dev, &connect, changed);
10809 wdev_unlock(dev->ieee80211_ptr);
10810
10811 return ret;
10812}
10813
b23aa676
SO
10814static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
10815{
4c476991
JB
10816 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10817 struct net_device *dev = info->user_ptr[1];
b23aa676 10818 u16 reason;
83739b03 10819 int ret;
b23aa676 10820
bad29297
AZ
10821 if (dev->ieee80211_ptr->conn_owner_nlportid &&
10822 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
10823 return -EPERM;
10824
b23aa676
SO
10825 if (!info->attrs[NL80211_ATTR_REASON_CODE])
10826 reason = WLAN_REASON_DEAUTH_LEAVING;
10827 else
10828 reason = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
10829
10830 if (reason == 0)
10831 return -EINVAL;
10832
074ac8df 10833 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
10834 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
10835 return -EOPNOTSUPP;
b23aa676 10836
83739b03
JB
10837 wdev_lock(dev->ieee80211_ptr);
10838 ret = cfg80211_disconnect(rdev, dev, reason, true);
10839 wdev_unlock(dev->ieee80211_ptr);
10840 return ret;
b23aa676
SO
10841}
10842
463d0183
JB
10843static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
10844{
4c476991 10845 struct cfg80211_registered_device *rdev = info->user_ptr[0];
463d0183
JB
10846 struct net *net;
10847 int err;
463d0183 10848
4b681c82
VK
10849 if (info->attrs[NL80211_ATTR_PID]) {
10850 u32 pid = nla_get_u32(info->attrs[NL80211_ATTR_PID]);
10851
10852 net = get_net_ns_by_pid(pid);
10853 } else if (info->attrs[NL80211_ATTR_NETNS_FD]) {
10854 u32 fd = nla_get_u32(info->attrs[NL80211_ATTR_NETNS_FD]);
463d0183 10855
4b681c82
VK
10856 net = get_net_ns_by_fd(fd);
10857 } else {
10858 return -EINVAL;
10859 }
463d0183 10860
4c476991
JB
10861 if (IS_ERR(net))
10862 return PTR_ERR(net);
463d0183
JB
10863
10864 err = 0;
10865
10866 /* check if anything to do */
4c476991
JB
10867 if (!net_eq(wiphy_net(&rdev->wiphy), net))
10868 err = cfg80211_switch_netns(rdev, net);
463d0183 10869
463d0183 10870 put_net(net);
463d0183
JB
10871 return err;
10872}
10873
67fbb16b
SO
10874static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info)
10875{
4c476991 10876 struct cfg80211_registered_device *rdev = info->user_ptr[0];
67fbb16b
SO
10877 int (*rdev_ops)(struct wiphy *wiphy, struct net_device *dev,
10878 struct cfg80211_pmksa *pmksa) = NULL;
4c476991 10879 struct net_device *dev = info->user_ptr[1];
67fbb16b
SO
10880 struct cfg80211_pmksa pmksa;
10881
10882 memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
10883
67fbb16b
SO
10884 if (!info->attrs[NL80211_ATTR_PMKID])
10885 return -EINVAL;
10886
67fbb16b 10887 pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
a3caf744
VK
10888
10889 if (info->attrs[NL80211_ATTR_MAC]) {
10890 pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
10891 } else if (info->attrs[NL80211_ATTR_SSID] &&
10892 info->attrs[NL80211_ATTR_FILS_CACHE_ID] &&
10893 (info->genlhdr->cmd == NL80211_CMD_DEL_PMKSA ||
10894 info->attrs[NL80211_ATTR_PMK])) {
10895 pmksa.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
10896 pmksa.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
10897 pmksa.cache_id =
10898 nla_data(info->attrs[NL80211_ATTR_FILS_CACHE_ID]);
10899 } else {
10900 return -EINVAL;
10901 }
10902 if (info->attrs[NL80211_ATTR_PMK]) {
10903 pmksa.pmk = nla_data(info->attrs[NL80211_ATTR_PMK]);
10904 pmksa.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]);
10905 }
67fbb16b 10906
7fc82af8
VJ
10907 if (info->attrs[NL80211_ATTR_PMK_LIFETIME])
10908 pmksa.pmk_lifetime =
10909 nla_get_u32(info->attrs[NL80211_ATTR_PMK_LIFETIME]);
10910
10911 if (info->attrs[NL80211_ATTR_PMK_REAUTH_THRESHOLD])
10912 pmksa.pmk_reauth_threshold =
10913 nla_get_u8(
10914 info->attrs[NL80211_ATTR_PMK_REAUTH_THRESHOLD]);
10915
074ac8df 10916 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
6c900360
LD
10917 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
10918 !(dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP &&
10919 wiphy_ext_feature_isset(&rdev->wiphy,
10920 NL80211_EXT_FEATURE_AP_PMKSA_CACHING)))
4c476991 10921 return -EOPNOTSUPP;
67fbb16b
SO
10922
10923 switch (info->genlhdr->cmd) {
10924 case NL80211_CMD_SET_PMKSA:
10925 rdev_ops = rdev->ops->set_pmksa;
10926 break;
10927 case NL80211_CMD_DEL_PMKSA:
10928 rdev_ops = rdev->ops->del_pmksa;
10929 break;
10930 default:
10931 WARN_ON(1);
10932 break;
10933 }
10934
4c476991
JB
10935 if (!rdev_ops)
10936 return -EOPNOTSUPP;
67fbb16b 10937
4c476991 10938 return rdev_ops(&rdev->wiphy, dev, &pmksa);
67fbb16b
SO
10939}
10940
10941static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info)
10942{
4c476991
JB
10943 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10944 struct net_device *dev = info->user_ptr[1];
67fbb16b 10945
074ac8df 10946 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
10947 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
10948 return -EOPNOTSUPP;
67fbb16b 10949
4c476991
JB
10950 if (!rdev->ops->flush_pmksa)
10951 return -EOPNOTSUPP;
67fbb16b 10952
e35e4d28 10953 return rdev_flush_pmksa(rdev, dev);
67fbb16b
SO
10954}
10955
109086ce
AN
10956static int nl80211_tdls_mgmt(struct sk_buff *skb, struct genl_info *info)
10957{
10958 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10959 struct net_device *dev = info->user_ptr[1];
10960 u8 action_code, dialog_token;
df942e7b 10961 u32 peer_capability = 0;
109086ce
AN
10962 u16 status_code;
10963 u8 *peer;
31fa97c5 10964 bool initiator;
109086ce
AN
10965
10966 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
10967 !rdev->ops->tdls_mgmt)
10968 return -EOPNOTSUPP;
10969
10970 if (!info->attrs[NL80211_ATTR_TDLS_ACTION] ||
10971 !info->attrs[NL80211_ATTR_STATUS_CODE] ||
10972 !info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN] ||
10973 !info->attrs[NL80211_ATTR_IE] ||
10974 !info->attrs[NL80211_ATTR_MAC])
10975 return -EINVAL;
10976
10977 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
10978 action_code = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_ACTION]);
10979 status_code = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
10980 dialog_token = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN]);
31fa97c5 10981 initiator = nla_get_flag(info->attrs[NL80211_ATTR_TDLS_INITIATOR]);
df942e7b
SDU
10982 if (info->attrs[NL80211_ATTR_TDLS_PEER_CAPABILITY])
10983 peer_capability =
10984 nla_get_u32(info->attrs[NL80211_ATTR_TDLS_PEER_CAPABILITY]);
109086ce 10985
e35e4d28 10986 return rdev_tdls_mgmt(rdev, dev, peer, action_code,
df942e7b 10987 dialog_token, status_code, peer_capability,
31fa97c5 10988 initiator,
e35e4d28
HG
10989 nla_data(info->attrs[NL80211_ATTR_IE]),
10990 nla_len(info->attrs[NL80211_ATTR_IE]));
109086ce
AN
10991}
10992
10993static int nl80211_tdls_oper(struct sk_buff *skb, struct genl_info *info)
10994{
10995 struct cfg80211_registered_device *rdev = info->user_ptr[0];
10996 struct net_device *dev = info->user_ptr[1];
10997 enum nl80211_tdls_operation operation;
10998 u8 *peer;
10999
11000 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
11001 !rdev->ops->tdls_oper)
11002 return -EOPNOTSUPP;
11003
11004 if (!info->attrs[NL80211_ATTR_TDLS_OPERATION] ||
11005 !info->attrs[NL80211_ATTR_MAC])
11006 return -EINVAL;
11007
11008 operation = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_OPERATION]);
11009 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
11010
e35e4d28 11011 return rdev_tdls_oper(rdev, dev, peer, operation);
109086ce
AN
11012}
11013
9588bbd5
JM
11014static int nl80211_remain_on_channel(struct sk_buff *skb,
11015 struct genl_info *info)
11016{
4c476991 11017 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 11018 struct wireless_dev *wdev = info->user_ptr[1];
683b6d3b 11019 struct cfg80211_chan_def chandef;
34373d12 11020 const struct cfg80211_chan_def *compat_chandef;
9588bbd5
JM
11021 struct sk_buff *msg;
11022 void *hdr;
11023 u64 cookie;
683b6d3b 11024 u32 duration;
9588bbd5
JM
11025 int err;
11026
11027 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
11028 !info->attrs[NL80211_ATTR_DURATION])
11029 return -EINVAL;
11030
11031 duration = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
11032
ebf348fc
JB
11033 if (!rdev->ops->remain_on_channel ||
11034 !(rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL))
11035 return -EOPNOTSUPP;
11036
9588bbd5 11037 /*
ebf348fc
JB
11038 * We should be on that channel for at least a minimum amount of
11039 * time (10ms) but no longer than the driver supports.
9588bbd5 11040 */
ebf348fc 11041 if (duration < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
a293911d 11042 duration > rdev->wiphy.max_remain_on_channel_duration)
9588bbd5
JM
11043 return -EINVAL;
11044
683b6d3b
JB
11045 err = nl80211_parse_chandef(rdev, info, &chandef);
11046 if (err)
11047 return err;
9588bbd5 11048
34373d12
VT
11049 wdev_lock(wdev);
11050 if (!cfg80211_off_channel_oper_allowed(wdev) &&
11051 !cfg80211_chandef_identical(&wdev->chandef, &chandef)) {
11052 compat_chandef = cfg80211_chandef_compatible(&wdev->chandef,
11053 &chandef);
11054 if (compat_chandef != &chandef) {
11055 wdev_unlock(wdev);
11056 return -EBUSY;
11057 }
11058 }
11059 wdev_unlock(wdev);
11060
9588bbd5 11061 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
11062 if (!msg)
11063 return -ENOMEM;
9588bbd5 11064
15e47304 11065 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
9588bbd5 11066 NL80211_CMD_REMAIN_ON_CHANNEL);
cb35fba3
DC
11067 if (!hdr) {
11068 err = -ENOBUFS;
9588bbd5
JM
11069 goto free_msg;
11070 }
11071
683b6d3b
JB
11072 err = rdev_remain_on_channel(rdev, wdev, chandef.chan,
11073 duration, &cookie);
9588bbd5
JM
11074
11075 if (err)
11076 goto free_msg;
11077
2dad624e
ND
11078 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
11079 NL80211_ATTR_PAD))
9360ffd1 11080 goto nla_put_failure;
9588bbd5
JM
11081
11082 genlmsg_end(msg, hdr);
4c476991
JB
11083
11084 return genlmsg_reply(msg, info);
9588bbd5
JM
11085
11086 nla_put_failure:
11087 err = -ENOBUFS;
11088 free_msg:
11089 nlmsg_free(msg);
9588bbd5
JM
11090 return err;
11091}
11092
11093static int nl80211_cancel_remain_on_channel(struct sk_buff *skb,
11094 struct genl_info *info)
11095{
4c476991 11096 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 11097 struct wireless_dev *wdev = info->user_ptr[1];
9588bbd5 11098 u64 cookie;
9588bbd5
JM
11099
11100 if (!info->attrs[NL80211_ATTR_COOKIE])
11101 return -EINVAL;
11102
4c476991
JB
11103 if (!rdev->ops->cancel_remain_on_channel)
11104 return -EOPNOTSUPP;
9588bbd5 11105
9588bbd5
JM
11106 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
11107
e35e4d28 11108 return rdev_cancel_remain_on_channel(rdev, wdev, cookie);
9588bbd5
JM
11109}
11110
13ae75b1
JM
11111static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
11112 struct genl_info *info)
11113{
13ae75b1 11114 struct cfg80211_bitrate_mask mask;
a7c7fbff 11115 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 11116 struct net_device *dev = info->user_ptr[1];
a7c7fbff 11117 int err;
13ae75b1 11118
4c476991
JB
11119 if (!rdev->ops->set_bitrate_mask)
11120 return -EOPNOTSUPP;
13ae75b1 11121
9a5f6488 11122 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
eb89a6a6 11123 NL80211_ATTR_TX_RATES, &mask,
857b34c4 11124 dev, true);
a7c7fbff
PK
11125 if (err)
11126 return err;
13ae75b1 11127
e35e4d28 11128 return rdev_set_bitrate_mask(rdev, dev, NULL, &mask);
13ae75b1
JM
11129}
11130
2e161f78 11131static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
026331c4 11132{
4c476991 11133 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 11134 struct wireless_dev *wdev = info->user_ptr[1];
2e161f78 11135 u16 frame_type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION;
026331c4
JM
11136
11137 if (!info->attrs[NL80211_ATTR_FRAME_MATCH])
11138 return -EINVAL;
11139
2e161f78
JB
11140 if (info->attrs[NL80211_ATTR_FRAME_TYPE])
11141 frame_type = nla_get_u16(info->attrs[NL80211_ATTR_FRAME_TYPE]);
026331c4 11142
71bbc994
JB
11143 switch (wdev->iftype) {
11144 case NL80211_IFTYPE_STATION:
11145 case NL80211_IFTYPE_ADHOC:
11146 case NL80211_IFTYPE_P2P_CLIENT:
11147 case NL80211_IFTYPE_AP:
11148 case NL80211_IFTYPE_AP_VLAN:
11149 case NL80211_IFTYPE_MESH_POINT:
11150 case NL80211_IFTYPE_P2P_GO:
98104fde 11151 case NL80211_IFTYPE_P2P_DEVICE:
71bbc994 11152 break;
cb3b7d87 11153 case NL80211_IFTYPE_NAN:
71bbc994 11154 default:
4c476991 11155 return -EOPNOTSUPP;
71bbc994 11156 }
026331c4
JM
11157
11158 /* not much point in registering if we can't reply */
4c476991
JB
11159 if (!rdev->ops->mgmt_tx)
11160 return -EOPNOTSUPP;
026331c4 11161
9dba48a6
JB
11162 if (info->attrs[NL80211_ATTR_RECEIVE_MULTICAST] &&
11163 !wiphy_ext_feature_isset(&rdev->wiphy,
11164 NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS)) {
11165 GENL_SET_ERR_MSG(info,
11166 "multicast RX registrations are not supported");
11167 return -EOPNOTSUPP;
11168 }
11169
15e47304 11170 return cfg80211_mlme_register_mgmt(wdev, info->snd_portid, frame_type,
ff74c51e
IP
11171 nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]),
11172 nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]),
9dba48a6 11173 info->attrs[NL80211_ATTR_RECEIVE_MULTICAST],
ff74c51e 11174 info->extack);
026331c4
JM
11175}
11176
2e161f78 11177static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
026331c4 11178{
4c476991 11179 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 11180 struct wireless_dev *wdev = info->user_ptr[1];
683b6d3b 11181 struct cfg80211_chan_def chandef;
026331c4 11182 int err;
d64d373f 11183 void *hdr = NULL;
026331c4 11184 u64 cookie;
e247bd90 11185 struct sk_buff *msg = NULL;
b176e629
AO
11186 struct cfg80211_mgmt_tx_params params = {
11187 .dont_wait_for_ack =
11188 info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK],
11189 };
026331c4 11190
683b6d3b 11191 if (!info->attrs[NL80211_ATTR_FRAME])
026331c4
JM
11192 return -EINVAL;
11193
4c476991
JB
11194 if (!rdev->ops->mgmt_tx)
11195 return -EOPNOTSUPP;
026331c4 11196
71bbc994 11197 switch (wdev->iftype) {
ea141b75
AQ
11198 case NL80211_IFTYPE_P2P_DEVICE:
11199 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
11200 return -EINVAL;
71bbc994
JB
11201 case NL80211_IFTYPE_STATION:
11202 case NL80211_IFTYPE_ADHOC:
11203 case NL80211_IFTYPE_P2P_CLIENT:
11204 case NL80211_IFTYPE_AP:
11205 case NL80211_IFTYPE_AP_VLAN:
11206 case NL80211_IFTYPE_MESH_POINT:
11207 case NL80211_IFTYPE_P2P_GO:
11208 break;
cb3b7d87 11209 case NL80211_IFTYPE_NAN:
71bbc994 11210 default:
4c476991 11211 return -EOPNOTSUPP;
71bbc994 11212 }
026331c4 11213
f7ca38df 11214 if (info->attrs[NL80211_ATTR_DURATION]) {
7c4ef712 11215 if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
f7ca38df 11216 return -EINVAL;
b176e629 11217 params.wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
ebf348fc
JB
11218
11219 /*
11220 * We should wait on the channel for at least a minimum amount
11221 * of time (10ms) but no longer than the driver supports.
11222 */
b176e629
AO
11223 if (params.wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
11224 params.wait > rdev->wiphy.max_remain_on_channel_duration)
ebf348fc 11225 return -EINVAL;
f7ca38df
JB
11226 }
11227
b176e629 11228 params.offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK];
f7ca38df 11229
b176e629 11230 if (params.offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
7c4ef712
JB
11231 return -EINVAL;
11232
b176e629 11233 params.no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
e9f935e3 11234
ea141b75
AQ
11235 /* get the channel if any has been specified, otherwise pass NULL to
11236 * the driver. The latter will use the current one
11237 */
11238 chandef.chan = NULL;
11239 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
11240 err = nl80211_parse_chandef(rdev, info, &chandef);
11241 if (err)
11242 return err;
11243 }
11244
b176e629 11245 if (!chandef.chan && params.offchan)
ea141b75 11246 return -EINVAL;
026331c4 11247
34373d12
VT
11248 wdev_lock(wdev);
11249 if (params.offchan && !cfg80211_off_channel_oper_allowed(wdev)) {
11250 wdev_unlock(wdev);
11251 return -EBUSY;
11252 }
11253 wdev_unlock(wdev);
11254
34d22ce2
AO
11255 params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
11256 params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
11257
11258 if (info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]) {
11259 int len = nla_len(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]);
11260 int i;
11261
11262 if (len % sizeof(u16))
11263 return -EINVAL;
11264
11265 params.n_csa_offsets = len / sizeof(u16);
11266 params.csa_offsets =
11267 nla_data(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]);
11268
11269 /* check that all the offsets fit the frame */
11270 for (i = 0; i < params.n_csa_offsets; i++) {
11271 if (params.csa_offsets[i] >= params.len)
11272 return -EINVAL;
11273 }
11274 }
11275
b176e629 11276 if (!params.dont_wait_for_ack) {
e247bd90
JB
11277 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
11278 if (!msg)
11279 return -ENOMEM;
026331c4 11280
15e47304 11281 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
e247bd90 11282 NL80211_CMD_FRAME);
cb35fba3
DC
11283 if (!hdr) {
11284 err = -ENOBUFS;
e247bd90
JB
11285 goto free_msg;
11286 }
026331c4 11287 }
e247bd90 11288
b176e629
AO
11289 params.chan = chandef.chan;
11290 err = cfg80211_mlme_mgmt_tx(rdev, wdev, &params, &cookie);
026331c4
JM
11291 if (err)
11292 goto free_msg;
11293
e247bd90 11294 if (msg) {
2dad624e
ND
11295 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
11296 NL80211_ATTR_PAD))
9360ffd1 11297 goto nla_put_failure;
026331c4 11298
e247bd90
JB
11299 genlmsg_end(msg, hdr);
11300 return genlmsg_reply(msg, info);
11301 }
11302
11303 return 0;
026331c4
JM
11304
11305 nla_put_failure:
11306 err = -ENOBUFS;
11307 free_msg:
11308 nlmsg_free(msg);
026331c4
JM
11309 return err;
11310}
11311
f7ca38df
JB
11312static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *info)
11313{
11314 struct cfg80211_registered_device *rdev = info->user_ptr[0];
71bbc994 11315 struct wireless_dev *wdev = info->user_ptr[1];
f7ca38df
JB
11316 u64 cookie;
11317
11318 if (!info->attrs[NL80211_ATTR_COOKIE])
11319 return -EINVAL;
11320
11321 if (!rdev->ops->mgmt_tx_cancel_wait)
11322 return -EOPNOTSUPP;
11323
71bbc994
JB
11324 switch (wdev->iftype) {
11325 case NL80211_IFTYPE_STATION:
11326 case NL80211_IFTYPE_ADHOC:
11327 case NL80211_IFTYPE_P2P_CLIENT:
11328 case NL80211_IFTYPE_AP:
11329 case NL80211_IFTYPE_AP_VLAN:
11330 case NL80211_IFTYPE_P2P_GO:
98104fde 11331 case NL80211_IFTYPE_P2P_DEVICE:
71bbc994 11332 break;
cb3b7d87 11333 case NL80211_IFTYPE_NAN:
71bbc994 11334 default:
f7ca38df 11335 return -EOPNOTSUPP;
71bbc994 11336 }
f7ca38df
JB
11337
11338 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
11339
e35e4d28 11340 return rdev_mgmt_tx_cancel_wait(rdev, wdev, cookie);
f7ca38df
JB
11341}
11342
ffb9eb3d
KV
11343static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info)
11344{
4c476991 11345 struct cfg80211_registered_device *rdev = info->user_ptr[0];
ffb9eb3d 11346 struct wireless_dev *wdev;
4c476991 11347 struct net_device *dev = info->user_ptr[1];
ffb9eb3d
KV
11348 u8 ps_state;
11349 bool state;
11350 int err;
11351
4c476991
JB
11352 if (!info->attrs[NL80211_ATTR_PS_STATE])
11353 return -EINVAL;
ffb9eb3d
KV
11354
11355 ps_state = nla_get_u32(info->attrs[NL80211_ATTR_PS_STATE]);
11356
ffb9eb3d
KV
11357 wdev = dev->ieee80211_ptr;
11358
4c476991
JB
11359 if (!rdev->ops->set_power_mgmt)
11360 return -EOPNOTSUPP;
ffb9eb3d
KV
11361
11362 state = (ps_state == NL80211_PS_ENABLED) ? true : false;
11363
11364 if (state == wdev->ps)
4c476991 11365 return 0;
ffb9eb3d 11366
e35e4d28 11367 err = rdev_set_power_mgmt(rdev, dev, state, wdev->ps_timeout);
4c476991
JB
11368 if (!err)
11369 wdev->ps = state;
ffb9eb3d
KV
11370 return err;
11371}
11372
11373static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info)
11374{
4c476991 11375 struct cfg80211_registered_device *rdev = info->user_ptr[0];
ffb9eb3d
KV
11376 enum nl80211_ps_state ps_state;
11377 struct wireless_dev *wdev;
4c476991 11378 struct net_device *dev = info->user_ptr[1];
ffb9eb3d
KV
11379 struct sk_buff *msg;
11380 void *hdr;
11381 int err;
11382
ffb9eb3d
KV
11383 wdev = dev->ieee80211_ptr;
11384
4c476991
JB
11385 if (!rdev->ops->set_power_mgmt)
11386 return -EOPNOTSUPP;
ffb9eb3d
KV
11387
11388 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4c476991
JB
11389 if (!msg)
11390 return -ENOMEM;
ffb9eb3d 11391
15e47304 11392 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
ffb9eb3d
KV
11393 NL80211_CMD_GET_POWER_SAVE);
11394 if (!hdr) {
4c476991 11395 err = -ENOBUFS;
ffb9eb3d
KV
11396 goto free_msg;
11397 }
11398
11399 if (wdev->ps)
11400 ps_state = NL80211_PS_ENABLED;
11401 else
11402 ps_state = NL80211_PS_DISABLED;
11403
9360ffd1
DM
11404 if (nla_put_u32(msg, NL80211_ATTR_PS_STATE, ps_state))
11405 goto nla_put_failure;
ffb9eb3d
KV
11406
11407 genlmsg_end(msg, hdr);
4c476991 11408 return genlmsg_reply(msg, info);
ffb9eb3d 11409
4c476991 11410 nla_put_failure:
ffb9eb3d 11411 err = -ENOBUFS;
4c476991 11412 free_msg:
ffb9eb3d 11413 nlmsg_free(msg);
ffb9eb3d
KV
11414 return err;
11415}
11416
94e860f1
JB
11417static const struct nla_policy
11418nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
4a4b8169 11419 [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_BINARY },
d6dc1a38
JO
11420 [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 },
11421 [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
84f10708
TP
11422 [NL80211_ATTR_CQM_TXE_RATE] = { .type = NLA_U32 },
11423 [NL80211_ATTR_CQM_TXE_PKTS] = { .type = NLA_U32 },
11424 [NL80211_ATTR_CQM_TXE_INTVL] = { .type = NLA_U32 },
bee427b8 11425 [NL80211_ATTR_CQM_RSSI_LEVEL] = { .type = NLA_S32 },
d6dc1a38
JO
11426};
11427
84f10708 11428static int nl80211_set_cqm_txe(struct genl_info *info,
d9d8b019 11429 u32 rate, u32 pkts, u32 intvl)
84f10708
TP
11430{
11431 struct cfg80211_registered_device *rdev = info->user_ptr[0];
84f10708 11432 struct net_device *dev = info->user_ptr[1];
1da5fcc8 11433 struct wireless_dev *wdev = dev->ieee80211_ptr;
84f10708 11434
d9d8b019 11435 if (rate > 100 || intvl > NL80211_CQM_TXE_MAX_INTVL)
84f10708
TP
11436 return -EINVAL;
11437
84f10708
TP
11438 if (!rdev->ops->set_cqm_txe_config)
11439 return -EOPNOTSUPP;
11440
11441 if (wdev->iftype != NL80211_IFTYPE_STATION &&
11442 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
11443 return -EOPNOTSUPP;
11444
e35e4d28 11445 return rdev_set_cqm_txe_config(rdev, dev, rate, pkts, intvl);
84f10708
TP
11446}
11447
4a4b8169
AZ
11448static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
11449 struct net_device *dev)
11450{
11451 struct wireless_dev *wdev = dev->ieee80211_ptr;
11452 s32 last, low, high;
11453 u32 hyst;
1222a160 11454 int i, n, low_index;
4a4b8169
AZ
11455 int err;
11456
11457 /* RSSI reporting disabled? */
11458 if (!wdev->cqm_config)
11459 return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0);
11460
11461 /*
11462 * Obtain current RSSI value if possible, if not and no RSSI threshold
11463 * event has been received yet, we should receive an event after a
11464 * connection is established and enough beacons received to calculate
11465 * the average.
11466 */
11467 if (!wdev->cqm_config->last_rssi_event_value && wdev->current_bss &&
11468 rdev->ops->get_station) {
73887fd9 11469 struct station_info sinfo = {};
4a4b8169
AZ
11470 u8 *mac_addr;
11471
11472 mac_addr = wdev->current_bss->pub.bssid;
11473
73887fd9
JB
11474 err = rdev_get_station(rdev, dev, mac_addr, &sinfo);
11475 if (err)
4a4b8169
AZ
11476 return err;
11477
df16737d 11478 cfg80211_sinfo_release_content(&sinfo);
397c657a 11479 if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG))
4a4b8169 11480 wdev->cqm_config->last_rssi_event_value =
73887fd9 11481 (s8) sinfo.rx_beacon_signal_avg;
4a4b8169
AZ
11482 }
11483
11484 last = wdev->cqm_config->last_rssi_event_value;
11485 hyst = wdev->cqm_config->rssi_hyst;
11486 n = wdev->cqm_config->n_rssi_thresholds;
11487
4b2c5a14
MH
11488 for (i = 0; i < n; i++) {
11489 i = array_index_nospec(i, n);
4a4b8169
AZ
11490 if (last < wdev->cqm_config->rssi_thresholds[i])
11491 break;
4b2c5a14 11492 }
4a4b8169 11493
1222a160
MH
11494 low_index = i - 1;
11495 if (low_index >= 0) {
11496 low_index = array_index_nospec(low_index, n);
11497 low = wdev->cqm_config->rssi_thresholds[low_index] - hyst;
11498 } else {
11499 low = S32_MIN;
11500 }
11501 if (i < n) {
11502 i = array_index_nospec(i, n);
11503 high = wdev->cqm_config->rssi_thresholds[i] + hyst - 1;
11504 } else {
11505 high = S32_MAX;
11506 }
4a4b8169
AZ
11507
11508 return rdev_set_cqm_rssi_range_config(rdev, dev, low, high);
11509}
11510
d6dc1a38 11511static int nl80211_set_cqm_rssi(struct genl_info *info,
4a4b8169
AZ
11512 const s32 *thresholds, int n_thresholds,
11513 u32 hysteresis)
d6dc1a38 11514{
4c476991 11515 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4c476991 11516 struct net_device *dev = info->user_ptr[1];
1da5fcc8 11517 struct wireless_dev *wdev = dev->ieee80211_ptr;
4a4b8169
AZ
11518 int i, err;
11519 s32 prev = S32_MIN;
d6dc1a38 11520
4a4b8169
AZ
11521 /* Check all values negative and sorted */
11522 for (i = 0; i < n_thresholds; i++) {
11523 if (thresholds[i] > 0 || thresholds[i] <= prev)
11524 return -EINVAL;
d6dc1a38 11525
4a4b8169
AZ
11526 prev = thresholds[i];
11527 }
d6dc1a38 11528
074ac8df 11529 if (wdev->iftype != NL80211_IFTYPE_STATION &&
4c476991
JB
11530 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
11531 return -EOPNOTSUPP;
d6dc1a38 11532
4a4b8169
AZ
11533 wdev_lock(wdev);
11534 cfg80211_cqm_config_free(wdev);
11535 wdev_unlock(wdev);
11536
11537 if (n_thresholds <= 1 && rdev->ops->set_cqm_rssi_config) {
11538 if (n_thresholds == 0 || thresholds[0] == 0) /* Disabling */
11539 return rdev_set_cqm_rssi_config(rdev, dev, 0, 0);
11540
11541 return rdev_set_cqm_rssi_config(rdev, dev,
11542 thresholds[0], hysteresis);
11543 }
11544
11545 if (!wiphy_ext_feature_isset(&rdev->wiphy,
11546 NL80211_EXT_FEATURE_CQM_RSSI_LIST))
11547 return -EOPNOTSUPP;
11548
11549 if (n_thresholds == 1 && thresholds[0] == 0) /* Disabling */
11550 n_thresholds = 0;
11551
11552 wdev_lock(wdev);
11553 if (n_thresholds) {
11554 struct cfg80211_cqm_config *cqm_config;
11555
11556 cqm_config = kzalloc(sizeof(struct cfg80211_cqm_config) +
11557 n_thresholds * sizeof(s32), GFP_KERNEL);
11558 if (!cqm_config) {
11559 err = -ENOMEM;
11560 goto unlock;
11561 }
11562
11563 cqm_config->rssi_hyst = hysteresis;
11564 cqm_config->n_rssi_thresholds = n_thresholds;
11565 memcpy(cqm_config->rssi_thresholds, thresholds,
11566 n_thresholds * sizeof(s32));
11567
11568 wdev->cqm_config = cqm_config;
11569 }
11570
11571 err = cfg80211_cqm_rssi_update(rdev, dev);
11572
11573unlock:
11574 wdev_unlock(wdev);
11575
11576 return err;
d6dc1a38
JO
11577}
11578
11579static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
11580{
11581 struct nlattr *attrs[NL80211_ATTR_CQM_MAX + 1];
11582 struct nlattr *cqm;
11583 int err;
11584
11585 cqm = info->attrs[NL80211_ATTR_CQM];
1da5fcc8
JB
11586 if (!cqm)
11587 return -EINVAL;
d6dc1a38 11588
8cb08174
JB
11589 err = nla_parse_nested_deprecated(attrs, NL80211_ATTR_CQM_MAX, cqm,
11590 nl80211_attr_cqm_policy,
11591 info->extack);
d6dc1a38 11592 if (err)
1da5fcc8 11593 return err;
d6dc1a38
JO
11594
11595 if (attrs[NL80211_ATTR_CQM_RSSI_THOLD] &&
11596 attrs[NL80211_ATTR_CQM_RSSI_HYST]) {
4a4b8169
AZ
11597 const s32 *thresholds =
11598 nla_data(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
11599 int len = nla_len(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
1da5fcc8 11600 u32 hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]);
d6dc1a38 11601
4a4b8169
AZ
11602 if (len % 4)
11603 return -EINVAL;
11604
11605 return nl80211_set_cqm_rssi(info, thresholds, len / 4,
11606 hysteresis);
1da5fcc8
JB
11607 }
11608
11609 if (attrs[NL80211_ATTR_CQM_TXE_RATE] &&
11610 attrs[NL80211_ATTR_CQM_TXE_PKTS] &&
11611 attrs[NL80211_ATTR_CQM_TXE_INTVL]) {
11612 u32 rate = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_RATE]);
11613 u32 pkts = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_PKTS]);
11614 u32 intvl = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_INTVL]);
11615
11616 return nl80211_set_cqm_txe(info, rate, pkts, intvl);
11617 }
11618
11619 return -EINVAL;
d6dc1a38
JO
11620}
11621
6e0bd6c3
RL
11622static int nl80211_join_ocb(struct sk_buff *skb, struct genl_info *info)
11623{
11624 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11625 struct net_device *dev = info->user_ptr[1];
11626 struct ocb_setup setup = {};
11627 int err;
11628
11629 err = nl80211_parse_chandef(rdev, info, &setup.chandef);
11630 if (err)
11631 return err;
11632
11633 return cfg80211_join_ocb(rdev, dev, &setup);
11634}
11635
11636static int nl80211_leave_ocb(struct sk_buff *skb, struct genl_info *info)
11637{
11638 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11639 struct net_device *dev = info->user_ptr[1];
11640
11641 return cfg80211_leave_ocb(rdev, dev);
11642}
11643
29cbe68c
JB
11644static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
11645{
11646 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11647 struct net_device *dev = info->user_ptr[1];
11648 struct mesh_config cfg;
c80d545d 11649 struct mesh_setup setup;
29cbe68c
JB
11650 int err;
11651
11652 /* start with default */
11653 memcpy(&cfg, &default_mesh_config, sizeof(cfg));
c80d545d 11654 memcpy(&setup, &default_mesh_setup, sizeof(setup));
29cbe68c 11655
24bdd9f4 11656 if (info->attrs[NL80211_ATTR_MESH_CONFIG]) {
29cbe68c 11657 /* and parse parameters if given */
24bdd9f4 11658 err = nl80211_parse_mesh_config(info, &cfg, NULL);
29cbe68c
JB
11659 if (err)
11660 return err;
11661 }
11662
11663 if (!info->attrs[NL80211_ATTR_MESH_ID] ||
11664 !nla_len(info->attrs[NL80211_ATTR_MESH_ID]))
11665 return -EINVAL;
11666
c80d545d
JC
11667 setup.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
11668 setup.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
11669
4bb62344
CYY
11670 if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
11671 !nl80211_parse_mcast_rate(rdev, setup.mcast_rate,
11672 nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE])))
11673 return -EINVAL;
11674
9bdbf04d
MP
11675 if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
11676 setup.beacon_interval =
11677 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
12d20fc9 11678
0c317a02
PK
11679 err = cfg80211_validate_beacon_int(rdev,
11680 NL80211_IFTYPE_MESH_POINT,
11681 setup.beacon_interval);
12d20fc9
PK
11682 if (err)
11683 return err;
9bdbf04d
MP
11684 }
11685
11686 if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
11687 setup.dtim_period =
11688 nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
11689 if (setup.dtim_period < 1 || setup.dtim_period > 100)
11690 return -EINVAL;
11691 }
11692
c80d545d
JC
11693 if (info->attrs[NL80211_ATTR_MESH_SETUP]) {
11694 /* parse additional setup parameters if given */
11695 err = nl80211_parse_mesh_setup(info, &setup);
11696 if (err)
11697 return err;
11698 }
11699
d37bb18a
TP
11700 if (setup.user_mpm)
11701 cfg.auto_open_plinks = false;
11702
cc1d2806 11703 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
683b6d3b
JB
11704 err = nl80211_parse_chandef(rdev, info, &setup.chandef);
11705 if (err)
11706 return err;
cc1d2806 11707 } else {
188c1b3c 11708 /* __cfg80211_join_mesh() will sort it out */
683b6d3b 11709 setup.chandef.chan = NULL;
cc1d2806
JB
11710 }
11711
ffb3cf30
AN
11712 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
11713 u8 *rates = nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
11714 int n_rates =
11715 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
11716 struct ieee80211_supported_band *sband;
11717
11718 if (!setup.chandef.chan)
11719 return -EINVAL;
11720
11721 sband = rdev->wiphy.bands[setup.chandef.chan->band];
11722
11723 err = ieee80211_get_ratemask(sband, rates, n_rates,
11724 &setup.basic_rates);
11725 if (err)
11726 return err;
11727 }
11728
8564e382 11729 if (info->attrs[NL80211_ATTR_TX_RATES]) {
9a5f6488
TC
11730 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
11731 NL80211_ATTR_TX_RATES,
eb89a6a6 11732 &setup.beacon_rate,
857b34c4 11733 dev, false);
8564e382
JB
11734 if (err)
11735 return err;
11736
265698d7
JB
11737 if (!setup.chandef.chan)
11738 return -EINVAL;
11739
8564e382
JB
11740 err = validate_beacon_tx_rate(rdev, setup.chandef.chan->band,
11741 &setup.beacon_rate);
11742 if (err)
11743 return err;
11744 }
11745
d37d49c2
BB
11746 setup.userspace_handles_dfs =
11747 nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]);
11748
1224f583
DK
11749 if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) {
11750 int r = validate_pae_over_nl80211(rdev, info);
11751
11752 if (r < 0)
11753 return r;
11754
11755 setup.control_port_over_nl80211 = true;
11756 }
11757
188c1b3c
DK
11758 wdev_lock(dev->ieee80211_ptr);
11759 err = __cfg80211_join_mesh(rdev, dev, &setup, &cfg);
11760 if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER])
11761 dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
11762 wdev_unlock(dev->ieee80211_ptr);
11763
11764 return err;
29cbe68c
JB
11765}
11766
11767static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info)
11768{
11769 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11770 struct net_device *dev = info->user_ptr[1];
11771
11772 return cfg80211_leave_mesh(rdev, dev);
11773}
11774
dfb89c56 11775#ifdef CONFIG_PM
bb92d199
AK
11776static int nl80211_send_wowlan_patterns(struct sk_buff *msg,
11777 struct cfg80211_registered_device *rdev)
11778{
6abb9cb9 11779 struct cfg80211_wowlan *wowlan = rdev->wiphy.wowlan_config;
bb92d199
AK
11780 struct nlattr *nl_pats, *nl_pat;
11781 int i, pat_len;
11782
6abb9cb9 11783 if (!wowlan->n_patterns)
bb92d199
AK
11784 return 0;
11785
ae0be8de 11786 nl_pats = nla_nest_start_noflag(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN);
bb92d199
AK
11787 if (!nl_pats)
11788 return -ENOBUFS;
11789
6abb9cb9 11790 for (i = 0; i < wowlan->n_patterns; i++) {
ae0be8de 11791 nl_pat = nla_nest_start_noflag(msg, i + 1);
bb92d199
AK
11792 if (!nl_pat)
11793 return -ENOBUFS;
6abb9cb9 11794 pat_len = wowlan->patterns[i].pattern_len;
50ac6607 11795 if (nla_put(msg, NL80211_PKTPAT_MASK, DIV_ROUND_UP(pat_len, 8),
6abb9cb9 11796 wowlan->patterns[i].mask) ||
50ac6607
AK
11797 nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
11798 wowlan->patterns[i].pattern) ||
11799 nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
6abb9cb9 11800 wowlan->patterns[i].pkt_offset))
bb92d199
AK
11801 return -ENOBUFS;
11802 nla_nest_end(msg, nl_pat);
11803 }
11804 nla_nest_end(msg, nl_pats);
11805
11806 return 0;
11807}
11808
2a0e047e
JB
11809static int nl80211_send_wowlan_tcp(struct sk_buff *msg,
11810 struct cfg80211_wowlan_tcp *tcp)
11811{
11812 struct nlattr *nl_tcp;
11813
11814 if (!tcp)
11815 return 0;
11816
ae0be8de
MK
11817 nl_tcp = nla_nest_start_noflag(msg,
11818 NL80211_WOWLAN_TRIG_TCP_CONNECTION);
2a0e047e
JB
11819 if (!nl_tcp)
11820 return -ENOBUFS;
11821
930345ea
JB
11822 if (nla_put_in_addr(msg, NL80211_WOWLAN_TCP_SRC_IPV4, tcp->src) ||
11823 nla_put_in_addr(msg, NL80211_WOWLAN_TCP_DST_IPV4, tcp->dst) ||
2a0e047e
JB
11824 nla_put(msg, NL80211_WOWLAN_TCP_DST_MAC, ETH_ALEN, tcp->dst_mac) ||
11825 nla_put_u16(msg, NL80211_WOWLAN_TCP_SRC_PORT, tcp->src_port) ||
11826 nla_put_u16(msg, NL80211_WOWLAN_TCP_DST_PORT, tcp->dst_port) ||
11827 nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
11828 tcp->payload_len, tcp->payload) ||
11829 nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
11830 tcp->data_interval) ||
11831 nla_put(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
11832 tcp->wake_len, tcp->wake_data) ||
11833 nla_put(msg, NL80211_WOWLAN_TCP_WAKE_MASK,
11834 DIV_ROUND_UP(tcp->wake_len, 8), tcp->wake_mask))
11835 return -ENOBUFS;
11836
11837 if (tcp->payload_seq.len &&
11838 nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ,
11839 sizeof(tcp->payload_seq), &tcp->payload_seq))
11840 return -ENOBUFS;
11841
11842 if (tcp->payload_tok.len &&
11843 nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
11844 sizeof(tcp->payload_tok) + tcp->tokens_size,
11845 &tcp->payload_tok))
11846 return -ENOBUFS;
11847
e248ad30
JB
11848 nla_nest_end(msg, nl_tcp);
11849
2a0e047e
JB
11850 return 0;
11851}
11852
75453ccb
LC
11853static int nl80211_send_wowlan_nd(struct sk_buff *msg,
11854 struct cfg80211_sched_scan_request *req)
11855{
3b06d277 11856 struct nlattr *nd, *freqs, *matches, *match, *scan_plans, *scan_plan;
75453ccb
LC
11857 int i;
11858
11859 if (!req)
11860 return 0;
11861
ae0be8de 11862 nd = nla_nest_start_noflag(msg, NL80211_WOWLAN_TRIG_NET_DETECT);
75453ccb
LC
11863 if (!nd)
11864 return -ENOBUFS;
11865
3b06d277
AS
11866 if (req->n_scan_plans == 1 &&
11867 nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL,
11868 req->scan_plans[0].interval * 1000))
75453ccb
LC
11869 return -ENOBUFS;
11870
21fea567
LC
11871 if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_DELAY, req->delay))
11872 return -ENOBUFS;
11873
bf95ecdb 11874 if (req->relative_rssi_set) {
11875 struct nl80211_bss_select_rssi_adjust rssi_adjust;
11876
11877 if (nla_put_s8(msg, NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI,
11878 req->relative_rssi))
11879 return -ENOBUFS;
11880
11881 rssi_adjust.band = req->rssi_adjust.band;
11882 rssi_adjust.delta = req->rssi_adjust.delta;
11883 if (nla_put(msg, NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST,
11884 sizeof(rssi_adjust), &rssi_adjust))
11885 return -ENOBUFS;
11886 }
11887
ae0be8de 11888 freqs = nla_nest_start_noflag(msg, NL80211_ATTR_SCAN_FREQUENCIES);
75453ccb
LC
11889 if (!freqs)
11890 return -ENOBUFS;
11891
53b18980
JB
11892 for (i = 0; i < req->n_channels; i++) {
11893 if (nla_put_u32(msg, i, req->channels[i]->center_freq))
11894 return -ENOBUFS;
11895 }
75453ccb
LC
11896
11897 nla_nest_end(msg, freqs);
11898
11899 if (req->n_match_sets) {
ae0be8de
MK
11900 matches = nla_nest_start_noflag(msg,
11901 NL80211_ATTR_SCHED_SCAN_MATCH);
76e1fb4b
JB
11902 if (!matches)
11903 return -ENOBUFS;
11904
75453ccb 11905 for (i = 0; i < req->n_match_sets; i++) {
ae0be8de 11906 match = nla_nest_start_noflag(msg, i);
76e1fb4b
JB
11907 if (!match)
11908 return -ENOBUFS;
11909
53b18980
JB
11910 if (nla_put(msg, NL80211_SCHED_SCAN_MATCH_ATTR_SSID,
11911 req->match_sets[i].ssid.ssid_len,
11912 req->match_sets[i].ssid.ssid))
11913 return -ENOBUFS;
75453ccb
LC
11914 nla_nest_end(msg, match);
11915 }
11916 nla_nest_end(msg, matches);
11917 }
11918
ae0be8de 11919 scan_plans = nla_nest_start_noflag(msg, NL80211_ATTR_SCHED_SCAN_PLANS);
3b06d277
AS
11920 if (!scan_plans)
11921 return -ENOBUFS;
11922
11923 for (i = 0; i < req->n_scan_plans; i++) {
ae0be8de 11924 scan_plan = nla_nest_start_noflag(msg, i + 1);
76e1fb4b
JB
11925 if (!scan_plan)
11926 return -ENOBUFS;
11927
67626964 11928 if (nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_INTERVAL,
3b06d277
AS
11929 req->scan_plans[i].interval) ||
11930 (req->scan_plans[i].iterations &&
11931 nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_ITERATIONS,
11932 req->scan_plans[i].iterations)))
11933 return -ENOBUFS;
11934 nla_nest_end(msg, scan_plan);
11935 }
11936 nla_nest_end(msg, scan_plans);
11937
75453ccb
LC
11938 nla_nest_end(msg, nd);
11939
11940 return 0;
11941}
11942
ff1b6e69
JB
11943static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
11944{
11945 struct cfg80211_registered_device *rdev = info->user_ptr[0];
11946 struct sk_buff *msg;
11947 void *hdr;
2a0e047e 11948 u32 size = NLMSG_DEFAULT_SIZE;
ff1b6e69 11949
964dc9e2 11950 if (!rdev->wiphy.wowlan)
ff1b6e69
JB
11951 return -EOPNOTSUPP;
11952
6abb9cb9 11953 if (rdev->wiphy.wowlan_config && rdev->wiphy.wowlan_config->tcp) {
2a0e047e 11954 /* adjust size to have room for all the data */
6abb9cb9
JB
11955 size += rdev->wiphy.wowlan_config->tcp->tokens_size +
11956 rdev->wiphy.wowlan_config->tcp->payload_len +
11957 rdev->wiphy.wowlan_config->tcp->wake_len +
11958 rdev->wiphy.wowlan_config->tcp->wake_len / 8;
2a0e047e
JB
11959 }
11960
11961 msg = nlmsg_new(size, GFP_KERNEL);
ff1b6e69
JB
11962 if (!msg)
11963 return -ENOMEM;
11964
15e47304 11965 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
ff1b6e69
JB
11966 NL80211_CMD_GET_WOWLAN);
11967 if (!hdr)
11968 goto nla_put_failure;
11969
6abb9cb9 11970 if (rdev->wiphy.wowlan_config) {
ff1b6e69
JB
11971 struct nlattr *nl_wowlan;
11972
ae0be8de
MK
11973 nl_wowlan = nla_nest_start_noflag(msg,
11974 NL80211_ATTR_WOWLAN_TRIGGERS);
ff1b6e69
JB
11975 if (!nl_wowlan)
11976 goto nla_put_failure;
11977
6abb9cb9 11978 if ((rdev->wiphy.wowlan_config->any &&
9360ffd1 11979 nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
6abb9cb9 11980 (rdev->wiphy.wowlan_config->disconnect &&
9360ffd1 11981 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
6abb9cb9 11982 (rdev->wiphy.wowlan_config->magic_pkt &&
9360ffd1 11983 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
6abb9cb9 11984 (rdev->wiphy.wowlan_config->gtk_rekey_failure &&
9360ffd1 11985 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
6abb9cb9 11986 (rdev->wiphy.wowlan_config->eap_identity_req &&
9360ffd1 11987 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
6abb9cb9 11988 (rdev->wiphy.wowlan_config->four_way_handshake &&
9360ffd1 11989 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
6abb9cb9 11990 (rdev->wiphy.wowlan_config->rfkill_release &&
9360ffd1
DM
11991 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
11992 goto nla_put_failure;
2a0e047e 11993
bb92d199
AK
11994 if (nl80211_send_wowlan_patterns(msg, rdev))
11995 goto nla_put_failure;
2a0e047e 11996
6abb9cb9
JB
11997 if (nl80211_send_wowlan_tcp(msg,
11998 rdev->wiphy.wowlan_config->tcp))
2a0e047e 11999 goto nla_put_failure;
75453ccb
LC
12000
12001 if (nl80211_send_wowlan_nd(
12002 msg,
12003 rdev->wiphy.wowlan_config->nd_config))
12004 goto nla_put_failure;
2a0e047e 12005
ff1b6e69
JB
12006 nla_nest_end(msg, nl_wowlan);
12007 }
12008
12009 genlmsg_end(msg, hdr);
12010 return genlmsg_reply(msg, info);
12011
12012nla_put_failure:
12013 nlmsg_free(msg);
12014 return -ENOBUFS;
12015}
12016
2a0e047e
JB
12017static int nl80211_parse_wowlan_tcp(struct cfg80211_registered_device *rdev,
12018 struct nlattr *attr,
12019 struct cfg80211_wowlan *trig)
12020{
12021 struct nlattr *tb[NUM_NL80211_WOWLAN_TCP];
12022 struct cfg80211_wowlan_tcp *cfg;
12023 struct nl80211_wowlan_tcp_data_token *tok = NULL;
12024 struct nl80211_wowlan_tcp_data_seq *seq = NULL;
12025 u32 size;
12026 u32 data_size, wake_size, tokens_size = 0, wake_mask_size;
12027 int err, port;
12028
964dc9e2 12029 if (!rdev->wiphy.wowlan->tcp)
2a0e047e
JB
12030 return -EINVAL;
12031
8cb08174
JB
12032 err = nla_parse_nested_deprecated(tb, MAX_NL80211_WOWLAN_TCP, attr,
12033 nl80211_wowlan_tcp_policy, NULL);
2a0e047e
JB
12034 if (err)
12035 return err;
12036
12037 if (!tb[NL80211_WOWLAN_TCP_SRC_IPV4] ||
12038 !tb[NL80211_WOWLAN_TCP_DST_IPV4] ||
12039 !tb[NL80211_WOWLAN_TCP_DST_MAC] ||
12040 !tb[NL80211_WOWLAN_TCP_DST_PORT] ||
12041 !tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD] ||
12042 !tb[NL80211_WOWLAN_TCP_DATA_INTERVAL] ||
12043 !tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD] ||
12044 !tb[NL80211_WOWLAN_TCP_WAKE_MASK])
12045 return -EINVAL;
12046
12047 data_size = nla_len(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD]);
964dc9e2 12048 if (data_size > rdev->wiphy.wowlan->tcp->data_payload_max)
2a0e047e
JB
12049 return -EINVAL;
12050
12051 if (nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) >
964dc9e2 12052 rdev->wiphy.wowlan->tcp->data_interval_max ||
723d568a 12053 nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) == 0)
2a0e047e
JB
12054 return -EINVAL;
12055
12056 wake_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]);
964dc9e2 12057 if (wake_size > rdev->wiphy.wowlan->tcp->wake_payload_max)
2a0e047e
JB
12058 return -EINVAL;
12059
12060 wake_mask_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_MASK]);
12061 if (wake_mask_size != DIV_ROUND_UP(wake_size, 8))
12062 return -EINVAL;
12063
12064 if (tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]) {
12065 u32 tokln = nla_len(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]);
12066
12067 tok = nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]);
12068 tokens_size = tokln - sizeof(*tok);
12069
12070 if (!tok->len || tokens_size % tok->len)
12071 return -EINVAL;
964dc9e2 12072 if (!rdev->wiphy.wowlan->tcp->tok)
2a0e047e 12073 return -EINVAL;
964dc9e2 12074 if (tok->len > rdev->wiphy.wowlan->tcp->tok->max_len)
2a0e047e 12075 return -EINVAL;
964dc9e2 12076 if (tok->len < rdev->wiphy.wowlan->tcp->tok->min_len)
2a0e047e 12077 return -EINVAL;
964dc9e2 12078 if (tokens_size > rdev->wiphy.wowlan->tcp->tok->bufsize)
2a0e047e
JB
12079 return -EINVAL;
12080 if (tok->offset + tok->len > data_size)
12081 return -EINVAL;
12082 }
12083
12084 if (tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]) {
12085 seq = nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]);
964dc9e2 12086 if (!rdev->wiphy.wowlan->tcp->seq)
2a0e047e
JB
12087 return -EINVAL;
12088 if (seq->len == 0 || seq->len > 4)
12089 return -EINVAL;
12090 if (seq->len + seq->offset > data_size)
12091 return -EINVAL;
12092 }
12093
12094 size = sizeof(*cfg);
12095 size += data_size;
12096 size += wake_size + wake_mask_size;
12097 size += tokens_size;
12098
12099 cfg = kzalloc(size, GFP_KERNEL);
12100 if (!cfg)
12101 return -ENOMEM;
67b61f6c
JB
12102 cfg->src = nla_get_in_addr(tb[NL80211_WOWLAN_TCP_SRC_IPV4]);
12103 cfg->dst = nla_get_in_addr(tb[NL80211_WOWLAN_TCP_DST_IPV4]);
2a0e047e
JB
12104 memcpy(cfg->dst_mac, nla_data(tb[NL80211_WOWLAN_TCP_DST_MAC]),
12105 ETH_ALEN);
12106 if (tb[NL80211_WOWLAN_TCP_SRC_PORT])
12107 port = nla_get_u16(tb[NL80211_WOWLAN_TCP_SRC_PORT]);
12108 else
12109 port = 0;
12110#ifdef CONFIG_INET
12111 /* allocate a socket and port for it and use it */
12112 err = __sock_create(wiphy_net(&rdev->wiphy), PF_INET, SOCK_STREAM,
12113 IPPROTO_TCP, &cfg->sock, 1);
12114 if (err) {
12115 kfree(cfg);
12116 return err;
12117 }
12118 if (inet_csk_get_port(cfg->sock->sk, port)) {
12119 sock_release(cfg->sock);
12120 kfree(cfg);
12121 return -EADDRINUSE;
12122 }
12123 cfg->src_port = inet_sk(cfg->sock->sk)->inet_num;
12124#else
12125 if (!port) {
12126 kfree(cfg);
12127 return -EINVAL;
12128 }
12129 cfg->src_port = port;
12130#endif
12131
12132 cfg->dst_port = nla_get_u16(tb[NL80211_WOWLAN_TCP_DST_PORT]);
12133 cfg->payload_len = data_size;
12134 cfg->payload = (u8 *)cfg + sizeof(*cfg) + tokens_size;
12135 memcpy((void *)cfg->payload,
12136 nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD]),
12137 data_size);
12138 if (seq)
12139 cfg->payload_seq = *seq;
12140 cfg->data_interval = nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]);
12141 cfg->wake_len = wake_size;
12142 cfg->wake_data = (u8 *)cfg + sizeof(*cfg) + tokens_size + data_size;
12143 memcpy((void *)cfg->wake_data,
12144 nla_data(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]),
12145 wake_size);
12146 cfg->wake_mask = (u8 *)cfg + sizeof(*cfg) + tokens_size +
12147 data_size + wake_size;
12148 memcpy((void *)cfg->wake_mask,
12149 nla_data(tb[NL80211_WOWLAN_TCP_WAKE_MASK]),
12150 wake_mask_size);
12151 if (tok) {
12152 cfg->tokens_size = tokens_size;
12153 memcpy(&cfg->payload_tok, tok, sizeof(*tok) + tokens_size);
12154 }
12155
12156 trig->tcp = cfg;
12157
12158 return 0;
12159}
12160
8cd4d456
LC
12161static int nl80211_parse_wowlan_nd(struct cfg80211_registered_device *rdev,
12162 const struct wiphy_wowlan_support *wowlan,
12163 struct nlattr *attr,
12164 struct cfg80211_wowlan *trig)
12165{
12166 struct nlattr **tb;
12167 int err;
12168
6396bb22 12169 tb = kcalloc(NUM_NL80211_ATTR, sizeof(*tb), GFP_KERNEL);
8cd4d456
LC
12170 if (!tb)
12171 return -ENOMEM;
12172
12173 if (!(wowlan->flags & WIPHY_WOWLAN_NET_DETECT)) {
12174 err = -EOPNOTSUPP;
12175 goto out;
12176 }
12177
8cb08174
JB
12178 err = nla_parse_nested_deprecated(tb, NL80211_ATTR_MAX, attr,
12179 nl80211_policy, NULL);
8cd4d456
LC
12180 if (err)
12181 goto out;
12182
aad1e812
AVS
12183 trig->nd_config = nl80211_parse_sched_scan(&rdev->wiphy, NULL, tb,
12184 wowlan->max_nd_match_sets);
8cd4d456
LC
12185 err = PTR_ERR_OR_ZERO(trig->nd_config);
12186 if (err)
12187 trig->nd_config = NULL;
12188
12189out:
12190 kfree(tb);
12191 return err;
12192}
12193
ff1b6e69
JB
12194static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
12195{
12196 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12197 struct nlattr *tb[NUM_NL80211_WOWLAN_TRIG];
ff1b6e69 12198 struct cfg80211_wowlan new_triggers = {};
ae33bd81 12199 struct cfg80211_wowlan *ntrig;
964dc9e2 12200 const struct wiphy_wowlan_support *wowlan = rdev->wiphy.wowlan;
ff1b6e69 12201 int err, i;
6abb9cb9 12202 bool prev_enabled = rdev->wiphy.wowlan_config;
98fc4386 12203 bool regular = false;
ff1b6e69 12204
964dc9e2 12205 if (!wowlan)
ff1b6e69
JB
12206 return -EOPNOTSUPP;
12207
ae33bd81
JB
12208 if (!info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) {
12209 cfg80211_rdev_free_wowlan(rdev);
6abb9cb9 12210 rdev->wiphy.wowlan_config = NULL;
ae33bd81
JB
12211 goto set_wakeup;
12212 }
ff1b6e69 12213
8cb08174
JB
12214 err = nla_parse_nested_deprecated(tb, MAX_NL80211_WOWLAN_TRIG,
12215 info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS],
12216 nl80211_wowlan_policy, info->extack);
ff1b6e69
JB
12217 if (err)
12218 return err;
12219
12220 if (tb[NL80211_WOWLAN_TRIG_ANY]) {
12221 if (!(wowlan->flags & WIPHY_WOWLAN_ANY))
12222 return -EINVAL;
12223 new_triggers.any = true;
12224 }
12225
12226 if (tb[NL80211_WOWLAN_TRIG_DISCONNECT]) {
12227 if (!(wowlan->flags & WIPHY_WOWLAN_DISCONNECT))
12228 return -EINVAL;
12229 new_triggers.disconnect = true;
98fc4386 12230 regular = true;
ff1b6e69
JB
12231 }
12232
12233 if (tb[NL80211_WOWLAN_TRIG_MAGIC_PKT]) {
12234 if (!(wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT))
12235 return -EINVAL;
12236 new_triggers.magic_pkt = true;
98fc4386 12237 regular = true;
ff1b6e69
JB
12238 }
12239
77dbbb13
JB
12240 if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED])
12241 return -EINVAL;
12242
12243 if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE]) {
12244 if (!(wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE))
12245 return -EINVAL;
12246 new_triggers.gtk_rekey_failure = true;
98fc4386 12247 regular = true;
77dbbb13
JB
12248 }
12249
12250 if (tb[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST]) {
12251 if (!(wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ))
12252 return -EINVAL;
12253 new_triggers.eap_identity_req = true;
98fc4386 12254 regular = true;
77dbbb13
JB
12255 }
12256
12257 if (tb[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE]) {
12258 if (!(wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE))
12259 return -EINVAL;
12260 new_triggers.four_way_handshake = true;
98fc4386 12261 regular = true;
77dbbb13
JB
12262 }
12263
12264 if (tb[NL80211_WOWLAN_TRIG_RFKILL_RELEASE]) {
12265 if (!(wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE))
12266 return -EINVAL;
12267 new_triggers.rfkill_release = true;
98fc4386 12268 regular = true;
77dbbb13
JB
12269 }
12270
ff1b6e69
JB
12271 if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) {
12272 struct nlattr *pat;
12273 int n_patterns = 0;
bb92d199 12274 int rem, pat_len, mask_len, pkt_offset;
50ac6607 12275 struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
ff1b6e69 12276
98fc4386
JB
12277 regular = true;
12278
ff1b6e69
JB
12279 nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
12280 rem)
12281 n_patterns++;
12282 if (n_patterns > wowlan->n_patterns)
12283 return -EINVAL;
12284
12285 new_triggers.patterns = kcalloc(n_patterns,
12286 sizeof(new_triggers.patterns[0]),
12287 GFP_KERNEL);
12288 if (!new_triggers.patterns)
12289 return -ENOMEM;
12290
12291 new_triggers.n_patterns = n_patterns;
12292 i = 0;
12293
12294 nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
12295 rem) {
922bd80f
JB
12296 u8 *mask_pat;
12297
8cb08174
JB
12298 err = nla_parse_nested_deprecated(pat_tb,
12299 MAX_NL80211_PKTPAT,
12300 pat,
12301 nl80211_packet_pattern_policy,
12302 info->extack);
95bca62f
JB
12303 if (err)
12304 goto error;
12305
ff1b6e69 12306 err = -EINVAL;
50ac6607
AK
12307 if (!pat_tb[NL80211_PKTPAT_MASK] ||
12308 !pat_tb[NL80211_PKTPAT_PATTERN])
ff1b6e69 12309 goto error;
50ac6607 12310 pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
ff1b6e69 12311 mask_len = DIV_ROUND_UP(pat_len, 8);
50ac6607 12312 if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
ff1b6e69
JB
12313 goto error;
12314 if (pat_len > wowlan->pattern_max_len ||
12315 pat_len < wowlan->pattern_min_len)
12316 goto error;
12317
50ac6607 12318 if (!pat_tb[NL80211_PKTPAT_OFFSET])
bb92d199
AK
12319 pkt_offset = 0;
12320 else
12321 pkt_offset = nla_get_u32(
50ac6607 12322 pat_tb[NL80211_PKTPAT_OFFSET]);
bb92d199
AK
12323 if (pkt_offset > wowlan->max_pkt_offset)
12324 goto error;
12325 new_triggers.patterns[i].pkt_offset = pkt_offset;
12326
922bd80f
JB
12327 mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL);
12328 if (!mask_pat) {
ff1b6e69
JB
12329 err = -ENOMEM;
12330 goto error;
12331 }
922bd80f
JB
12332 new_triggers.patterns[i].mask = mask_pat;
12333 memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]),
ff1b6e69 12334 mask_len);
922bd80f
JB
12335 mask_pat += mask_len;
12336 new_triggers.patterns[i].pattern = mask_pat;
ff1b6e69 12337 new_triggers.patterns[i].pattern_len = pat_len;
922bd80f 12338 memcpy(mask_pat,
50ac6607 12339 nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
ff1b6e69
JB
12340 pat_len);
12341 i++;
12342 }
12343 }
12344
2a0e047e 12345 if (tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION]) {
98fc4386 12346 regular = true;
2a0e047e
JB
12347 err = nl80211_parse_wowlan_tcp(
12348 rdev, tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION],
12349 &new_triggers);
12350 if (err)
12351 goto error;
12352 }
12353
8cd4d456 12354 if (tb[NL80211_WOWLAN_TRIG_NET_DETECT]) {
98fc4386 12355 regular = true;
8cd4d456
LC
12356 err = nl80211_parse_wowlan_nd(
12357 rdev, wowlan, tb[NL80211_WOWLAN_TRIG_NET_DETECT],
12358 &new_triggers);
12359 if (err)
12360 goto error;
12361 }
12362
98fc4386
JB
12363 /* The 'any' trigger means the device continues operating more or less
12364 * as in its normal operation mode and wakes up the host on most of the
12365 * normal interrupts (like packet RX, ...)
12366 * It therefore makes little sense to combine with the more constrained
12367 * wakeup trigger modes.
12368 */
12369 if (new_triggers.any && regular) {
12370 err = -EINVAL;
12371 goto error;
12372 }
12373
ae33bd81
JB
12374 ntrig = kmemdup(&new_triggers, sizeof(new_triggers), GFP_KERNEL);
12375 if (!ntrig) {
12376 err = -ENOMEM;
12377 goto error;
ff1b6e69 12378 }
ae33bd81 12379 cfg80211_rdev_free_wowlan(rdev);
6abb9cb9 12380 rdev->wiphy.wowlan_config = ntrig;
ff1b6e69 12381
ae33bd81 12382 set_wakeup:
6abb9cb9
JB
12383 if (rdev->ops->set_wakeup &&
12384 prev_enabled != !!rdev->wiphy.wowlan_config)
12385 rdev_set_wakeup(rdev, rdev->wiphy.wowlan_config);
6d52563f 12386
ff1b6e69
JB
12387 return 0;
12388 error:
12389 for (i = 0; i < new_triggers.n_patterns; i++)
12390 kfree(new_triggers.patterns[i].mask);
12391 kfree(new_triggers.patterns);
2a0e047e
JB
12392 if (new_triggers.tcp && new_triggers.tcp->sock)
12393 sock_release(new_triggers.tcp->sock);
12394 kfree(new_triggers.tcp);
e5dbe070 12395 kfree(new_triggers.nd_config);
ff1b6e69
JB
12396 return err;
12397}
dfb89c56 12398#endif
ff1b6e69 12399
be29b99a
AK
12400static int nl80211_send_coalesce_rules(struct sk_buff *msg,
12401 struct cfg80211_registered_device *rdev)
12402{
12403 struct nlattr *nl_pats, *nl_pat, *nl_rule, *nl_rules;
12404 int i, j, pat_len;
12405 struct cfg80211_coalesce_rules *rule;
12406
12407 if (!rdev->coalesce->n_rules)
12408 return 0;
12409
ae0be8de 12410 nl_rules = nla_nest_start_noflag(msg, NL80211_ATTR_COALESCE_RULE);
be29b99a
AK
12411 if (!nl_rules)
12412 return -ENOBUFS;
12413
12414 for (i = 0; i < rdev->coalesce->n_rules; i++) {
ae0be8de 12415 nl_rule = nla_nest_start_noflag(msg, i + 1);
be29b99a
AK
12416 if (!nl_rule)
12417 return -ENOBUFS;
12418
12419 rule = &rdev->coalesce->rules[i];
12420 if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_DELAY,
12421 rule->delay))
12422 return -ENOBUFS;
12423
12424 if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_CONDITION,
12425 rule->condition))
12426 return -ENOBUFS;
12427
ae0be8de
MK
12428 nl_pats = nla_nest_start_noflag(msg,
12429 NL80211_ATTR_COALESCE_RULE_PKT_PATTERN);
be29b99a
AK
12430 if (!nl_pats)
12431 return -ENOBUFS;
12432
12433 for (j = 0; j < rule->n_patterns; j++) {
ae0be8de 12434 nl_pat = nla_nest_start_noflag(msg, j + 1);
be29b99a
AK
12435 if (!nl_pat)
12436 return -ENOBUFS;
12437 pat_len = rule->patterns[j].pattern_len;
12438 if (nla_put(msg, NL80211_PKTPAT_MASK,
12439 DIV_ROUND_UP(pat_len, 8),
12440 rule->patterns[j].mask) ||
12441 nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
12442 rule->patterns[j].pattern) ||
12443 nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
12444 rule->patterns[j].pkt_offset))
12445 return -ENOBUFS;
12446 nla_nest_end(msg, nl_pat);
12447 }
12448 nla_nest_end(msg, nl_pats);
12449 nla_nest_end(msg, nl_rule);
12450 }
12451 nla_nest_end(msg, nl_rules);
12452
12453 return 0;
12454}
12455
12456static int nl80211_get_coalesce(struct sk_buff *skb, struct genl_info *info)
12457{
12458 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12459 struct sk_buff *msg;
12460 void *hdr;
12461
12462 if (!rdev->wiphy.coalesce)
12463 return -EOPNOTSUPP;
12464
12465 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
12466 if (!msg)
12467 return -ENOMEM;
12468
12469 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
12470 NL80211_CMD_GET_COALESCE);
12471 if (!hdr)
12472 goto nla_put_failure;
12473
12474 if (rdev->coalesce && nl80211_send_coalesce_rules(msg, rdev))
12475 goto nla_put_failure;
12476
12477 genlmsg_end(msg, hdr);
12478 return genlmsg_reply(msg, info);
12479
12480nla_put_failure:
12481 nlmsg_free(msg);
12482 return -ENOBUFS;
12483}
12484
12485void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev)
12486{
12487 struct cfg80211_coalesce *coalesce = rdev->coalesce;
12488 int i, j;
12489 struct cfg80211_coalesce_rules *rule;
12490
12491 if (!coalesce)
12492 return;
12493
12494 for (i = 0; i < coalesce->n_rules; i++) {
12495 rule = &coalesce->rules[i];
12496 for (j = 0; j < rule->n_patterns; j++)
12497 kfree(rule->patterns[j].mask);
12498 kfree(rule->patterns);
12499 }
12500 kfree(coalesce->rules);
12501 kfree(coalesce);
12502 rdev->coalesce = NULL;
12503}
12504
12505static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev,
12506 struct nlattr *rule,
12507 struct cfg80211_coalesce_rules *new_rule)
12508{
12509 int err, i;
12510 const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce;
12511 struct nlattr *tb[NUM_NL80211_ATTR_COALESCE_RULE], *pat;
12512 int rem, pat_len, mask_len, pkt_offset, n_patterns = 0;
12513 struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
12514
8cb08174
JB
12515 err = nla_parse_nested_deprecated(tb, NL80211_ATTR_COALESCE_RULE_MAX,
12516 rule, nl80211_coalesce_policy, NULL);
be29b99a
AK
12517 if (err)
12518 return err;
12519
12520 if (tb[NL80211_ATTR_COALESCE_RULE_DELAY])
12521 new_rule->delay =
12522 nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_DELAY]);
12523 if (new_rule->delay > coalesce->max_delay)
12524 return -EINVAL;
12525
12526 if (tb[NL80211_ATTR_COALESCE_RULE_CONDITION])
12527 new_rule->condition =
12528 nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_CONDITION]);
be29b99a
AK
12529
12530 if (!tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN])
12531 return -EINVAL;
12532
12533 nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
12534 rem)
12535 n_patterns++;
12536 if (n_patterns > coalesce->n_patterns)
12537 return -EINVAL;
12538
12539 new_rule->patterns = kcalloc(n_patterns, sizeof(new_rule->patterns[0]),
12540 GFP_KERNEL);
12541 if (!new_rule->patterns)
12542 return -ENOMEM;
12543
12544 new_rule->n_patterns = n_patterns;
12545 i = 0;
12546
12547 nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
12548 rem) {
922bd80f
JB
12549 u8 *mask_pat;
12550
8cb08174
JB
12551 err = nla_parse_nested_deprecated(pat_tb, MAX_NL80211_PKTPAT,
12552 pat,
12553 nl80211_packet_pattern_policy,
12554 NULL);
95bca62f
JB
12555 if (err)
12556 return err;
12557
be29b99a
AK
12558 if (!pat_tb[NL80211_PKTPAT_MASK] ||
12559 !pat_tb[NL80211_PKTPAT_PATTERN])
12560 return -EINVAL;
12561 pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
12562 mask_len = DIV_ROUND_UP(pat_len, 8);
12563 if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
12564 return -EINVAL;
12565 if (pat_len > coalesce->pattern_max_len ||
12566 pat_len < coalesce->pattern_min_len)
12567 return -EINVAL;
12568
12569 if (!pat_tb[NL80211_PKTPAT_OFFSET])
12570 pkt_offset = 0;
12571 else
12572 pkt_offset = nla_get_u32(pat_tb[NL80211_PKTPAT_OFFSET]);
12573 if (pkt_offset > coalesce->max_pkt_offset)
12574 return -EINVAL;
12575 new_rule->patterns[i].pkt_offset = pkt_offset;
12576
922bd80f
JB
12577 mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL);
12578 if (!mask_pat)
be29b99a 12579 return -ENOMEM;
922bd80f
JB
12580
12581 new_rule->patterns[i].mask = mask_pat;
12582 memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]),
12583 mask_len);
12584
12585 mask_pat += mask_len;
12586 new_rule->patterns[i].pattern = mask_pat;
be29b99a 12587 new_rule->patterns[i].pattern_len = pat_len;
922bd80f
JB
12588 memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
12589 pat_len);
be29b99a
AK
12590 i++;
12591 }
12592
12593 return 0;
12594}
12595
12596static int nl80211_set_coalesce(struct sk_buff *skb, struct genl_info *info)
12597{
12598 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12599 const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce;
12600 struct cfg80211_coalesce new_coalesce = {};
12601 struct cfg80211_coalesce *n_coalesce;
12602 int err, rem_rule, n_rules = 0, i, j;
12603 struct nlattr *rule;
12604 struct cfg80211_coalesce_rules *tmp_rule;
12605
12606 if (!rdev->wiphy.coalesce || !rdev->ops->set_coalesce)
12607 return -EOPNOTSUPP;
12608
12609 if (!info->attrs[NL80211_ATTR_COALESCE_RULE]) {
12610 cfg80211_rdev_free_coalesce(rdev);
a1056b1b 12611 rdev_set_coalesce(rdev, NULL);
be29b99a
AK
12612 return 0;
12613 }
12614
12615 nla_for_each_nested(rule, info->attrs[NL80211_ATTR_COALESCE_RULE],
12616 rem_rule)
12617 n_rules++;
12618 if (n_rules > coalesce->n_rules)
12619 return -EINVAL;
12620
12621 new_coalesce.rules = kcalloc(n_rules, sizeof(new_coalesce.rules[0]),
12622 GFP_KERNEL);
12623 if (!new_coalesce.rules)
12624 return -ENOMEM;
12625
12626 new_coalesce.n_rules = n_rules;
12627 i = 0;
12628
12629 nla_for_each_nested(rule, info->attrs[NL80211_ATTR_COALESCE_RULE],
12630 rem_rule) {
12631 err = nl80211_parse_coalesce_rule(rdev, rule,
12632 &new_coalesce.rules[i]);
12633 if (err)
12634 goto error;
12635
12636 i++;
12637 }
12638
a1056b1b 12639 err = rdev_set_coalesce(rdev, &new_coalesce);
be29b99a
AK
12640 if (err)
12641 goto error;
12642
12643 n_coalesce = kmemdup(&new_coalesce, sizeof(new_coalesce), GFP_KERNEL);
12644 if (!n_coalesce) {
12645 err = -ENOMEM;
12646 goto error;
12647 }
12648 cfg80211_rdev_free_coalesce(rdev);
12649 rdev->coalesce = n_coalesce;
12650
12651 return 0;
12652error:
12653 for (i = 0; i < new_coalesce.n_rules; i++) {
12654 tmp_rule = &new_coalesce.rules[i];
12655 for (j = 0; j < tmp_rule->n_patterns; j++)
12656 kfree(tmp_rule->patterns[j].mask);
12657 kfree(tmp_rule->patterns);
12658 }
12659 kfree(new_coalesce.rules);
12660
12661 return err;
12662}
12663
e5497d76
JB
12664static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
12665{
12666 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12667 struct net_device *dev = info->user_ptr[1];
12668 struct wireless_dev *wdev = dev->ieee80211_ptr;
12669 struct nlattr *tb[NUM_NL80211_REKEY_DATA];
12670 struct cfg80211_gtk_rekey_data rekey_data;
12671 int err;
12672
12673 if (!info->attrs[NL80211_ATTR_REKEY_DATA])
12674 return -EINVAL;
12675
8cb08174
JB
12676 err = nla_parse_nested_deprecated(tb, MAX_NL80211_REKEY_DATA,
12677 info->attrs[NL80211_ATTR_REKEY_DATA],
12678 nl80211_rekey_policy, info->extack);
e5497d76
JB
12679 if (err)
12680 return err;
12681
e785fa0a
VD
12682 if (!tb[NL80211_REKEY_DATA_REPLAY_CTR] || !tb[NL80211_REKEY_DATA_KEK] ||
12683 !tb[NL80211_REKEY_DATA_KCK])
12684 return -EINVAL;
093a48d2
NE
12685 if (nla_len(tb[NL80211_REKEY_DATA_KEK]) != NL80211_KEK_LEN &&
12686 !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK &&
12687 nla_len(tb[NL80211_REKEY_DATA_KEK]) == NL80211_KEK_EXT_LEN))
e5497d76 12688 return -ERANGE;
093a48d2
NE
12689 if (nla_len(tb[NL80211_REKEY_DATA_KCK]) != NL80211_KCK_LEN &&
12690 !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK &&
12691 nla_len(tb[NL80211_REKEY_DATA_KEK]) == NL80211_KCK_EXT_LEN))
e5497d76
JB
12692 return -ERANGE;
12693
78f686ca
JB
12694 rekey_data.kek = nla_data(tb[NL80211_REKEY_DATA_KEK]);
12695 rekey_data.kck = nla_data(tb[NL80211_REKEY_DATA_KCK]);
12696 rekey_data.replay_ctr = nla_data(tb[NL80211_REKEY_DATA_REPLAY_CTR]);
093a48d2
NE
12697 rekey_data.kek_len = nla_len(tb[NL80211_REKEY_DATA_KEK]);
12698 rekey_data.kck_len = nla_len(tb[NL80211_REKEY_DATA_KCK]);
12699 if (tb[NL80211_REKEY_DATA_AKM])
12700 rekey_data.akm = nla_get_u32(tb[NL80211_REKEY_DATA_AKM]);
e5497d76
JB
12701
12702 wdev_lock(wdev);
12703 if (!wdev->current_bss) {
12704 err = -ENOTCONN;
12705 goto out;
12706 }
12707
12708 if (!rdev->ops->set_rekey_data) {
12709 err = -EOPNOTSUPP;
12710 goto out;
12711 }
12712
e35e4d28 12713 err = rdev_set_rekey_data(rdev, dev, &rekey_data);
e5497d76
JB
12714 out:
12715 wdev_unlock(wdev);
12716 return err;
12717}
12718
28946da7
JB
12719static int nl80211_register_unexpected_frame(struct sk_buff *skb,
12720 struct genl_info *info)
12721{
12722 struct net_device *dev = info->user_ptr[1];
12723 struct wireless_dev *wdev = dev->ieee80211_ptr;
12724
12725 if (wdev->iftype != NL80211_IFTYPE_AP &&
12726 wdev->iftype != NL80211_IFTYPE_P2P_GO)
12727 return -EINVAL;
12728
15e47304 12729 if (wdev->ap_unexpected_nlportid)
28946da7
JB
12730 return -EBUSY;
12731
15e47304 12732 wdev->ap_unexpected_nlportid = info->snd_portid;
28946da7
JB
12733 return 0;
12734}
12735
7f6cf311
JB
12736static int nl80211_probe_client(struct sk_buff *skb,
12737 struct genl_info *info)
12738{
12739 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12740 struct net_device *dev = info->user_ptr[1];
12741 struct wireless_dev *wdev = dev->ieee80211_ptr;
12742 struct sk_buff *msg;
12743 void *hdr;
12744 const u8 *addr;
12745 u64 cookie;
12746 int err;
12747
12748 if (wdev->iftype != NL80211_IFTYPE_AP &&
12749 wdev->iftype != NL80211_IFTYPE_P2P_GO)
12750 return -EOPNOTSUPP;
12751
12752 if (!info->attrs[NL80211_ATTR_MAC])
12753 return -EINVAL;
12754
12755 if (!rdev->ops->probe_client)
12756 return -EOPNOTSUPP;
12757
12758 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
12759 if (!msg)
12760 return -ENOMEM;
12761
15e47304 12762 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
7f6cf311 12763 NL80211_CMD_PROBE_CLIENT);
cb35fba3
DC
12764 if (!hdr) {
12765 err = -ENOBUFS;
7f6cf311
JB
12766 goto free_msg;
12767 }
12768
12769 addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
12770
e35e4d28 12771 err = rdev_probe_client(rdev, dev, addr, &cookie);
7f6cf311
JB
12772 if (err)
12773 goto free_msg;
12774
2dad624e
ND
12775 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
12776 NL80211_ATTR_PAD))
9360ffd1 12777 goto nla_put_failure;
7f6cf311
JB
12778
12779 genlmsg_end(msg, hdr);
12780
12781 return genlmsg_reply(msg, info);
12782
12783 nla_put_failure:
12784 err = -ENOBUFS;
12785 free_msg:
12786 nlmsg_free(msg);
12787 return err;
12788}
12789
5e760230
JB
12790static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info)
12791{
12792 struct cfg80211_registered_device *rdev = info->user_ptr[0];
37c73b5f
BG
12793 struct cfg80211_beacon_registration *reg, *nreg;
12794 int rv;
5e760230
JB
12795
12796 if (!(rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS))
12797 return -EOPNOTSUPP;
12798
37c73b5f
BG
12799 nreg = kzalloc(sizeof(*nreg), GFP_KERNEL);
12800 if (!nreg)
12801 return -ENOMEM;
12802
12803 /* First, check if already registered. */
12804 spin_lock_bh(&rdev->beacon_registrations_lock);
12805 list_for_each_entry(reg, &rdev->beacon_registrations, list) {
12806 if (reg->nlportid == info->snd_portid) {
12807 rv = -EALREADY;
12808 goto out_err;
12809 }
12810 }
12811 /* Add it to the list */
12812 nreg->nlportid = info->snd_portid;
12813 list_add(&nreg->list, &rdev->beacon_registrations);
5e760230 12814
37c73b5f 12815 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230
JB
12816
12817 return 0;
37c73b5f
BG
12818out_err:
12819 spin_unlock_bh(&rdev->beacon_registrations_lock);
12820 kfree(nreg);
12821 return rv;
5e760230
JB
12822}
12823
98104fde
JB
12824static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
12825{
12826 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12827 struct wireless_dev *wdev = info->user_ptr[1];
12828 int err;
12829
12830 if (!rdev->ops->start_p2p_device)
12831 return -EOPNOTSUPP;
12832
12833 if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
12834 return -EOPNOTSUPP;
12835
73c7da3d 12836 if (wdev_running(wdev))
98104fde
JB
12837 return 0;
12838
b6a55015
LC
12839 if (rfkill_blocked(rdev->rfkill))
12840 return -ERFKILL;
98104fde 12841
eeb126e9 12842 err = rdev_start_p2p_device(rdev, wdev);
98104fde
JB
12843 if (err)
12844 return err;
12845
73c7da3d 12846 wdev->is_running = true;
98104fde 12847 rdev->opencount++;
98104fde
JB
12848
12849 return 0;
12850}
12851
12852static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
12853{
12854 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12855 struct wireless_dev *wdev = info->user_ptr[1];
12856
12857 if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
12858 return -EOPNOTSUPP;
12859
12860 if (!rdev->ops->stop_p2p_device)
12861 return -EOPNOTSUPP;
12862
f9f47529 12863 cfg80211_stop_p2p_device(rdev, wdev);
98104fde
JB
12864
12865 return 0;
12866}
12867
cb3b7d87
AB
12868static int nl80211_start_nan(struct sk_buff *skb, struct genl_info *info)
12869{
12870 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12871 struct wireless_dev *wdev = info->user_ptr[1];
12872 struct cfg80211_nan_conf conf = {};
12873 int err;
12874
12875 if (wdev->iftype != NL80211_IFTYPE_NAN)
12876 return -EOPNOTSUPP;
12877
eeb04a96 12878 if (wdev_running(wdev))
cb3b7d87
AB
12879 return -EEXIST;
12880
12881 if (rfkill_blocked(rdev->rfkill))
12882 return -ERFKILL;
12883
12884 if (!info->attrs[NL80211_ATTR_NAN_MASTER_PREF])
12885 return -EINVAL;
12886
cb3b7d87
AB
12887 conf.master_pref =
12888 nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]);
cb3b7d87 12889
8585989d
LC
12890 if (info->attrs[NL80211_ATTR_BANDS]) {
12891 u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]);
12892
12893 if (bands & ~(u32)wdev->wiphy->nan_supported_bands)
12894 return -EOPNOTSUPP;
12895
12896 if (bands && !(bands & BIT(NL80211_BAND_2GHZ)))
12897 return -EINVAL;
12898
12899 conf.bands = bands;
12900 }
cb3b7d87
AB
12901
12902 err = rdev_start_nan(rdev, wdev, &conf);
12903 if (err)
12904 return err;
12905
73c7da3d 12906 wdev->is_running = true;
cb3b7d87
AB
12907 rdev->opencount++;
12908
12909 return 0;
12910}
12911
12912static int nl80211_stop_nan(struct sk_buff *skb, struct genl_info *info)
12913{
12914 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12915 struct wireless_dev *wdev = info->user_ptr[1];
12916
12917 if (wdev->iftype != NL80211_IFTYPE_NAN)
12918 return -EOPNOTSUPP;
12919
12920 cfg80211_stop_nan(rdev, wdev);
12921
12922 return 0;
12923}
12924
a442b761
AB
12925static int validate_nan_filter(struct nlattr *filter_attr)
12926{
12927 struct nlattr *attr;
12928 int len = 0, n_entries = 0, rem;
12929
12930 nla_for_each_nested(attr, filter_attr, rem) {
12931 len += nla_len(attr);
12932 n_entries++;
12933 }
12934
12935 if (len >= U8_MAX)
12936 return -EINVAL;
12937
12938 return n_entries;
12939}
12940
12941static int handle_nan_filter(struct nlattr *attr_filter,
12942 struct cfg80211_nan_func *func,
12943 bool tx)
12944{
12945 struct nlattr *attr;
12946 int n_entries, rem, i;
12947 struct cfg80211_nan_func_filter *filter;
12948
12949 n_entries = validate_nan_filter(attr_filter);
12950 if (n_entries < 0)
12951 return n_entries;
12952
12953 BUILD_BUG_ON(sizeof(*func->rx_filters) != sizeof(*func->tx_filters));
12954
12955 filter = kcalloc(n_entries, sizeof(*func->rx_filters), GFP_KERNEL);
12956 if (!filter)
12957 return -ENOMEM;
12958
12959 i = 0;
12960 nla_for_each_nested(attr, attr_filter, rem) {
b15ca182 12961 filter[i].filter = nla_memdup(attr, GFP_KERNEL);
a442b761
AB
12962 filter[i].len = nla_len(attr);
12963 i++;
12964 }
12965 if (tx) {
12966 func->num_tx_filters = n_entries;
12967 func->tx_filters = filter;
12968 } else {
12969 func->num_rx_filters = n_entries;
12970 func->rx_filters = filter;
12971 }
12972
12973 return 0;
12974}
12975
12976static int nl80211_nan_add_func(struct sk_buff *skb,
12977 struct genl_info *info)
12978{
12979 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12980 struct wireless_dev *wdev = info->user_ptr[1];
12981 struct nlattr *tb[NUM_NL80211_NAN_FUNC_ATTR], *func_attr;
12982 struct cfg80211_nan_func *func;
12983 struct sk_buff *msg = NULL;
12984 void *hdr = NULL;
12985 int err = 0;
12986
12987 if (wdev->iftype != NL80211_IFTYPE_NAN)
12988 return -EOPNOTSUPP;
12989
73c7da3d 12990 if (!wdev_running(wdev))
a442b761
AB
12991 return -ENOTCONN;
12992
12993 if (!info->attrs[NL80211_ATTR_NAN_FUNC])
12994 return -EINVAL;
12995
8cb08174
JB
12996 err = nla_parse_nested_deprecated(tb, NL80211_NAN_FUNC_ATTR_MAX,
12997 info->attrs[NL80211_ATTR_NAN_FUNC],
12998 nl80211_nan_func_policy,
12999 info->extack);
a442b761
AB
13000 if (err)
13001 return err;
13002
13003 func = kzalloc(sizeof(*func), GFP_KERNEL);
13004 if (!func)
13005 return -ENOMEM;
13006
b60ad348 13007 func->cookie = cfg80211_assign_cookie(rdev);
a442b761 13008
cb9abd48 13009 if (!tb[NL80211_NAN_FUNC_TYPE]) {
a442b761
AB
13010 err = -EINVAL;
13011 goto out;
13012 }
13013
13014
13015 func->type = nla_get_u8(tb[NL80211_NAN_FUNC_TYPE]);
13016
13017 if (!tb[NL80211_NAN_FUNC_SERVICE_ID]) {
13018 err = -EINVAL;
13019 goto out;
13020 }
13021
13022 memcpy(func->service_id, nla_data(tb[NL80211_NAN_FUNC_SERVICE_ID]),
13023 sizeof(func->service_id));
13024
13025 func->close_range =
13026 nla_get_flag(tb[NL80211_NAN_FUNC_CLOSE_RANGE]);
13027
13028 if (tb[NL80211_NAN_FUNC_SERVICE_INFO]) {
13029 func->serv_spec_info_len =
13030 nla_len(tb[NL80211_NAN_FUNC_SERVICE_INFO]);
13031 func->serv_spec_info =
13032 kmemdup(nla_data(tb[NL80211_NAN_FUNC_SERVICE_INFO]),
13033 func->serv_spec_info_len,
13034 GFP_KERNEL);
13035 if (!func->serv_spec_info) {
13036 err = -ENOMEM;
13037 goto out;
13038 }
13039 }
13040
13041 if (tb[NL80211_NAN_FUNC_TTL])
13042 func->ttl = nla_get_u32(tb[NL80211_NAN_FUNC_TTL]);
13043
13044 switch (func->type) {
13045 case NL80211_NAN_FUNC_PUBLISH:
13046 if (!tb[NL80211_NAN_FUNC_PUBLISH_TYPE]) {
13047 err = -EINVAL;
13048 goto out;
13049 }
13050
13051 func->publish_type =
13052 nla_get_u8(tb[NL80211_NAN_FUNC_PUBLISH_TYPE]);
13053 func->publish_bcast =
13054 nla_get_flag(tb[NL80211_NAN_FUNC_PUBLISH_BCAST]);
13055
13056 if ((!(func->publish_type & NL80211_NAN_SOLICITED_PUBLISH)) &&
13057 func->publish_bcast) {
13058 err = -EINVAL;
13059 goto out;
13060 }
13061 break;
13062 case NL80211_NAN_FUNC_SUBSCRIBE:
13063 func->subscribe_active =
13064 nla_get_flag(tb[NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE]);
13065 break;
13066 case NL80211_NAN_FUNC_FOLLOW_UP:
13067 if (!tb[NL80211_NAN_FUNC_FOLLOW_UP_ID] ||
3ea15452
HC
13068 !tb[NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID] ||
13069 !tb[NL80211_NAN_FUNC_FOLLOW_UP_DEST]) {
a442b761
AB
13070 err = -EINVAL;
13071 goto out;
13072 }
13073
13074 func->followup_id =
13075 nla_get_u8(tb[NL80211_NAN_FUNC_FOLLOW_UP_ID]);
13076 func->followup_reqid =
13077 nla_get_u8(tb[NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID]);
13078 memcpy(func->followup_dest.addr,
13079 nla_data(tb[NL80211_NAN_FUNC_FOLLOW_UP_DEST]),
13080 sizeof(func->followup_dest.addr));
13081 if (func->ttl) {
13082 err = -EINVAL;
13083 goto out;
13084 }
13085 break;
13086 default:
13087 err = -EINVAL;
13088 goto out;
13089 }
13090
13091 if (tb[NL80211_NAN_FUNC_SRF]) {
13092 struct nlattr *srf_tb[NUM_NL80211_NAN_SRF_ATTR];
13093
8cb08174
JB
13094 err = nla_parse_nested_deprecated(srf_tb,
13095 NL80211_NAN_SRF_ATTR_MAX,
13096 tb[NL80211_NAN_FUNC_SRF],
13097 nl80211_nan_srf_policy,
13098 info->extack);
a442b761
AB
13099 if (err)
13100 goto out;
13101
13102 func->srf_include =
13103 nla_get_flag(srf_tb[NL80211_NAN_SRF_INCLUDE]);
13104
13105 if (srf_tb[NL80211_NAN_SRF_BF]) {
13106 if (srf_tb[NL80211_NAN_SRF_MAC_ADDRS] ||
13107 !srf_tb[NL80211_NAN_SRF_BF_IDX]) {
13108 err = -EINVAL;
13109 goto out;
13110 }
13111
13112 func->srf_bf_len =
13113 nla_len(srf_tb[NL80211_NAN_SRF_BF]);
13114 func->srf_bf =
13115 kmemdup(nla_data(srf_tb[NL80211_NAN_SRF_BF]),
13116 func->srf_bf_len, GFP_KERNEL);
13117 if (!func->srf_bf) {
13118 err = -ENOMEM;
13119 goto out;
13120 }
13121
13122 func->srf_bf_idx =
13123 nla_get_u8(srf_tb[NL80211_NAN_SRF_BF_IDX]);
13124 } else {
13125 struct nlattr *attr, *mac_attr =
13126 srf_tb[NL80211_NAN_SRF_MAC_ADDRS];
13127 int n_entries, rem, i = 0;
13128
13129 if (!mac_attr) {
13130 err = -EINVAL;
13131 goto out;
13132 }
13133
13134 n_entries = validate_acl_mac_addrs(mac_attr);
13135 if (n_entries <= 0) {
13136 err = -EINVAL;
13137 goto out;
13138 }
13139
13140 func->srf_num_macs = n_entries;
13141 func->srf_macs =
6396bb22 13142 kcalloc(n_entries, sizeof(*func->srf_macs),
a442b761
AB
13143 GFP_KERNEL);
13144 if (!func->srf_macs) {
13145 err = -ENOMEM;
13146 goto out;
13147 }
13148
13149 nla_for_each_nested(attr, mac_attr, rem)
13150 memcpy(func->srf_macs[i++].addr, nla_data(attr),
13151 sizeof(*func->srf_macs));
13152 }
13153 }
13154
13155 if (tb[NL80211_NAN_FUNC_TX_MATCH_FILTER]) {
13156 err = handle_nan_filter(tb[NL80211_NAN_FUNC_TX_MATCH_FILTER],
13157 func, true);
13158 if (err)
13159 goto out;
13160 }
13161
13162 if (tb[NL80211_NAN_FUNC_RX_MATCH_FILTER]) {
13163 err = handle_nan_filter(tb[NL80211_NAN_FUNC_RX_MATCH_FILTER],
13164 func, false);
13165 if (err)
13166 goto out;
13167 }
13168
13169 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
13170 if (!msg) {
13171 err = -ENOMEM;
13172 goto out;
13173 }
13174
13175 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
13176 NL80211_CMD_ADD_NAN_FUNCTION);
13177 /* This can't really happen - we just allocated 4KB */
13178 if (WARN_ON(!hdr)) {
13179 err = -ENOMEM;
13180 goto out;
13181 }
13182
13183 err = rdev_add_nan_func(rdev, wdev, func);
13184out:
13185 if (err < 0) {
13186 cfg80211_free_nan_func(func);
13187 nlmsg_free(msg);
13188 return err;
13189 }
13190
13191 /* propagate the instance id and cookie to userspace */
13192 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, func->cookie,
13193 NL80211_ATTR_PAD))
13194 goto nla_put_failure;
13195
ae0be8de 13196 func_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_FUNC);
a442b761
AB
13197 if (!func_attr)
13198 goto nla_put_failure;
13199
13200 if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID,
13201 func->instance_id))
13202 goto nla_put_failure;
13203
13204 nla_nest_end(msg, func_attr);
13205
13206 genlmsg_end(msg, hdr);
13207 return genlmsg_reply(msg, info);
13208
13209nla_put_failure:
13210 nlmsg_free(msg);
13211 return -ENOBUFS;
13212}
13213
13214static int nl80211_nan_del_func(struct sk_buff *skb,
13215 struct genl_info *info)
13216{
13217 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13218 struct wireless_dev *wdev = info->user_ptr[1];
13219 u64 cookie;
13220
13221 if (wdev->iftype != NL80211_IFTYPE_NAN)
13222 return -EOPNOTSUPP;
13223
73c7da3d 13224 if (!wdev_running(wdev))
a442b761
AB
13225 return -ENOTCONN;
13226
13227 if (!info->attrs[NL80211_ATTR_COOKIE])
13228 return -EINVAL;
13229
a442b761
AB
13230 cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
13231
13232 rdev_del_nan_func(rdev, wdev, cookie);
13233
13234 return 0;
13235}
13236
a5a9dcf2
AB
13237static int nl80211_nan_change_config(struct sk_buff *skb,
13238 struct genl_info *info)
13239{
13240 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13241 struct wireless_dev *wdev = info->user_ptr[1];
13242 struct cfg80211_nan_conf conf = {};
13243 u32 changed = 0;
13244
13245 if (wdev->iftype != NL80211_IFTYPE_NAN)
13246 return -EOPNOTSUPP;
13247
73c7da3d 13248 if (!wdev_running(wdev))
a5a9dcf2
AB
13249 return -ENOTCONN;
13250
13251 if (info->attrs[NL80211_ATTR_NAN_MASTER_PREF]) {
13252 conf.master_pref =
13253 nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]);
13254 if (conf.master_pref <= 1 || conf.master_pref == 255)
13255 return -EINVAL;
13256
13257 changed |= CFG80211_NAN_CONF_CHANGED_PREF;
13258 }
13259
8585989d
LC
13260 if (info->attrs[NL80211_ATTR_BANDS]) {
13261 u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]);
13262
13263 if (bands & ~(u32)wdev->wiphy->nan_supported_bands)
13264 return -EOPNOTSUPP;
13265
13266 if (bands && !(bands & BIT(NL80211_BAND_2GHZ)))
13267 return -EINVAL;
13268
13269 conf.bands = bands;
13270 changed |= CFG80211_NAN_CONF_CHANGED_BANDS;
a5a9dcf2
AB
13271 }
13272
13273 if (!changed)
13274 return -EINVAL;
13275
13276 return rdev_nan_change_conf(rdev, wdev, &conf, changed);
13277}
13278
50bcd31d
AB
13279void cfg80211_nan_match(struct wireless_dev *wdev,
13280 struct cfg80211_nan_match_params *match, gfp_t gfp)
13281{
13282 struct wiphy *wiphy = wdev->wiphy;
13283 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
13284 struct nlattr *match_attr, *local_func_attr, *peer_func_attr;
13285 struct sk_buff *msg;
13286 void *hdr;
13287
13288 if (WARN_ON(!match->inst_id || !match->peer_inst_id || !match->addr))
13289 return;
13290
13291 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
13292 if (!msg)
13293 return;
13294
13295 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NAN_MATCH);
13296 if (!hdr) {
13297 nlmsg_free(msg);
13298 return;
13299 }
13300
13301 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
13302 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
13303 wdev->netdev->ifindex)) ||
13304 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
13305 NL80211_ATTR_PAD))
13306 goto nla_put_failure;
13307
13308 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, match->cookie,
13309 NL80211_ATTR_PAD) ||
13310 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, match->addr))
13311 goto nla_put_failure;
13312
ae0be8de 13313 match_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_MATCH);
50bcd31d
AB
13314 if (!match_attr)
13315 goto nla_put_failure;
13316
ae0be8de
MK
13317 local_func_attr = nla_nest_start_noflag(msg,
13318 NL80211_NAN_MATCH_FUNC_LOCAL);
50bcd31d
AB
13319 if (!local_func_attr)
13320 goto nla_put_failure;
13321
13322 if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, match->inst_id))
13323 goto nla_put_failure;
13324
13325 nla_nest_end(msg, local_func_attr);
13326
ae0be8de
MK
13327 peer_func_attr = nla_nest_start_noflag(msg,
13328 NL80211_NAN_MATCH_FUNC_PEER);
50bcd31d
AB
13329 if (!peer_func_attr)
13330 goto nla_put_failure;
13331
13332 if (nla_put_u8(msg, NL80211_NAN_FUNC_TYPE, match->type) ||
13333 nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, match->peer_inst_id))
13334 goto nla_put_failure;
13335
13336 if (match->info && match->info_len &&
13337 nla_put(msg, NL80211_NAN_FUNC_SERVICE_INFO, match->info_len,
13338 match->info))
13339 goto nla_put_failure;
13340
13341 nla_nest_end(msg, peer_func_attr);
13342 nla_nest_end(msg, match_attr);
13343 genlmsg_end(msg, hdr);
13344
13345 if (!wdev->owner_nlportid)
13346 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
13347 msg, 0, NL80211_MCGRP_NAN, gfp);
13348 else
13349 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
13350 wdev->owner_nlportid);
13351
13352 return;
13353
13354nla_put_failure:
13355 nlmsg_free(msg);
13356}
13357EXPORT_SYMBOL(cfg80211_nan_match);
13358
368e5a7b
AB
13359void cfg80211_nan_func_terminated(struct wireless_dev *wdev,
13360 u8 inst_id,
13361 enum nl80211_nan_func_term_reason reason,
13362 u64 cookie, gfp_t gfp)
13363{
13364 struct wiphy *wiphy = wdev->wiphy;
13365 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
13366 struct sk_buff *msg;
13367 struct nlattr *func_attr;
13368 void *hdr;
13369
13370 if (WARN_ON(!inst_id))
13371 return;
13372
13373 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
13374 if (!msg)
13375 return;
13376
13377 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DEL_NAN_FUNCTION);
13378 if (!hdr) {
13379 nlmsg_free(msg);
13380 return;
13381 }
13382
13383 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
13384 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
13385 wdev->netdev->ifindex)) ||
13386 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
13387 NL80211_ATTR_PAD))
13388 goto nla_put_failure;
13389
13390 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
13391 NL80211_ATTR_PAD))
13392 goto nla_put_failure;
13393
ae0be8de 13394 func_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_FUNC);
368e5a7b
AB
13395 if (!func_attr)
13396 goto nla_put_failure;
13397
13398 if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, inst_id) ||
13399 nla_put_u8(msg, NL80211_NAN_FUNC_TERM_REASON, reason))
13400 goto nla_put_failure;
13401
13402 nla_nest_end(msg, func_attr);
13403 genlmsg_end(msg, hdr);
13404
13405 if (!wdev->owner_nlportid)
13406 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
13407 msg, 0, NL80211_MCGRP_NAN, gfp);
13408 else
13409 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
13410 wdev->owner_nlportid);
13411
13412 return;
13413
13414nla_put_failure:
13415 nlmsg_free(msg);
13416}
13417EXPORT_SYMBOL(cfg80211_nan_func_terminated);
13418
3713b4e3
JB
13419static int nl80211_get_protocol_features(struct sk_buff *skb,
13420 struct genl_info *info)
13421{
13422 void *hdr;
13423 struct sk_buff *msg;
13424
13425 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
13426 if (!msg)
13427 return -ENOMEM;
13428
13429 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
13430 NL80211_CMD_GET_PROTOCOL_FEATURES);
13431 if (!hdr)
13432 goto nla_put_failure;
13433
13434 if (nla_put_u32(msg, NL80211_ATTR_PROTOCOL_FEATURES,
13435 NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP))
13436 goto nla_put_failure;
13437
13438 genlmsg_end(msg, hdr);
13439 return genlmsg_reply(msg, info);
13440
13441 nla_put_failure:
13442 kfree_skb(msg);
13443 return -ENOBUFS;
13444}
13445
355199e0
JM
13446static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info)
13447{
13448 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13449 struct cfg80211_update_ft_ies_params ft_params;
13450 struct net_device *dev = info->user_ptr[1];
13451
13452 if (!rdev->ops->update_ft_ies)
13453 return -EOPNOTSUPP;
13454
13455 if (!info->attrs[NL80211_ATTR_MDID] ||
3d7af878 13456 !info->attrs[NL80211_ATTR_IE])
355199e0
JM
13457 return -EINVAL;
13458
13459 memset(&ft_params, 0, sizeof(ft_params));
13460 ft_params.md = nla_get_u16(info->attrs[NL80211_ATTR_MDID]);
13461 ft_params.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
13462 ft_params.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
13463
13464 return rdev_update_ft_ies(rdev, dev, &ft_params);
13465}
13466
5de17984
AS
13467static int nl80211_crit_protocol_start(struct sk_buff *skb,
13468 struct genl_info *info)
13469{
13470 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13471 struct wireless_dev *wdev = info->user_ptr[1];
13472 enum nl80211_crit_proto_id proto = NL80211_CRIT_PROTO_UNSPEC;
13473 u16 duration;
13474 int ret;
13475
13476 if (!rdev->ops->crit_proto_start)
13477 return -EOPNOTSUPP;
13478
13479 if (WARN_ON(!rdev->ops->crit_proto_stop))
13480 return -EINVAL;
13481
13482 if (rdev->crit_proto_nlportid)
13483 return -EBUSY;
13484
13485 /* determine protocol if provided */
13486 if (info->attrs[NL80211_ATTR_CRIT_PROT_ID])
13487 proto = nla_get_u16(info->attrs[NL80211_ATTR_CRIT_PROT_ID]);
13488
13489 if (proto >= NUM_NL80211_CRIT_PROTO)
13490 return -EINVAL;
13491
13492 /* timeout must be provided */
13493 if (!info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION])
13494 return -EINVAL;
13495
13496 duration =
13497 nla_get_u16(info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION]);
13498
5de17984
AS
13499 ret = rdev_crit_proto_start(rdev, wdev, proto, duration);
13500 if (!ret)
13501 rdev->crit_proto_nlportid = info->snd_portid;
13502
13503 return ret;
13504}
13505
13506static int nl80211_crit_protocol_stop(struct sk_buff *skb,
13507 struct genl_info *info)
13508{
13509 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13510 struct wireless_dev *wdev = info->user_ptr[1];
13511
13512 if (!rdev->ops->crit_proto_stop)
13513 return -EOPNOTSUPP;
13514
13515 if (rdev->crit_proto_nlportid) {
13516 rdev->crit_proto_nlportid = 0;
13517 rdev_crit_proto_stop(rdev, wdev);
13518 }
13519 return 0;
13520}
13521
901bb989
JB
13522static int nl80211_vendor_check_policy(const struct wiphy_vendor_command *vcmd,
13523 struct nlattr *attr,
13524 struct netlink_ext_ack *extack)
13525{
13526 if (vcmd->policy == VENDOR_CMD_RAW_DATA) {
13527 if (attr->nla_type & NLA_F_NESTED) {
13528 NL_SET_ERR_MSG_ATTR(extack, attr,
13529 "unexpected nested data");
13530 return -EINVAL;
13531 }
13532
13533 return 0;
13534 }
13535
13536 if (!(attr->nla_type & NLA_F_NESTED)) {
13537 NL_SET_ERR_MSG_ATTR(extack, attr, "expected nested data");
13538 return -EINVAL;
13539 }
13540
32d5109a 13541 return nla_validate_nested(attr, vcmd->maxattr, vcmd->policy, extack);
901bb989
JB
13542}
13543
ad7e718c
JB
13544static int nl80211_vendor_cmd(struct sk_buff *skb, struct genl_info *info)
13545{
13546 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13547 struct wireless_dev *wdev =
13548 __cfg80211_wdev_from_attrs(genl_info_net(info), info->attrs);
13549 int i, err;
13550 u32 vid, subcmd;
13551
13552 if (!rdev->wiphy.vendor_commands)
13553 return -EOPNOTSUPP;
13554
13555 if (IS_ERR(wdev)) {
13556 err = PTR_ERR(wdev);
13557 if (err != -EINVAL)
13558 return err;
13559 wdev = NULL;
13560 } else if (wdev->wiphy != &rdev->wiphy) {
13561 return -EINVAL;
13562 }
13563
13564 if (!info->attrs[NL80211_ATTR_VENDOR_ID] ||
13565 !info->attrs[NL80211_ATTR_VENDOR_SUBCMD])
13566 return -EINVAL;
13567
13568 vid = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_ID]);
13569 subcmd = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_SUBCMD]);
13570 for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) {
13571 const struct wiphy_vendor_command *vcmd;
13572 void *data = NULL;
13573 int len = 0;
13574
13575 vcmd = &rdev->wiphy.vendor_commands[i];
13576
13577 if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd)
13578 continue;
13579
13580 if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV |
13581 WIPHY_VENDOR_CMD_NEED_NETDEV)) {
13582 if (!wdev)
13583 return -EINVAL;
13584 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV &&
13585 !wdev->netdev)
13586 return -EINVAL;
13587
13588 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
73c7da3d 13589 if (!wdev_running(wdev))
ad7e718c
JB
13590 return -ENETDOWN;
13591 }
13592 } else {
13593 wdev = NULL;
13594 }
13595
4052d3d2
JS
13596 if (!vcmd->doit)
13597 return -EOPNOTSUPP;
13598
ad7e718c
JB
13599 if (info->attrs[NL80211_ATTR_VENDOR_DATA]) {
13600 data = nla_data(info->attrs[NL80211_ATTR_VENDOR_DATA]);
13601 len = nla_len(info->attrs[NL80211_ATTR_VENDOR_DATA]);
901bb989
JB
13602
13603 err = nl80211_vendor_check_policy(vcmd,
13604 info->attrs[NL80211_ATTR_VENDOR_DATA],
13605 info->extack);
13606 if (err)
13607 return err;
ad7e718c
JB
13608 }
13609
13610 rdev->cur_cmd_info = info;
901bb989 13611 err = vcmd->doit(&rdev->wiphy, wdev, data, len);
ad7e718c
JB
13612 rdev->cur_cmd_info = NULL;
13613 return err;
13614 }
13615
13616 return -EOPNOTSUPP;
13617}
13618
7bdbe400
JB
13619static int nl80211_prepare_vendor_dump(struct sk_buff *skb,
13620 struct netlink_callback *cb,
13621 struct cfg80211_registered_device **rdev,
13622 struct wireless_dev **wdev)
13623{
50508d94 13624 struct nlattr **attrbuf;
7bdbe400
JB
13625 u32 vid, subcmd;
13626 unsigned int i;
13627 int vcmd_idx = -1;
13628 int err;
13629 void *data = NULL;
13630 unsigned int data_len = 0;
13631
7bdbe400
JB
13632 if (cb->args[0]) {
13633 /* subtract the 1 again here */
13634 struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
13635 struct wireless_dev *tmp;
13636
ea90e0dc
JB
13637 if (!wiphy)
13638 return -ENODEV;
7bdbe400
JB
13639 *rdev = wiphy_to_rdev(wiphy);
13640 *wdev = NULL;
13641
13642 if (cb->args[1]) {
53873f13 13643 list_for_each_entry(tmp, &wiphy->wdev_list, list) {
7bdbe400
JB
13644 if (tmp->identifier == cb->args[1] - 1) {
13645 *wdev = tmp;
13646 break;
13647 }
13648 }
13649 }
13650
13651 /* keep rtnl locked in successful case */
13652 return 0;
13653 }
13654
50508d94
JB
13655 attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), GFP_KERNEL);
13656 if (!attrbuf)
13657 return -ENOMEM;
13658
8cb08174
JB
13659 err = nlmsg_parse_deprecated(cb->nlh,
13660 GENL_HDRLEN + nl80211_fam.hdrsize,
13661 attrbuf, nl80211_fam.maxattr,
13662 nl80211_policy, NULL);
7bdbe400 13663 if (err)
50508d94 13664 goto out;
7bdbe400 13665
c90c39da 13666 if (!attrbuf[NL80211_ATTR_VENDOR_ID] ||
50508d94
JB
13667 !attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) {
13668 err = -EINVAL;
13669 goto out;
13670 }
7bdbe400 13671
c90c39da 13672 *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk), attrbuf);
7bdbe400
JB
13673 if (IS_ERR(*wdev))
13674 *wdev = NULL;
13675
c90c39da 13676 *rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
50508d94
JB
13677 if (IS_ERR(*rdev)) {
13678 err = PTR_ERR(*rdev);
13679 goto out;
13680 }
7bdbe400 13681
c90c39da
JB
13682 vid = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_ID]);
13683 subcmd = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_SUBCMD]);
7bdbe400
JB
13684
13685 for (i = 0; i < (*rdev)->wiphy.n_vendor_commands; i++) {
13686 const struct wiphy_vendor_command *vcmd;
13687
13688 vcmd = &(*rdev)->wiphy.vendor_commands[i];
13689
13690 if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd)
13691 continue;
13692
50508d94
JB
13693 if (!vcmd->dumpit) {
13694 err = -EOPNOTSUPP;
13695 goto out;
13696 }
7bdbe400
JB
13697
13698 vcmd_idx = i;
13699 break;
13700 }
13701
50508d94
JB
13702 if (vcmd_idx < 0) {
13703 err = -EOPNOTSUPP;
13704 goto out;
13705 }
7bdbe400 13706
c90c39da
JB
13707 if (attrbuf[NL80211_ATTR_VENDOR_DATA]) {
13708 data = nla_data(attrbuf[NL80211_ATTR_VENDOR_DATA]);
13709 data_len = nla_len(attrbuf[NL80211_ATTR_VENDOR_DATA]);
901bb989
JB
13710
13711 err = nl80211_vendor_check_policy(
13712 &(*rdev)->wiphy.vendor_commands[vcmd_idx],
13713 attrbuf[NL80211_ATTR_VENDOR_DATA],
13714 cb->extack);
13715 if (err)
50508d94 13716 goto out;
7bdbe400
JB
13717 }
13718
13719 /* 0 is the first index - add 1 to parse only once */
13720 cb->args[0] = (*rdev)->wiphy_idx + 1;
13721 /* add 1 to know if it was NULL */
13722 cb->args[1] = *wdev ? (*wdev)->identifier + 1 : 0;
13723 cb->args[2] = vcmd_idx;
13724 cb->args[3] = (unsigned long)data;
13725 cb->args[4] = data_len;
13726
13727 /* keep rtnl locked in successful case */
50508d94
JB
13728 err = 0;
13729out:
13730 kfree(attrbuf);
13731 return err;
7bdbe400
JB
13732}
13733
13734static int nl80211_vendor_cmd_dump(struct sk_buff *skb,
13735 struct netlink_callback *cb)
13736{
13737 struct cfg80211_registered_device *rdev;
13738 struct wireless_dev *wdev;
13739 unsigned int vcmd_idx;
13740 const struct wiphy_vendor_command *vcmd;
13741 void *data;
13742 int data_len;
13743 int err;
13744 struct nlattr *vendor_data;
13745
ea90e0dc 13746 rtnl_lock();
7bdbe400
JB
13747 err = nl80211_prepare_vendor_dump(skb, cb, &rdev, &wdev);
13748 if (err)
ea90e0dc 13749 goto out;
7bdbe400
JB
13750
13751 vcmd_idx = cb->args[2];
13752 data = (void *)cb->args[3];
13753 data_len = cb->args[4];
13754 vcmd = &rdev->wiphy.vendor_commands[vcmd_idx];
13755
13756 if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV |
13757 WIPHY_VENDOR_CMD_NEED_NETDEV)) {
ea90e0dc
JB
13758 if (!wdev) {
13759 err = -EINVAL;
13760 goto out;
13761 }
7bdbe400 13762 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV &&
ea90e0dc
JB
13763 !wdev->netdev) {
13764 err = -EINVAL;
13765 goto out;
13766 }
7bdbe400
JB
13767
13768 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
ea90e0dc
JB
13769 if (!wdev_running(wdev)) {
13770 err = -ENETDOWN;
13771 goto out;
13772 }
7bdbe400
JB
13773 }
13774 }
13775
13776 while (1) {
13777 void *hdr = nl80211hdr_put(skb, NETLINK_CB(cb->skb).portid,
13778 cb->nlh->nlmsg_seq, NLM_F_MULTI,
13779 NL80211_CMD_VENDOR);
13780 if (!hdr)
13781 break;
13782
13783 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
2dad624e
ND
13784 (wdev && nla_put_u64_64bit(skb, NL80211_ATTR_WDEV,
13785 wdev_id(wdev),
13786 NL80211_ATTR_PAD))) {
7bdbe400
JB
13787 genlmsg_cancel(skb, hdr);
13788 break;
13789 }
13790
ae0be8de
MK
13791 vendor_data = nla_nest_start_noflag(skb,
13792 NL80211_ATTR_VENDOR_DATA);
7bdbe400
JB
13793 if (!vendor_data) {
13794 genlmsg_cancel(skb, hdr);
13795 break;
13796 }
13797
13798 err = vcmd->dumpit(&rdev->wiphy, wdev, skb, data, data_len,
13799 (unsigned long *)&cb->args[5]);
13800 nla_nest_end(skb, vendor_data);
13801
13802 if (err == -ENOBUFS || err == -ENOENT) {
13803 genlmsg_cancel(skb, hdr);
13804 break;
9c167b2d 13805 } else if (err <= 0) {
7bdbe400
JB
13806 genlmsg_cancel(skb, hdr);
13807 goto out;
13808 }
13809
13810 genlmsg_end(skb, hdr);
13811 }
13812
13813 err = skb->len;
13814 out:
13815 rtnl_unlock();
13816 return err;
13817}
13818
ad7e718c
JB
13819struct sk_buff *__cfg80211_alloc_reply_skb(struct wiphy *wiphy,
13820 enum nl80211_commands cmd,
13821 enum nl80211_attrs attr,
13822 int approxlen)
13823{
f26cbf40 13824 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
ad7e718c
JB
13825
13826 if (WARN_ON(!rdev->cur_cmd_info))
13827 return NULL;
13828
6c09e791 13829 return __cfg80211_alloc_vendor_skb(rdev, NULL, approxlen,
ad7e718c
JB
13830 rdev->cur_cmd_info->snd_portid,
13831 rdev->cur_cmd_info->snd_seq,
567ffc35 13832 cmd, attr, NULL, GFP_KERNEL);
ad7e718c
JB
13833}
13834EXPORT_SYMBOL(__cfg80211_alloc_reply_skb);
13835
13836int cfg80211_vendor_cmd_reply(struct sk_buff *skb)
13837{
13838 struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
13839 void *hdr = ((void **)skb->cb)[1];
13840 struct nlattr *data = ((void **)skb->cb)[2];
13841
bd8c78e7
JB
13842 /* clear CB data for netlink core to own from now on */
13843 memset(skb->cb, 0, sizeof(skb->cb));
13844
ad7e718c
JB
13845 if (WARN_ON(!rdev->cur_cmd_info)) {
13846 kfree_skb(skb);
13847 return -EINVAL;
13848 }
13849
13850 nla_nest_end(skb, data);
13851 genlmsg_end(skb, hdr);
13852 return genlmsg_reply(skb, rdev->cur_cmd_info);
13853}
13854EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_reply);
13855
55c1fdf0
JB
13856unsigned int cfg80211_vendor_cmd_get_sender(struct wiphy *wiphy)
13857{
13858 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
13859
13860 if (WARN_ON(!rdev->cur_cmd_info))
13861 return 0;
13862
13863 return rdev->cur_cmd_info->snd_portid;
13864}
13865EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_get_sender);
13866
fa9ffc74
KP
13867static int nl80211_set_qos_map(struct sk_buff *skb,
13868 struct genl_info *info)
13869{
13870 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13871 struct cfg80211_qos_map *qos_map = NULL;
13872 struct net_device *dev = info->user_ptr[1];
13873 u8 *pos, len, num_des, des_len, des;
13874 int ret;
13875
13876 if (!rdev->ops->set_qos_map)
13877 return -EOPNOTSUPP;
13878
13879 if (info->attrs[NL80211_ATTR_QOS_MAP]) {
13880 pos = nla_data(info->attrs[NL80211_ATTR_QOS_MAP]);
13881 len = nla_len(info->attrs[NL80211_ATTR_QOS_MAP]);
13882
c8b82802 13883 if (len % 2)
fa9ffc74
KP
13884 return -EINVAL;
13885
13886 qos_map = kzalloc(sizeof(struct cfg80211_qos_map), GFP_KERNEL);
13887 if (!qos_map)
13888 return -ENOMEM;
13889
13890 num_des = (len - IEEE80211_QOS_MAP_LEN_MIN) >> 1;
13891 if (num_des) {
13892 des_len = num_des *
13893 sizeof(struct cfg80211_dscp_exception);
13894 memcpy(qos_map->dscp_exception, pos, des_len);
13895 qos_map->num_des = num_des;
13896 for (des = 0; des < num_des; des++) {
13897 if (qos_map->dscp_exception[des].up > 7) {
13898 kfree(qos_map);
13899 return -EINVAL;
13900 }
13901 }
13902 pos += des_len;
13903 }
13904 memcpy(qos_map->up, pos, IEEE80211_QOS_MAP_LEN_MIN);
13905 }
13906
13907 wdev_lock(dev->ieee80211_ptr);
13908 ret = nl80211_key_allowed(dev->ieee80211_ptr);
13909 if (!ret)
13910 ret = rdev_set_qos_map(rdev, dev, qos_map);
13911 wdev_unlock(dev->ieee80211_ptr);
13912
13913 kfree(qos_map);
13914 return ret;
13915}
13916
960d01ac
JB
13917static int nl80211_add_tx_ts(struct sk_buff *skb, struct genl_info *info)
13918{
13919 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13920 struct net_device *dev = info->user_ptr[1];
13921 struct wireless_dev *wdev = dev->ieee80211_ptr;
13922 const u8 *peer;
13923 u8 tsid, up;
13924 u16 admitted_time = 0;
13925 int err;
13926
723e73ac 13927 if (!(rdev->wiphy.features & NL80211_FEATURE_SUPPORTS_WMM_ADMISSION))
960d01ac
JB
13928 return -EOPNOTSUPP;
13929
13930 if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC] ||
13931 !info->attrs[NL80211_ATTR_USER_PRIO])
13932 return -EINVAL;
13933
13934 tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
960d01ac 13935 up = nla_get_u8(info->attrs[NL80211_ATTR_USER_PRIO]);
960d01ac
JB
13936
13937 /* WMM uses TIDs 0-7 even for TSPEC */
723e73ac 13938 if (tsid >= IEEE80211_FIRST_TSPEC_TSID) {
960d01ac 13939 /* TODO: handle 802.11 TSPEC/admission control
723e73ac
JB
13940 * need more attributes for that (e.g. BA session requirement);
13941 * change the WMM adminssion test above to allow both then
960d01ac
JB
13942 */
13943 return -EINVAL;
13944 }
13945
13946 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
13947
13948 if (info->attrs[NL80211_ATTR_ADMITTED_TIME]) {
13949 admitted_time =
13950 nla_get_u16(info->attrs[NL80211_ATTR_ADMITTED_TIME]);
13951 if (!admitted_time)
13952 return -EINVAL;
13953 }
13954
13955 wdev_lock(wdev);
13956 switch (wdev->iftype) {
13957 case NL80211_IFTYPE_STATION:
13958 case NL80211_IFTYPE_P2P_CLIENT:
13959 if (wdev->current_bss)
13960 break;
13961 err = -ENOTCONN;
13962 goto out;
13963 default:
13964 err = -EOPNOTSUPP;
13965 goto out;
13966 }
13967
13968 err = rdev_add_tx_ts(rdev, dev, tsid, peer, up, admitted_time);
13969
13970 out:
13971 wdev_unlock(wdev);
13972 return err;
13973}
13974
13975static int nl80211_del_tx_ts(struct sk_buff *skb, struct genl_info *info)
13976{
13977 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13978 struct net_device *dev = info->user_ptr[1];
13979 struct wireless_dev *wdev = dev->ieee80211_ptr;
13980 const u8 *peer;
13981 u8 tsid;
13982 int err;
13983
13984 if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC])
13985 return -EINVAL;
13986
13987 tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
13988 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
13989
13990 wdev_lock(wdev);
13991 err = rdev_del_tx_ts(rdev, dev, tsid, peer);
13992 wdev_unlock(wdev);
13993
13994 return err;
13995}
13996
1057d35e
AN
13997static int nl80211_tdls_channel_switch(struct sk_buff *skb,
13998 struct genl_info *info)
13999{
14000 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14001 struct net_device *dev = info->user_ptr[1];
14002 struct wireless_dev *wdev = dev->ieee80211_ptr;
14003 struct cfg80211_chan_def chandef = {};
14004 const u8 *addr;
14005 u8 oper_class;
14006 int err;
14007
14008 if (!rdev->ops->tdls_channel_switch ||
14009 !(rdev->wiphy.features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH))
14010 return -EOPNOTSUPP;
14011
14012 switch (dev->ieee80211_ptr->iftype) {
14013 case NL80211_IFTYPE_STATION:
14014 case NL80211_IFTYPE_P2P_CLIENT:
14015 break;
14016 default:
14017 return -EOPNOTSUPP;
14018 }
14019
14020 if (!info->attrs[NL80211_ATTR_MAC] ||
14021 !info->attrs[NL80211_ATTR_OPER_CLASS])
14022 return -EINVAL;
14023
14024 err = nl80211_parse_chandef(rdev, info, &chandef);
14025 if (err)
14026 return err;
14027
14028 /*
14029 * Don't allow wide channels on the 2.4Ghz band, as per IEEE802.11-2012
14030 * section 10.22.6.2.1. Disallow 5/10Mhz channels as well for now, the
14031 * specification is not defined for them.
14032 */
57fbcce3 14033 if (chandef.chan->band == NL80211_BAND_2GHZ &&
1057d35e
AN
14034 chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
14035 chandef.width != NL80211_CHAN_WIDTH_20)
14036 return -EINVAL;
14037
14038 /* we will be active on the TDLS link */
923b352f
AN
14039 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
14040 wdev->iftype))
1057d35e
AN
14041 return -EINVAL;
14042
14043 /* don't allow switching to DFS channels */
14044 if (cfg80211_chandef_dfs_required(wdev->wiphy, &chandef, wdev->iftype))
14045 return -EINVAL;
14046
14047 addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
14048 oper_class = nla_get_u8(info->attrs[NL80211_ATTR_OPER_CLASS]);
14049
14050 wdev_lock(wdev);
14051 err = rdev_tdls_channel_switch(rdev, dev, addr, oper_class, &chandef);
14052 wdev_unlock(wdev);
14053
14054 return err;
14055}
14056
14057static int nl80211_tdls_cancel_channel_switch(struct sk_buff *skb,
14058 struct genl_info *info)
14059{
14060 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14061 struct net_device *dev = info->user_ptr[1];
14062 struct wireless_dev *wdev = dev->ieee80211_ptr;
14063 const u8 *addr;
14064
14065 if (!rdev->ops->tdls_channel_switch ||
14066 !rdev->ops->tdls_cancel_channel_switch ||
14067 !(rdev->wiphy.features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH))
14068 return -EOPNOTSUPP;
14069
14070 switch (dev->ieee80211_ptr->iftype) {
14071 case NL80211_IFTYPE_STATION:
14072 case NL80211_IFTYPE_P2P_CLIENT:
14073 break;
14074 default:
14075 return -EOPNOTSUPP;
14076 }
14077
14078 if (!info->attrs[NL80211_ATTR_MAC])
14079 return -EINVAL;
14080
14081 addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
14082
14083 wdev_lock(wdev);
14084 rdev_tdls_cancel_channel_switch(rdev, dev, addr);
14085 wdev_unlock(wdev);
14086
14087 return 0;
14088}
14089
ce0ce13a
MB
14090static int nl80211_set_multicast_to_unicast(struct sk_buff *skb,
14091 struct genl_info *info)
14092{
14093 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14094 struct net_device *dev = info->user_ptr[1];
14095 struct wireless_dev *wdev = dev->ieee80211_ptr;
14096 const struct nlattr *nla;
14097 bool enabled;
14098
ce0ce13a
MB
14099 if (!rdev->ops->set_multicast_to_unicast)
14100 return -EOPNOTSUPP;
14101
14102 if (wdev->iftype != NL80211_IFTYPE_AP &&
14103 wdev->iftype != NL80211_IFTYPE_P2P_GO)
14104 return -EOPNOTSUPP;
14105
14106 nla = info->attrs[NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED];
14107 enabled = nla_get_flag(nla);
14108
14109 return rdev_set_multicast_to_unicast(rdev, dev, enabled);
14110}
14111
3a00df57
AS
14112static int nl80211_set_pmk(struct sk_buff *skb, struct genl_info *info)
14113{
14114 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14115 struct net_device *dev = info->user_ptr[1];
14116 struct wireless_dev *wdev = dev->ieee80211_ptr;
14117 struct cfg80211_pmk_conf pmk_conf = {};
14118 int ret;
14119
14120 if (wdev->iftype != NL80211_IFTYPE_STATION &&
14121 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
14122 return -EOPNOTSUPP;
14123
14124 if (!wiphy_ext_feature_isset(&rdev->wiphy,
14125 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
14126 return -EOPNOTSUPP;
14127
14128 if (!info->attrs[NL80211_ATTR_MAC] || !info->attrs[NL80211_ATTR_PMK])
14129 return -EINVAL;
14130
14131 wdev_lock(wdev);
14132 if (!wdev->current_bss) {
14133 ret = -ENOTCONN;
14134 goto out;
14135 }
14136
14137 pmk_conf.aa = nla_data(info->attrs[NL80211_ATTR_MAC]);
14138 if (memcmp(pmk_conf.aa, wdev->current_bss->pub.bssid, ETH_ALEN)) {
14139 ret = -EINVAL;
14140 goto out;
14141 }
14142
14143 pmk_conf.pmk = nla_data(info->attrs[NL80211_ATTR_PMK]);
14144 pmk_conf.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]);
14145 if (pmk_conf.pmk_len != WLAN_PMK_LEN &&
14146 pmk_conf.pmk_len != WLAN_PMK_LEN_SUITE_B_192) {
14147 ret = -EINVAL;
14148 goto out;
14149 }
14150
cb9abd48 14151 if (info->attrs[NL80211_ATTR_PMKR0_NAME])
3a00df57
AS
14152 pmk_conf.pmk_r0_name =
14153 nla_data(info->attrs[NL80211_ATTR_PMKR0_NAME]);
3a00df57
AS
14154
14155 ret = rdev_set_pmk(rdev, dev, &pmk_conf);
14156out:
14157 wdev_unlock(wdev);
14158 return ret;
14159}
14160
14161static int nl80211_del_pmk(struct sk_buff *skb, struct genl_info *info)
14162{
14163 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14164 struct net_device *dev = info->user_ptr[1];
14165 struct wireless_dev *wdev = dev->ieee80211_ptr;
14166 const u8 *aa;
14167 int ret;
14168
14169 if (wdev->iftype != NL80211_IFTYPE_STATION &&
14170 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
14171 return -EOPNOTSUPP;
14172
14173 if (!wiphy_ext_feature_isset(&rdev->wiphy,
14174 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
14175 return -EOPNOTSUPP;
14176
14177 if (!info->attrs[NL80211_ATTR_MAC])
14178 return -EINVAL;
14179
14180 wdev_lock(wdev);
14181 aa = nla_data(info->attrs[NL80211_ATTR_MAC]);
14182 ret = rdev_del_pmk(rdev, dev, aa);
14183 wdev_unlock(wdev);
14184
14185 return ret;
14186}
14187
40cbfa90
SD
14188static int nl80211_external_auth(struct sk_buff *skb, struct genl_info *info)
14189{
14190 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14191 struct net_device *dev = info->user_ptr[1];
14192 struct cfg80211_external_auth_params params;
14193
db8d93a7 14194 if (!rdev->ops->external_auth)
40cbfa90
SD
14195 return -EOPNOTSUPP;
14196
fe494370
SD
14197 if (!info->attrs[NL80211_ATTR_SSID] &&
14198 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
14199 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
40cbfa90
SD
14200 return -EINVAL;
14201
14202 if (!info->attrs[NL80211_ATTR_BSSID])
14203 return -EINVAL;
14204
14205 if (!info->attrs[NL80211_ATTR_STATUS_CODE])
14206 return -EINVAL;
14207
14208 memset(&params, 0, sizeof(params));
14209
fe494370
SD
14210 if (info->attrs[NL80211_ATTR_SSID]) {
14211 params.ssid.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
cb9abd48 14212 if (params.ssid.ssid_len == 0)
fe494370
SD
14213 return -EINVAL;
14214 memcpy(params.ssid.ssid,
14215 nla_data(info->attrs[NL80211_ATTR_SSID]),
14216 params.ssid.ssid_len);
14217 }
40cbfa90
SD
14218
14219 memcpy(params.bssid, nla_data(info->attrs[NL80211_ATTR_BSSID]),
14220 ETH_ALEN);
14221
14222 params.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
14223
fe494370
SD
14224 if (info->attrs[NL80211_ATTR_PMKID])
14225 params.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
14226
40cbfa90
SD
14227 return rdev_external_auth(rdev, dev, &params);
14228}
14229
2576a9ac
DK
14230static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
14231{
dca9ca2d 14232 bool dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK];
2576a9ac
DK
14233 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14234 struct net_device *dev = info->user_ptr[1];
14235 struct wireless_dev *wdev = dev->ieee80211_ptr;
14236 const u8 *buf;
14237 size_t len;
14238 u8 *dest;
14239 u16 proto;
14240 bool noencrypt;
dca9ca2d 14241 u64 cookie = 0;
2576a9ac
DK
14242 int err;
14243
14244 if (!wiphy_ext_feature_isset(&rdev->wiphy,
14245 NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211))
14246 return -EOPNOTSUPP;
14247
14248 if (!rdev->ops->tx_control_port)
14249 return -EOPNOTSUPP;
14250
14251 if (!info->attrs[NL80211_ATTR_FRAME] ||
14252 !info->attrs[NL80211_ATTR_MAC] ||
14253 !info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) {
14254 GENL_SET_ERR_MSG(info, "Frame, MAC or ethertype missing");
14255 return -EINVAL;
14256 }
14257
14258 wdev_lock(wdev);
14259
14260 switch (wdev->iftype) {
14261 case NL80211_IFTYPE_AP:
14262 case NL80211_IFTYPE_P2P_GO:
14263 case NL80211_IFTYPE_MESH_POINT:
14264 break;
14265 case NL80211_IFTYPE_ADHOC:
14266 case NL80211_IFTYPE_STATION:
14267 case NL80211_IFTYPE_P2P_CLIENT:
14268 if (wdev->current_bss)
14269 break;
14270 err = -ENOTCONN;
14271 goto out;
14272 default:
14273 err = -EOPNOTSUPP;
14274 goto out;
14275 }
14276
14277 wdev_unlock(wdev);
14278
14279 buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
14280 len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
14281 dest = nla_data(info->attrs[NL80211_ATTR_MAC]);
14282 proto = nla_get_u16(info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]);
14283 noencrypt =
14284 nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]);
14285
dca9ca2d
MT
14286 err = rdev_tx_control_port(rdev, dev, buf, len,
14287 dest, cpu_to_be16(proto), noencrypt,
14288 dont_wait_for_ack ? NULL : &cookie);
14289 if (!err && !dont_wait_for_ack)
14290 nl_set_extack_cookie_u64(info->extack, cookie);
14291 return err;
2576a9ac
DK
14292 out:
14293 wdev_unlock(wdev);
14294 return err;
14295}
14296
81e54d08
PKC
14297static int nl80211_get_ftm_responder_stats(struct sk_buff *skb,
14298 struct genl_info *info)
14299{
14300 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14301 struct net_device *dev = info->user_ptr[1];
14302 struct wireless_dev *wdev = dev->ieee80211_ptr;
14303 struct cfg80211_ftm_responder_stats ftm_stats = {};
14304 struct sk_buff *msg;
14305 void *hdr;
14306 struct nlattr *ftm_stats_attr;
14307 int err;
14308
14309 if (wdev->iftype != NL80211_IFTYPE_AP || !wdev->beacon_interval)
14310 return -EOPNOTSUPP;
14311
14312 err = rdev_get_ftm_responder_stats(rdev, dev, &ftm_stats);
14313 if (err)
14314 return err;
14315
14316 if (!ftm_stats.filled)
14317 return -ENODATA;
14318
14319 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
14320 if (!msg)
14321 return -ENOMEM;
14322
14323 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
14324 NL80211_CMD_GET_FTM_RESPONDER_STATS);
14325 if (!hdr)
1399c59f 14326 goto nla_put_failure;
81e54d08
PKC
14327
14328 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
14329 goto nla_put_failure;
14330
ae0be8de
MK
14331 ftm_stats_attr = nla_nest_start_noflag(msg,
14332 NL80211_ATTR_FTM_RESPONDER_STATS);
81e54d08
PKC
14333 if (!ftm_stats_attr)
14334 goto nla_put_failure;
14335
14336#define SET_FTM(field, name, type) \
14337 do { if ((ftm_stats.filled & BIT(NL80211_FTM_STATS_ ## name)) && \
14338 nla_put_ ## type(msg, NL80211_FTM_STATS_ ## name, \
14339 ftm_stats.field)) \
14340 goto nla_put_failure; } while (0)
14341#define SET_FTM_U64(field, name) \
14342 do { if ((ftm_stats.filled & BIT(NL80211_FTM_STATS_ ## name)) && \
14343 nla_put_u64_64bit(msg, NL80211_FTM_STATS_ ## name, \
14344 ftm_stats.field, NL80211_FTM_STATS_PAD)) \
14345 goto nla_put_failure; } while (0)
14346
14347 SET_FTM(success_num, SUCCESS_NUM, u32);
14348 SET_FTM(partial_num, PARTIAL_NUM, u32);
14349 SET_FTM(failed_num, FAILED_NUM, u32);
14350 SET_FTM(asap_num, ASAP_NUM, u32);
14351 SET_FTM(non_asap_num, NON_ASAP_NUM, u32);
14352 SET_FTM_U64(total_duration_ms, TOTAL_DURATION_MSEC);
14353 SET_FTM(unknown_triggers_num, UNKNOWN_TRIGGERS_NUM, u32);
14354 SET_FTM(reschedule_requests_num, RESCHEDULE_REQUESTS_NUM, u32);
14355 SET_FTM(out_of_window_triggers_num, OUT_OF_WINDOW_TRIGGERS_NUM, u32);
14356#undef SET_FTM
14357
14358 nla_nest_end(msg, ftm_stats_attr);
14359
14360 genlmsg_end(msg, hdr);
14361 return genlmsg_reply(msg, info);
14362
14363nla_put_failure:
14364 nlmsg_free(msg);
14365 return -ENOBUFS;
14366}
14367
cb74e977
SD
14368static int nl80211_update_owe_info(struct sk_buff *skb, struct genl_info *info)
14369{
14370 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14371 struct cfg80211_update_owe_info owe_info;
14372 struct net_device *dev = info->user_ptr[1];
14373
14374 if (!rdev->ops->update_owe_info)
14375 return -EOPNOTSUPP;
14376
14377 if (!info->attrs[NL80211_ATTR_STATUS_CODE] ||
14378 !info->attrs[NL80211_ATTR_MAC])
14379 return -EINVAL;
14380
14381 memset(&owe_info, 0, sizeof(owe_info));
14382 owe_info.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
14383 nla_memcpy(owe_info.peer, info->attrs[NL80211_ATTR_MAC], ETH_ALEN);
14384
14385 if (info->attrs[NL80211_ATTR_IE]) {
14386 owe_info.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
14387 owe_info.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
14388 }
14389
14390 return rdev_update_owe_info(rdev, dev, &owe_info);
14391}
14392
5ab92e7f
RM
14393static int nl80211_probe_mesh_link(struct sk_buff *skb, struct genl_info *info)
14394{
14395 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14396 struct net_device *dev = info->user_ptr[1];
14397 struct wireless_dev *wdev = dev->ieee80211_ptr;
14398 struct station_info sinfo = {};
14399 const u8 *buf;
14400 size_t len;
14401 u8 *dest;
14402 int err;
14403
14404 if (!rdev->ops->probe_mesh_link || !rdev->ops->get_station)
14405 return -EOPNOTSUPP;
14406
14407 if (!info->attrs[NL80211_ATTR_MAC] ||
14408 !info->attrs[NL80211_ATTR_FRAME]) {
14409 GENL_SET_ERR_MSG(info, "Frame or MAC missing");
14410 return -EINVAL;
14411 }
14412
14413 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
14414 return -EOPNOTSUPP;
14415
14416 dest = nla_data(info->attrs[NL80211_ATTR_MAC]);
14417 buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
14418 len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
14419
14420 if (len < sizeof(struct ethhdr))
14421 return -EINVAL;
14422
14423 if (!ether_addr_equal(buf, dest) || is_multicast_ether_addr(buf) ||
14424 !ether_addr_equal(buf + ETH_ALEN, dev->dev_addr))
14425 return -EINVAL;
14426
14427 err = rdev_get_station(rdev, dev, dest, &sinfo);
14428 if (err)
14429 return err;
14430
2a279b34
FF
14431 cfg80211_sinfo_release_content(&sinfo);
14432
5ab92e7f
RM
14433 return rdev_probe_mesh_link(rdev, dev, dest, buf, len);
14434}
14435
77f576de
T
14436static int parse_tid_conf(struct cfg80211_registered_device *rdev,
14437 struct nlattr *attrs[], struct net_device *dev,
3710a8a6 14438 struct cfg80211_tid_cfg *tid_conf,
77f576de
T
14439 struct genl_info *info, const u8 *peer)
14440{
14441 struct netlink_ext_ack *extack = info->extack;
3710a8a6 14442 u64 mask;
77f576de
T
14443 int err;
14444
14445 if (!attrs[NL80211_TID_CONFIG_ATTR_TIDS])
14446 return -EINVAL;
14447
14448 tid_conf->config_override =
14449 nla_get_flag(attrs[NL80211_TID_CONFIG_ATTR_OVERRIDE]);
3710a8a6 14450 tid_conf->tids = nla_get_u16(attrs[NL80211_TID_CONFIG_ATTR_TIDS]);
77f576de
T
14451
14452 if (tid_conf->config_override) {
14453 if (rdev->ops->reset_tid_config) {
14454 err = rdev_reset_tid_config(rdev, dev, peer,
3710a8a6 14455 tid_conf->tids);
c0336955 14456 if (err)
77f576de
T
14457 return err;
14458 } else {
14459 return -EINVAL;
14460 }
14461 }
14462
14463 if (attrs[NL80211_TID_CONFIG_ATTR_NOACK]) {
3710a8a6 14464 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_NOACK);
77f576de
T
14465 tid_conf->noack =
14466 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_NOACK]);
14467 }
14468
6a21d16c
T
14469 if (attrs[NL80211_TID_CONFIG_ATTR_RETRY_SHORT]) {
14470 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RETRY_SHORT);
14471 tid_conf->retry_short =
14472 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RETRY_SHORT]);
14473
14474 if (tid_conf->retry_short > rdev->wiphy.max_data_retry_count)
14475 return -EINVAL;
14476 }
14477
14478 if (attrs[NL80211_TID_CONFIG_ATTR_RETRY_LONG]) {
14479 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RETRY_LONG);
14480 tid_conf->retry_long =
14481 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RETRY_LONG]);
14482
14483 if (tid_conf->retry_long > rdev->wiphy.max_data_retry_count)
14484 return -EINVAL;
14485 }
14486
ade274b2
T
14487 if (attrs[NL80211_TID_CONFIG_ATTR_AMPDU_CTRL]) {
14488 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL);
14489 tid_conf->ampdu =
14490 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_AMPDU_CTRL]);
14491 }
14492
04f7d142
T
14493 if (attrs[NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL]) {
14494 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL);
14495 tid_conf->rtscts =
14496 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL]);
14497 }
14498
33462e68
SM
14499 if (attrs[NL80211_TID_CONFIG_ATTR_AMSDU_CTRL]) {
14500 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_AMSDU_CTRL);
14501 tid_conf->amsdu =
14502 nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_AMSDU_CTRL]);
14503 }
14504
9a5f6488
TC
14505 if (attrs[NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE]) {
14506 u32 idx = NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE, attr;
14507
14508 tid_conf->txrate_type = nla_get_u8(attrs[idx]);
14509
14510 if (tid_conf->txrate_type != NL80211_TX_RATE_AUTOMATIC) {
14511 attr = NL80211_TID_CONFIG_ATTR_TX_RATE;
14512 err = nl80211_parse_tx_bitrate_mask(info, attrs, attr,
857b34c4
RM
14513 &tid_conf->txrate_mask, dev,
14514 true);
9a5f6488
TC
14515 if (err)
14516 return err;
14517
14518 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_TX_RATE);
14519 }
14520 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE);
14521 }
14522
3710a8a6
JB
14523 if (peer)
14524 mask = rdev->wiphy.tid_config_support.peer;
14525 else
14526 mask = rdev->wiphy.tid_config_support.vif;
14527
14528 if (tid_conf->mask & ~mask) {
14529 NL_SET_ERR_MSG(extack, "unsupported TID configuration");
14530 return -ENOTSUPP;
14531 }
14532
77f576de
T
14533 return 0;
14534}
14535
14536static int nl80211_set_tid_config(struct sk_buff *skb,
14537 struct genl_info *info)
14538{
14539 struct cfg80211_registered_device *rdev = info->user_ptr[0];
14540 struct nlattr *attrs[NL80211_TID_CONFIG_ATTR_MAX + 1];
14541 struct net_device *dev = info->user_ptr[1];
3710a8a6 14542 struct cfg80211_tid_config *tid_config;
77f576de
T
14543 struct nlattr *tid;
14544 int conf_idx = 0, rem_conf;
14545 int ret = -EINVAL;
14546 u32 num_conf = 0;
14547
14548 if (!info->attrs[NL80211_ATTR_TID_CONFIG])
14549 return -EINVAL;
14550
14551 if (!rdev->ops->set_tid_config)
14552 return -EOPNOTSUPP;
14553
14554 nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
14555 rem_conf)
14556 num_conf++;
14557
14558 tid_config = kzalloc(struct_size(tid_config, tid_conf, num_conf),
14559 GFP_KERNEL);
14560 if (!tid_config)
14561 return -ENOMEM;
14562
14563 tid_config->n_tid_conf = num_conf;
14564
14565 if (info->attrs[NL80211_ATTR_MAC])
14566 tid_config->peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
14567
14568 nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
14569 rem_conf) {
14570 ret = nla_parse_nested(attrs, NL80211_TID_CONFIG_ATTR_MAX,
14571 tid, NULL, NULL);
14572
14573 if (ret)
14574 goto bad_tid_conf;
14575
14576 ret = parse_tid_conf(rdev, attrs, dev,
14577 &tid_config->tid_conf[conf_idx],
14578 info, tid_config->peer);
14579 if (ret)
14580 goto bad_tid_conf;
14581
14582 conf_idx++;
14583 }
14584
14585 ret = rdev_set_tid_config(rdev, dev, tid_config);
14586
14587bad_tid_conf:
14588 kfree(tid_config);
14589 return ret;
14590}
14591
4c476991
JB
14592#define NL80211_FLAG_NEED_WIPHY 0x01
14593#define NL80211_FLAG_NEED_NETDEV 0x02
14594#define NL80211_FLAG_NEED_RTNL 0x04
41265714
JB
14595#define NL80211_FLAG_CHECK_NETDEV_UP 0x08
14596#define NL80211_FLAG_NEED_NETDEV_UP (NL80211_FLAG_NEED_NETDEV |\
14597 NL80211_FLAG_CHECK_NETDEV_UP)
1bf614ef 14598#define NL80211_FLAG_NEED_WDEV 0x10
98104fde 14599/* If a netdev is associated, it must be UP, P2P must be started */
1bf614ef
JB
14600#define NL80211_FLAG_NEED_WDEV_UP (NL80211_FLAG_NEED_WDEV |\
14601 NL80211_FLAG_CHECK_NETDEV_UP)
5393b917 14602#define NL80211_FLAG_CLEAR_SKB 0x20
4c476991 14603
f84f771d 14604static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
4c476991
JB
14605 struct genl_info *info)
14606{
14607 struct cfg80211_registered_device *rdev;
89a54e48 14608 struct wireless_dev *wdev;
4c476991 14609 struct net_device *dev;
4c476991
JB
14610 bool rtnl = ops->internal_flags & NL80211_FLAG_NEED_RTNL;
14611
14612 if (rtnl)
14613 rtnl_lock();
14614
14615 if (ops->internal_flags & NL80211_FLAG_NEED_WIPHY) {
4f7eff10 14616 rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
4c476991
JB
14617 if (IS_ERR(rdev)) {
14618 if (rtnl)
14619 rtnl_unlock();
14620 return PTR_ERR(rdev);
14621 }
14622 info->user_ptr[0] = rdev;
1bf614ef
JB
14623 } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV ||
14624 ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
5fe231e8
JB
14625 ASSERT_RTNL();
14626
89a54e48
JB
14627 wdev = __cfg80211_wdev_from_attrs(genl_info_net(info),
14628 info->attrs);
14629 if (IS_ERR(wdev)) {
4c476991
JB
14630 if (rtnl)
14631 rtnl_unlock();
89a54e48 14632 return PTR_ERR(wdev);
4c476991 14633 }
89a54e48 14634
89a54e48 14635 dev = wdev->netdev;
f26cbf40 14636 rdev = wiphy_to_rdev(wdev->wiphy);
89a54e48 14637
1bf614ef
JB
14638 if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
14639 if (!dev) {
1bf614ef
JB
14640 if (rtnl)
14641 rtnl_unlock();
14642 return -EINVAL;
14643 }
14644
14645 info->user_ptr[1] = dev;
14646 } else {
14647 info->user_ptr[1] = wdev;
41265714 14648 }
1bf614ef 14649
73c7da3d
AVS
14650 if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
14651 !wdev_running(wdev)) {
14652 if (rtnl)
14653 rtnl_unlock();
14654 return -ENETDOWN;
14655 }
1bf614ef 14656
73c7da3d 14657 if (dev)
1bf614ef 14658 dev_hold(dev);
89a54e48 14659
4c476991 14660 info->user_ptr[0] = rdev;
4c476991
JB
14661 }
14662
14663 return 0;
14664}
14665
f84f771d 14666static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
4c476991
JB
14667 struct genl_info *info)
14668{
1bf614ef
JB
14669 if (info->user_ptr[1]) {
14670 if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
14671 struct wireless_dev *wdev = info->user_ptr[1];
14672
14673 if (wdev->netdev)
14674 dev_put(wdev->netdev);
14675 } else {
14676 dev_put(info->user_ptr[1]);
14677 }
14678 }
5393b917 14679
4c476991
JB
14680 if (ops->internal_flags & NL80211_FLAG_NEED_RTNL)
14681 rtnl_unlock();
5393b917
JB
14682
14683 /* If needed, clear the netlink message payload from the SKB
14684 * as it might contain key data that shouldn't stick around on
14685 * the heap after the SKB is freed. The netlink message header
14686 * is still needed for further processing, so leave it intact.
14687 */
14688 if (ops->internal_flags & NL80211_FLAG_CLEAR_SKB) {
14689 struct nlmsghdr *nlh = nlmsg_hdr(skb);
14690
14691 memset(nlmsg_data(nlh), 0, nlmsg_len(nlh));
14692 }
4c476991
JB
14693}
14694
4534de83 14695static const struct genl_ops nl80211_ops[] = {
55682965
JB
14696 {
14697 .cmd = NL80211_CMD_GET_WIPHY,
ef6243ac 14698 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965
JB
14699 .doit = nl80211_get_wiphy,
14700 .dumpit = nl80211_dump_wiphy,
86e8cf98 14701 .done = nl80211_dump_wiphy_done,
55682965 14702 /* can be retrieved by unprivileged users */
5fe231e8
JB
14703 .internal_flags = NL80211_FLAG_NEED_WIPHY |
14704 NL80211_FLAG_NEED_RTNL,
55682965 14705 },
66a9b928
JK
14706};
14707
14708static const struct genl_small_ops nl80211_small_ops[] = {
55682965
JB
14709 {
14710 .cmd = NL80211_CMD_SET_WIPHY,
ef6243ac 14711 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 14712 .doit = nl80211_set_wiphy,
5617c6cd 14713 .flags = GENL_UNS_ADMIN_PERM,
4c476991 14714 .internal_flags = NL80211_FLAG_NEED_RTNL,
55682965
JB
14715 },
14716 {
14717 .cmd = NL80211_CMD_GET_INTERFACE,
ef6243ac 14718 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965
JB
14719 .doit = nl80211_get_interface,
14720 .dumpit = nl80211_dump_interface,
55682965 14721 /* can be retrieved by unprivileged users */
5fe231e8
JB
14722 .internal_flags = NL80211_FLAG_NEED_WDEV |
14723 NL80211_FLAG_NEED_RTNL,
55682965
JB
14724 },
14725 {
14726 .cmd = NL80211_CMD_SET_INTERFACE,
ef6243ac 14727 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 14728 .doit = nl80211_set_interface,
5617c6cd 14729 .flags = GENL_UNS_ADMIN_PERM,
4c476991
JB
14730 .internal_flags = NL80211_FLAG_NEED_NETDEV |
14731 NL80211_FLAG_NEED_RTNL,
55682965
JB
14732 },
14733 {
14734 .cmd = NL80211_CMD_NEW_INTERFACE,
ef6243ac 14735 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 14736 .doit = nl80211_new_interface,
5617c6cd 14737 .flags = GENL_UNS_ADMIN_PERM,
4c476991
JB
14738 .internal_flags = NL80211_FLAG_NEED_WIPHY |
14739 NL80211_FLAG_NEED_RTNL,
55682965
JB
14740 },
14741 {
14742 .cmd = NL80211_CMD_DEL_INTERFACE,
ef6243ac 14743 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
55682965 14744 .doit = nl80211_del_interface,
5617c6cd 14745 .flags = GENL_UNS_ADMIN_PERM,
84efbb84 14746 .internal_flags = NL80211_FLAG_NEED_WDEV |
4c476991 14747 NL80211_FLAG_NEED_RTNL,
41ade00f
JB
14748 },
14749 {
14750 .cmd = NL80211_CMD_GET_KEY,
ef6243ac 14751 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 14752 .doit = nl80211_get_key,
5617c6cd 14753 .flags = GENL_UNS_ADMIN_PERM,
2b5f8b0b 14754 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14755 NL80211_FLAG_NEED_RTNL,
41ade00f
JB
14756 },
14757 {
14758 .cmd = NL80211_CMD_SET_KEY,
ef6243ac 14759 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 14760 .doit = nl80211_set_key,
5617c6cd 14761 .flags = GENL_UNS_ADMIN_PERM,
41265714 14762 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
5393b917
JB
14763 NL80211_FLAG_NEED_RTNL |
14764 NL80211_FLAG_CLEAR_SKB,
41ade00f
JB
14765 },
14766 {
14767 .cmd = NL80211_CMD_NEW_KEY,
ef6243ac 14768 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 14769 .doit = nl80211_new_key,
5617c6cd 14770 .flags = GENL_UNS_ADMIN_PERM,
41265714 14771 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
5393b917
JB
14772 NL80211_FLAG_NEED_RTNL |
14773 NL80211_FLAG_CLEAR_SKB,
41ade00f
JB
14774 },
14775 {
14776 .cmd = NL80211_CMD_DEL_KEY,
ef6243ac 14777 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
41ade00f 14778 .doit = nl80211_del_key,
5617c6cd 14779 .flags = GENL_UNS_ADMIN_PERM,
41265714 14780 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14781 NL80211_FLAG_NEED_RTNL,
55682965 14782 },
ed1b6cc7
JB
14783 {
14784 .cmd = NL80211_CMD_SET_BEACON,
ef6243ac 14785 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5617c6cd 14786 .flags = GENL_UNS_ADMIN_PERM,
8860020e 14787 .doit = nl80211_set_beacon,
2b5f8b0b 14788 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14789 NL80211_FLAG_NEED_RTNL,
ed1b6cc7
JB
14790 },
14791 {
8860020e 14792 .cmd = NL80211_CMD_START_AP,
ef6243ac 14793 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5617c6cd 14794 .flags = GENL_UNS_ADMIN_PERM,
8860020e 14795 .doit = nl80211_start_ap,
2b5f8b0b 14796 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14797 NL80211_FLAG_NEED_RTNL,
ed1b6cc7
JB
14798 },
14799 {
8860020e 14800 .cmd = NL80211_CMD_STOP_AP,
ef6243ac 14801 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5617c6cd 14802 .flags = GENL_UNS_ADMIN_PERM,
8860020e 14803 .doit = nl80211_stop_ap,
2b5f8b0b 14804 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14805 NL80211_FLAG_NEED_RTNL,
ed1b6cc7 14806 },
5727ef1b
JB
14807 {
14808 .cmd = NL80211_CMD_GET_STATION,
ef6243ac 14809 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 14810 .doit = nl80211_get_station,
2ec600d6 14811 .dumpit = nl80211_dump_station,
4c476991
JB
14812 .internal_flags = NL80211_FLAG_NEED_NETDEV |
14813 NL80211_FLAG_NEED_RTNL,
5727ef1b
JB
14814 },
14815 {
14816 .cmd = NL80211_CMD_SET_STATION,
ef6243ac 14817 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 14818 .doit = nl80211_set_station,
5617c6cd 14819 .flags = GENL_UNS_ADMIN_PERM,
2b5f8b0b 14820 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14821 NL80211_FLAG_NEED_RTNL,
5727ef1b
JB
14822 },
14823 {
14824 .cmd = NL80211_CMD_NEW_STATION,
ef6243ac 14825 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 14826 .doit = nl80211_new_station,
5617c6cd 14827 .flags = GENL_UNS_ADMIN_PERM,
41265714 14828 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14829 NL80211_FLAG_NEED_RTNL,
5727ef1b
JB
14830 },
14831 {
14832 .cmd = NL80211_CMD_DEL_STATION,
ef6243ac 14833 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5727ef1b 14834 .doit = nl80211_del_station,
5617c6cd 14835 .flags = GENL_UNS_ADMIN_PERM,
2b5f8b0b 14836 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14837 NL80211_FLAG_NEED_RTNL,
2ec600d6
LCC
14838 },
14839 {
14840 .cmd = NL80211_CMD_GET_MPATH,
ef6243ac 14841 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6
LCC
14842 .doit = nl80211_get_mpath,
14843 .dumpit = nl80211_dump_mpath,
5617c6cd 14844 .flags = GENL_UNS_ADMIN_PERM,
41265714 14845 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14846 NL80211_FLAG_NEED_RTNL,
2ec600d6 14847 },
66be7d2b
HR
14848 {
14849 .cmd = NL80211_CMD_GET_MPP,
ef6243ac 14850 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
66be7d2b
HR
14851 .doit = nl80211_get_mpp,
14852 .dumpit = nl80211_dump_mpp,
5617c6cd 14853 .flags = GENL_UNS_ADMIN_PERM,
66be7d2b
HR
14854 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
14855 NL80211_FLAG_NEED_RTNL,
14856 },
2ec600d6
LCC
14857 {
14858 .cmd = NL80211_CMD_SET_MPATH,
ef6243ac 14859 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6 14860 .doit = nl80211_set_mpath,
5617c6cd 14861 .flags = GENL_UNS_ADMIN_PERM,
41265714 14862 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14863 NL80211_FLAG_NEED_RTNL,
2ec600d6
LCC
14864 },
14865 {
14866 .cmd = NL80211_CMD_NEW_MPATH,
ef6243ac 14867 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6 14868 .doit = nl80211_new_mpath,
5617c6cd 14869 .flags = GENL_UNS_ADMIN_PERM,
41265714 14870 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14871 NL80211_FLAG_NEED_RTNL,
2ec600d6
LCC
14872 },
14873 {
14874 .cmd = NL80211_CMD_DEL_MPATH,
ef6243ac 14875 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2ec600d6 14876 .doit = nl80211_del_mpath,
5617c6cd 14877 .flags = GENL_UNS_ADMIN_PERM,
2b5f8b0b 14878 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14879 NL80211_FLAG_NEED_RTNL,
9f1ba906
JM
14880 },
14881 {
14882 .cmd = NL80211_CMD_SET_BSS,
ef6243ac 14883 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9f1ba906 14884 .doit = nl80211_set_bss,
5617c6cd 14885 .flags = GENL_UNS_ADMIN_PERM,
2b5f8b0b 14886 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14887 NL80211_FLAG_NEED_RTNL,
b2e1b302 14888 },
f130347c
LR
14889 {
14890 .cmd = NL80211_CMD_GET_REG,
ef6243ac 14891 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ad30ca2c
AN
14892 .doit = nl80211_get_reg_do,
14893 .dumpit = nl80211_get_reg_dump,
5fe231e8 14894 .internal_flags = NL80211_FLAG_NEED_RTNL,
f130347c
LR
14895 /* can be retrieved by unprivileged users */
14896 },
b6863036 14897#ifdef CONFIG_CFG80211_CRDA_SUPPORT
b2e1b302
LR
14898 {
14899 .cmd = NL80211_CMD_SET_REG,
ef6243ac 14900 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b2e1b302 14901 .doit = nl80211_set_reg,
b2e1b302 14902 .flags = GENL_ADMIN_PERM,
5fe231e8 14903 .internal_flags = NL80211_FLAG_NEED_RTNL,
b2e1b302 14904 },
b6863036 14905#endif
b2e1b302
LR
14906 {
14907 .cmd = NL80211_CMD_REQ_SET_REG,
ef6243ac 14908 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b2e1b302 14909 .doit = nl80211_req_set_reg,
93da9cc1 14910 .flags = GENL_ADMIN_PERM,
14911 },
1ea4ff3e
JB
14912 {
14913 .cmd = NL80211_CMD_RELOAD_REGDB,
ef6243ac 14914 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1ea4ff3e 14915 .doit = nl80211_reload_regdb,
1ea4ff3e
JB
14916 .flags = GENL_ADMIN_PERM,
14917 },
93da9cc1 14918 {
24bdd9f4 14919 .cmd = NL80211_CMD_GET_MESH_CONFIG,
ef6243ac 14920 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
24bdd9f4 14921 .doit = nl80211_get_mesh_config,
93da9cc1 14922 /* can be retrieved by unprivileged users */
2b5f8b0b 14923 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14924 NL80211_FLAG_NEED_RTNL,
93da9cc1 14925 },
14926 {
24bdd9f4 14927 .cmd = NL80211_CMD_SET_MESH_CONFIG,
ef6243ac 14928 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
24bdd9f4 14929 .doit = nl80211_update_mesh_config,
5617c6cd 14930 .flags = GENL_UNS_ADMIN_PERM,
29cbe68c 14931 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14932 NL80211_FLAG_NEED_RTNL,
9aed3cc1 14933 },
2a519311
JB
14934 {
14935 .cmd = NL80211_CMD_TRIGGER_SCAN,
ef6243ac 14936 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2a519311 14937 .doit = nl80211_trigger_scan,
5617c6cd 14938 .flags = GENL_UNS_ADMIN_PERM,
fd014284 14939 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
4c476991 14940 NL80211_FLAG_NEED_RTNL,
2a519311 14941 },
91d3ab46
VK
14942 {
14943 .cmd = NL80211_CMD_ABORT_SCAN,
ef6243ac 14944 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
91d3ab46 14945 .doit = nl80211_abort_scan,
5617c6cd 14946 .flags = GENL_UNS_ADMIN_PERM,
91d3ab46
VK
14947 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
14948 NL80211_FLAG_NEED_RTNL,
14949 },
2a519311
JB
14950 {
14951 .cmd = NL80211_CMD_GET_SCAN,
ef6243ac 14952 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2a519311
JB
14953 .dumpit = nl80211_dump_scan,
14954 },
807f8a8c
LC
14955 {
14956 .cmd = NL80211_CMD_START_SCHED_SCAN,
ef6243ac 14957 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
807f8a8c 14958 .doit = nl80211_start_sched_scan,
5617c6cd 14959 .flags = GENL_UNS_ADMIN_PERM,
807f8a8c
LC
14960 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
14961 NL80211_FLAG_NEED_RTNL,
14962 },
14963 {
14964 .cmd = NL80211_CMD_STOP_SCHED_SCAN,
ef6243ac 14965 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
807f8a8c 14966 .doit = nl80211_stop_sched_scan,
5617c6cd 14967 .flags = GENL_UNS_ADMIN_PERM,
807f8a8c
LC
14968 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
14969 NL80211_FLAG_NEED_RTNL,
14970 },
636a5d36
JM
14971 {
14972 .cmd = NL80211_CMD_AUTHENTICATE,
ef6243ac 14973 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 14974 .doit = nl80211_authenticate,
5617c6cd 14975 .flags = GENL_UNS_ADMIN_PERM,
41265714 14976 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
5393b917
JB
14977 NL80211_FLAG_NEED_RTNL |
14978 NL80211_FLAG_CLEAR_SKB,
636a5d36
JM
14979 },
14980 {
14981 .cmd = NL80211_CMD_ASSOCIATE,
ef6243ac 14982 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 14983 .doit = nl80211_associate,
5617c6cd 14984 .flags = GENL_UNS_ADMIN_PERM,
41265714 14985 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
d6db02a8
SD
14986 NL80211_FLAG_NEED_RTNL |
14987 NL80211_FLAG_CLEAR_SKB,
636a5d36
JM
14988 },
14989 {
14990 .cmd = NL80211_CMD_DEAUTHENTICATE,
ef6243ac 14991 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 14992 .doit = nl80211_deauthenticate,
5617c6cd 14993 .flags = GENL_UNS_ADMIN_PERM,
41265714 14994 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 14995 NL80211_FLAG_NEED_RTNL,
636a5d36
JM
14996 },
14997 {
14998 .cmd = NL80211_CMD_DISASSOCIATE,
ef6243ac 14999 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
636a5d36 15000 .doit = nl80211_disassociate,
5617c6cd 15001 .flags = GENL_UNS_ADMIN_PERM,
41265714 15002 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 15003 NL80211_FLAG_NEED_RTNL,
636a5d36 15004 },
04a773ad
JB
15005 {
15006 .cmd = NL80211_CMD_JOIN_IBSS,
ef6243ac 15007 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
04a773ad 15008 .doit = nl80211_join_ibss,
5617c6cd 15009 .flags = GENL_UNS_ADMIN_PERM,
41265714 15010 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 15011 NL80211_FLAG_NEED_RTNL,
04a773ad
JB
15012 },
15013 {
15014 .cmd = NL80211_CMD_LEAVE_IBSS,
ef6243ac 15015 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
04a773ad 15016 .doit = nl80211_leave_ibss,
5617c6cd 15017 .flags = GENL_UNS_ADMIN_PERM,
41265714 15018 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 15019 NL80211_FLAG_NEED_RTNL,
04a773ad 15020 },
aff89a9b
JB
15021#ifdef CONFIG_NL80211_TESTMODE
15022 {
15023 .cmd = NL80211_CMD_TESTMODE,
ef6243ac 15024 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
aff89a9b 15025 .doit = nl80211_testmode_do,
71063f0e 15026 .dumpit = nl80211_testmode_dump,
5617c6cd 15027 .flags = GENL_UNS_ADMIN_PERM,
4c476991
JB
15028 .internal_flags = NL80211_FLAG_NEED_WIPHY |
15029 NL80211_FLAG_NEED_RTNL,
aff89a9b
JB
15030 },
15031#endif
b23aa676
SO
15032 {
15033 .cmd = NL80211_CMD_CONNECT,
ef6243ac 15034 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b23aa676 15035 .doit = nl80211_connect,
5617c6cd 15036 .flags = GENL_UNS_ADMIN_PERM,
41265714 15037 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
d6db02a8
SD
15038 NL80211_FLAG_NEED_RTNL |
15039 NL80211_FLAG_CLEAR_SKB,
b23aa676 15040 },
088e8df8 15041 {
15042 .cmd = NL80211_CMD_UPDATE_CONNECT_PARAMS,
ef6243ac 15043 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
088e8df8 15044 .doit = nl80211_update_connect_params,
088e8df8 15045 .flags = GENL_ADMIN_PERM,
15046 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
d6db02a8
SD
15047 NL80211_FLAG_NEED_RTNL |
15048 NL80211_FLAG_CLEAR_SKB,
088e8df8 15049 },
b23aa676
SO
15050 {
15051 .cmd = NL80211_CMD_DISCONNECT,
ef6243ac 15052 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
b23aa676 15053 .doit = nl80211_disconnect,
5617c6cd 15054 .flags = GENL_UNS_ADMIN_PERM,
41265714 15055 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 15056 NL80211_FLAG_NEED_RTNL,
b23aa676 15057 },
463d0183
JB
15058 {
15059 .cmd = NL80211_CMD_SET_WIPHY_NETNS,
ef6243ac 15060 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
463d0183 15061 .doit = nl80211_wiphy_netns,
5617c6cd 15062 .flags = GENL_UNS_ADMIN_PERM,
4c476991
JB
15063 .internal_flags = NL80211_FLAG_NEED_WIPHY |
15064 NL80211_FLAG_NEED_RTNL,
463d0183 15065 },
61fa713c
HS
15066 {
15067 .cmd = NL80211_CMD_GET_SURVEY,
ef6243ac 15068 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
61fa713c
HS
15069 .dumpit = nl80211_dump_survey,
15070 },
67fbb16b
SO
15071 {
15072 .cmd = NL80211_CMD_SET_PMKSA,
ef6243ac 15073 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
67fbb16b 15074 .doit = nl80211_setdel_pmksa,
5617c6cd 15075 .flags = GENL_UNS_ADMIN_PERM,
2b5f8b0b 15076 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
d6db02a8
SD
15077 NL80211_FLAG_NEED_RTNL |
15078 NL80211_FLAG_CLEAR_SKB,
67fbb16b
SO
15079 },
15080 {
15081 .cmd = NL80211_CMD_DEL_PMKSA,
ef6243ac 15082 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
67fbb16b 15083 .doit = nl80211_setdel_pmksa,
5617c6cd 15084 .flags = GENL_UNS_ADMIN_PERM,
2b5f8b0b 15085 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 15086 NL80211_FLAG_NEED_RTNL,
67fbb16b
SO
15087 },
15088 {
15089 .cmd = NL80211_CMD_FLUSH_PMKSA,
ef6243ac 15090 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
67fbb16b 15091 .doit = nl80211_flush_pmksa,
5617c6cd 15092 .flags = GENL_UNS_ADMIN_PERM,
2b5f8b0b 15093 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4c476991 15094 NL80211_FLAG_NEED_RTNL,
67fbb16b 15095 },
9588bbd5
JM
15096 {
15097 .cmd = NL80211_CMD_REMAIN_ON_CHANNEL,
ef6243ac 15098 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9588bbd5 15099 .doit = nl80211_remain_on_channel,
5617c6cd 15100 .flags = GENL_UNS_ADMIN_PERM,
71bbc994 15101 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
4c476991 15102 NL80211_FLAG_NEED_RTNL,
9588bbd5
JM
15103 },
15104 {
15105 .cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
ef6243ac 15106 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9588bbd5 15107 .doit = nl80211_cancel_remain_on_channel,
5617c6cd 15108 .flags = GENL_UNS_ADMIN_PERM,
71bbc994 15109 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
4c476991 15110 NL80211_FLAG_NEED_RTNL,
9588bbd5 15111 },
13ae75b1
JM
15112 {
15113 .cmd = NL80211_CMD_SET_TX_BITRATE_MASK,
ef6243ac 15114 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
13ae75b1 15115 .doit = nl80211_set_tx_bitrate_mask,
5617c6cd 15116 .flags = GENL_UNS_ADMIN_PERM,
4c476991
JB
15117 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15118 NL80211_FLAG_NEED_RTNL,
13ae75b1 15119 },
026331c4 15120 {
2e161f78 15121 .cmd = NL80211_CMD_REGISTER_FRAME,
ef6243ac 15122 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2e161f78 15123 .doit = nl80211_register_mgmt,
5617c6cd 15124 .flags = GENL_UNS_ADMIN_PERM,
71bbc994 15125 .internal_flags = NL80211_FLAG_NEED_WDEV |
4c476991 15126 NL80211_FLAG_NEED_RTNL,
026331c4
JM
15127 },
15128 {
2e161f78 15129 .cmd = NL80211_CMD_FRAME,
ef6243ac 15130 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2e161f78 15131 .doit = nl80211_tx_mgmt,
5617c6cd 15132 .flags = GENL_UNS_ADMIN_PERM,
71bbc994 15133 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
f7ca38df
JB
15134 NL80211_FLAG_NEED_RTNL,
15135 },
15136 {
15137 .cmd = NL80211_CMD_FRAME_WAIT_CANCEL,
ef6243ac 15138 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
f7ca38df 15139 .doit = nl80211_tx_mgmt_cancel_wait,
5617c6cd 15140 .flags = GENL_UNS_ADMIN_PERM,
71bbc994 15141 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
4c476991 15142 NL80211_FLAG_NEED_RTNL,
026331c4 15143 },
ffb9eb3d
KV
15144 {
15145 .cmd = NL80211_CMD_SET_POWER_SAVE,
ef6243ac 15146 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ffb9eb3d 15147 .doit = nl80211_set_power_save,
5617c6cd 15148 .flags = GENL_UNS_ADMIN_PERM,
4c476991
JB
15149 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15150 NL80211_FLAG_NEED_RTNL,
ffb9eb3d
KV
15151 },
15152 {
15153 .cmd = NL80211_CMD_GET_POWER_SAVE,
ef6243ac 15154 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ffb9eb3d 15155 .doit = nl80211_get_power_save,
ffb9eb3d 15156 /* can be retrieved by unprivileged users */
4c476991
JB
15157 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15158 NL80211_FLAG_NEED_RTNL,
ffb9eb3d 15159 },
d6dc1a38
JO
15160 {
15161 .cmd = NL80211_CMD_SET_CQM,
ef6243ac 15162 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
d6dc1a38 15163 .doit = nl80211_set_cqm,
5617c6cd 15164 .flags = GENL_UNS_ADMIN_PERM,
4c476991
JB
15165 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15166 NL80211_FLAG_NEED_RTNL,
d6dc1a38 15167 },
f444de05
JB
15168 {
15169 .cmd = NL80211_CMD_SET_CHANNEL,
ef6243ac 15170 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
f444de05 15171 .doit = nl80211_set_channel,
5617c6cd 15172 .flags = GENL_UNS_ADMIN_PERM,
4c476991
JB
15173 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15174 NL80211_FLAG_NEED_RTNL,
f444de05 15175 },
e8347eba
BJ
15176 {
15177 .cmd = NL80211_CMD_SET_WDS_PEER,
ef6243ac 15178 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
e8347eba 15179 .doit = nl80211_set_wds_peer,
5617c6cd 15180 .flags = GENL_UNS_ADMIN_PERM,
43b19952
JB
15181 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15182 NL80211_FLAG_NEED_RTNL,
e8347eba 15183 },
29cbe68c
JB
15184 {
15185 .cmd = NL80211_CMD_JOIN_MESH,
ef6243ac 15186 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
29cbe68c 15187 .doit = nl80211_join_mesh,
5617c6cd 15188 .flags = GENL_UNS_ADMIN_PERM,
29cbe68c
JB
15189 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15190 NL80211_FLAG_NEED_RTNL,
15191 },
15192 {
15193 .cmd = NL80211_CMD_LEAVE_MESH,
ef6243ac 15194 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
29cbe68c 15195 .doit = nl80211_leave_mesh,
5617c6cd 15196 .flags = GENL_UNS_ADMIN_PERM,
29cbe68c
JB
15197 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15198 NL80211_FLAG_NEED_RTNL,
15199 },
6e0bd6c3
RL
15200 {
15201 .cmd = NL80211_CMD_JOIN_OCB,
ef6243ac 15202 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6e0bd6c3 15203 .doit = nl80211_join_ocb,
5617c6cd 15204 .flags = GENL_UNS_ADMIN_PERM,
6e0bd6c3
RL
15205 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15206 NL80211_FLAG_NEED_RTNL,
15207 },
15208 {
15209 .cmd = NL80211_CMD_LEAVE_OCB,
ef6243ac 15210 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6e0bd6c3 15211 .doit = nl80211_leave_ocb,
5617c6cd 15212 .flags = GENL_UNS_ADMIN_PERM,
6e0bd6c3
RL
15213 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15214 NL80211_FLAG_NEED_RTNL,
15215 },
dfb89c56 15216#ifdef CONFIG_PM
ff1b6e69
JB
15217 {
15218 .cmd = NL80211_CMD_GET_WOWLAN,
ef6243ac 15219 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ff1b6e69 15220 .doit = nl80211_get_wowlan,
ff1b6e69
JB
15221 /* can be retrieved by unprivileged users */
15222 .internal_flags = NL80211_FLAG_NEED_WIPHY |
15223 NL80211_FLAG_NEED_RTNL,
15224 },
15225 {
15226 .cmd = NL80211_CMD_SET_WOWLAN,
ef6243ac 15227 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ff1b6e69 15228 .doit = nl80211_set_wowlan,
5617c6cd 15229 .flags = GENL_UNS_ADMIN_PERM,
ff1b6e69
JB
15230 .internal_flags = NL80211_FLAG_NEED_WIPHY |
15231 NL80211_FLAG_NEED_RTNL,
15232 },
dfb89c56 15233#endif
e5497d76
JB
15234 {
15235 .cmd = NL80211_CMD_SET_REKEY_OFFLOAD,
ef6243ac 15236 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
e5497d76 15237 .doit = nl80211_set_rekey_data,
5617c6cd 15238 .flags = GENL_UNS_ADMIN_PERM,
e5497d76 15239 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
5393b917
JB
15240 NL80211_FLAG_NEED_RTNL |
15241 NL80211_FLAG_CLEAR_SKB,
e5497d76 15242 },
109086ce
AN
15243 {
15244 .cmd = NL80211_CMD_TDLS_MGMT,
ef6243ac 15245 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
109086ce 15246 .doit = nl80211_tdls_mgmt,
5617c6cd 15247 .flags = GENL_UNS_ADMIN_PERM,
109086ce
AN
15248 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15249 NL80211_FLAG_NEED_RTNL,
15250 },
15251 {
15252 .cmd = NL80211_CMD_TDLS_OPER,
ef6243ac 15253 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
109086ce 15254 .doit = nl80211_tdls_oper,
5617c6cd 15255 .flags = GENL_UNS_ADMIN_PERM,
109086ce
AN
15256 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15257 NL80211_FLAG_NEED_RTNL,
15258 },
28946da7
JB
15259 {
15260 .cmd = NL80211_CMD_UNEXPECTED_FRAME,
ef6243ac 15261 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
28946da7 15262 .doit = nl80211_register_unexpected_frame,
5617c6cd 15263 .flags = GENL_UNS_ADMIN_PERM,
28946da7
JB
15264 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15265 NL80211_FLAG_NEED_RTNL,
15266 },
7f6cf311
JB
15267 {
15268 .cmd = NL80211_CMD_PROBE_CLIENT,
ef6243ac 15269 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
7f6cf311 15270 .doit = nl80211_probe_client,
5617c6cd 15271 .flags = GENL_UNS_ADMIN_PERM,
2b5f8b0b 15272 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
7f6cf311
JB
15273 NL80211_FLAG_NEED_RTNL,
15274 },
5e760230
JB
15275 {
15276 .cmd = NL80211_CMD_REGISTER_BEACONS,
ef6243ac 15277 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5e760230 15278 .doit = nl80211_register_beacons,
5617c6cd 15279 .flags = GENL_UNS_ADMIN_PERM,
5e760230
JB
15280 .internal_flags = NL80211_FLAG_NEED_WIPHY |
15281 NL80211_FLAG_NEED_RTNL,
15282 },
1d9d9213
SW
15283 {
15284 .cmd = NL80211_CMD_SET_NOACK_MAP,
ef6243ac 15285 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1d9d9213 15286 .doit = nl80211_set_noack_map,
5617c6cd 15287 .flags = GENL_UNS_ADMIN_PERM,
1d9d9213
SW
15288 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15289 NL80211_FLAG_NEED_RTNL,
15290 },
98104fde
JB
15291 {
15292 .cmd = NL80211_CMD_START_P2P_DEVICE,
ef6243ac 15293 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
98104fde 15294 .doit = nl80211_start_p2p_device,
5617c6cd 15295 .flags = GENL_UNS_ADMIN_PERM,
98104fde
JB
15296 .internal_flags = NL80211_FLAG_NEED_WDEV |
15297 NL80211_FLAG_NEED_RTNL,
15298 },
15299 {
15300 .cmd = NL80211_CMD_STOP_P2P_DEVICE,
ef6243ac 15301 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
98104fde 15302 .doit = nl80211_stop_p2p_device,
5617c6cd 15303 .flags = GENL_UNS_ADMIN_PERM,
98104fde
JB
15304 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
15305 NL80211_FLAG_NEED_RTNL,
cb3b7d87
AB
15306 },
15307 {
15308 .cmd = NL80211_CMD_START_NAN,
ef6243ac 15309 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
cb3b7d87 15310 .doit = nl80211_start_nan,
cb3b7d87
AB
15311 .flags = GENL_ADMIN_PERM,
15312 .internal_flags = NL80211_FLAG_NEED_WDEV |
15313 NL80211_FLAG_NEED_RTNL,
15314 },
15315 {
15316 .cmd = NL80211_CMD_STOP_NAN,
ef6243ac 15317 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
cb3b7d87 15318 .doit = nl80211_stop_nan,
cb3b7d87
AB
15319 .flags = GENL_ADMIN_PERM,
15320 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
15321 NL80211_FLAG_NEED_RTNL,
a442b761
AB
15322 },
15323 {
15324 .cmd = NL80211_CMD_ADD_NAN_FUNCTION,
ef6243ac 15325 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
a442b761 15326 .doit = nl80211_nan_add_func,
a442b761
AB
15327 .flags = GENL_ADMIN_PERM,
15328 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
15329 NL80211_FLAG_NEED_RTNL,
15330 },
15331 {
15332 .cmd = NL80211_CMD_DEL_NAN_FUNCTION,
ef6243ac 15333 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
a442b761 15334 .doit = nl80211_nan_del_func,
a442b761
AB
15335 .flags = GENL_ADMIN_PERM,
15336 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
15337 NL80211_FLAG_NEED_RTNL,
a5a9dcf2
AB
15338 },
15339 {
15340 .cmd = NL80211_CMD_CHANGE_NAN_CONFIG,
ef6243ac 15341 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
a5a9dcf2 15342 .doit = nl80211_nan_change_config,
a5a9dcf2
AB
15343 .flags = GENL_ADMIN_PERM,
15344 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
15345 NL80211_FLAG_NEED_RTNL,
98104fde 15346 },
f4e583c8
AQ
15347 {
15348 .cmd = NL80211_CMD_SET_MCAST_RATE,
ef6243ac 15349 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
f4e583c8 15350 .doit = nl80211_set_mcast_rate,
5617c6cd 15351 .flags = GENL_UNS_ADMIN_PERM,
77765eaf
VT
15352 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15353 NL80211_FLAG_NEED_RTNL,
15354 },
15355 {
15356 .cmd = NL80211_CMD_SET_MAC_ACL,
ef6243ac 15357 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
77765eaf 15358 .doit = nl80211_set_mac_acl,
5617c6cd 15359 .flags = GENL_UNS_ADMIN_PERM,
f4e583c8
AQ
15360 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15361 NL80211_FLAG_NEED_RTNL,
15362 },
04f39047
SW
15363 {
15364 .cmd = NL80211_CMD_RADAR_DETECT,
ef6243ac 15365 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
04f39047 15366 .doit = nl80211_start_radar_detection,
5617c6cd 15367 .flags = GENL_UNS_ADMIN_PERM,
04f39047
SW
15368 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15369 NL80211_FLAG_NEED_RTNL,
15370 },
3713b4e3
JB
15371 {
15372 .cmd = NL80211_CMD_GET_PROTOCOL_FEATURES,
ef6243ac 15373 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3713b4e3 15374 .doit = nl80211_get_protocol_features,
3713b4e3 15375 },
355199e0
JM
15376 {
15377 .cmd = NL80211_CMD_UPDATE_FT_IES,
ef6243ac 15378 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
355199e0 15379 .doit = nl80211_update_ft_ies,
5617c6cd 15380 .flags = GENL_UNS_ADMIN_PERM,
355199e0
JM
15381 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15382 NL80211_FLAG_NEED_RTNL,
15383 },
5de17984
AS
15384 {
15385 .cmd = NL80211_CMD_CRIT_PROTOCOL_START,
ef6243ac 15386 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5de17984 15387 .doit = nl80211_crit_protocol_start,
5617c6cd 15388 .flags = GENL_UNS_ADMIN_PERM,
5de17984
AS
15389 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
15390 NL80211_FLAG_NEED_RTNL,
15391 },
15392 {
15393 .cmd = NL80211_CMD_CRIT_PROTOCOL_STOP,
ef6243ac 15394 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5de17984 15395 .doit = nl80211_crit_protocol_stop,
5617c6cd 15396 .flags = GENL_UNS_ADMIN_PERM,
5de17984
AS
15397 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
15398 NL80211_FLAG_NEED_RTNL,
be29b99a
AK
15399 },
15400 {
15401 .cmd = NL80211_CMD_GET_COALESCE,
ef6243ac 15402 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
be29b99a 15403 .doit = nl80211_get_coalesce,
be29b99a
AK
15404 .internal_flags = NL80211_FLAG_NEED_WIPHY |
15405 NL80211_FLAG_NEED_RTNL,
15406 },
15407 {
15408 .cmd = NL80211_CMD_SET_COALESCE,
ef6243ac 15409 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
be29b99a 15410 .doit = nl80211_set_coalesce,
5617c6cd 15411 .flags = GENL_UNS_ADMIN_PERM,
be29b99a
AK
15412 .internal_flags = NL80211_FLAG_NEED_WIPHY |
15413 NL80211_FLAG_NEED_RTNL,
16ef1fe2
SW
15414 },
15415 {
15416 .cmd = NL80211_CMD_CHANNEL_SWITCH,
ef6243ac 15417 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
16ef1fe2 15418 .doit = nl80211_channel_switch,
5617c6cd 15419 .flags = GENL_UNS_ADMIN_PERM,
16ef1fe2
SW
15420 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15421 NL80211_FLAG_NEED_RTNL,
15422 },
ad7e718c
JB
15423 {
15424 .cmd = NL80211_CMD_VENDOR,
ef6243ac 15425 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ad7e718c 15426 .doit = nl80211_vendor_cmd,
7bdbe400 15427 .dumpit = nl80211_vendor_cmd_dump,
5617c6cd 15428 .flags = GENL_UNS_ADMIN_PERM,
ad7e718c 15429 .internal_flags = NL80211_FLAG_NEED_WIPHY |
d6db02a8
SD
15430 NL80211_FLAG_NEED_RTNL |
15431 NL80211_FLAG_CLEAR_SKB,
ad7e718c 15432 },
fa9ffc74
KP
15433 {
15434 .cmd = NL80211_CMD_SET_QOS_MAP,
ef6243ac 15435 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
fa9ffc74 15436 .doit = nl80211_set_qos_map,
5617c6cd 15437 .flags = GENL_UNS_ADMIN_PERM,
fa9ffc74
KP
15438 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15439 NL80211_FLAG_NEED_RTNL,
15440 },
960d01ac
JB
15441 {
15442 .cmd = NL80211_CMD_ADD_TX_TS,
ef6243ac 15443 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
960d01ac 15444 .doit = nl80211_add_tx_ts,
5617c6cd 15445 .flags = GENL_UNS_ADMIN_PERM,
960d01ac
JB
15446 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15447 NL80211_FLAG_NEED_RTNL,
15448 },
15449 {
15450 .cmd = NL80211_CMD_DEL_TX_TS,
ef6243ac 15451 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
960d01ac 15452 .doit = nl80211_del_tx_ts,
5617c6cd 15453 .flags = GENL_UNS_ADMIN_PERM,
960d01ac
JB
15454 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15455 NL80211_FLAG_NEED_RTNL,
15456 },
1057d35e
AN
15457 {
15458 .cmd = NL80211_CMD_TDLS_CHANNEL_SWITCH,
ef6243ac 15459 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1057d35e 15460 .doit = nl80211_tdls_channel_switch,
5617c6cd 15461 .flags = GENL_UNS_ADMIN_PERM,
1057d35e
AN
15462 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15463 NL80211_FLAG_NEED_RTNL,
15464 },
15465 {
15466 .cmd = NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH,
ef6243ac 15467 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1057d35e 15468 .doit = nl80211_tdls_cancel_channel_switch,
5617c6cd 15469 .flags = GENL_UNS_ADMIN_PERM,
1057d35e
AN
15470 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15471 NL80211_FLAG_NEED_RTNL,
15472 },
ce0ce13a
MB
15473 {
15474 .cmd = NL80211_CMD_SET_MULTICAST_TO_UNICAST,
ef6243ac 15475 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
ce0ce13a 15476 .doit = nl80211_set_multicast_to_unicast,
ce0ce13a
MB
15477 .flags = GENL_UNS_ADMIN_PERM,
15478 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15479 NL80211_FLAG_NEED_RTNL,
15480 },
3a00df57
AS
15481 {
15482 .cmd = NL80211_CMD_SET_PMK,
ef6243ac 15483 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3a00df57 15484 .doit = nl80211_set_pmk,
3a00df57 15485 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
d6db02a8
SD
15486 NL80211_FLAG_NEED_RTNL |
15487 NL80211_FLAG_CLEAR_SKB,
3a00df57
AS
15488 },
15489 {
15490 .cmd = NL80211_CMD_DEL_PMK,
ef6243ac 15491 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3a00df57 15492 .doit = nl80211_del_pmk,
3a00df57
AS
15493 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15494 NL80211_FLAG_NEED_RTNL,
15495 },
40cbfa90
SD
15496 {
15497 .cmd = NL80211_CMD_EXTERNAL_AUTH,
ef6243ac 15498 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
40cbfa90 15499 .doit = nl80211_external_auth,
40cbfa90
SD
15500 .flags = GENL_ADMIN_PERM,
15501 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15502 NL80211_FLAG_NEED_RTNL,
15503 },
2576a9ac
DK
15504 {
15505 .cmd = NL80211_CMD_CONTROL_PORT_FRAME,
ef6243ac 15506 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2576a9ac 15507 .doit = nl80211_tx_control_port,
2576a9ac
DK
15508 .flags = GENL_UNS_ADMIN_PERM,
15509 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15510 NL80211_FLAG_NEED_RTNL,
15511 },
81e54d08
PKC
15512 {
15513 .cmd = NL80211_CMD_GET_FTM_RESPONDER_STATS,
ef6243ac 15514 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
81e54d08 15515 .doit = nl80211_get_ftm_responder_stats,
81e54d08
PKC
15516 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15517 NL80211_FLAG_NEED_RTNL,
15518 },
9bb7e0f2
JB
15519 {
15520 .cmd = NL80211_CMD_PEER_MEASUREMENT_START,
ef6243ac 15521 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9bb7e0f2 15522 .doit = nl80211_pmsr_start,
9bb7e0f2
JB
15523 .flags = GENL_UNS_ADMIN_PERM,
15524 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
15525 NL80211_FLAG_NEED_RTNL,
15526 },
30c63115
S
15527 {
15528 .cmd = NL80211_CMD_NOTIFY_RADAR,
ef6243ac 15529 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
30c63115 15530 .doit = nl80211_notify_radar_detection,
30c63115
S
15531 .flags = GENL_UNS_ADMIN_PERM,
15532 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15533 NL80211_FLAG_NEED_RTNL,
15534 },
cb74e977
SD
15535 {
15536 .cmd = NL80211_CMD_UPDATE_OWE_INFO,
15537 .doit = nl80211_update_owe_info,
15538 .flags = GENL_ADMIN_PERM,
5ab92e7f
RM
15539 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15540 NL80211_FLAG_NEED_RTNL,
15541 },
15542 {
15543 .cmd = NL80211_CMD_PROBE_MESH_LINK,
15544 .doit = nl80211_probe_mesh_link,
15545 .flags = GENL_UNS_ADMIN_PERM,
cb74e977
SD
15546 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15547 NL80211_FLAG_NEED_RTNL,
15548 },
77f576de
T
15549 {
15550 .cmd = NL80211_CMD_SET_TID_CONFIG,
15551 .doit = nl80211_set_tid_config,
15552 .flags = GENL_UNS_ADMIN_PERM,
15553 .internal_flags = NL80211_FLAG_NEED_NETDEV |
15554 NL80211_FLAG_NEED_RTNL,
15555 },
55682965 15556};
9588bbd5 15557
56989f6d 15558static struct genl_family nl80211_fam __ro_after_init = {
489111e5
JB
15559 .name = NL80211_GENL_NAME, /* have users key off the name instead */
15560 .hdrsize = 0, /* no private header */
15561 .version = 1, /* no particular meaning now */
15562 .maxattr = NL80211_ATTR_MAX,
3b0f31f2 15563 .policy = nl80211_policy,
489111e5
JB
15564 .netnsok = true,
15565 .pre_doit = nl80211_pre_doit,
15566 .post_doit = nl80211_post_doit,
15567 .module = THIS_MODULE,
15568 .ops = nl80211_ops,
15569 .n_ops = ARRAY_SIZE(nl80211_ops),
66a9b928
JK
15570 .small_ops = nl80211_small_ops,
15571 .n_small_ops = ARRAY_SIZE(nl80211_small_ops),
489111e5
JB
15572 .mcgrps = nl80211_mcgrps,
15573 .n_mcgrps = ARRAY_SIZE(nl80211_mcgrps),
50508d94 15574 .parallel_ops = true,
489111e5
JB
15575};
15576
55682965
JB
15577/* notification functions */
15578
3bb20556
JB
15579void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev,
15580 enum nl80211_commands cmd)
55682965
JB
15581{
15582 struct sk_buff *msg;
86e8cf98 15583 struct nl80211_dump_wiphy_state state = {};
55682965 15584
3bb20556
JB
15585 WARN_ON(cmd != NL80211_CMD_NEW_WIPHY &&
15586 cmd != NL80211_CMD_DEL_WIPHY);
15587
fd2120ca 15588 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
55682965
JB
15589 if (!msg)
15590 return;
15591
3bb20556 15592 if (nl80211_send_wiphy(rdev, cmd, msg, 0, 0, 0, &state) < 0) {
55682965
JB
15593 nlmsg_free(msg);
15594 return;
15595 }
15596
68eb5503 15597 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 15598 NL80211_MCGRP_CONFIG, GFP_KERNEL);
55682965
JB
15599}
15600
896ff063
DK
15601void nl80211_notify_iface(struct cfg80211_registered_device *rdev,
15602 struct wireless_dev *wdev,
15603 enum nl80211_commands cmd)
15604{
15605 struct sk_buff *msg;
15606
896ff063
DK
15607 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
15608 if (!msg)
15609 return;
15610
3d1a5bbf 15611 if (nl80211_send_iface(msg, 0, 0, 0, rdev, wdev, cmd) < 0) {
896ff063
DK
15612 nlmsg_free(msg);
15613 return;
15614 }
15615
15616 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
15617 NL80211_MCGRP_CONFIG, GFP_KERNEL);
15618}
15619
362a415d
JB
15620static int nl80211_add_scan_req(struct sk_buff *msg,
15621 struct cfg80211_registered_device *rdev)
15622{
15623 struct cfg80211_scan_request *req = rdev->scan_req;
15624 struct nlattr *nest;
15625 int i;
c8cb5b85 15626 struct cfg80211_scan_info *info;
362a415d
JB
15627
15628 if (WARN_ON(!req))
15629 return 0;
15630
ae0be8de 15631 nest = nla_nest_start_noflag(msg, NL80211_ATTR_SCAN_SSIDS);
362a415d
JB
15632 if (!nest)
15633 goto nla_put_failure;
9360ffd1
DM
15634 for (i = 0; i < req->n_ssids; i++) {
15635 if (nla_put(msg, i, req->ssids[i].ssid_len, req->ssids[i].ssid))
15636 goto nla_put_failure;
15637 }
362a415d
JB
15638 nla_nest_end(msg, nest);
15639
2032f3b2
TP
15640 if (req->flags & NL80211_SCAN_FLAG_FREQ_KHZ) {
15641 nest = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQ_KHZ);
15642 if (!nest)
15643 goto nla_put_failure;
15644 for (i = 0; i < req->n_channels; i++) {
15645 if (nla_put_u32(msg, i,
15646 ieee80211_channel_to_khz(req->channels[i])))
15647 goto nla_put_failure;
15648 }
15649 nla_nest_end(msg, nest);
15650 } else {
15651 nest = nla_nest_start_noflag(msg,
15652 NL80211_ATTR_SCAN_FREQUENCIES);
15653 if (!nest)
9360ffd1 15654 goto nla_put_failure;
2032f3b2
TP
15655 for (i = 0; i < req->n_channels; i++) {
15656 if (nla_put_u32(msg, i, req->channels[i]->center_freq))
15657 goto nla_put_failure;
15658 }
15659 nla_nest_end(msg, nest);
9360ffd1 15660 }
362a415d 15661
9360ffd1
DM
15662 if (req->ie &&
15663 nla_put(msg, NL80211_ATTR_IE, req->ie_len, req->ie))
15664 goto nla_put_failure;
362a415d 15665
ae917c9f
JB
15666 if (req->flags &&
15667 nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags))
15668 goto nla_put_failure;
ed473771 15669
c8cb5b85
TM
15670 info = rdev->int_scan_req ? &rdev->int_scan_req->info :
15671 &rdev->scan_req->info;
15672 if (info->scan_start_tsf &&
1d76250b 15673 (nla_put_u64_64bit(msg, NL80211_ATTR_SCAN_START_TIME_TSF,
c8cb5b85 15674 info->scan_start_tsf, NL80211_BSS_PAD) ||
1d76250b 15675 nla_put(msg, NL80211_ATTR_SCAN_START_TIME_TSF_BSSID, ETH_ALEN,
c8cb5b85 15676 info->tsf_bssid)))
1d76250b
AS
15677 goto nla_put_failure;
15678
362a415d
JB
15679 return 0;
15680 nla_put_failure:
15681 return -ENOBUFS;
15682}
15683
505a2e88 15684static int nl80211_prep_scan_msg(struct sk_buff *msg,
a538e2d5 15685 struct cfg80211_registered_device *rdev,
fd014284 15686 struct wireless_dev *wdev,
15e47304 15687 u32 portid, u32 seq, int flags,
a538e2d5 15688 u32 cmd)
2a519311
JB
15689{
15690 void *hdr;
15691
15e47304 15692 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
2a519311
JB
15693 if (!hdr)
15694 return -1;
15695
9360ffd1 15696 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
fd014284
JB
15697 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
15698 wdev->netdev->ifindex)) ||
2dad624e
ND
15699 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
15700 NL80211_ATTR_PAD))
9360ffd1 15701 goto nla_put_failure;
2a519311 15702
362a415d
JB
15703 /* ignore errors and send incomplete event anyway */
15704 nl80211_add_scan_req(msg, rdev);
2a519311 15705
053c095a
JB
15706 genlmsg_end(msg, hdr);
15707 return 0;
2a519311
JB
15708
15709 nla_put_failure:
15710 genlmsg_cancel(msg, hdr);
15711 return -EMSGSIZE;
15712}
15713
807f8a8c 15714static int
505a2e88 15715nl80211_prep_sched_scan_msg(struct sk_buff *msg,
96b08fd6 15716 struct cfg80211_sched_scan_request *req, u32 cmd)
807f8a8c
LC
15717{
15718 void *hdr;
15719
96b08fd6 15720 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
807f8a8c
LC
15721 if (!hdr)
15722 return -1;
15723
96b08fd6
AVS
15724 if (nla_put_u32(msg, NL80211_ATTR_WIPHY,
15725 wiphy_to_rdev(req->wiphy)->wiphy_idx) ||
15726 nla_put_u32(msg, NL80211_ATTR_IFINDEX, req->dev->ifindex) ||
15727 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, req->reqid,
15728 NL80211_ATTR_PAD))
9360ffd1 15729 goto nla_put_failure;
807f8a8c 15730
053c095a
JB
15731 genlmsg_end(msg, hdr);
15732 return 0;
807f8a8c
LC
15733
15734 nla_put_failure:
15735 genlmsg_cancel(msg, hdr);
15736 return -EMSGSIZE;
15737}
15738
a538e2d5 15739void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
fd014284 15740 struct wireless_dev *wdev)
a538e2d5
JB
15741{
15742 struct sk_buff *msg;
15743
58050fce 15744 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
a538e2d5
JB
15745 if (!msg)
15746 return;
15747
505a2e88 15748 if (nl80211_prep_scan_msg(msg, rdev, wdev, 0, 0, 0,
a538e2d5
JB
15749 NL80211_CMD_TRIGGER_SCAN) < 0) {
15750 nlmsg_free(msg);
15751 return;
15752 }
15753
68eb5503 15754 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 15755 NL80211_MCGRP_SCAN, GFP_KERNEL);
a538e2d5
JB
15756}
15757
f9d15d16
JB
15758struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
15759 struct wireless_dev *wdev, bool aborted)
2a519311
JB
15760{
15761 struct sk_buff *msg;
15762
fd2120ca 15763 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2a519311 15764 if (!msg)
f9d15d16 15765 return NULL;
2a519311 15766
505a2e88 15767 if (nl80211_prep_scan_msg(msg, rdev, wdev, 0, 0, 0,
f9d15d16
JB
15768 aborted ? NL80211_CMD_SCAN_ABORTED :
15769 NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
2a519311 15770 nlmsg_free(msg);
f9d15d16 15771 return NULL;
2a519311
JB
15772 }
15773
f9d15d16 15774 return msg;
2a519311
JB
15775}
15776
505a2e88
AVS
15777/* send message created by nl80211_build_scan_msg() */
15778void nl80211_send_scan_msg(struct cfg80211_registered_device *rdev,
15779 struct sk_buff *msg)
807f8a8c 15780{
807f8a8c
LC
15781 if (!msg)
15782 return;
15783
68eb5503 15784 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 15785 NL80211_MCGRP_SCAN, GFP_KERNEL);
807f8a8c
LC
15786}
15787
96b08fd6 15788void nl80211_send_sched_scan(struct cfg80211_sched_scan_request *req, u32 cmd)
807f8a8c
LC
15789{
15790 struct sk_buff *msg;
15791
58050fce 15792 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
807f8a8c
LC
15793 if (!msg)
15794 return;
15795
96b08fd6 15796 if (nl80211_prep_sched_scan_msg(msg, req, cmd) < 0) {
807f8a8c
LC
15797 nlmsg_free(msg);
15798 return;
15799 }
15800
96b08fd6 15801 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(req->wiphy), msg, 0,
2a94fe48 15802 NL80211_MCGRP_SCAN, GFP_KERNEL);
807f8a8c
LC
15803}
15804
b0d7aa59
JD
15805static bool nl80211_reg_change_event_fill(struct sk_buff *msg,
15806 struct regulatory_request *request)
73d54c9e 15807{
73d54c9e 15808 /* Userspace can always count this one always being set */
9360ffd1
DM
15809 if (nla_put_u8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator))
15810 goto nla_put_failure;
15811
15812 if (request->alpha2[0] == '0' && request->alpha2[1] == '0') {
15813 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
15814 NL80211_REGDOM_TYPE_WORLD))
15815 goto nla_put_failure;
15816 } else if (request->alpha2[0] == '9' && request->alpha2[1] == '9') {
15817 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
15818 NL80211_REGDOM_TYPE_CUSTOM_WORLD))
15819 goto nla_put_failure;
15820 } else if ((request->alpha2[0] == '9' && request->alpha2[1] == '8') ||
15821 request->intersect) {
15822 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
15823 NL80211_REGDOM_TYPE_INTERSECTION))
15824 goto nla_put_failure;
15825 } else {
15826 if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
15827 NL80211_REGDOM_TYPE_COUNTRY) ||
15828 nla_put_string(msg, NL80211_ATTR_REG_ALPHA2,
15829 request->alpha2))
15830 goto nla_put_failure;
15831 }
15832
ad30ca2c
AN
15833 if (request->wiphy_idx != WIPHY_IDX_INVALID) {
15834 struct wiphy *wiphy = wiphy_idx_to_wiphy(request->wiphy_idx);
15835
15836 if (wiphy &&
15837 nla_put_u32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx))
15838 goto nla_put_failure;
1bdd716c
AN
15839
15840 if (wiphy &&
15841 wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
15842 nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
15843 goto nla_put_failure;
ad30ca2c 15844 }
73d54c9e 15845
b0d7aa59
JD
15846 return true;
15847
15848nla_put_failure:
15849 return false;
15850}
15851
15852/*
15853 * This can happen on global regulatory changes or device specific settings
15854 * based on custom regulatory domains.
15855 */
15856void nl80211_common_reg_change_event(enum nl80211_commands cmd_id,
15857 struct regulatory_request *request)
15858{
15859 struct sk_buff *msg;
15860 void *hdr;
15861
15862 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
15863 if (!msg)
15864 return;
15865
15866 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd_id);
24f6d765 15867 if (!hdr)
15868 goto nla_put_failure;
b0d7aa59 15869
24f6d765 15870 if (!nl80211_reg_change_event_fill(msg, request))
b0d7aa59
JD
15871 goto nla_put_failure;
15872
3b7b72ee 15873 genlmsg_end(msg, hdr);
73d54c9e 15874
bc43b28c 15875 rcu_read_lock();
68eb5503 15876 genlmsg_multicast_allns(&nl80211_fam, msg, 0,
2a94fe48 15877 NL80211_MCGRP_REGULATORY, GFP_ATOMIC);
bc43b28c 15878 rcu_read_unlock();
73d54c9e
LR
15879
15880 return;
15881
15882nla_put_failure:
73d54c9e
LR
15883 nlmsg_free(msg);
15884}
15885
6039f6d2
JM
15886static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
15887 struct net_device *netdev,
15888 const u8 *buf, size_t len,
b0b6aa2c 15889 enum nl80211_commands cmd, gfp_t gfp,
4d9ec73d
JM
15890 int uapsd_queues, const u8 *req_ies,
15891 size_t req_ies_len)
6039f6d2
JM
15892{
15893 struct sk_buff *msg;
15894 void *hdr;
15895
4d9ec73d 15896 msg = nlmsg_new(100 + len + req_ies_len, gfp);
6039f6d2
JM
15897 if (!msg)
15898 return;
15899
15900 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
15901 if (!hdr) {
15902 nlmsg_free(msg);
15903 return;
15904 }
15905
9360ffd1
DM
15906 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
15907 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
4d9ec73d
JM
15908 nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
15909 (req_ies &&
15910 nla_put(msg, NL80211_ATTR_REQ_IE, req_ies_len, req_ies)))
9360ffd1 15911 goto nla_put_failure;
6039f6d2 15912
b0b6aa2c
EP
15913 if (uapsd_queues >= 0) {
15914 struct nlattr *nla_wmm =
ae0be8de 15915 nla_nest_start_noflag(msg, NL80211_ATTR_STA_WME);
b0b6aa2c
EP
15916 if (!nla_wmm)
15917 goto nla_put_failure;
15918
15919 if (nla_put_u8(msg, NL80211_STA_WME_UAPSD_QUEUES,
15920 uapsd_queues))
15921 goto nla_put_failure;
15922
15923 nla_nest_end(msg, nla_wmm);
15924 }
15925
3b7b72ee 15926 genlmsg_end(msg, hdr);
6039f6d2 15927
68eb5503 15928 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 15929 NL80211_MCGRP_MLME, gfp);
6039f6d2
JM
15930 return;
15931
15932 nla_put_failure:
6039f6d2
JM
15933 nlmsg_free(msg);
15934}
15935
15936void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
e6d6e342
JB
15937 struct net_device *netdev, const u8 *buf,
15938 size_t len, gfp_t gfp)
6039f6d2
JM
15939{
15940 nl80211_send_mlme_event(rdev, netdev, buf, len,
4d9ec73d 15941 NL80211_CMD_AUTHENTICATE, gfp, -1, NULL, 0);
6039f6d2
JM
15942}
15943
15944void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
15945 struct net_device *netdev, const u8 *buf,
4d9ec73d
JM
15946 size_t len, gfp_t gfp, int uapsd_queues,
15947 const u8 *req_ies, size_t req_ies_len)
6039f6d2 15948{
e6d6e342 15949 nl80211_send_mlme_event(rdev, netdev, buf, len,
4d9ec73d
JM
15950 NL80211_CMD_ASSOCIATE, gfp, uapsd_queues,
15951 req_ies, req_ies_len);
6039f6d2
JM
15952}
15953
53b46b84 15954void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
e6d6e342
JB
15955 struct net_device *netdev, const u8 *buf,
15956 size_t len, gfp_t gfp)
6039f6d2
JM
15957{
15958 nl80211_send_mlme_event(rdev, netdev, buf, len,
4d9ec73d 15959 NL80211_CMD_DEAUTHENTICATE, gfp, -1, NULL, 0);
6039f6d2
JM
15960}
15961
53b46b84
JM
15962void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
15963 struct net_device *netdev, const u8 *buf,
e6d6e342 15964 size_t len, gfp_t gfp)
6039f6d2
JM
15965{
15966 nl80211_send_mlme_event(rdev, netdev, buf, len,
4d9ec73d 15967 NL80211_CMD_DISASSOCIATE, gfp, -1, NULL, 0);
6039f6d2
JM
15968}
15969
6ff57cf8
JB
15970void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf,
15971 size_t len)
cf4e594e 15972{
947add36
JB
15973 struct wireless_dev *wdev = dev->ieee80211_ptr;
15974 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 15975 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
6ff57cf8
JB
15976 const struct ieee80211_mgmt *mgmt = (void *)buf;
15977 u32 cmd;
947add36 15978
6ff57cf8
JB
15979 if (WARN_ON(len < 2))
15980 return;
cf4e594e 15981
4d797fce 15982 if (ieee80211_is_deauth(mgmt->frame_control)) {
6ff57cf8 15983 cmd = NL80211_CMD_UNPROT_DEAUTHENTICATE;
4d797fce 15984 } else if (ieee80211_is_disassoc(mgmt->frame_control)) {
6ff57cf8 15985 cmd = NL80211_CMD_UNPROT_DISASSOCIATE;
4d797fce
JM
15986 } else if (ieee80211_is_beacon(mgmt->frame_control)) {
15987 if (wdev->unprot_beacon_reported &&
15988 elapsed_jiffies_msecs(wdev->unprot_beacon_reported) < 10000)
15989 return;
15990 cmd = NL80211_CMD_UNPROT_BEACON;
15991 wdev->unprot_beacon_reported = jiffies;
15992 } else {
15993 return;
15994 }
947add36 15995
6ff57cf8 15996 trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len);
4d9ec73d
JM
15997 nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1,
15998 NULL, 0);
cf4e594e 15999}
6ff57cf8 16000EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt);
cf4e594e 16001
1b06bb40
LR
16002static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev,
16003 struct net_device *netdev, int cmd,
e6d6e342 16004 const u8 *addr, gfp_t gfp)
1965c853
JM
16005{
16006 struct sk_buff *msg;
16007 void *hdr;
16008
e6d6e342 16009 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
1965c853
JM
16010 if (!msg)
16011 return;
16012
16013 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
16014 if (!hdr) {
16015 nlmsg_free(msg);
16016 return;
16017 }
16018
9360ffd1
DM
16019 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16020 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
16021 nla_put_flag(msg, NL80211_ATTR_TIMED_OUT) ||
16022 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
16023 goto nla_put_failure;
1965c853 16024
3b7b72ee 16025 genlmsg_end(msg, hdr);
1965c853 16026
68eb5503 16027 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16028 NL80211_MCGRP_MLME, gfp);
1965c853
JM
16029 return;
16030
16031 nla_put_failure:
1965c853
JM
16032 nlmsg_free(msg);
16033}
16034
16035void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
e6d6e342
JB
16036 struct net_device *netdev, const u8 *addr,
16037 gfp_t gfp)
1965c853
JM
16038{
16039 nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_AUTHENTICATE,
e6d6e342 16040 addr, gfp);
1965c853
JM
16041}
16042
16043void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev,
e6d6e342
JB
16044 struct net_device *netdev, const u8 *addr,
16045 gfp_t gfp)
1965c853 16046{
e6d6e342
JB
16047 nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_ASSOCIATE,
16048 addr, gfp);
1965c853
JM
16049}
16050
b23aa676 16051void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
5349a0f7
VK
16052 struct net_device *netdev,
16053 struct cfg80211_connect_resp_params *cr,
3093ebbe 16054 gfp_t gfp)
b23aa676
SO
16055{
16056 struct sk_buff *msg;
16057 void *hdr;
16058
a3caf744 16059 msg = nlmsg_new(100 + cr->req_ie_len + cr->resp_ie_len +
76804d28
AVS
16060 cr->fils.kek_len + cr->fils.pmk_len +
16061 (cr->fils.pmkid ? WLAN_PMKID_LEN : 0), gfp);
b23aa676
SO
16062 if (!msg)
16063 return;
16064
16065 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONNECT);
16066 if (!hdr) {
16067 nlmsg_free(msg);
16068 return;
16069 }
16070
9360ffd1
DM
16071 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16072 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
5349a0f7
VK
16073 (cr->bssid &&
16074 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, cr->bssid)) ||
bf1ecd21 16075 nla_put_u16(msg, NL80211_ATTR_STATUS_CODE,
5349a0f7
VK
16076 cr->status < 0 ? WLAN_STATUS_UNSPECIFIED_FAILURE :
16077 cr->status) ||
16078 (cr->status < 0 &&
3093ebbe 16079 (nla_put_flag(msg, NL80211_ATTR_TIMED_OUT) ||
5349a0f7
VK
16080 nla_put_u32(msg, NL80211_ATTR_TIMEOUT_REASON,
16081 cr->timeout_reason))) ||
16082 (cr->req_ie &&
16083 nla_put(msg, NL80211_ATTR_REQ_IE, cr->req_ie_len, cr->req_ie)) ||
16084 (cr->resp_ie &&
16085 nla_put(msg, NL80211_ATTR_RESP_IE, cr->resp_ie_len,
a3caf744 16086 cr->resp_ie)) ||
76804d28 16087 (cr->fils.update_erp_next_seq_num &&
a3caf744 16088 nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM,
76804d28 16089 cr->fils.erp_next_seq_num)) ||
a3caf744 16090 (cr->status == WLAN_STATUS_SUCCESS &&
76804d28
AVS
16091 ((cr->fils.kek &&
16092 nla_put(msg, NL80211_ATTR_FILS_KEK, cr->fils.kek_len,
16093 cr->fils.kek)) ||
16094 (cr->fils.pmk &&
16095 nla_put(msg, NL80211_ATTR_PMK, cr->fils.pmk_len, cr->fils.pmk)) ||
16096 (cr->fils.pmkid &&
16097 nla_put(msg, NL80211_ATTR_PMKID, WLAN_PMKID_LEN, cr->fils.pmkid)))))
9360ffd1 16098 goto nla_put_failure;
b23aa676 16099
3b7b72ee 16100 genlmsg_end(msg, hdr);
b23aa676 16101
68eb5503 16102 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16103 NL80211_MCGRP_MLME, gfp);
b23aa676
SO
16104 return;
16105
16106 nla_put_failure:
b23aa676 16107 nlmsg_free(msg);
b23aa676
SO
16108}
16109
16110void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
29ce6ecb
AS
16111 struct net_device *netdev,
16112 struct cfg80211_roam_info *info, gfp_t gfp)
b23aa676
SO
16113{
16114 struct sk_buff *msg;
16115 void *hdr;
29ce6ecb 16116 const u8 *bssid = info->bss ? info->bss->bssid : info->bssid;
b23aa676 16117
e841b7b1
AVS
16118 msg = nlmsg_new(100 + info->req_ie_len + info->resp_ie_len +
16119 info->fils.kek_len + info->fils.pmk_len +
16120 (info->fils.pmkid ? WLAN_PMKID_LEN : 0), gfp);
b23aa676
SO
16121 if (!msg)
16122 return;
16123
16124 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ROAM);
16125 if (!hdr) {
16126 nlmsg_free(msg);
16127 return;
16128 }
16129
9360ffd1
DM
16130 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16131 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
16132 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid) ||
29ce6ecb
AS
16133 (info->req_ie &&
16134 nla_put(msg, NL80211_ATTR_REQ_IE, info->req_ie_len,
16135 info->req_ie)) ||
16136 (info->resp_ie &&
16137 nla_put(msg, NL80211_ATTR_RESP_IE, info->resp_ie_len,
e841b7b1
AVS
16138 info->resp_ie)) ||
16139 (info->fils.update_erp_next_seq_num &&
16140 nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM,
16141 info->fils.erp_next_seq_num)) ||
16142 (info->fils.kek &&
16143 nla_put(msg, NL80211_ATTR_FILS_KEK, info->fils.kek_len,
16144 info->fils.kek)) ||
16145 (info->fils.pmk &&
16146 nla_put(msg, NL80211_ATTR_PMK, info->fils.pmk_len, info->fils.pmk)) ||
16147 (info->fils.pmkid &&
16148 nla_put(msg, NL80211_ATTR_PMKID, WLAN_PMKID_LEN, info->fils.pmkid)))
9360ffd1 16149 goto nla_put_failure;
b23aa676 16150
3b7b72ee 16151 genlmsg_end(msg, hdr);
b23aa676 16152
68eb5503 16153 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16154 NL80211_MCGRP_MLME, gfp);
b23aa676
SO
16155 return;
16156
503c1fb9 16157 nla_put_failure:
503c1fb9
AS
16158 nlmsg_free(msg);
16159}
16160
16161void nl80211_send_port_authorized(struct cfg80211_registered_device *rdev,
16162 struct net_device *netdev, const u8 *bssid)
16163{
16164 struct sk_buff *msg;
16165 void *hdr;
16166
16167 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
16168 if (!msg)
16169 return;
16170
16171 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PORT_AUTHORIZED);
16172 if (!hdr) {
16173 nlmsg_free(msg);
16174 return;
16175 }
16176
f4d75993
CHH
16177 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16178 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
16179 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
503c1fb9
AS
16180 goto nla_put_failure;
16181
16182 genlmsg_end(msg, hdr);
16183
16184 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
16185 NL80211_MCGRP_MLME, GFP_KERNEL);
16186 return;
16187
b23aa676 16188 nla_put_failure:
b23aa676 16189 nlmsg_free(msg);
b23aa676
SO
16190}
16191
16192void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
16193 struct net_device *netdev, u16 reason,
667503dd 16194 const u8 *ie, size_t ie_len, bool from_ap)
b23aa676
SO
16195{
16196 struct sk_buff *msg;
16197 void *hdr;
16198
4ef8c1c9 16199 msg = nlmsg_new(100 + ie_len, GFP_KERNEL);
b23aa676
SO
16200 if (!msg)
16201 return;
16202
16203 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DISCONNECT);
16204 if (!hdr) {
16205 nlmsg_free(msg);
16206 return;
16207 }
16208
9360ffd1
DM
16209 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16210 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
86b6c465 16211 (reason &&
9360ffd1
DM
16212 nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason)) ||
16213 (from_ap &&
16214 nla_put_flag(msg, NL80211_ATTR_DISCONNECTED_BY_AP)) ||
16215 (ie && nla_put(msg, NL80211_ATTR_IE, ie_len, ie)))
16216 goto nla_put_failure;
b23aa676 16217
3b7b72ee 16218 genlmsg_end(msg, hdr);
b23aa676 16219
68eb5503 16220 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16221 NL80211_MCGRP_MLME, GFP_KERNEL);
b23aa676
SO
16222 return;
16223
16224 nla_put_failure:
b23aa676 16225 nlmsg_free(msg);
b23aa676
SO
16226}
16227
04a773ad
JB
16228void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
16229 struct net_device *netdev, const u8 *bssid,
16230 gfp_t gfp)
16231{
16232 struct sk_buff *msg;
16233 void *hdr;
16234
fd2120ca 16235 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
04a773ad
JB
16236 if (!msg)
16237 return;
16238
16239 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_JOIN_IBSS);
16240 if (!hdr) {
16241 nlmsg_free(msg);
16242 return;
16243 }
16244
9360ffd1
DM
16245 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16246 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
16247 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
16248 goto nla_put_failure;
04a773ad 16249
3b7b72ee 16250 genlmsg_end(msg, hdr);
04a773ad 16251
68eb5503 16252 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16253 NL80211_MCGRP_MLME, gfp);
04a773ad
JB
16254 return;
16255
16256 nla_put_failure:
04a773ad
JB
16257 nlmsg_free(msg);
16258}
16259
947add36 16260void cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr,
ecbc12ad
BC
16261 const u8 *ie, u8 ie_len,
16262 int sig_dbm, gfp_t gfp)
c93b5e71 16263{
947add36 16264 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 16265 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
c93b5e71
JC
16266 struct sk_buff *msg;
16267 void *hdr;
16268
947add36
JB
16269 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT))
16270 return;
16271
16272 trace_cfg80211_notify_new_peer_candidate(dev, addr);
16273
4ef8c1c9 16274 msg = nlmsg_new(100 + ie_len, gfp);
c93b5e71
JC
16275 if (!msg)
16276 return;
16277
16278 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NEW_PEER_CANDIDATE);
16279 if (!hdr) {
16280 nlmsg_free(msg);
16281 return;
16282 }
16283
9360ffd1 16284 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
947add36
JB
16285 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
16286 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
9360ffd1 16287 (ie_len && ie &&
ecbc12ad
BC
16288 nla_put(msg, NL80211_ATTR_IE, ie_len, ie)) ||
16289 (sig_dbm &&
16290 nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)))
9360ffd1 16291 goto nla_put_failure;
c93b5e71 16292
3b7b72ee 16293 genlmsg_end(msg, hdr);
c93b5e71 16294
68eb5503 16295 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16296 NL80211_MCGRP_MLME, gfp);
c93b5e71
JC
16297 return;
16298
16299 nla_put_failure:
c93b5e71
JC
16300 nlmsg_free(msg);
16301}
947add36 16302EXPORT_SYMBOL(cfg80211_notify_new_peer_candidate);
c93b5e71 16303
a3b8b056
JM
16304void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
16305 struct net_device *netdev, const u8 *addr,
16306 enum nl80211_key_type key_type, int key_id,
e6d6e342 16307 const u8 *tsc, gfp_t gfp)
a3b8b056
JM
16308{
16309 struct sk_buff *msg;
16310 void *hdr;
16311
e6d6e342 16312 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
a3b8b056
JM
16313 if (!msg)
16314 return;
16315
16316 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_MICHAEL_MIC_FAILURE);
16317 if (!hdr) {
16318 nlmsg_free(msg);
16319 return;
16320 }
16321
9360ffd1
DM
16322 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16323 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
16324 (addr && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) ||
16325 nla_put_u32(msg, NL80211_ATTR_KEY_TYPE, key_type) ||
16326 (key_id != -1 &&
16327 nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_id)) ||
16328 (tsc && nla_put(msg, NL80211_ATTR_KEY_SEQ, 6, tsc)))
16329 goto nla_put_failure;
a3b8b056 16330
3b7b72ee 16331 genlmsg_end(msg, hdr);
a3b8b056 16332
68eb5503 16333 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16334 NL80211_MCGRP_MLME, gfp);
a3b8b056
JM
16335 return;
16336
16337 nla_put_failure:
a3b8b056
JM
16338 nlmsg_free(msg);
16339}
16340
6bad8766
LR
16341void nl80211_send_beacon_hint_event(struct wiphy *wiphy,
16342 struct ieee80211_channel *channel_before,
16343 struct ieee80211_channel *channel_after)
16344{
16345 struct sk_buff *msg;
16346 void *hdr;
16347 struct nlattr *nl_freq;
16348
fd2120ca 16349 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
6bad8766
LR
16350 if (!msg)
16351 return;
16352
16353 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_BEACON_HINT);
16354 if (!hdr) {
16355 nlmsg_free(msg);
16356 return;
16357 }
16358
16359 /*
16360 * Since we are applying the beacon hint to a wiphy we know its
16361 * wiphy_idx is valid
16362 */
9360ffd1
DM
16363 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
16364 goto nla_put_failure;
6bad8766
LR
16365
16366 /* Before */
ae0be8de 16367 nl_freq = nla_nest_start_noflag(msg, NL80211_ATTR_FREQ_BEFORE);
6bad8766
LR
16368 if (!nl_freq)
16369 goto nla_put_failure;
50f32718
HD
16370
16371 if (nl80211_msg_put_channel(msg, wiphy, channel_before, false))
6bad8766
LR
16372 goto nla_put_failure;
16373 nla_nest_end(msg, nl_freq);
16374
16375 /* After */
ae0be8de 16376 nl_freq = nla_nest_start_noflag(msg, NL80211_ATTR_FREQ_AFTER);
6bad8766
LR
16377 if (!nl_freq)
16378 goto nla_put_failure;
50f32718
HD
16379
16380 if (nl80211_msg_put_channel(msg, wiphy, channel_after, false))
6bad8766
LR
16381 goto nla_put_failure;
16382 nla_nest_end(msg, nl_freq);
16383
3b7b72ee 16384 genlmsg_end(msg, hdr);
6bad8766 16385
463d0183 16386 rcu_read_lock();
68eb5503 16387 genlmsg_multicast_allns(&nl80211_fam, msg, 0,
2a94fe48 16388 NL80211_MCGRP_REGULATORY, GFP_ATOMIC);
463d0183 16389 rcu_read_unlock();
6bad8766
LR
16390
16391 return;
16392
16393nla_put_failure:
6bad8766
LR
16394 nlmsg_free(msg);
16395}
16396
9588bbd5
JM
16397static void nl80211_send_remain_on_chan_event(
16398 int cmd, struct cfg80211_registered_device *rdev,
71bbc994 16399 struct wireless_dev *wdev, u64 cookie,
9588bbd5 16400 struct ieee80211_channel *chan,
9588bbd5
JM
16401 unsigned int duration, gfp_t gfp)
16402{
16403 struct sk_buff *msg;
16404 void *hdr;
16405
16406 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
16407 if (!msg)
16408 return;
16409
16410 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
16411 if (!hdr) {
16412 nlmsg_free(msg);
16413 return;
16414 }
16415
9360ffd1 16416 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
71bbc994
JB
16417 (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
16418 wdev->netdev->ifindex)) ||
2dad624e
ND
16419 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
16420 NL80211_ATTR_PAD) ||
9360ffd1 16421 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq) ||
42d97a59
JB
16422 nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
16423 NL80211_CHAN_NO_HT) ||
2dad624e
ND
16424 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
16425 NL80211_ATTR_PAD))
9360ffd1 16426 goto nla_put_failure;
9588bbd5 16427
9360ffd1
DM
16428 if (cmd == NL80211_CMD_REMAIN_ON_CHANNEL &&
16429 nla_put_u32(msg, NL80211_ATTR_DURATION, duration))
16430 goto nla_put_failure;
9588bbd5 16431
3b7b72ee 16432 genlmsg_end(msg, hdr);
9588bbd5 16433
68eb5503 16434 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16435 NL80211_MCGRP_MLME, gfp);
9588bbd5
JM
16436 return;
16437
16438 nla_put_failure:
9588bbd5
JM
16439 nlmsg_free(msg);
16440}
16441
947add36
JB
16442void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
16443 struct ieee80211_channel *chan,
16444 unsigned int duration, gfp_t gfp)
9588bbd5 16445{
947add36 16446 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 16447 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
16448
16449 trace_cfg80211_ready_on_channel(wdev, cookie, chan, duration);
9588bbd5 16450 nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL,
71bbc994 16451 rdev, wdev, cookie, chan,
42d97a59 16452 duration, gfp);
9588bbd5 16453}
947add36 16454EXPORT_SYMBOL(cfg80211_ready_on_channel);
9588bbd5 16455
947add36
JB
16456void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
16457 struct ieee80211_channel *chan,
16458 gfp_t gfp)
9588bbd5 16459{
947add36 16460 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 16461 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
16462
16463 trace_cfg80211_ready_on_channel_expired(wdev, cookie, chan);
9588bbd5 16464 nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
42d97a59 16465 rdev, wdev, cookie, chan, 0, gfp);
9588bbd5 16466}
947add36 16467EXPORT_SYMBOL(cfg80211_remain_on_channel_expired);
9588bbd5 16468
1c38c7f2
JP
16469void cfg80211_tx_mgmt_expired(struct wireless_dev *wdev, u64 cookie,
16470 struct ieee80211_channel *chan,
16471 gfp_t gfp)
16472{
16473 struct wiphy *wiphy = wdev->wiphy;
16474 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
16475
16476 trace_cfg80211_tx_mgmt_expired(wdev, cookie, chan);
16477 nl80211_send_remain_on_chan_event(NL80211_CMD_FRAME_WAIT_CANCEL,
16478 rdev, wdev, cookie, chan, 0, gfp);
16479}
16480EXPORT_SYMBOL(cfg80211_tx_mgmt_expired);
16481
947add36
JB
16482void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
16483 struct station_info *sinfo, gfp_t gfp)
98b62183 16484{
947add36 16485 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
f26cbf40 16486 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
98b62183
JB
16487 struct sk_buff *msg;
16488
947add36
JB
16489 trace_cfg80211_new_sta(dev, mac_addr, sinfo);
16490
58050fce 16491 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
98b62183
JB
16492 if (!msg)
16493 return;
16494
cf5ead82 16495 if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION, 0, 0, 0,
66266b3a 16496 rdev, dev, mac_addr, sinfo) < 0) {
98b62183
JB
16497 nlmsg_free(msg);
16498 return;
16499 }
16500
68eb5503 16501 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16502 NL80211_MCGRP_MLME, gfp);
98b62183 16503}
947add36 16504EXPORT_SYMBOL(cfg80211_new_sta);
98b62183 16505
cf5ead82
JB
16506void cfg80211_del_sta_sinfo(struct net_device *dev, const u8 *mac_addr,
16507 struct station_info *sinfo, gfp_t gfp)
ec15e68b 16508{
947add36 16509 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
f26cbf40 16510 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
ec15e68b 16511 struct sk_buff *msg;
73887fd9 16512 struct station_info empty_sinfo = {};
cf5ead82 16513
73887fd9
JB
16514 if (!sinfo)
16515 sinfo = &empty_sinfo;
ec15e68b 16516
947add36
JB
16517 trace_cfg80211_del_sta(dev, mac_addr);
16518
58050fce 16519 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
7ea3e110
JB
16520 if (!msg) {
16521 cfg80211_sinfo_release_content(sinfo);
73887fd9 16522 return;
7ea3e110 16523 }
ec15e68b 16524
cf5ead82 16525 if (nl80211_send_station(msg, NL80211_CMD_DEL_STATION, 0, 0, 0,
57007121 16526 rdev, dev, mac_addr, sinfo) < 0) {
ec15e68b 16527 nlmsg_free(msg);
73887fd9 16528 return;
ec15e68b
JM
16529 }
16530
68eb5503 16531 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16532 NL80211_MCGRP_MLME, gfp);
ec15e68b 16533}
cf5ead82 16534EXPORT_SYMBOL(cfg80211_del_sta_sinfo);
ec15e68b 16535
947add36
JB
16536void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr,
16537 enum nl80211_connect_failed_reason reason,
16538 gfp_t gfp)
ed44a951 16539{
947add36 16540 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
f26cbf40 16541 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
ed44a951
PP
16542 struct sk_buff *msg;
16543 void *hdr;
16544
16545 msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
16546 if (!msg)
16547 return;
16548
16549 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONN_FAILED);
16550 if (!hdr) {
16551 nlmsg_free(msg);
16552 return;
16553 }
16554
16555 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
16556 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) ||
16557 nla_put_u32(msg, NL80211_ATTR_CONN_FAILED_REASON, reason))
16558 goto nla_put_failure;
16559
16560 genlmsg_end(msg, hdr);
16561
68eb5503 16562 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16563 NL80211_MCGRP_MLME, gfp);
ed44a951
PP
16564 return;
16565
16566 nla_put_failure:
ed44a951
PP
16567 nlmsg_free(msg);
16568}
947add36 16569EXPORT_SYMBOL(cfg80211_conn_failed);
ed44a951 16570
b92ab5d8
JB
16571static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd,
16572 const u8 *addr, gfp_t gfp)
28946da7
JB
16573{
16574 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 16575 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
28946da7
JB
16576 struct sk_buff *msg;
16577 void *hdr;
6aa7de05 16578 u32 nlportid = READ_ONCE(wdev->ap_unexpected_nlportid);
28946da7 16579
15e47304 16580 if (!nlportid)
28946da7
JB
16581 return false;
16582
16583 msg = nlmsg_new(100, gfp);
16584 if (!msg)
16585 return true;
16586
b92ab5d8 16587 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
28946da7
JB
16588 if (!hdr) {
16589 nlmsg_free(msg);
16590 return true;
16591 }
16592
9360ffd1
DM
16593 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16594 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
16595 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
16596 goto nla_put_failure;
28946da7 16597
9c90a9f6 16598 genlmsg_end(msg, hdr);
15e47304 16599 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
28946da7
JB
16600 return true;
16601
16602 nla_put_failure:
28946da7
JB
16603 nlmsg_free(msg);
16604 return true;
16605}
16606
947add36
JB
16607bool cfg80211_rx_spurious_frame(struct net_device *dev,
16608 const u8 *addr, gfp_t gfp)
b92ab5d8 16609{
947add36
JB
16610 struct wireless_dev *wdev = dev->ieee80211_ptr;
16611 bool ret;
16612
16613 trace_cfg80211_rx_spurious_frame(dev, addr);
16614
16615 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
16616 wdev->iftype != NL80211_IFTYPE_P2P_GO)) {
16617 trace_cfg80211_return_bool(false);
16618 return false;
16619 }
16620 ret = __nl80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME,
16621 addr, gfp);
16622 trace_cfg80211_return_bool(ret);
16623 return ret;
b92ab5d8 16624}
947add36 16625EXPORT_SYMBOL(cfg80211_rx_spurious_frame);
b92ab5d8 16626
947add36
JB
16627bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
16628 const u8 *addr, gfp_t gfp)
b92ab5d8 16629{
947add36
JB
16630 struct wireless_dev *wdev = dev->ieee80211_ptr;
16631 bool ret;
16632
16633 trace_cfg80211_rx_unexpected_4addr_frame(dev, addr);
16634
16635 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
16636 wdev->iftype != NL80211_IFTYPE_P2P_GO &&
16637 wdev->iftype != NL80211_IFTYPE_AP_VLAN)) {
16638 trace_cfg80211_return_bool(false);
16639 return false;
16640 }
16641 ret = __nl80211_unexpected_frame(dev,
16642 NL80211_CMD_UNEXPECTED_4ADDR_FRAME,
16643 addr, gfp);
16644 trace_cfg80211_return_bool(ret);
16645 return ret;
b92ab5d8 16646}
947add36 16647EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame);
b92ab5d8 16648
2e161f78 16649int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
15e47304 16650 struct wireless_dev *wdev, u32 nlportid,
804483e9 16651 int freq, int sig_dbm,
19504cf5 16652 const u8 *buf, size_t len, u32 flags, gfp_t gfp)
026331c4 16653{
71bbc994 16654 struct net_device *netdev = wdev->netdev;
026331c4
JM
16655 struct sk_buff *msg;
16656 void *hdr;
026331c4 16657
4ef8c1c9 16658 msg = nlmsg_new(100 + len, gfp);
026331c4
JM
16659 if (!msg)
16660 return -ENOMEM;
16661
2e161f78 16662 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME);
026331c4
JM
16663 if (!hdr) {
16664 nlmsg_free(msg);
16665 return -ENOMEM;
16666 }
16667
9360ffd1 16668 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
71bbc994
JB
16669 (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
16670 netdev->ifindex)) ||
2dad624e
ND
16671 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
16672 NL80211_ATTR_PAD) ||
e76fede8 16673 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, KHZ_TO_MHZ(freq)) ||
942ba88b 16674 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET, freq % 1000) ||
9360ffd1
DM
16675 (sig_dbm &&
16676 nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||
19504cf5
VK
16677 nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
16678 (flags &&
16679 nla_put_u32(msg, NL80211_ATTR_RXMGMT_FLAGS, flags)))
9360ffd1 16680 goto nla_put_failure;
026331c4 16681
3b7b72ee 16682 genlmsg_end(msg, hdr);
026331c4 16683
15e47304 16684 return genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
026331c4
JM
16685
16686 nla_put_failure:
026331c4
JM
16687 nlmsg_free(msg);
16688 return -ENOBUFS;
16689}
16690
dca9ca2d
MT
16691static void nl80211_frame_tx_status(struct wireless_dev *wdev, u64 cookie,
16692 const u8 *buf, size_t len, bool ack,
16693 gfp_t gfp, enum nl80211_commands command)
026331c4 16694{
947add36 16695 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 16696 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
71bbc994 16697 struct net_device *netdev = wdev->netdev;
026331c4
JM
16698 struct sk_buff *msg;
16699 void *hdr;
16700
dca9ca2d
MT
16701 if (command == NL80211_CMD_FRAME_TX_STATUS)
16702 trace_cfg80211_mgmt_tx_status(wdev, cookie, ack);
16703 else
16704 trace_cfg80211_control_port_tx_status(wdev, cookie, ack);
947add36 16705
4ef8c1c9 16706 msg = nlmsg_new(100 + len, gfp);
026331c4
JM
16707 if (!msg)
16708 return;
16709
dca9ca2d 16710 hdr = nl80211hdr_put(msg, 0, 0, 0, command);
026331c4
JM
16711 if (!hdr) {
16712 nlmsg_free(msg);
16713 return;
16714 }
16715
9360ffd1 16716 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
71bbc994
JB
16717 (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
16718 netdev->ifindex)) ||
2dad624e
ND
16719 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
16720 NL80211_ATTR_PAD) ||
9360ffd1 16721 nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
2dad624e
ND
16722 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
16723 NL80211_ATTR_PAD) ||
9360ffd1
DM
16724 (ack && nla_put_flag(msg, NL80211_ATTR_ACK)))
16725 goto nla_put_failure;
026331c4 16726
3b7b72ee 16727 genlmsg_end(msg, hdr);
026331c4 16728
68eb5503 16729 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16730 NL80211_MCGRP_MLME, gfp);
026331c4
JM
16731 return;
16732
dca9ca2d 16733nla_put_failure:
026331c4
JM
16734 nlmsg_free(msg);
16735}
dca9ca2d
MT
16736
16737void cfg80211_control_port_tx_status(struct wireless_dev *wdev, u64 cookie,
16738 const u8 *buf, size_t len, bool ack,
16739 gfp_t gfp)
16740{
16741 nl80211_frame_tx_status(wdev, cookie, buf, len, ack, gfp,
16742 NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS);
16743}
16744EXPORT_SYMBOL(cfg80211_control_port_tx_status);
16745
16746void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
16747 const u8 *buf, size_t len, bool ack, gfp_t gfp)
16748{
16749 nl80211_frame_tx_status(wdev, cookie, buf, len, ack, gfp,
16750 NL80211_CMD_FRAME_TX_STATUS);
16751}
947add36 16752EXPORT_SYMBOL(cfg80211_mgmt_tx_status);
026331c4 16753
6a671a50 16754static int __nl80211_rx_control_port(struct net_device *dev,
a948f713 16755 struct sk_buff *skb,
6a671a50
DK
16756 bool unencrypted, gfp_t gfp)
16757{
16758 struct wireless_dev *wdev = dev->ieee80211_ptr;
16759 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
a948f713 16760 struct ethhdr *ehdr = eth_hdr(skb);
8d74a623 16761 const u8 *addr = ehdr->h_source;
a948f713 16762 u16 proto = be16_to_cpu(skb->protocol);
6a671a50
DK
16763 struct sk_buff *msg;
16764 void *hdr;
a948f713
DK
16765 struct nlattr *frame;
16766
6a671a50
DK
16767 u32 nlportid = READ_ONCE(wdev->conn_owner_nlportid);
16768
16769 if (!nlportid)
16770 return -ENOENT;
16771
a948f713 16772 msg = nlmsg_new(100 + skb->len, gfp);
6a671a50
DK
16773 if (!msg)
16774 return -ENOMEM;
16775
16776 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONTROL_PORT_FRAME);
16777 if (!hdr) {
16778 nlmsg_free(msg);
16779 return -ENOBUFS;
16780 }
16781
16782 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16783 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
16784 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
16785 NL80211_ATTR_PAD) ||
8d74a623 16786 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
6a671a50
DK
16787 nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, proto) ||
16788 (unencrypted && nla_put_flag(msg,
16789 NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)))
16790 goto nla_put_failure;
16791
a948f713
DK
16792 frame = nla_reserve(msg, NL80211_ATTR_FRAME, skb->len);
16793 if (!frame)
16794 goto nla_put_failure;
16795
16796 skb_copy_bits(skb, 0, nla_data(frame), skb->len);
6a671a50
DK
16797 genlmsg_end(msg, hdr);
16798
16799 return genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
16800
16801 nla_put_failure:
16802 nlmsg_free(msg);
16803 return -ENOBUFS;
16804}
16805
16806bool cfg80211_rx_control_port(struct net_device *dev,
a948f713 16807 struct sk_buff *skb, bool unencrypted)
6a671a50
DK
16808{
16809 int ret;
16810
a948f713
DK
16811 trace_cfg80211_rx_control_port(dev, skb, unencrypted);
16812 ret = __nl80211_rx_control_port(dev, skb, unencrypted, GFP_ATOMIC);
6a671a50
DK
16813 trace_cfg80211_return_bool(ret == 0);
16814 return ret == 0;
16815}
16816EXPORT_SYMBOL(cfg80211_rx_control_port);
16817
5b97f49d
JB
16818static struct sk_buff *cfg80211_prepare_cqm(struct net_device *dev,
16819 const char *mac, gfp_t gfp)
d6dc1a38 16820{
947add36 16821 struct wireless_dev *wdev = dev->ieee80211_ptr;
5b97f49d
JB
16822 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
16823 struct sk_buff *msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
16824 void **cb;
947add36 16825
d6dc1a38 16826 if (!msg)
5b97f49d 16827 return NULL;
d6dc1a38 16828
5b97f49d
JB
16829 cb = (void **)msg->cb;
16830
16831 cb[0] = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_CQM);
16832 if (!cb[0]) {
d6dc1a38 16833 nlmsg_free(msg);
5b97f49d 16834 return NULL;
d6dc1a38
JO
16835 }
16836
9360ffd1 16837 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
947add36 16838 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
9360ffd1 16839 goto nla_put_failure;
d6dc1a38 16840
5b97f49d 16841 if (mac && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac))
d6dc1a38
JO
16842 goto nla_put_failure;
16843
ae0be8de 16844 cb[1] = nla_nest_start_noflag(msg, NL80211_ATTR_CQM);
5b97f49d 16845 if (!cb[1])
9360ffd1 16846 goto nla_put_failure;
d6dc1a38 16847
5b97f49d 16848 cb[2] = rdev;
d6dc1a38 16849
5b97f49d
JB
16850 return msg;
16851 nla_put_failure:
16852 nlmsg_free(msg);
16853 return NULL;
16854}
16855
16856static void cfg80211_send_cqm(struct sk_buff *msg, gfp_t gfp)
16857{
16858 void **cb = (void **)msg->cb;
16859 struct cfg80211_registered_device *rdev = cb[2];
16860
16861 nla_nest_end(msg, cb[1]);
16862 genlmsg_end(msg, cb[0]);
16863
16864 memset(msg->cb, 0, sizeof(msg->cb));
d6dc1a38 16865
68eb5503 16866 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 16867 NL80211_MCGRP_MLME, gfp);
5b97f49d
JB
16868}
16869
16870void cfg80211_cqm_rssi_notify(struct net_device *dev,
16871 enum nl80211_cqm_rssi_threshold_event rssi_event,
bee427b8 16872 s32 rssi_level, gfp_t gfp)
5b97f49d
JB
16873{
16874 struct sk_buff *msg;
4a4b8169
AZ
16875 struct wireless_dev *wdev = dev->ieee80211_ptr;
16876 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
5b97f49d 16877
bee427b8 16878 trace_cfg80211_cqm_rssi_notify(dev, rssi_event, rssi_level);
5b97f49d 16879
98f03342
JB
16880 if (WARN_ON(rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW &&
16881 rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH))
16882 return;
16883
4a4b8169
AZ
16884 if (wdev->cqm_config) {
16885 wdev->cqm_config->last_rssi_event_value = rssi_level;
16886
16887 cfg80211_cqm_rssi_update(rdev, dev);
16888
16889 if (rssi_level == 0)
16890 rssi_level = wdev->cqm_config->last_rssi_event_value;
16891 }
16892
5b97f49d
JB
16893 msg = cfg80211_prepare_cqm(dev, NULL, gfp);
16894 if (!msg)
16895 return;
16896
16897 if (nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT,
16898 rssi_event))
16899 goto nla_put_failure;
16900
bee427b8
AZ
16901 if (rssi_level && nla_put_s32(msg, NL80211_ATTR_CQM_RSSI_LEVEL,
16902 rssi_level))
16903 goto nla_put_failure;
16904
5b97f49d
JB
16905 cfg80211_send_cqm(msg, gfp);
16906
d6dc1a38
JO
16907 return;
16908
16909 nla_put_failure:
d6dc1a38
JO
16910 nlmsg_free(msg);
16911}
947add36 16912EXPORT_SYMBOL(cfg80211_cqm_rssi_notify);
d6dc1a38 16913
5b97f49d
JB
16914void cfg80211_cqm_txe_notify(struct net_device *dev,
16915 const u8 *peer, u32 num_packets,
16916 u32 rate, u32 intvl, gfp_t gfp)
16917{
16918 struct sk_buff *msg;
16919
16920 msg = cfg80211_prepare_cqm(dev, peer, gfp);
16921 if (!msg)
16922 return;
16923
16924 if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_PKTS, num_packets))
16925 goto nla_put_failure;
16926
16927 if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_RATE, rate))
16928 goto nla_put_failure;
16929
16930 if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_INTVL, intvl))
16931 goto nla_put_failure;
16932
16933 cfg80211_send_cqm(msg, gfp);
16934 return;
16935
16936 nla_put_failure:
16937 nlmsg_free(msg);
16938}
16939EXPORT_SYMBOL(cfg80211_cqm_txe_notify);
16940
16941void cfg80211_cqm_pktloss_notify(struct net_device *dev,
16942 const u8 *peer, u32 num_packets, gfp_t gfp)
16943{
16944 struct sk_buff *msg;
16945
16946 trace_cfg80211_cqm_pktloss_notify(dev, peer, num_packets);
16947
16948 msg = cfg80211_prepare_cqm(dev, peer, gfp);
16949 if (!msg)
16950 return;
16951
16952 if (nla_put_u32(msg, NL80211_ATTR_CQM_PKT_LOSS_EVENT, num_packets))
16953 goto nla_put_failure;
16954
16955 cfg80211_send_cqm(msg, gfp);
16956 return;
16957
16958 nla_put_failure:
16959 nlmsg_free(msg);
16960}
16961EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify);
16962
98f03342
JB
16963void cfg80211_cqm_beacon_loss_notify(struct net_device *dev, gfp_t gfp)
16964{
16965 struct sk_buff *msg;
16966
16967 msg = cfg80211_prepare_cqm(dev, NULL, gfp);
16968 if (!msg)
16969 return;
16970
16971 if (nla_put_flag(msg, NL80211_ATTR_CQM_BEACON_LOSS_EVENT))
16972 goto nla_put_failure;
16973
16974 cfg80211_send_cqm(msg, gfp);
16975 return;
16976
16977 nla_put_failure:
16978 nlmsg_free(msg);
16979}
16980EXPORT_SYMBOL(cfg80211_cqm_beacon_loss_notify);
16981
947add36
JB
16982static void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
16983 struct net_device *netdev, const u8 *bssid,
16984 const u8 *replay_ctr, gfp_t gfp)
e5497d76
JB
16985{
16986 struct sk_buff *msg;
16987 struct nlattr *rekey_attr;
16988 void *hdr;
16989
58050fce 16990 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
e5497d76
JB
16991 if (!msg)
16992 return;
16993
16994 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_REKEY_OFFLOAD);
16995 if (!hdr) {
16996 nlmsg_free(msg);
16997 return;
16998 }
16999
9360ffd1
DM
17000 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17001 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
17002 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
17003 goto nla_put_failure;
e5497d76 17004
ae0be8de 17005 rekey_attr = nla_nest_start_noflag(msg, NL80211_ATTR_REKEY_DATA);
e5497d76
JB
17006 if (!rekey_attr)
17007 goto nla_put_failure;
17008
9360ffd1
DM
17009 if (nla_put(msg, NL80211_REKEY_DATA_REPLAY_CTR,
17010 NL80211_REPLAY_CTR_LEN, replay_ctr))
17011 goto nla_put_failure;
e5497d76
JB
17012
17013 nla_nest_end(msg, rekey_attr);
17014
3b7b72ee 17015 genlmsg_end(msg, hdr);
e5497d76 17016
68eb5503 17017 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17018 NL80211_MCGRP_MLME, gfp);
e5497d76
JB
17019 return;
17020
17021 nla_put_failure:
e5497d76
JB
17022 nlmsg_free(msg);
17023}
17024
947add36
JB
17025void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,
17026 const u8 *replay_ctr, gfp_t gfp)
17027{
17028 struct wireless_dev *wdev = dev->ieee80211_ptr;
17029 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 17030 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
17031
17032 trace_cfg80211_gtk_rekey_notify(dev, bssid);
17033 nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp);
17034}
17035EXPORT_SYMBOL(cfg80211_gtk_rekey_notify);
17036
17037static void
17038nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev,
17039 struct net_device *netdev, int index,
17040 const u8 *bssid, bool preauth, gfp_t gfp)
c9df56b4
JM
17041{
17042 struct sk_buff *msg;
17043 struct nlattr *attr;
17044 void *hdr;
17045
58050fce 17046 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
c9df56b4
JM
17047 if (!msg)
17048 return;
17049
17050 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PMKSA_CANDIDATE);
17051 if (!hdr) {
17052 nlmsg_free(msg);
17053 return;
17054 }
17055
9360ffd1
DM
17056 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17057 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
17058 goto nla_put_failure;
c9df56b4 17059
ae0be8de 17060 attr = nla_nest_start_noflag(msg, NL80211_ATTR_PMKSA_CANDIDATE);
c9df56b4
JM
17061 if (!attr)
17062 goto nla_put_failure;
17063
9360ffd1
DM
17064 if (nla_put_u32(msg, NL80211_PMKSA_CANDIDATE_INDEX, index) ||
17065 nla_put(msg, NL80211_PMKSA_CANDIDATE_BSSID, ETH_ALEN, bssid) ||
17066 (preauth &&
17067 nla_put_flag(msg, NL80211_PMKSA_CANDIDATE_PREAUTH)))
17068 goto nla_put_failure;
c9df56b4
JM
17069
17070 nla_nest_end(msg, attr);
17071
3b7b72ee 17072 genlmsg_end(msg, hdr);
c9df56b4 17073
68eb5503 17074 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17075 NL80211_MCGRP_MLME, gfp);
c9df56b4
JM
17076 return;
17077
17078 nla_put_failure:
c9df56b4
JM
17079 nlmsg_free(msg);
17080}
17081
947add36
JB
17082void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
17083 const u8 *bssid, bool preauth, gfp_t gfp)
17084{
17085 struct wireless_dev *wdev = dev->ieee80211_ptr;
17086 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 17087 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36
JB
17088
17089 trace_cfg80211_pmksa_candidate_notify(dev, index, bssid, preauth);
17090 nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp);
17091}
17092EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
17093
17094static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
17095 struct net_device *netdev,
17096 struct cfg80211_chan_def *chandef,
f8d7552e
LC
17097 gfp_t gfp,
17098 enum nl80211_commands notif,
17099 u8 count)
5314526b
TP
17100{
17101 struct sk_buff *msg;
17102 void *hdr;
17103
58050fce 17104 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
5314526b
TP
17105 if (!msg)
17106 return;
17107
f8d7552e 17108 hdr = nl80211hdr_put(msg, 0, 0, 0, notif);
5314526b
TP
17109 if (!hdr) {
17110 nlmsg_free(msg);
17111 return;
17112 }
17113
683b6d3b
JB
17114 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
17115 goto nla_put_failure;
17116
17117 if (nl80211_send_chandef(msg, chandef))
7eab0f64 17118 goto nla_put_failure;
5314526b 17119
f8d7552e
LC
17120 if ((notif == NL80211_CMD_CH_SWITCH_STARTED_NOTIFY) &&
17121 (nla_put_u32(msg, NL80211_ATTR_CH_SWITCH_COUNT, count)))
17122 goto nla_put_failure;
17123
5314526b
TP
17124 genlmsg_end(msg, hdr);
17125
68eb5503 17126 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17127 NL80211_MCGRP_MLME, gfp);
5314526b
TP
17128 return;
17129
17130 nla_put_failure:
5314526b
TP
17131 nlmsg_free(msg);
17132}
17133
947add36
JB
17134void cfg80211_ch_switch_notify(struct net_device *dev,
17135 struct cfg80211_chan_def *chandef)
84f10708 17136{
947add36
JB
17137 struct wireless_dev *wdev = dev->ieee80211_ptr;
17138 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 17139 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
947add36 17140
e487eaeb 17141 ASSERT_WDEV_LOCK(wdev);
947add36 17142
e487eaeb 17143 trace_cfg80211_ch_switch_notify(dev, chandef);
947add36 17144
9e0e2961 17145 wdev->chandef = *chandef;
96f55f12 17146 wdev->preset_chandef = *chandef;
5dc8cdce
SM
17147
17148 if (wdev->iftype == NL80211_IFTYPE_STATION &&
17149 !WARN_ON(!wdev->current_bss))
0afd425b 17150 cfg80211_update_assoc_bss_entry(wdev, chandef->chan);
5dc8cdce 17151
d34990bb
MV
17152 cfg80211_sched_dfs_chan_update(rdev);
17153
f8d7552e
LC
17154 nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
17155 NL80211_CMD_CH_SWITCH_NOTIFY, 0);
947add36
JB
17156}
17157EXPORT_SYMBOL(cfg80211_ch_switch_notify);
17158
f8d7552e
LC
17159void cfg80211_ch_switch_started_notify(struct net_device *dev,
17160 struct cfg80211_chan_def *chandef,
17161 u8 count)
17162{
17163 struct wireless_dev *wdev = dev->ieee80211_ptr;
17164 struct wiphy *wiphy = wdev->wiphy;
17165 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
17166
17167 trace_cfg80211_ch_switch_started_notify(dev, chandef);
17168
17169 nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
17170 NL80211_CMD_CH_SWITCH_STARTED_NOTIFY, count);
17171}
17172EXPORT_SYMBOL(cfg80211_ch_switch_started_notify);
17173
04f39047
SW
17174void
17175nl80211_radar_notify(struct cfg80211_registered_device *rdev,
d2859df5 17176 const struct cfg80211_chan_def *chandef,
04f39047
SW
17177 enum nl80211_radar_event event,
17178 struct net_device *netdev, gfp_t gfp)
17179{
17180 struct sk_buff *msg;
17181 void *hdr;
17182
17183 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
17184 if (!msg)
17185 return;
17186
17187 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_RADAR_DETECT);
17188 if (!hdr) {
17189 nlmsg_free(msg);
17190 return;
17191 }
17192
17193 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
17194 goto nla_put_failure;
17195
17196 /* NOP and radar events don't need a netdev parameter */
17197 if (netdev) {
17198 struct wireless_dev *wdev = netdev->ieee80211_ptr;
17199
17200 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
2dad624e
ND
17201 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
17202 NL80211_ATTR_PAD))
04f39047
SW
17203 goto nla_put_failure;
17204 }
17205
17206 if (nla_put_u32(msg, NL80211_ATTR_RADAR_EVENT, event))
17207 goto nla_put_failure;
17208
17209 if (nl80211_send_chandef(msg, chandef))
17210 goto nla_put_failure;
17211
9c90a9f6 17212 genlmsg_end(msg, hdr);
04f39047 17213
68eb5503 17214 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17215 NL80211_MCGRP_MLME, gfp);
04f39047
SW
17216 return;
17217
17218 nla_put_failure:
04f39047
SW
17219 nlmsg_free(msg);
17220}
17221
466b9936 17222void cfg80211_sta_opmode_change_notify(struct net_device *dev, const u8 *mac,
17223 struct sta_opmode_info *sta_opmode,
17224 gfp_t gfp)
17225{
17226 struct sk_buff *msg;
17227 struct wireless_dev *wdev = dev->ieee80211_ptr;
17228 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
17229 void *hdr;
17230
17231 if (WARN_ON(!mac))
17232 return;
17233
17234 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
17235 if (!msg)
17236 return;
17237
17238 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STA_OPMODE_CHANGED);
17239 if (!hdr) {
17240 nlmsg_free(msg);
17241 return;
17242 }
17243
17244 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
17245 goto nla_put_failure;
17246
17247 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
17248 goto nla_put_failure;
17249
17250 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac))
17251 goto nla_put_failure;
17252
17253 if ((sta_opmode->changed & STA_OPMODE_SMPS_MODE_CHANGED) &&
17254 nla_put_u8(msg, NL80211_ATTR_SMPS_MODE, sta_opmode->smps_mode))
17255 goto nla_put_failure;
17256
17257 if ((sta_opmode->changed & STA_OPMODE_MAX_BW_CHANGED) &&
0016d320 17258 nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, sta_opmode->bw))
466b9936 17259 goto nla_put_failure;
17260
17261 if ((sta_opmode->changed & STA_OPMODE_N_SS_CHANGED) &&
17262 nla_put_u8(msg, NL80211_ATTR_NSS, sta_opmode->rx_nss))
17263 goto nla_put_failure;
17264
17265 genlmsg_end(msg, hdr);
17266
17267 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
17268 NL80211_MCGRP_MLME, gfp);
17269
17270 return;
17271
17272nla_put_failure:
17273 nlmsg_free(msg);
17274}
17275EXPORT_SYMBOL(cfg80211_sta_opmode_change_notify);
17276
7f6cf311 17277void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
c4b50cd3
VN
17278 u64 cookie, bool acked, s32 ack_signal,
17279 bool is_valid_ack_signal, gfp_t gfp)
7f6cf311
JB
17280{
17281 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 17282 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
7f6cf311
JB
17283 struct sk_buff *msg;
17284 void *hdr;
7f6cf311 17285
4ee3e063
BL
17286 trace_cfg80211_probe_status(dev, addr, cookie, acked);
17287
58050fce 17288 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
4ee3e063 17289
7f6cf311
JB
17290 if (!msg)
17291 return;
17292
17293 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PROBE_CLIENT);
17294 if (!hdr) {
17295 nlmsg_free(msg);
17296 return;
17297 }
17298
9360ffd1
DM
17299 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17300 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
17301 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
2dad624e
ND
17302 nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
17303 NL80211_ATTR_PAD) ||
c4b50cd3
VN
17304 (acked && nla_put_flag(msg, NL80211_ATTR_ACK)) ||
17305 (is_valid_ack_signal && nla_put_s32(msg, NL80211_ATTR_ACK_SIGNAL,
17306 ack_signal)))
9360ffd1 17307 goto nla_put_failure;
7f6cf311 17308
9c90a9f6 17309 genlmsg_end(msg, hdr);
7f6cf311 17310
68eb5503 17311 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17312 NL80211_MCGRP_MLME, gfp);
7f6cf311
JB
17313 return;
17314
17315 nla_put_failure:
7f6cf311
JB
17316 nlmsg_free(msg);
17317}
17318EXPORT_SYMBOL(cfg80211_probe_status);
17319
e76fede8
TP
17320void cfg80211_report_obss_beacon_khz(struct wiphy *wiphy, const u8 *frame,
17321 size_t len, int freq, int sig_dbm)
5e760230 17322{
f26cbf40 17323 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
5e760230
JB
17324 struct sk_buff *msg;
17325 void *hdr;
37c73b5f 17326 struct cfg80211_beacon_registration *reg;
5e760230 17327
4ee3e063
BL
17328 trace_cfg80211_report_obss_beacon(wiphy, frame, len, freq, sig_dbm);
17329
37c73b5f
BG
17330 spin_lock_bh(&rdev->beacon_registrations_lock);
17331 list_for_each_entry(reg, &rdev->beacon_registrations, list) {
17332 msg = nlmsg_new(len + 100, GFP_ATOMIC);
17333 if (!msg) {
17334 spin_unlock_bh(&rdev->beacon_registrations_lock);
17335 return;
17336 }
5e760230 17337
37c73b5f
BG
17338 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME);
17339 if (!hdr)
17340 goto nla_put_failure;
5e760230 17341
37c73b5f
BG
17342 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17343 (freq &&
942ba88b
TP
17344 (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
17345 KHZ_TO_MHZ(freq)) ||
17346 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
17347 freq % 1000))) ||
37c73b5f
BG
17348 (sig_dbm &&
17349 nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||
17350 nla_put(msg, NL80211_ATTR_FRAME, len, frame))
17351 goto nla_put_failure;
5e760230 17352
37c73b5f 17353 genlmsg_end(msg, hdr);
5e760230 17354
37c73b5f
BG
17355 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, reg->nlportid);
17356 }
17357 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230
JB
17358 return;
17359
17360 nla_put_failure:
37c73b5f 17361 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230
JB
17362 nlmsg_free(msg);
17363}
e76fede8 17364EXPORT_SYMBOL(cfg80211_report_obss_beacon_khz);
5e760230 17365
cd8f7cb4 17366#ifdef CONFIG_PM
8cd4d456
LC
17367static int cfg80211_net_detect_results(struct sk_buff *msg,
17368 struct cfg80211_wowlan_wakeup *wakeup)
17369{
17370 struct cfg80211_wowlan_nd_info *nd = wakeup->net_detect;
17371 struct nlattr *nl_results, *nl_match, *nl_freqs;
17372 int i, j;
17373
ae0be8de
MK
17374 nl_results = nla_nest_start_noflag(msg,
17375 NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS);
8cd4d456
LC
17376 if (!nl_results)
17377 return -EMSGSIZE;
17378
17379 for (i = 0; i < nd->n_matches; i++) {
17380 struct cfg80211_wowlan_nd_match *match = nd->matches[i];
17381
ae0be8de 17382 nl_match = nla_nest_start_noflag(msg, i);
8cd4d456
LC
17383 if (!nl_match)
17384 break;
17385
17386 /* The SSID attribute is optional in nl80211, but for
17387 * simplicity reasons it's always present in the
17388 * cfg80211 structure. If a driver can't pass the
17389 * SSID, that needs to be changed. A zero length SSID
17390 * is still a valid SSID (wildcard), so it cannot be
17391 * used for this purpose.
17392 */
17393 if (nla_put(msg, NL80211_ATTR_SSID, match->ssid.ssid_len,
17394 match->ssid.ssid)) {
17395 nla_nest_cancel(msg, nl_match);
17396 goto out;
17397 }
17398
17399 if (match->n_channels) {
ae0be8de
MK
17400 nl_freqs = nla_nest_start_noflag(msg,
17401 NL80211_ATTR_SCAN_FREQUENCIES);
8cd4d456
LC
17402 if (!nl_freqs) {
17403 nla_nest_cancel(msg, nl_match);
17404 goto out;
17405 }
17406
17407 for (j = 0; j < match->n_channels; j++) {
5528fae8 17408 if (nla_put_u32(msg, j, match->channels[j])) {
8cd4d456
LC
17409 nla_nest_cancel(msg, nl_freqs);
17410 nla_nest_cancel(msg, nl_match);
17411 goto out;
17412 }
17413 }
17414
17415 nla_nest_end(msg, nl_freqs);
17416 }
17417
17418 nla_nest_end(msg, nl_match);
17419 }
17420
17421out:
17422 nla_nest_end(msg, nl_results);
17423 return 0;
17424}
17425
cd8f7cb4
JB
17426void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
17427 struct cfg80211_wowlan_wakeup *wakeup,
17428 gfp_t gfp)
17429{
f26cbf40 17430 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
cd8f7cb4
JB
17431 struct sk_buff *msg;
17432 void *hdr;
9c90a9f6 17433 int size = 200;
cd8f7cb4
JB
17434
17435 trace_cfg80211_report_wowlan_wakeup(wdev->wiphy, wdev, wakeup);
17436
17437 if (wakeup)
17438 size += wakeup->packet_present_len;
17439
17440 msg = nlmsg_new(size, gfp);
17441 if (!msg)
17442 return;
17443
17444 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_WOWLAN);
17445 if (!hdr)
17446 goto free_msg;
17447
17448 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
2dad624e
ND
17449 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
17450 NL80211_ATTR_PAD))
cd8f7cb4
JB
17451 goto free_msg;
17452
17453 if (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
17454 wdev->netdev->ifindex))
17455 goto free_msg;
17456
17457 if (wakeup) {
17458 struct nlattr *reasons;
17459
ae0be8de
MK
17460 reasons = nla_nest_start_noflag(msg,
17461 NL80211_ATTR_WOWLAN_TRIGGERS);
7fa322c8
JB
17462 if (!reasons)
17463 goto free_msg;
cd8f7cb4
JB
17464
17465 if (wakeup->disconnect &&
17466 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT))
17467 goto free_msg;
17468 if (wakeup->magic_pkt &&
17469 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT))
17470 goto free_msg;
17471 if (wakeup->gtk_rekey_failure &&
17472 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE))
17473 goto free_msg;
17474 if (wakeup->eap_identity_req &&
17475 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST))
17476 goto free_msg;
17477 if (wakeup->four_way_handshake &&
17478 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE))
17479 goto free_msg;
17480 if (wakeup->rfkill_release &&
17481 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))
17482 goto free_msg;
17483
17484 if (wakeup->pattern_idx >= 0 &&
17485 nla_put_u32(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
17486 wakeup->pattern_idx))
17487 goto free_msg;
17488
ae917c9f
JB
17489 if (wakeup->tcp_match &&
17490 nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH))
17491 goto free_msg;
2a0e047e 17492
ae917c9f
JB
17493 if (wakeup->tcp_connlost &&
17494 nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST))
17495 goto free_msg;
2a0e047e 17496
ae917c9f
JB
17497 if (wakeup->tcp_nomoretokens &&
17498 nla_put_flag(msg,
17499 NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS))
17500 goto free_msg;
2a0e047e 17501
cd8f7cb4
JB
17502 if (wakeup->packet) {
17503 u32 pkt_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211;
17504 u32 len_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN;
17505
17506 if (!wakeup->packet_80211) {
17507 pkt_attr =
17508 NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023;
17509 len_attr =
17510 NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN;
17511 }
17512
17513 if (wakeup->packet_len &&
17514 nla_put_u32(msg, len_attr, wakeup->packet_len))
17515 goto free_msg;
17516
17517 if (nla_put(msg, pkt_attr, wakeup->packet_present_len,
17518 wakeup->packet))
17519 goto free_msg;
17520 }
17521
8cd4d456
LC
17522 if (wakeup->net_detect &&
17523 cfg80211_net_detect_results(msg, wakeup))
17524 goto free_msg;
17525
cd8f7cb4
JB
17526 nla_nest_end(msg, reasons);
17527 }
17528
9c90a9f6 17529 genlmsg_end(msg, hdr);
cd8f7cb4 17530
68eb5503 17531 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17532 NL80211_MCGRP_MLME, gfp);
cd8f7cb4
JB
17533 return;
17534
17535 free_msg:
17536 nlmsg_free(msg);
17537}
17538EXPORT_SYMBOL(cfg80211_report_wowlan_wakeup);
17539#endif
17540
3475b094
JM
17541void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer,
17542 enum nl80211_tdls_operation oper,
17543 u16 reason_code, gfp_t gfp)
17544{
17545 struct wireless_dev *wdev = dev->ieee80211_ptr;
f26cbf40 17546 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
3475b094
JM
17547 struct sk_buff *msg;
17548 void *hdr;
3475b094
JM
17549
17550 trace_cfg80211_tdls_oper_request(wdev->wiphy, dev, peer, oper,
17551 reason_code);
17552
17553 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
17554 if (!msg)
17555 return;
17556
17557 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_TDLS_OPER);
17558 if (!hdr) {
17559 nlmsg_free(msg);
17560 return;
17561 }
17562
17563 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17564 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
17565 nla_put_u8(msg, NL80211_ATTR_TDLS_OPERATION, oper) ||
17566 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer) ||
17567 (reason_code > 0 &&
17568 nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code)))
17569 goto nla_put_failure;
17570
9c90a9f6 17571 genlmsg_end(msg, hdr);
3475b094 17572
68eb5503 17573 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17574 NL80211_MCGRP_MLME, gfp);
3475b094
JM
17575 return;
17576
17577 nla_put_failure:
3475b094
JM
17578 nlmsg_free(msg);
17579}
17580EXPORT_SYMBOL(cfg80211_tdls_oper_request);
17581
026331c4
JM
17582static int nl80211_netlink_notify(struct notifier_block * nb,
17583 unsigned long state,
17584 void *_notify)
17585{
17586 struct netlink_notify *notify = _notify;
17587 struct cfg80211_registered_device *rdev;
17588 struct wireless_dev *wdev;
37c73b5f 17589 struct cfg80211_beacon_registration *reg, *tmp;
026331c4 17590
8f815cdd 17591 if (state != NETLINK_URELEASE || notify->protocol != NETLINK_GENERIC)
026331c4
JM
17592 return NOTIFY_DONE;
17593
17594 rcu_read_lock();
17595
5e760230 17596 list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
ca986ad9 17597 struct cfg80211_sched_scan_request *sched_scan_req;
753aacfd 17598
ca986ad9
AVS
17599 list_for_each_entry_rcu(sched_scan_req,
17600 &rdev->sched_scan_req_list,
17601 list) {
17602 if (sched_scan_req->owner_nlportid == notify->portid) {
17603 sched_scan_req->nl_owner_dead = true;
753aacfd 17604 schedule_work(&rdev->sched_scan_stop_wk);
ca986ad9 17605 }
753aacfd 17606 }
78f22b6a 17607
53873f13 17608 list_for_each_entry_rcu(wdev, &rdev->wiphy.wdev_list, list) {
15e47304 17609 cfg80211_mlme_unregister_socket(wdev, notify->portid);
37c73b5f 17610
ab81007a
JB
17611 if (wdev->owner_nlportid == notify->portid) {
17612 wdev->nl_owner_dead = true;
17613 schedule_work(&rdev->destroy_work);
17614 } else if (wdev->conn_owner_nlportid == notify->portid) {
bd2522b1 17615 schedule_work(&wdev->disconnect_wk);
ab81007a 17616 }
9bb7e0f2
JB
17617
17618 cfg80211_release_pmsr(wdev, notify->portid);
78f22b6a
JB
17619 }
17620
37c73b5f
BG
17621 spin_lock_bh(&rdev->beacon_registrations_lock);
17622 list_for_each_entry_safe(reg, tmp, &rdev->beacon_registrations,
17623 list) {
17624 if (reg->nlportid == notify->portid) {
17625 list_del(&reg->list);
17626 kfree(reg);
17627 break;
17628 }
17629 }
17630 spin_unlock_bh(&rdev->beacon_registrations_lock);
5e760230 17631 }
026331c4
JM
17632
17633 rcu_read_unlock();
17634
05050753
I
17635 /*
17636 * It is possible that the user space process that is controlling the
17637 * indoor setting disappeared, so notify the regulatory core.
17638 */
17639 regulatory_netlink_notify(notify->portid);
6784c7db 17640 return NOTIFY_OK;
026331c4
JM
17641}
17642
17643static struct notifier_block nl80211_netlink_notifier = {
17644 .notifier_call = nl80211_netlink_notify,
17645};
17646
355199e0
JM
17647void cfg80211_ft_event(struct net_device *netdev,
17648 struct cfg80211_ft_event_params *ft_event)
17649{
17650 struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy;
f26cbf40 17651 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
355199e0
JM
17652 struct sk_buff *msg;
17653 void *hdr;
355199e0
JM
17654
17655 trace_cfg80211_ft_event(wiphy, netdev, ft_event);
17656
17657 if (!ft_event->target_ap)
17658 return;
17659
1039d081
DL
17660 msg = nlmsg_new(100 + ft_event->ies_len + ft_event->ric_ies_len,
17661 GFP_KERNEL);
355199e0
JM
17662 if (!msg)
17663 return;
17664
17665 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FT_EVENT);
ae917c9f
JB
17666 if (!hdr)
17667 goto out;
355199e0 17668
ae917c9f
JB
17669 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17670 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
17671 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ft_event->target_ap))
17672 goto out;
355199e0 17673
ae917c9f
JB
17674 if (ft_event->ies &&
17675 nla_put(msg, NL80211_ATTR_IE, ft_event->ies_len, ft_event->ies))
17676 goto out;
17677 if (ft_event->ric_ies &&
17678 nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len,
17679 ft_event->ric_ies))
17680 goto out;
355199e0 17681
9c90a9f6 17682 genlmsg_end(msg, hdr);
355199e0 17683
68eb5503 17684 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
2a94fe48 17685 NL80211_MCGRP_MLME, GFP_KERNEL);
ae917c9f
JB
17686 return;
17687 out:
17688 nlmsg_free(msg);
355199e0
JM
17689}
17690EXPORT_SYMBOL(cfg80211_ft_event);
17691
5de17984
AS
17692void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp)
17693{
17694 struct cfg80211_registered_device *rdev;
17695 struct sk_buff *msg;
17696 void *hdr;
17697 u32 nlportid;
17698
f26cbf40 17699 rdev = wiphy_to_rdev(wdev->wiphy);
5de17984
AS
17700 if (!rdev->crit_proto_nlportid)
17701 return;
17702
17703 nlportid = rdev->crit_proto_nlportid;
17704 rdev->crit_proto_nlportid = 0;
17705
17706 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
17707 if (!msg)
17708 return;
17709
17710 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CRIT_PROTOCOL_STOP);
17711 if (!hdr)
17712 goto nla_put_failure;
17713
17714 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
2dad624e
ND
17715 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
17716 NL80211_ATTR_PAD))
5de17984
AS
17717 goto nla_put_failure;
17718
17719 genlmsg_end(msg, hdr);
17720
17721 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
17722 return;
17723
17724 nla_put_failure:
5de17984 17725 nlmsg_free(msg);
5de17984
AS
17726}
17727EXPORT_SYMBOL(cfg80211_crit_proto_stopped);
17728
348baf0e
JB
17729void nl80211_send_ap_stopped(struct wireless_dev *wdev)
17730{
17731 struct wiphy *wiphy = wdev->wiphy;
f26cbf40 17732 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
348baf0e
JB
17733 struct sk_buff *msg;
17734 void *hdr;
17735
17736 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
17737 if (!msg)
17738 return;
17739
17740 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STOP_AP);
17741 if (!hdr)
17742 goto out;
17743
17744 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17745 nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) ||
2dad624e
ND
17746 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
17747 NL80211_ATTR_PAD))
348baf0e
JB
17748 goto out;
17749
17750 genlmsg_end(msg, hdr);
17751
17752 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0,
17753 NL80211_MCGRP_MLME, GFP_KERNEL);
17754 return;
17755 out:
17756 nlmsg_free(msg);
17757}
17758
40cbfa90
SD
17759int cfg80211_external_auth_request(struct net_device *dev,
17760 struct cfg80211_external_auth_params *params,
17761 gfp_t gfp)
17762{
17763 struct wireless_dev *wdev = dev->ieee80211_ptr;
17764 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
17765 struct sk_buff *msg;
17766 void *hdr;
17767
17768 if (!wdev->conn_owner_nlportid)
17769 return -EINVAL;
17770
17771 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
17772 if (!msg)
17773 return -ENOMEM;
17774
17775 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_EXTERNAL_AUTH);
17776 if (!hdr)
17777 goto nla_put_failure;
17778
17779 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17780 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
17781 nla_put_u32(msg, NL80211_ATTR_AKM_SUITES, params->key_mgmt_suite) ||
17782 nla_put_u32(msg, NL80211_ATTR_EXTERNAL_AUTH_ACTION,
17783 params->action) ||
17784 nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, params->bssid) ||
17785 nla_put(msg, NL80211_ATTR_SSID, params->ssid.ssid_len,
17786 params->ssid.ssid))
17787 goto nla_put_failure;
17788
17789 genlmsg_end(msg, hdr);
17790 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
17791 wdev->conn_owner_nlportid);
17792 return 0;
17793
17794 nla_put_failure:
17795 nlmsg_free(msg);
17796 return -ENOBUFS;
17797}
17798EXPORT_SYMBOL(cfg80211_external_auth_request);
17799
cb74e977
SD
17800void cfg80211_update_owe_info_event(struct net_device *netdev,
17801 struct cfg80211_update_owe_info *owe_info,
17802 gfp_t gfp)
17803{
17804 struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy;
17805 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
17806 struct sk_buff *msg;
17807 void *hdr;
17808
17809 trace_cfg80211_update_owe_info_event(wiphy, netdev, owe_info);
17810
17811 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
17812 if (!msg)
17813 return;
17814
17815 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_UPDATE_OWE_INFO);
17816 if (!hdr)
17817 goto nla_put_failure;
17818
17819 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
17820 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
17821 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, owe_info->peer))
17822 goto nla_put_failure;
17823
17824 if (!owe_info->ie_len ||
17825 nla_put(msg, NL80211_ATTR_IE, owe_info->ie_len, owe_info->ie))
17826 goto nla_put_failure;
17827
17828 genlmsg_end(msg, hdr);
17829
17830 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
17831 NL80211_MCGRP_MLME, gfp);
17832 return;
17833
17834nla_put_failure:
17835 genlmsg_cancel(msg, hdr);
17836 nlmsg_free(msg);
17837}
17838EXPORT_SYMBOL(cfg80211_update_owe_info_event);
17839
55682965
JB
17840/* initialisation/exit functions */
17841
56989f6d 17842int __init nl80211_init(void)
55682965 17843{
0d63cbb5 17844 int err;
55682965 17845
489111e5 17846 err = genl_register_family(&nl80211_fam);
55682965
JB
17847 if (err)
17848 return err;
17849
026331c4
JM
17850 err = netlink_register_notifier(&nl80211_netlink_notifier);
17851 if (err)
17852 goto err_out;
17853
55682965
JB
17854 return 0;
17855 err_out:
17856 genl_unregister_family(&nl80211_fam);
17857 return err;
17858}
17859
17860void nl80211_exit(void)
17861{
026331c4 17862 netlink_unregister_notifier(&nl80211_netlink_notifier);
55682965
JB
17863 genl_unregister_family(&nl80211_fam);
17864}