hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/net/wireless/nl80211.c
....@@ -1,10 +1,11 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * This is the new netlink-based wireless configuration interface.
34 *
45 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
56 * Copyright 2013-2014 Intel Mobile Communications GmbH
67 * Copyright 2015-2017 Intel Deutschland GmbH
7
- * Copyright (C) 2018 Intel Corporation
8
+ * Copyright (C) 2018-2021 Intel Corporation
89 */
910
1011 #include <linux/if.h>
....@@ -19,6 +20,7 @@
1920 #include <linux/netlink.h>
2021 #include <linux/nospec.h>
2122 #include <linux/etherdevice.h>
23
+#include <linux/if_vlan.h>
2224 #include <net/net_namespace.h>
2325 #include <net/genetlink.h>
2426 #include <net/cfg80211.h>
....@@ -207,14 +209,27 @@
207209 unsigned int len = nla_len(attr);
208210 const struct element *elem;
209211 const struct ieee80211_mgmt *mgmt = (void *)data;
210
- unsigned int fixedlen = offsetof(struct ieee80211_mgmt,
211
- u.beacon.variable);
212
+ unsigned int fixedlen, hdrlen;
213
+ bool s1g_bcn;
214
+
215
+ if (len < offsetofend(typeof(*mgmt), frame_control))
216
+ goto err;
217
+
218
+ s1g_bcn = ieee80211_is_s1g_beacon(mgmt->frame_control);
219
+ if (s1g_bcn) {
220
+ fixedlen = offsetof(struct ieee80211_ext,
221
+ u.s1g_beacon.variable);
222
+ hdrlen = offsetof(struct ieee80211_ext, u.s1g_beacon);
223
+ } else {
224
+ fixedlen = offsetof(struct ieee80211_mgmt,
225
+ u.beacon.variable);
226
+ hdrlen = offsetof(struct ieee80211_mgmt, u.beacon);
227
+ }
212228
213229 if (len < fixedlen)
214230 goto err;
215231
216
- if (ieee80211_hdrlen(mgmt->frame_control) !=
217
- offsetof(struct ieee80211_mgmt, u.beacon))
232
+ if (ieee80211_hdrlen(mgmt->frame_control) != hdrlen)
218233 goto err;
219234
220235 data += fixedlen;
....@@ -232,8 +247,164 @@
232247 return -EINVAL;
233248 }
234249
250
+static int validate_ie_attr(const struct nlattr *attr,
251
+ struct netlink_ext_ack *extack)
252
+{
253
+ const u8 *data = nla_data(attr);
254
+ unsigned int len = nla_len(attr);
255
+ const struct element *elem;
256
+
257
+ for_each_element(elem, data, len) {
258
+ /* nothing */
259
+ }
260
+
261
+ if (for_each_element_completed(elem, data, len))
262
+ return 0;
263
+
264
+ NL_SET_ERR_MSG_ATTR(extack, attr, "malformed information elements");
265
+ return -EINVAL;
266
+}
267
+
235268 /* policy for the attributes */
269
+static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR];
270
+
271
+static const struct nla_policy
272
+nl80211_ftm_responder_policy[NL80211_FTM_RESP_ATTR_MAX + 1] = {
273
+ [NL80211_FTM_RESP_ATTR_ENABLED] = { .type = NLA_FLAG, },
274
+ [NL80211_FTM_RESP_ATTR_LCI] = { .type = NLA_BINARY,
275
+ .len = U8_MAX },
276
+ [NL80211_FTM_RESP_ATTR_CIVICLOC] = { .type = NLA_BINARY,
277
+ .len = U8_MAX },
278
+};
279
+
280
+static const struct nla_policy
281
+nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = {
282
+ [NL80211_PMSR_FTM_REQ_ATTR_ASAP] = { .type = NLA_FLAG },
283
+ [NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE] = { .type = NLA_U32 },
284
+ [NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP] =
285
+ NLA_POLICY_MAX(NLA_U8, 15),
286
+ [NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD] = { .type = NLA_U16 },
287
+ [NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION] =
288
+ NLA_POLICY_MAX(NLA_U8, 15),
289
+ [NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST] =
290
+ NLA_POLICY_MAX(NLA_U8, 31),
291
+ [NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES] = { .type = NLA_U8 },
292
+ [NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI] = { .type = NLA_FLAG },
293
+ [NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC] = { .type = NLA_FLAG },
294
+ [NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED] = { .type = NLA_FLAG },
295
+ [NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED] = { .type = NLA_FLAG },
296
+};
297
+
298
+static const struct nla_policy
299
+nl80211_pmsr_req_data_policy[NL80211_PMSR_TYPE_MAX + 1] = {
300
+ [NL80211_PMSR_TYPE_FTM] =
301
+ NLA_POLICY_NESTED(nl80211_pmsr_ftm_req_attr_policy),
302
+};
303
+
304
+static const struct nla_policy
305
+nl80211_pmsr_req_attr_policy[NL80211_PMSR_REQ_ATTR_MAX + 1] = {
306
+ [NL80211_PMSR_REQ_ATTR_DATA] =
307
+ NLA_POLICY_NESTED(nl80211_pmsr_req_data_policy),
308
+ [NL80211_PMSR_REQ_ATTR_GET_AP_TSF] = { .type = NLA_FLAG },
309
+};
310
+
311
+static const struct nla_policy
312
+nl80211_psmr_peer_attr_policy[NL80211_PMSR_PEER_ATTR_MAX + 1] = {
313
+ [NL80211_PMSR_PEER_ATTR_ADDR] = NLA_POLICY_ETH_ADDR,
314
+ [NL80211_PMSR_PEER_ATTR_CHAN] = NLA_POLICY_NESTED(nl80211_policy),
315
+ [NL80211_PMSR_PEER_ATTR_REQ] =
316
+ NLA_POLICY_NESTED(nl80211_pmsr_req_attr_policy),
317
+ [NL80211_PMSR_PEER_ATTR_RESP] = { .type = NLA_REJECT },
318
+};
319
+
320
+static const struct nla_policy
321
+nl80211_pmsr_attr_policy[NL80211_PMSR_ATTR_MAX + 1] = {
322
+ [NL80211_PMSR_ATTR_MAX_PEERS] = { .type = NLA_REJECT },
323
+ [NL80211_PMSR_ATTR_REPORT_AP_TSF] = { .type = NLA_REJECT },
324
+ [NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR] = { .type = NLA_REJECT },
325
+ [NL80211_PMSR_ATTR_TYPE_CAPA] = { .type = NLA_REJECT },
326
+ [NL80211_PMSR_ATTR_PEERS] =
327
+ NLA_POLICY_NESTED_ARRAY(nl80211_psmr_peer_attr_policy),
328
+};
329
+
330
+static const struct nla_policy
331
+he_obss_pd_policy[NL80211_HE_OBSS_PD_ATTR_MAX + 1] = {
332
+ [NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET] =
333
+ NLA_POLICY_RANGE(NLA_U8, 1, 20),
334
+ [NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET] =
335
+ NLA_POLICY_RANGE(NLA_U8, 1, 20),
336
+ [NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET] =
337
+ NLA_POLICY_RANGE(NLA_U8, 1, 20),
338
+ [NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP] =
339
+ NLA_POLICY_EXACT_LEN(8),
340
+ [NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP] =
341
+ NLA_POLICY_EXACT_LEN(8),
342
+ [NL80211_HE_OBSS_PD_ATTR_SR_CTRL] = { .type = NLA_U8 },
343
+};
344
+
345
+static const struct nla_policy
346
+he_bss_color_policy[NL80211_HE_BSS_COLOR_ATTR_MAX + 1] = {
347
+ [NL80211_HE_BSS_COLOR_ATTR_COLOR] = NLA_POLICY_RANGE(NLA_U8, 1, 63),
348
+ [NL80211_HE_BSS_COLOR_ATTR_DISABLED] = { .type = NLA_FLAG },
349
+ [NL80211_HE_BSS_COLOR_ATTR_PARTIAL] = { .type = NLA_FLAG },
350
+};
351
+
352
+static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = {
353
+ [NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY,
354
+ .len = NL80211_MAX_SUPP_RATES },
355
+ [NL80211_TXRATE_HT] = { .type = NLA_BINARY,
356
+ .len = NL80211_MAX_SUPP_HT_RATES },
357
+ [NL80211_TXRATE_VHT] = NLA_POLICY_EXACT_LEN_WARN(sizeof(struct nl80211_txrate_vht)),
358
+ [NL80211_TXRATE_GI] = { .type = NLA_U8 },
359
+ [NL80211_TXRATE_HE] = NLA_POLICY_EXACT_LEN(sizeof(struct nl80211_txrate_he)),
360
+ [NL80211_TXRATE_HE_GI] = NLA_POLICY_RANGE(NLA_U8,
361
+ NL80211_RATE_INFO_HE_GI_0_8,
362
+ NL80211_RATE_INFO_HE_GI_3_2),
363
+ [NL80211_TXRATE_HE_LTF] = NLA_POLICY_RANGE(NLA_U8,
364
+ NL80211_RATE_INFO_HE_1XLTF,
365
+ NL80211_RATE_INFO_HE_4XLTF),
366
+};
367
+
368
+static const struct nla_policy
369
+nl80211_tid_config_attr_policy[NL80211_TID_CONFIG_ATTR_MAX + 1] = {
370
+ [NL80211_TID_CONFIG_ATTR_VIF_SUPP] = { .type = NLA_U64 },
371
+ [NL80211_TID_CONFIG_ATTR_PEER_SUPP] = { .type = NLA_U64 },
372
+ [NL80211_TID_CONFIG_ATTR_OVERRIDE] = { .type = NLA_FLAG },
373
+ [NL80211_TID_CONFIG_ATTR_TIDS] = NLA_POLICY_RANGE(NLA_U16, 1, 0xff),
374
+ [NL80211_TID_CONFIG_ATTR_NOACK] =
375
+ NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
376
+ [NL80211_TID_CONFIG_ATTR_RETRY_SHORT] = NLA_POLICY_MIN(NLA_U8, 1),
377
+ [NL80211_TID_CONFIG_ATTR_RETRY_LONG] = NLA_POLICY_MIN(NLA_U8, 1),
378
+ [NL80211_TID_CONFIG_ATTR_AMPDU_CTRL] =
379
+ NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
380
+ [NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL] =
381
+ NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
382
+ [NL80211_TID_CONFIG_ATTR_AMSDU_CTRL] =
383
+ NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
384
+ [NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE] =
385
+ NLA_POLICY_MAX(NLA_U8, NL80211_TX_RATE_FIXED),
386
+ [NL80211_TID_CONFIG_ATTR_TX_RATE] =
387
+ NLA_POLICY_NESTED(nl80211_txattr_policy),
388
+};
389
+
390
+static const struct nla_policy
391
+nl80211_fils_discovery_policy[NL80211_FILS_DISCOVERY_ATTR_MAX + 1] = {
392
+ [NL80211_FILS_DISCOVERY_ATTR_INT_MIN] = NLA_POLICY_MAX(NLA_U32, 10000),
393
+ [NL80211_FILS_DISCOVERY_ATTR_INT_MAX] = NLA_POLICY_MAX(NLA_U32, 10000),
394
+ NLA_POLICY_RANGE(NLA_BINARY,
395
+ NL80211_FILS_DISCOVERY_TMPL_MIN_LEN,
396
+ IEEE80211_MAX_DATA_LEN),
397
+};
398
+
399
+static const struct nla_policy
400
+nl80211_unsol_bcast_probe_resp_policy[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX + 1] = {
401
+ [NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT] = NLA_POLICY_MAX(NLA_U32, 20),
402
+ [NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL] = { .type = NLA_BINARY,
403
+ .len = IEEE80211_MAX_DATA_LEN }
404
+};
405
+
236406 static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
407
+ [0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD },
237408 [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
238409 [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
239410 .len = 20-1 },
....@@ -241,55 +412,71 @@
241412
242413 [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
243414 [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 },
244
- [NL80211_ATTR_WIPHY_EDMG_CHANNELS] = { .type = NLA_U8 },
245
- [NL80211_ATTR_WIPHY_EDMG_BW_CONFIG] = { .type = NLA_U8 },
415
+ [NL80211_ATTR_WIPHY_EDMG_CHANNELS] = NLA_POLICY_RANGE(NLA_U8,
416
+ NL80211_EDMG_CHANNELS_MIN,
417
+ NL80211_EDMG_CHANNELS_MAX),
418
+ [NL80211_ATTR_WIPHY_EDMG_BW_CONFIG] = NLA_POLICY_RANGE(NLA_U8,
419
+ NL80211_EDMG_BW_CONFIG_MIN,
420
+ NL80211_EDMG_BW_CONFIG_MAX),
421
+
246422 [NL80211_ATTR_CHANNEL_WIDTH] = { .type = NLA_U32 },
247423 [NL80211_ATTR_CENTER_FREQ1] = { .type = NLA_U32 },
424
+ [NL80211_ATTR_CENTER_FREQ1_OFFSET] = NLA_POLICY_RANGE(NLA_U32, 0, 999),
248425 [NL80211_ATTR_CENTER_FREQ2] = { .type = NLA_U32 },
249426
250
- [NL80211_ATTR_WIPHY_RETRY_SHORT] = { .type = NLA_U8 },
251
- [NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 },
427
+ [NL80211_ATTR_WIPHY_RETRY_SHORT] = NLA_POLICY_MIN(NLA_U8, 1),
428
+ [NL80211_ATTR_WIPHY_RETRY_LONG] = NLA_POLICY_MIN(NLA_U8, 1),
252429 [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 },
253430 [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 },
254431 [NL80211_ATTR_WIPHY_COVERAGE_CLASS] = { .type = NLA_U8 },
255432 [NL80211_ATTR_WIPHY_DYN_ACK] = { .type = NLA_FLAG },
256433
257
- [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 },
434
+ [NL80211_ATTR_IFTYPE] = NLA_POLICY_MAX(NLA_U32, NL80211_IFTYPE_MAX),
258435 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
259436 [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
260437
261
- [NL80211_ATTR_MAC] = { .len = ETH_ALEN },
262
- [NL80211_ATTR_PREV_BSSID] = { .len = ETH_ALEN },
438
+ [NL80211_ATTR_MAC] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
439
+ [NL80211_ATTR_PREV_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
263440
264441 [NL80211_ATTR_KEY] = { .type = NLA_NESTED, },
265442 [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
266443 .len = WLAN_MAX_KEY_LEN },
267
- [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 },
444
+ [NL80211_ATTR_KEY_IDX] = NLA_POLICY_MAX(NLA_U8, 7),
268445 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
269446 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
270447 [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
271
- [NL80211_ATTR_KEY_TYPE] = { .type = NLA_U32 },
448
+ [NL80211_ATTR_KEY_TYPE] =
449
+ NLA_POLICY_MAX(NLA_U32, NUM_NL80211_KEYTYPES),
272450
273451 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
274452 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
275
- [NL80211_ATTR_BEACON_HEAD] = { .type = NLA_BINARY,
276
- .len = IEEE80211_MAX_DATA_LEN },
277
- [NL80211_ATTR_BEACON_TAIL] = { .type = NLA_BINARY,
278
- .len = IEEE80211_MAX_DATA_LEN },
279
- [NL80211_ATTR_STA_AID] = { .type = NLA_U16 },
453
+ [NL80211_ATTR_BEACON_HEAD] =
454
+ NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_beacon_head,
455
+ IEEE80211_MAX_DATA_LEN),
456
+ [NL80211_ATTR_BEACON_TAIL] =
457
+ NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
458
+ IEEE80211_MAX_DATA_LEN),
459
+ [NL80211_ATTR_STA_AID] =
460
+ NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
280461 [NL80211_ATTR_STA_FLAGS] = { .type = NLA_NESTED },
281462 [NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 },
282463 [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
283464 .len = NL80211_MAX_SUPP_RATES },
284
- [NL80211_ATTR_STA_PLINK_ACTION] = { .type = NLA_U8 },
465
+ [NL80211_ATTR_STA_PLINK_ACTION] =
466
+ NLA_POLICY_MAX(NLA_U8, NUM_NL80211_PLINK_ACTIONS - 1),
467
+ [NL80211_ATTR_STA_TX_POWER_SETTING] =
468
+ NLA_POLICY_RANGE(NLA_U8,
469
+ NL80211_TX_POWER_AUTOMATIC,
470
+ NL80211_TX_POWER_FIXED),
471
+ [NL80211_ATTR_STA_TX_POWER] = { .type = NLA_S16 },
285472 [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
286473 [NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ },
287474 [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
288475 .len = IEEE80211_MAX_MESH_ID_LEN },
289
- [NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_BINARY,
290
- .len = ETH_ALEN },
476
+ [NL80211_ATTR_MPATH_NEXT_HOP] = NLA_POLICY_ETH_ADDR_COMPAT,
291477
292
- [NL80211_ATTR_REG_ALPHA2] = { .type = NLA_STRING, .len = 2 },
478
+ /* allow 3 for NUL-termination, we used to declare this NLA_STRING */
479
+ [NL80211_ATTR_REG_ALPHA2] = NLA_POLICY_RANGE(NLA_BINARY, 2, 3),
293480 [NL80211_ATTR_REG_RULES] = { .type = NLA_NESTED },
294481
295482 [NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 },
....@@ -302,11 +489,12 @@
302489 [NL80211_ATTR_MESH_CONFIG] = { .type = NLA_NESTED },
303490 [NL80211_ATTR_SUPPORT_MESH_AUTH] = { .type = NLA_FLAG },
304491
305
- [NL80211_ATTR_HT_CAPABILITY] = { .len = NL80211_HT_CAPABILITY_LEN },
492
+ [NL80211_ATTR_HT_CAPABILITY] = NLA_POLICY_EXACT_LEN_WARN(NL80211_HT_CAPABILITY_LEN),
306493
307494 [NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 },
308
- [NL80211_ATTR_IE] = { .type = NLA_BINARY,
309
- .len = IEEE80211_MAX_DATA_LEN },
495
+ [NL80211_ATTR_IE] = NLA_POLICY_VALIDATE_FN(NLA_BINARY,
496
+ validate_ie_attr,
497
+ IEEE80211_MAX_DATA_LEN),
310498 [NL80211_ATTR_SCAN_FREQUENCIES] = { .type = NLA_NESTED },
311499 [NL80211_ATTR_SCAN_SSIDS] = { .type = NLA_NESTED },
312500
....@@ -316,7 +504,9 @@
316504 [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 },
317505 [NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG },
318506 [NL80211_ATTR_TIMED_OUT] = { .type = NLA_FLAG },
319
- [NL80211_ATTR_USE_MFP] = { .type = NLA_U32 },
507
+ [NL80211_ATTR_USE_MFP] = NLA_POLICY_RANGE(NLA_U32,
508
+ NL80211_MFP_NO,
509
+ NL80211_MFP_OPTIONAL),
320510 [NL80211_ATTR_STA_FLAGS2] = {
321511 .len = sizeof(struct nl80211_sta_flag_update),
322512 },
....@@ -330,14 +520,16 @@
330520 [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
331521 [NL80211_ATTR_PID] = { .type = NLA_U32 },
332522 [NL80211_ATTR_4ADDR] = { .type = NLA_U8 },
333
- [NL80211_ATTR_PMKID] = { .len = WLAN_PMKID_LEN },
523
+ [NL80211_ATTR_PMKID] = NLA_POLICY_EXACT_LEN_WARN(WLAN_PMKID_LEN),
334524 [NL80211_ATTR_DURATION] = { .type = NLA_U32 },
335525 [NL80211_ATTR_COOKIE] = { .type = NLA_U64 },
336526 [NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED },
337527 [NL80211_ATTR_FRAME] = { .type = NLA_BINARY,
338528 .len = IEEE80211_MAX_DATA_LEN },
339529 [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, },
340
- [NL80211_ATTR_PS_STATE] = { .type = NLA_U32 },
530
+ [NL80211_ATTR_PS_STATE] = NLA_POLICY_RANGE(NLA_U32,
531
+ NL80211_PS_DISABLED,
532
+ NL80211_PS_ENABLED),
341533 [NL80211_ATTR_CQM] = { .type = NLA_NESTED, },
342534 [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG },
343535 [NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 },
....@@ -350,17 +542,25 @@
350542 [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG },
351543 [NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
352544 [NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED },
353
- [NL80211_ATTR_STA_PLINK_STATE] = { .type = NLA_U8 },
545
+ [NL80211_ATTR_STA_PLINK_STATE] =
546
+ NLA_POLICY_MAX(NLA_U8, NUM_NL80211_PLINK_STATES - 1),
354547 [NL80211_ATTR_MEASUREMENT_DURATION] = { .type = NLA_U16 },
355548 [NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY] = { .type = NLA_FLAG },
549
+ [NL80211_ATTR_MESH_PEER_AID] =
550
+ NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
356551 [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 },
357552 [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED },
358553 [NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED },
359
- [NL80211_ATTR_HIDDEN_SSID] = { .type = NLA_U32 },
360
- [NL80211_ATTR_IE_PROBE_RESP] = { .type = NLA_BINARY,
361
- .len = IEEE80211_MAX_DATA_LEN },
362
- [NL80211_ATTR_IE_ASSOC_RESP] = { .type = NLA_BINARY,
363
- .len = IEEE80211_MAX_DATA_LEN },
554
+ [NL80211_ATTR_HIDDEN_SSID] =
555
+ NLA_POLICY_RANGE(NLA_U32,
556
+ NL80211_HIDDEN_SSID_NOT_IN_USE,
557
+ NL80211_HIDDEN_SSID_ZERO_CONTENTS),
558
+ [NL80211_ATTR_IE_PROBE_RESP] =
559
+ NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
560
+ IEEE80211_MAX_DATA_LEN),
561
+ [NL80211_ATTR_IE_ASSOC_RESP] =
562
+ NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
563
+ IEEE80211_MAX_DATA_LEN),
364564 [NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG },
365565 [NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED },
366566 [NL80211_ATTR_TX_NO_CCK_RATE] = { .type = NLA_FLAG },
....@@ -383,12 +583,18 @@
383583 [NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
384584 [NL80211_ATTR_WDEV] = { .type = NLA_U64 },
385585 [NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },
386
- [NL80211_ATTR_AUTH_DATA] = { .type = NLA_BINARY, },
387
- [NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN },
586
+
587
+ /* need to include at least Auth Transaction and Status Code */
588
+ [NL80211_ATTR_AUTH_DATA] = NLA_POLICY_MIN_LEN(4),
589
+
590
+ [NL80211_ATTR_VHT_CAPABILITY] = NLA_POLICY_EXACT_LEN_WARN(NL80211_VHT_CAPABILITY_LEN),
388591 [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
389
- [NL80211_ATTR_P2P_CTWINDOW] = { .type = NLA_U8 },
390
- [NL80211_ATTR_P2P_OPPPS] = { .type = NLA_U8 },
391
- [NL80211_ATTR_LOCAL_MESH_POWER_MODE] = {. type = NLA_U32 },
592
+ [NL80211_ATTR_P2P_CTWINDOW] = NLA_POLICY_MAX(NLA_U8, 127),
593
+ [NL80211_ATTR_P2P_OPPPS] = NLA_POLICY_MAX(NLA_U8, 1),
594
+ [NL80211_ATTR_LOCAL_MESH_POWER_MODE] =
595
+ NLA_POLICY_RANGE(NLA_U32,
596
+ NL80211_MESH_POWER_UNKNOWN + 1,
597
+ NL80211_MESH_POWER_MAX),
392598 [NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 },
393599 [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED },
394600 [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 },
....@@ -402,53 +608,63 @@
402608 [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,
403609 .len = IEEE80211_MAX_DATA_LEN },
404610 [NL80211_ATTR_CRIT_PROT_ID] = { .type = NLA_U16 },
405
- [NL80211_ATTR_MAX_CRIT_PROT_DURATION] = { .type = NLA_U16 },
406
- [NL80211_ATTR_PEER_AID] = { .type = NLA_U16 },
611
+ [NL80211_ATTR_MAX_CRIT_PROT_DURATION] =
612
+ NLA_POLICY_MAX(NLA_U16, NL80211_CRIT_PROTO_MAX_DURATION),
613
+ [NL80211_ATTR_PEER_AID] =
614
+ NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
407615 [NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 },
408616 [NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG },
409617 [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED },
410
- [NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_BINARY },
411
- [NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_BINARY },
412
- [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY },
413
- [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY },
618
+ [NL80211_ATTR_CNTDWN_OFFS_BEACON] = { .type = NLA_BINARY },
619
+ [NL80211_ATTR_CNTDWN_OFFS_PRESP] = { .type = NLA_BINARY },
620
+ [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = NLA_POLICY_MIN_LEN(2),
621
+ /*
622
+ * The value of the Length field of the Supported Operating
623
+ * Classes element is between 2 and 253.
624
+ */
625
+ [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] =
626
+ NLA_POLICY_RANGE(NLA_BINARY, 2, 253),
414627 [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG },
415628 [NL80211_ATTR_OPMODE_NOTIF] = { .type = NLA_U8 },
416629 [NL80211_ATTR_VENDOR_ID] = { .type = NLA_U32 },
417630 [NL80211_ATTR_VENDOR_SUBCMD] = { .type = NLA_U32 },
418631 [NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY },
419
- [NL80211_ATTR_QOS_MAP] = { .type = NLA_BINARY,
420
- .len = IEEE80211_QOS_MAP_LEN_MAX },
421
- [NL80211_ATTR_MAC_HINT] = { .len = ETH_ALEN },
632
+ [NL80211_ATTR_QOS_MAP] = NLA_POLICY_RANGE(NLA_BINARY,
633
+ IEEE80211_QOS_MAP_LEN_MIN,
634
+ IEEE80211_QOS_MAP_LEN_MAX),
635
+ [NL80211_ATTR_MAC_HINT] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
422636 [NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 },
423637 [NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 },
424638 [NL80211_ATTR_SOCKET_OWNER] = { .type = NLA_FLAG },
425639 [NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY },
426640 [NL80211_ATTR_USE_RRM] = { .type = NLA_FLAG },
427
- [NL80211_ATTR_TSID] = { .type = NLA_U8 },
428
- [NL80211_ATTR_USER_PRIO] = { .type = NLA_U8 },
641
+ [NL80211_ATTR_TSID] = NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_TIDS - 1),
642
+ [NL80211_ATTR_USER_PRIO] =
643
+ NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_UPS - 1),
429644 [NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 },
430645 [NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 },
431646 [NL80211_ATTR_OPER_CLASS] = { .type = NLA_U8 },
432
- [NL80211_ATTR_MAC_MASK] = { .len = ETH_ALEN },
647
+ [NL80211_ATTR_MAC_MASK] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
433648 [NL80211_ATTR_WIPHY_SELF_MANAGED_REG] = { .type = NLA_FLAG },
434649 [NL80211_ATTR_NETNS_FD] = { .type = NLA_U32 },
435650 [NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 },
436651 [NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG },
437652 [NL80211_ATTR_PBSS] = { .type = NLA_FLAG },
438653 [NL80211_ATTR_BSS_SELECT] = { .type = NLA_NESTED },
439
- [NL80211_ATTR_STA_SUPPORT_P2P_PS] = { .type = NLA_U8 },
654
+ [NL80211_ATTR_STA_SUPPORT_P2P_PS] =
655
+ NLA_POLICY_MAX(NLA_U8, NUM_NL80211_P2P_PS_STATUS - 1),
440656 [NL80211_ATTR_MU_MIMO_GROUP_DATA] = {
441657 .len = VHT_MUMIMO_GROUPS_DATA_LEN
442658 },
443
- [NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = { .len = ETH_ALEN },
444
- [NL80211_ATTR_NAN_MASTER_PREF] = { .type = NLA_U8 },
659
+ [NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
660
+ [NL80211_ATTR_NAN_MASTER_PREF] = NLA_POLICY_MIN(NLA_U8, 1),
445661 [NL80211_ATTR_BANDS] = { .type = NLA_U32 },
446662 [NL80211_ATTR_NAN_FUNC] = { .type = NLA_NESTED },
447663 [NL80211_ATTR_FILS_KEK] = { .type = NLA_BINARY,
448664 .len = FILS_MAX_KEK_LEN },
449
- [NL80211_ATTR_FILS_NONCES] = { .len = 2 * FILS_NONCE_LEN },
665
+ [NL80211_ATTR_FILS_NONCES] = NLA_POLICY_EXACT_LEN_WARN(2 * FILS_NONCE_LEN),
450666 [NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED] = { .type = NLA_FLAG, },
451
- [NL80211_ATTR_BSSID] = { .len = ETH_ALEN },
667
+ [NL80211_ATTR_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
452668 [NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] = { .type = NLA_S8 },
453669 [NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST] = {
454670 .len = sizeof(struct nl80211_bss_select_rssi_adjust)
....@@ -461,16 +677,52 @@
461677 [NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] = { .type = NLA_U16 },
462678 [NL80211_ATTR_FILS_ERP_RRK] = { .type = NLA_BINARY,
463679 .len = FILS_ERP_MAX_RRK_LEN },
464
- [NL80211_ATTR_FILS_CACHE_ID] = { .len = 2 },
680
+ [NL80211_ATTR_FILS_CACHE_ID] = NLA_POLICY_EXACT_LEN_WARN(2),
465681 [NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN },
682
+ [NL80211_ATTR_PMKR0_NAME] = NLA_POLICY_EXACT_LEN(WLAN_PMK_NAME_LEN),
466683 [NL80211_ATTR_SCHED_SCAN_MULTI] = { .type = NLA_FLAG },
467684 [NL80211_ATTR_EXTERNAL_AUTH_SUPPORT] = { .type = NLA_FLAG },
468685
469686 [NL80211_ATTR_TXQ_LIMIT] = { .type = NLA_U32 },
470687 [NL80211_ATTR_TXQ_MEMORY_LIMIT] = { .type = NLA_U32 },
471688 [NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 },
472
- [NL80211_ATTR_HE_CAPABILITY] = { .type = NLA_BINARY,
473
- .len = NL80211_HE_MAX_CAPABILITY_LEN },
689
+ [NL80211_ATTR_HE_CAPABILITY] =
690
+ NLA_POLICY_RANGE(NLA_BINARY,
691
+ NL80211_HE_MIN_CAPABILITY_LEN,
692
+ NL80211_HE_MAX_CAPABILITY_LEN),
693
+ [NL80211_ATTR_FTM_RESPONDER] =
694
+ NLA_POLICY_NESTED(nl80211_ftm_responder_policy),
695
+ [NL80211_ATTR_TIMEOUT] = NLA_POLICY_MIN(NLA_U32, 1),
696
+ [NL80211_ATTR_PEER_MEASUREMENTS] =
697
+ NLA_POLICY_NESTED(nl80211_pmsr_attr_policy),
698
+ [NL80211_ATTR_AIRTIME_WEIGHT] = NLA_POLICY_MIN(NLA_U16, 1),
699
+ [NL80211_ATTR_SAE_PASSWORD] = { .type = NLA_BINARY,
700
+ .len = SAE_PASSWORD_MAX_LEN },
701
+ [NL80211_ATTR_TWT_RESPONDER] = { .type = NLA_FLAG },
702
+ [NL80211_ATTR_HE_OBSS_PD] = NLA_POLICY_NESTED(he_obss_pd_policy),
703
+ [NL80211_ATTR_VLAN_ID] = NLA_POLICY_RANGE(NLA_U16, 1, VLAN_N_VID - 2),
704
+ [NL80211_ATTR_HE_BSS_COLOR] = NLA_POLICY_NESTED(he_bss_color_policy),
705
+ [NL80211_ATTR_TID_CONFIG] =
706
+ NLA_POLICY_NESTED_ARRAY(nl80211_tid_config_attr_policy),
707
+ [NL80211_ATTR_CONTROL_PORT_NO_PREAUTH] = { .type = NLA_FLAG },
708
+ [NL80211_ATTR_PMK_LIFETIME] = NLA_POLICY_MIN(NLA_U32, 1),
709
+ [NL80211_ATTR_PMK_REAUTH_THRESHOLD] = NLA_POLICY_RANGE(NLA_U8, 1, 100),
710
+ [NL80211_ATTR_RECEIVE_MULTICAST] = { .type = NLA_FLAG },
711
+ [NL80211_ATTR_WIPHY_FREQ_OFFSET] = NLA_POLICY_RANGE(NLA_U32, 0, 999),
712
+ [NL80211_ATTR_SCAN_FREQ_KHZ] = { .type = NLA_NESTED },
713
+ [NL80211_ATTR_HE_6GHZ_CAPABILITY] =
714
+ NLA_POLICY_EXACT_LEN(sizeof(struct ieee80211_he_6ghz_capa)),
715
+ [NL80211_ATTR_FILS_DISCOVERY] =
716
+ NLA_POLICY_NESTED(nl80211_fils_discovery_policy),
717
+ [NL80211_ATTR_UNSOL_BCAST_PROBE_RESP] =
718
+ NLA_POLICY_NESTED(nl80211_unsol_bcast_probe_resp_policy),
719
+ [NL80211_ATTR_S1G_CAPABILITY] =
720
+ NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN),
721
+ [NL80211_ATTR_S1G_CAPABILITY_MASK] =
722
+ NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN),
723
+ [NL80211_ATTR_SAE_PWE] =
724
+ NLA_POLICY_RANGE(NLA_U8, NL80211_SAE_PWE_HUNT_AND_PECK,
725
+ NL80211_SAE_PWE_BOTH),
474726 };
475727
476728 /* policy for the key attributes */
....@@ -481,8 +733,9 @@
481733 [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
482734 [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG },
483735 [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
484
- [NL80211_KEY_TYPE] = { .type = NLA_U32 },
736
+ [NL80211_KEY_TYPE] = NLA_POLICY_MAX(NLA_U32, NUM_NL80211_KEYTYPES - 1),
485737 [NL80211_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
738
+ [NL80211_KEY_MODE] = NLA_POLICY_RANGE(NLA_U8, 0, NL80211_KEY_SET_TX),
486739 };
487740
488741 /* policy for the key default flags */
....@@ -512,10 +765,10 @@
512765 nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = {
513766 [NL80211_WOWLAN_TCP_SRC_IPV4] = { .type = NLA_U32 },
514767 [NL80211_WOWLAN_TCP_DST_IPV4] = { .type = NLA_U32 },
515
- [NL80211_WOWLAN_TCP_DST_MAC] = { .len = ETH_ALEN },
768
+ [NL80211_WOWLAN_TCP_DST_MAC] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
516769 [NL80211_WOWLAN_TCP_SRC_PORT] = { .type = NLA_U16 },
517770 [NL80211_WOWLAN_TCP_DST_PORT] = { .type = NLA_U16 },
518
- [NL80211_WOWLAN_TCP_DATA_PAYLOAD] = { .len = 1 },
771
+ [NL80211_WOWLAN_TCP_DATA_PAYLOAD] = NLA_POLICY_MIN_LEN(1),
519772 [NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ] = {
520773 .len = sizeof(struct nl80211_wowlan_tcp_data_seq)
521774 },
....@@ -523,8 +776,8 @@
523776 .len = sizeof(struct nl80211_wowlan_tcp_data_token)
524777 },
525778 [NL80211_WOWLAN_TCP_DATA_INTERVAL] = { .type = NLA_U32 },
526
- [NL80211_WOWLAN_TCP_WAKE_PAYLOAD] = { .len = 1 },
527
- [NL80211_WOWLAN_TCP_WAKE_MASK] = { .len = 1 },
779
+ [NL80211_WOWLAN_TCP_WAKE_PAYLOAD] = NLA_POLICY_MIN_LEN(1),
780
+ [NL80211_WOWLAN_TCP_WAKE_MASK] = NLA_POLICY_MIN_LEN(1),
528781 };
529782 #endif /* CONFIG_PM */
530783
....@@ -532,25 +785,44 @@
532785 static const struct nla_policy
533786 nl80211_coalesce_policy[NUM_NL80211_ATTR_COALESCE_RULE] = {
534787 [NL80211_ATTR_COALESCE_RULE_DELAY] = { .type = NLA_U32 },
535
- [NL80211_ATTR_COALESCE_RULE_CONDITION] = { .type = NLA_U32 },
788
+ [NL80211_ATTR_COALESCE_RULE_CONDITION] =
789
+ NLA_POLICY_RANGE(NLA_U32,
790
+ NL80211_COALESCE_CONDITION_MATCH,
791
+ NL80211_COALESCE_CONDITION_NO_MATCH),
536792 [NL80211_ATTR_COALESCE_RULE_PKT_PATTERN] = { .type = NLA_NESTED },
537793 };
538794
539795 /* policy for GTK rekey offload attributes */
540796 static const struct nla_policy
541797 nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = {
542
- [NL80211_REKEY_DATA_KEK] = { .type = NLA_BINARY,
543
- .len = FILS_MAX_KEK_LEN },
544
- [NL80211_REKEY_DATA_KCK] = { .len = NL80211_KCK_LEN },
545
- [NL80211_REKEY_DATA_REPLAY_CTR] = { .len = NL80211_REPLAY_CTR_LEN },
798
+ [NL80211_REKEY_DATA_KEK] = {
799
+ .type = NLA_BINARY,
800
+ .len = NL80211_KEK_EXT_LEN
801
+ },
802
+ [NL80211_REKEY_DATA_KCK] = {
803
+ .type = NLA_BINARY,
804
+ .len = NL80211_KCK_EXT_LEN
805
+ },
806
+ [NL80211_REKEY_DATA_REPLAY_CTR] = NLA_POLICY_EXACT_LEN(NL80211_REPLAY_CTR_LEN),
807
+ [NL80211_REKEY_DATA_AKM] = { .type = NLA_U32 },
808
+};
809
+
810
+static const struct nla_policy
811
+nl80211_match_band_rssi_policy[NUM_NL80211_BANDS] = {
812
+ [NL80211_BAND_2GHZ] = { .type = NLA_S32 },
813
+ [NL80211_BAND_5GHZ] = { .type = NLA_S32 },
814
+ [NL80211_BAND_6GHZ] = { .type = NLA_S32 },
815
+ [NL80211_BAND_60GHZ] = { .type = NLA_S32 },
546816 };
547817
548818 static const struct nla_policy
549819 nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = {
550820 [NL80211_SCHED_SCAN_MATCH_ATTR_SSID] = { .type = NLA_BINARY,
551821 .len = IEEE80211_MAX_SSID_LEN },
552
- [NL80211_SCHED_SCAN_MATCH_ATTR_BSSID] = { .len = ETH_ALEN },
822
+ [NL80211_SCHED_SCAN_MATCH_ATTR_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
553823 [NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] = { .type = NLA_U32 },
824
+ [NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI] =
825
+ NLA_POLICY_NESTED(nl80211_match_band_rssi_policy),
554826 };
555827
556828 static const struct nla_policy
....@@ -571,7 +843,8 @@
571843 /* policy for NAN function attributes */
572844 static const struct nla_policy
573845 nl80211_nan_func_policy[NL80211_NAN_FUNC_ATTR_MAX + 1] = {
574
- [NL80211_NAN_FUNC_TYPE] = { .type = NLA_U8 },
846
+ [NL80211_NAN_FUNC_TYPE] =
847
+ NLA_POLICY_MAX(NLA_U8, NL80211_NAN_FUNC_MAX_TYPE),
575848 [NL80211_NAN_FUNC_SERVICE_ID] = {
576849 .len = NL80211_NAN_FUNC_SERVICE_ID_LEN },
577850 [NL80211_NAN_FUNC_PUBLISH_TYPE] = { .type = NLA_U8 },
....@@ -579,7 +852,7 @@
579852 [NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE] = { .type = NLA_FLAG },
580853 [NL80211_NAN_FUNC_FOLLOW_UP_ID] = { .type = NLA_U8 },
581854 [NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID] = { .type = NLA_U8 },
582
- [NL80211_NAN_FUNC_FOLLOW_UP_DEST] = { .len = ETH_ALEN },
855
+ [NL80211_NAN_FUNC_FOLLOW_UP_DEST] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
583856 [NL80211_NAN_FUNC_CLOSE_RANGE] = { .type = NLA_FLAG },
584857 [NL80211_NAN_FUNC_TTL] = { .type = NLA_U32 },
585858 [NL80211_NAN_FUNC_SERVICE_INFO] = { .type = NLA_BINARY,
....@@ -609,23 +882,32 @@
609882 [NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 },
610883 };
611884
612
-static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
613
- struct netlink_callback *cb,
614
- struct cfg80211_registered_device **rdev,
615
- struct wireless_dev **wdev)
885
+int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
886
+ struct cfg80211_registered_device **rdev,
887
+ struct wireless_dev **wdev)
616888 {
617889 int err;
618890
619891 if (!cb->args[0]) {
620
- err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
621
- genl_family_attrbuf(&nl80211_fam),
622
- nl80211_fam.maxattr, nl80211_policy, NULL);
623
- if (err)
624
- return err;
892
+ struct nlattr **attrbuf;
625893
626
- *wdev = __cfg80211_wdev_from_attrs(
627
- sock_net(skb->sk),
628
- genl_family_attrbuf(&nl80211_fam));
894
+ attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf),
895
+ GFP_KERNEL);
896
+ if (!attrbuf)
897
+ return -ENOMEM;
898
+
899
+ err = nlmsg_parse_deprecated(cb->nlh,
900
+ GENL_HDRLEN + nl80211_fam.hdrsize,
901
+ attrbuf, nl80211_fam.maxattr,
902
+ nl80211_policy, NULL);
903
+ if (err) {
904
+ kfree(attrbuf);
905
+ return err;
906
+ }
907
+
908
+ *wdev = __cfg80211_wdev_from_attrs(sock_net(cb->skb->sk),
909
+ attrbuf);
910
+ kfree(attrbuf);
629911 if (IS_ERR(*wdev))
630912 return PTR_ERR(*wdev);
631913 *rdev = wiphy_to_rdev((*wdev)->wiphy);
....@@ -656,39 +938,9 @@
656938 return 0;
657939 }
658940
659
-/* IE validation */
660
-static bool is_valid_ie_attr(const struct nlattr *attr)
661
-{
662
- const u8 *pos;
663
- int len;
664
-
665
- if (!attr)
666
- return true;
667
-
668
- pos = nla_data(attr);
669
- len = nla_len(attr);
670
-
671
- while (len) {
672
- u8 elemlen;
673
-
674
- if (len < 2)
675
- return false;
676
- len -= 2;
677
-
678
- elemlen = pos[1];
679
- if (elemlen > len)
680
- return false;
681
-
682
- len -= elemlen;
683
- pos += 2 + elemlen;
684
- }
685
-
686
- return true;
687
-}
688
-
689941 /* message building helper */
690
-static inline void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
691
- int flags, u8 cmd)
942
+void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
943
+ int flags, u8 cmd)
692944 {
693945 /* since there is no private header just add the generic one */
694946 return genlmsg_put(skb, portid, seq, &nl80211_fam, flags, cmd);
....@@ -699,13 +951,13 @@
699951 {
700952 int j;
701953 struct nlattr *nl_wmm_rules =
702
- nla_nest_start(msg, NL80211_FREQUENCY_ATTR_WMM);
954
+ nla_nest_start_noflag(msg, NL80211_FREQUENCY_ATTR_WMM);
703955
704956 if (!nl_wmm_rules)
705957 goto nla_put_failure;
706958
707959 for (j = 0; j < IEEE80211_NUM_ACS; j++) {
708
- struct nlattr *nl_wmm_rule = nla_nest_start(msg, j);
960
+ struct nlattr *nl_wmm_rule = nla_nest_start_noflag(msg, j);
709961
710962 if (!nl_wmm_rule)
711963 goto nla_put_failure;
....@@ -740,9 +992,14 @@
740992 if (!large && chan->flags &
741993 (IEEE80211_CHAN_NO_10MHZ | IEEE80211_CHAN_NO_20MHZ))
742994 return 0;
995
+ if (!large && chan->freq_offset)
996
+ return 0;
743997
744998 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_FREQ,
745999 chan->center_freq))
1000
+ goto nla_put_failure;
1001
+
1002
+ if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_OFFSET, chan->freq_offset))
7461003 goto nla_put_failure;
7471004
7481005 if ((chan->flags & IEEE80211_CHAN_DISABLED) &&
....@@ -800,6 +1057,24 @@
8001057 if ((chan->flags & IEEE80211_CHAN_NO_10MHZ) &&
8011058 nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_10MHZ))
8021059 goto nla_put_failure;
1060
+ if ((chan->flags & IEEE80211_CHAN_NO_HE) &&
1061
+ nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HE))
1062
+ goto nla_put_failure;
1063
+ if ((chan->flags & IEEE80211_CHAN_1MHZ) &&
1064
+ nla_put_flag(msg, NL80211_FREQUENCY_ATTR_1MHZ))
1065
+ goto nla_put_failure;
1066
+ if ((chan->flags & IEEE80211_CHAN_2MHZ) &&
1067
+ nla_put_flag(msg, NL80211_FREQUENCY_ATTR_2MHZ))
1068
+ goto nla_put_failure;
1069
+ if ((chan->flags & IEEE80211_CHAN_4MHZ) &&
1070
+ nla_put_flag(msg, NL80211_FREQUENCY_ATTR_4MHZ))
1071
+ goto nla_put_failure;
1072
+ if ((chan->flags & IEEE80211_CHAN_8MHZ) &&
1073
+ nla_put_flag(msg, NL80211_FREQUENCY_ATTR_8MHZ))
1074
+ goto nla_put_failure;
1075
+ if ((chan->flags & IEEE80211_CHAN_16MHZ) &&
1076
+ nla_put_flag(msg, NL80211_FREQUENCY_ATTR_16MHZ))
1077
+ goto nla_put_failure;
8031078 }
8041079
8051080 if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
....@@ -834,7 +1109,7 @@
8341109 return false; \
8351110 } while (0)
8361111
837
- txqattr = nla_nest_start(msg, attrtype);
1112
+ txqattr = nla_nest_start_noflag(msg, attrtype);
8381113 if (!txqattr)
8391114 return false;
8401115
....@@ -869,8 +1144,9 @@
8691144 struct key_parse *k)
8701145 {
8711146 struct nlattr *tb[NL80211_KEY_MAX + 1];
872
- int err = nla_parse_nested(tb, NL80211_KEY_MAX, key,
873
- nl80211_key_policy, info->extack);
1147
+ int err = nla_parse_nested_deprecated(tb, NL80211_KEY_MAX, key,
1148
+ nl80211_key_policy,
1149
+ info->extack);
8741150 if (err)
8751151 return err;
8761152
....@@ -901,26 +1177,26 @@
9011177 if (tb[NL80211_KEY_CIPHER])
9021178 k->p.cipher = nla_get_u32(tb[NL80211_KEY_CIPHER]);
9031179
904
- if (tb[NL80211_KEY_TYPE]) {
1180
+ if (tb[NL80211_KEY_TYPE])
9051181 k->type = nla_get_u32(tb[NL80211_KEY_TYPE]);
906
- if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES)
907
- return genl_err_attr(info, -EINVAL,
908
- tb[NL80211_KEY_TYPE]);
909
- }
9101182
9111183 if (tb[NL80211_KEY_DEFAULT_TYPES]) {
9121184 struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
9131185
914
- err = nla_parse_nested(kdt, NUM_NL80211_KEY_DEFAULT_TYPES - 1,
915
- tb[NL80211_KEY_DEFAULT_TYPES],
916
- nl80211_key_default_policy,
917
- info->extack);
1186
+ err = nla_parse_nested_deprecated(kdt,
1187
+ NUM_NL80211_KEY_DEFAULT_TYPES - 1,
1188
+ tb[NL80211_KEY_DEFAULT_TYPES],
1189
+ nl80211_key_default_policy,
1190
+ info->extack);
9181191 if (err)
9191192 return err;
9201193
9211194 k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST];
9221195 k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
9231196 }
1197
+
1198
+ if (tb[NL80211_KEY_MODE])
1199
+ k->p.mode = nla_get_u8(tb[NL80211_KEY_MODE]);
9241200
9251201 return 0;
9261202 }
....@@ -953,21 +1229,16 @@
9531229 if (k->defmgmt)
9541230 k->def_multi = true;
9551231
956
- if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
1232
+ if (info->attrs[NL80211_ATTR_KEY_TYPE])
9571233 k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
958
- if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES) {
959
- GENL_SET_ERR_MSG(info, "key type out of range");
960
- return -EINVAL;
961
- }
962
- }
9631234
9641235 if (info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES]) {
9651236 struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
966
- int err = nla_parse_nested(kdt,
967
- NUM_NL80211_KEY_DEFAULT_TYPES - 1,
968
- info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES],
969
- nl80211_key_default_policy,
970
- info->extack);
1237
+ int err = nla_parse_nested_deprecated(kdt,
1238
+ NUM_NL80211_KEY_DEFAULT_TYPES - 1,
1239
+ info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES],
1240
+ nl80211_key_default_policy,
1241
+ info->extack);
9711242 if (err)
9721243 return err;
9731244
....@@ -1151,13 +1422,11 @@
11511422 }
11521423
11531424 static struct ieee80211_channel *nl80211_get_valid_chan(struct wiphy *wiphy,
1154
- struct nlattr *tb)
1425
+ u32 freq)
11551426 {
11561427 struct ieee80211_channel *chan;
11571428
1158
- if (tb == NULL)
1159
- return NULL;
1160
- chan = ieee80211_get_channel(wiphy, nla_get_u32(tb));
1429
+ chan = ieee80211_get_channel_khz(wiphy, freq);
11611430 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
11621431 return NULL;
11631432 return chan;
....@@ -1165,7 +1434,7 @@
11651434
11661435 static int nl80211_put_iftypes(struct sk_buff *msg, u32 attr, u16 ifmodes)
11671436 {
1168
- struct nlattr *nl_modes = nla_nest_start(msg, attr);
1437
+ struct nlattr *nl_modes = nla_nest_start_noflag(msg, attr);
11691438 int i;
11701439
11711440 if (!nl_modes)
....@@ -1193,8 +1462,8 @@
11931462 struct nlattr *nl_combis;
11941463 int i, j;
11951464
1196
- nl_combis = nla_nest_start(msg,
1197
- NL80211_ATTR_INTERFACE_COMBINATIONS);
1465
+ nl_combis = nla_nest_start_noflag(msg,
1466
+ NL80211_ATTR_INTERFACE_COMBINATIONS);
11981467 if (!nl_combis)
11991468 goto nla_put_failure;
12001469
....@@ -1204,18 +1473,19 @@
12041473
12051474 c = &wiphy->iface_combinations[i];
12061475
1207
- nl_combi = nla_nest_start(msg, i + 1);
1476
+ nl_combi = nla_nest_start_noflag(msg, i + 1);
12081477 if (!nl_combi)
12091478 goto nla_put_failure;
12101479
1211
- nl_limits = nla_nest_start(msg, NL80211_IFACE_COMB_LIMITS);
1480
+ nl_limits = nla_nest_start_noflag(msg,
1481
+ NL80211_IFACE_COMB_LIMITS);
12121482 if (!nl_limits)
12131483 goto nla_put_failure;
12141484
12151485 for (j = 0; j < c->n_limits; j++) {
12161486 struct nlattr *nl_limit;
12171487
1218
- nl_limit = nla_nest_start(msg, j + 1);
1488
+ nl_limit = nla_nest_start_noflag(msg, j + 1);
12191489 if (!nl_limit)
12201490 goto nla_put_failure;
12211491 if (nla_put_u32(msg, NL80211_IFACE_LIMIT_MAX,
....@@ -1268,7 +1538,8 @@
12681538 if (!tcp)
12691539 return 0;
12701540
1271
- nl_tcp = nla_nest_start(msg, NL80211_WOWLAN_TRIG_TCP_CONNECTION);
1541
+ nl_tcp = nla_nest_start_noflag(msg,
1542
+ NL80211_WOWLAN_TRIG_TCP_CONNECTION);
12721543 if (!nl_tcp)
12731544 return -ENOBUFS;
12741545
....@@ -1308,7 +1579,8 @@
13081579 if (!rdev->wiphy.wowlan)
13091580 return 0;
13101581
1311
- nl_wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED);
1582
+ nl_wowlan = nla_nest_start_noflag(msg,
1583
+ NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED);
13121584 if (!nl_wowlan)
13131585 return -ENOBUFS;
13141586
....@@ -1380,6 +1652,7 @@
13801652
13811653 static int
13821654 nl80211_send_iftype_data(struct sk_buff *msg,
1655
+ const struct ieee80211_supported_band *sband,
13831656 const struct ieee80211_sband_iftype_data *iftdata)
13841657 {
13851658 const struct ieee80211_sta_he_cap *he_cap = &iftdata->he_cap;
....@@ -1403,11 +1676,18 @@
14031676 return -ENOBUFS;
14041677 }
14051678
1679
+ if (sband->band == NL80211_BAND_6GHZ &&
1680
+ nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA,
1681
+ sizeof(iftdata->he_6ghz_capa),
1682
+ &iftdata->he_6ghz_capa))
1683
+ return -ENOBUFS;
1684
+
14061685 return 0;
14071686 }
14081687
14091688 static int nl80211_send_band_rateinfo(struct sk_buff *msg,
1410
- struct ieee80211_supported_band *sband)
1689
+ struct ieee80211_supported_band *sband,
1690
+ bool large)
14111691 {
14121692 struct nlattr *nl_rates, *nl_rate;
14131693 struct ieee80211_rate *rate;
....@@ -1435,9 +1715,10 @@
14351715 sband->vht_cap.cap)))
14361716 return -ENOBUFS;
14371717
1438
- if (sband->n_iftype_data) {
1718
+ if (large && sband->n_iftype_data) {
14391719 struct nlattr *nl_iftype_data =
1440
- nla_nest_start(msg, NL80211_BAND_ATTR_IFTYPE_DATA);
1720
+ nla_nest_start_noflag(msg,
1721
+ NL80211_BAND_ATTR_IFTYPE_DATA);
14411722 int err;
14421723
14431724 if (!nl_iftype_data)
....@@ -1446,11 +1727,11 @@
14461727 for (i = 0; i < sband->n_iftype_data; i++) {
14471728 struct nlattr *iftdata;
14481729
1449
- iftdata = nla_nest_start(msg, i + 1);
1730
+ iftdata = nla_nest_start_noflag(msg, i + 1);
14501731 if (!iftdata)
14511732 return -ENOBUFS;
14521733
1453
- err = nl80211_send_iftype_data(msg,
1734
+ err = nl80211_send_iftype_data(msg, sband,
14541735 &sband->iftype_data[i]);
14551736 if (err)
14561737 return err;
....@@ -1462,7 +1743,7 @@
14621743 }
14631744
14641745 /* add EDMG info */
1465
- if (sband->edmg_cap.channels &&
1746
+ if (large && sband->edmg_cap.channels &&
14661747 (nla_put_u8(msg, NL80211_BAND_ATTR_EDMG_CHANNELS,
14671748 sband->edmg_cap.channels) ||
14681749 nla_put_u8(msg, NL80211_BAND_ATTR_EDMG_BW_CONFIG,
....@@ -1471,12 +1752,12 @@
14711752 return -ENOBUFS;
14721753
14731754 /* add bitrates */
1474
- nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES);
1755
+ nl_rates = nla_nest_start_noflag(msg, NL80211_BAND_ATTR_RATES);
14751756 if (!nl_rates)
14761757 return -ENOBUFS;
14771758
14781759 for (i = 0; i < sband->n_bitrates; i++) {
1479
- nl_rate = nla_nest_start(msg, i);
1760
+ nl_rate = nla_nest_start_noflag(msg, i);
14801761 if (!nl_rate)
14811762 return -ENOBUFS;
14821763
....@@ -1509,12 +1790,12 @@
15091790 if (!mgmt_stypes)
15101791 return 0;
15111792
1512
- nl_ifs = nla_nest_start(msg, NL80211_ATTR_TX_FRAME_TYPES);
1793
+ nl_ifs = nla_nest_start_noflag(msg, NL80211_ATTR_TX_FRAME_TYPES);
15131794 if (!nl_ifs)
15141795 return -ENOBUFS;
15151796
15161797 for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
1517
- nl_ftypes = nla_nest_start(msg, ift);
1798
+ nl_ftypes = nla_nest_start_noflag(msg, ift);
15181799 if (!nl_ftypes)
15191800 return -ENOBUFS;
15201801 i = 0;
....@@ -1532,12 +1813,12 @@
15321813
15331814 nla_nest_end(msg, nl_ifs);
15341815
1535
- nl_ifs = nla_nest_start(msg, NL80211_ATTR_RX_FRAME_TYPES);
1816
+ nl_ifs = nla_nest_start_noflag(msg, NL80211_ATTR_RX_FRAME_TYPES);
15361817 if (!nl_ifs)
15371818 return -ENOBUFS;
15381819
15391820 for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
1540
- nl_ftypes = nla_nest_start(msg, ift);
1821
+ nl_ftypes = nla_nest_start_noflag(msg, ift);
15411822 if (!nl_ftypes)
15421823 return -ENOBUFS;
15431824 i = 0;
....@@ -1647,6 +1928,97 @@
16471928 }
16481929
16491930 static int
1931
+nl80211_send_pmsr_ftm_capa(const struct cfg80211_pmsr_capabilities *cap,
1932
+ struct sk_buff *msg)
1933
+{
1934
+ struct nlattr *ftm;
1935
+
1936
+ if (!cap->ftm.supported)
1937
+ return 0;
1938
+
1939
+ ftm = nla_nest_start_noflag(msg, NL80211_PMSR_TYPE_FTM);
1940
+ if (!ftm)
1941
+ return -ENOBUFS;
1942
+
1943
+ if (cap->ftm.asap && nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_ASAP))
1944
+ return -ENOBUFS;
1945
+ if (cap->ftm.non_asap &&
1946
+ nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_NON_ASAP))
1947
+ return -ENOBUFS;
1948
+ if (cap->ftm.request_lci &&
1949
+ nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_REQ_LCI))
1950
+ return -ENOBUFS;
1951
+ if (cap->ftm.request_civicloc &&
1952
+ nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_REQ_CIVICLOC))
1953
+ return -ENOBUFS;
1954
+ if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES,
1955
+ cap->ftm.preambles))
1956
+ return -ENOBUFS;
1957
+ if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS,
1958
+ cap->ftm.bandwidths))
1959
+ return -ENOBUFS;
1960
+ if (cap->ftm.max_bursts_exponent >= 0 &&
1961
+ nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT,
1962
+ cap->ftm.max_bursts_exponent))
1963
+ return -ENOBUFS;
1964
+ if (cap->ftm.max_ftms_per_burst &&
1965
+ nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST,
1966
+ cap->ftm.max_ftms_per_burst))
1967
+ return -ENOBUFS;
1968
+ if (cap->ftm.trigger_based &&
1969
+ nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED))
1970
+ return -ENOBUFS;
1971
+ if (cap->ftm.non_trigger_based &&
1972
+ nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED))
1973
+ return -ENOBUFS;
1974
+
1975
+ nla_nest_end(msg, ftm);
1976
+ return 0;
1977
+}
1978
+
1979
+static int nl80211_send_pmsr_capa(struct cfg80211_registered_device *rdev,
1980
+ struct sk_buff *msg)
1981
+{
1982
+ const struct cfg80211_pmsr_capabilities *cap = rdev->wiphy.pmsr_capa;
1983
+ struct nlattr *pmsr, *caps;
1984
+
1985
+ if (!cap)
1986
+ return 0;
1987
+
1988
+ /*
1989
+ * we don't need to clean up anything here since the caller
1990
+ * will genlmsg_cancel() if we fail
1991
+ */
1992
+
1993
+ pmsr = nla_nest_start_noflag(msg, NL80211_ATTR_PEER_MEASUREMENTS);
1994
+ if (!pmsr)
1995
+ return -ENOBUFS;
1996
+
1997
+ if (nla_put_u32(msg, NL80211_PMSR_ATTR_MAX_PEERS, cap->max_peers))
1998
+ return -ENOBUFS;
1999
+
2000
+ if (cap->report_ap_tsf &&
2001
+ nla_put_flag(msg, NL80211_PMSR_ATTR_REPORT_AP_TSF))
2002
+ return -ENOBUFS;
2003
+
2004
+ if (cap->randomize_mac_addr &&
2005
+ nla_put_flag(msg, NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR))
2006
+ return -ENOBUFS;
2007
+
2008
+ caps = nla_nest_start_noflag(msg, NL80211_PMSR_ATTR_TYPE_CAPA);
2009
+ if (!caps)
2010
+ return -ENOBUFS;
2011
+
2012
+ if (nl80211_send_pmsr_ftm_capa(cap, msg))
2013
+ return -ENOBUFS;
2014
+
2015
+ nla_nest_end(msg, caps);
2016
+ nla_nest_end(msg, pmsr);
2017
+
2018
+ return 0;
2019
+}
2020
+
2021
+static int
16502022 nl80211_put_iftype_akm_suites(struct cfg80211_registered_device *rdev,
16512023 struct sk_buff *msg)
16522024 {
....@@ -1684,6 +2056,48 @@
16842056 nla_nest_end(msg, nested);
16852057
16862058 return 0;
2059
+}
2060
+
2061
+static int
2062
+nl80211_put_tid_config_support(struct cfg80211_registered_device *rdev,
2063
+ struct sk_buff *msg)
2064
+{
2065
+ struct nlattr *supp;
2066
+
2067
+ if (!rdev->wiphy.tid_config_support.vif &&
2068
+ !rdev->wiphy.tid_config_support.peer)
2069
+ return 0;
2070
+
2071
+ supp = nla_nest_start(msg, NL80211_ATTR_TID_CONFIG);
2072
+ if (!supp)
2073
+ return -ENOSPC;
2074
+
2075
+ if (rdev->wiphy.tid_config_support.vif &&
2076
+ nla_put_u64_64bit(msg, NL80211_TID_CONFIG_ATTR_VIF_SUPP,
2077
+ rdev->wiphy.tid_config_support.vif,
2078
+ NL80211_TID_CONFIG_ATTR_PAD))
2079
+ goto fail;
2080
+
2081
+ if (rdev->wiphy.tid_config_support.peer &&
2082
+ nla_put_u64_64bit(msg, NL80211_TID_CONFIG_ATTR_PEER_SUPP,
2083
+ rdev->wiphy.tid_config_support.peer,
2084
+ NL80211_TID_CONFIG_ATTR_PAD))
2085
+ goto fail;
2086
+
2087
+ /* for now we just use the same value ... makes more sense */
2088
+ if (nla_put_u8(msg, NL80211_TID_CONFIG_ATTR_RETRY_SHORT,
2089
+ rdev->wiphy.tid_config_support.max_retry))
2090
+ goto fail;
2091
+ if (nla_put_u8(msg, NL80211_TID_CONFIG_ATTR_RETRY_LONG,
2092
+ rdev->wiphy.tid_config_support.max_retry))
2093
+ goto fail;
2094
+
2095
+ nla_nest_end(msg, supp);
2096
+
2097
+ return 0;
2098
+fail:
2099
+ nla_nest_cancel(msg, supp);
2100
+ return -ENOBUFS;
16872101 }
16882102
16892103 struct nl80211_dump_wiphy_state {
....@@ -1747,13 +2161,7 @@
17472161 nla_put_u16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN,
17482162 rdev->wiphy.max_sched_scan_ie_len) ||
17492163 nla_put_u8(msg, NL80211_ATTR_MAX_MATCH_SETS,
1750
- rdev->wiphy.max_match_sets) ||
1751
- nla_put_u32(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS,
1752
- rdev->wiphy.max_sched_scan_plans) ||
1753
- nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL,
1754
- rdev->wiphy.max_sched_scan_plan_interval) ||
1755
- nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS,
1756
- rdev->wiphy.max_sched_scan_plan_iterations))
2164
+ rdev->wiphy.max_match_sets))
17572165 goto nla_put_failure;
17582166
17592167 if ((rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) &&
....@@ -1777,6 +2185,7 @@
17772185 state->split_start++;
17782186 if (state->split)
17792187 break;
2188
+ fallthrough;
17802189 case 1:
17812190 if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES,
17822191 sizeof(u32) * rdev->wiphy.n_cipher_suites,
....@@ -1823,6 +2232,7 @@
18232232 state->split_start++;
18242233 if (state->split)
18252234 break;
2235
+ fallthrough;
18262236 case 2:
18272237 if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES,
18282238 rdev->wiphy.interface_modes))
....@@ -1830,8 +2240,10 @@
18302240 state->split_start++;
18312241 if (state->split)
18322242 break;
2243
+ fallthrough;
18332244 case 3:
1834
- nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS);
2245
+ nl_bands = nla_nest_start_noflag(msg,
2246
+ NL80211_ATTR_WIPHY_BANDS);
18352247 if (!nl_bands)
18362248 goto nla_put_failure;
18372249
....@@ -1839,33 +2251,40 @@
18392251 band < NUM_NL80211_BANDS; band++) {
18402252 struct ieee80211_supported_band *sband;
18412253
2254
+ /* omit higher bands for ancient software */
2255
+ if (band > NL80211_BAND_5GHZ && !state->split)
2256
+ break;
2257
+
18422258 sband = rdev->wiphy.bands[band];
18432259
18442260 if (!sband)
18452261 continue;
18462262
1847
- nl_band = nla_nest_start(msg, band);
2263
+ nl_band = nla_nest_start_noflag(msg, band);
18482264 if (!nl_band)
18492265 goto nla_put_failure;
18502266
18512267 switch (state->chan_start) {
18522268 case 0:
1853
- if (nl80211_send_band_rateinfo(msg, sband))
2269
+ if (nl80211_send_band_rateinfo(msg, sband,
2270
+ state->split))
18542271 goto nla_put_failure;
18552272 state->chan_start++;
18562273 if (state->split)
18572274 break;
2275
+ fallthrough;
18582276 default:
18592277 /* add frequencies */
1860
- nl_freqs = nla_nest_start(
1861
- msg, NL80211_BAND_ATTR_FREQS);
2278
+ nl_freqs = nla_nest_start_noflag(msg,
2279
+ NL80211_BAND_ATTR_FREQS);
18622280 if (!nl_freqs)
18632281 goto nla_put_failure;
18642282
18652283 for (i = state->chan_start - 1;
18662284 i < sband->n_channels;
18672285 i++) {
1868
- nl_freq = nla_nest_start(msg, i);
2286
+ nl_freq = nla_nest_start_noflag(msg,
2287
+ i);
18692288 if (!nl_freq)
18702289 goto nla_put_failure;
18712290
....@@ -1908,8 +2327,10 @@
19082327 state->split_start++;
19092328 if (state->split)
19102329 break;
2330
+ fallthrough;
19112331 case 4:
1912
- nl_cmds = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_COMMANDS);
2332
+ nl_cmds = nla_nest_start_noflag(msg,
2333
+ NL80211_ATTR_SUPPORTED_COMMANDS);
19132334 if (!nl_cmds)
19142335 goto nla_put_failure;
19152336
....@@ -1927,6 +2348,7 @@
19272348 CMD(add_tx_ts, ADD_TX_TS);
19282349 CMD(set_multicast_to_unicast, SET_MULTICAST_TO_UNICAST);
19292350 CMD(update_connect_params, UPDATE_CONNECT_PARAMS);
2351
+ CMD(update_ft_ies, UPDATE_FT_IES);
19302352 }
19312353 #undef CMD
19322354
....@@ -1934,6 +2356,7 @@
19342356 state->split_start++;
19352357 if (state->split)
19362358 break;
2359
+ fallthrough;
19372360 case 5:
19382361 if (rdev->ops->remain_on_channel &&
19392362 (rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) &&
....@@ -1946,11 +2369,10 @@
19462369 nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK))
19472370 goto nla_put_failure;
19482371
1949
- if (nl80211_send_mgmt_stypes(msg, mgmt_stypes))
1950
- goto nla_put_failure;
19512372 state->split_start++;
19522373 if (state->split)
19532374 break;
2375
+ fallthrough;
19542376 case 6:
19552377 #ifdef CONFIG_PM
19562378 if (nl80211_send_wowlan(msg, rdev, state->split))
....@@ -1961,6 +2383,7 @@
19612383 #else
19622384 state->split_start++;
19632385 #endif
2386
+ fallthrough;
19642387 case 7:
19652388 if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES,
19662389 rdev->wiphy.software_iftypes))
....@@ -1973,6 +2396,7 @@
19732396 state->split_start++;
19742397 if (state->split)
19752398 break;
2399
+ fallthrough;
19762400 case 8:
19772401 if ((rdev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) &&
19782402 nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME,
....@@ -2018,6 +2442,17 @@
20182442 state->split_start = 0;
20192443 break;
20202444 case 9:
2445
+ if (nl80211_send_mgmt_stypes(msg, mgmt_stypes))
2446
+ goto nla_put_failure;
2447
+
2448
+ if (nla_put_u32(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS,
2449
+ rdev->wiphy.max_sched_scan_plans) ||
2450
+ nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL,
2451
+ rdev->wiphy.max_sched_scan_plan_interval) ||
2452
+ nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS,
2453
+ rdev->wiphy.max_sched_scan_plan_iterations))
2454
+ goto nla_put_failure;
2455
+
20212456 if (rdev->wiphy.extended_capabilities &&
20222457 (nla_put(msg, NL80211_ATTR_EXT_CAPA,
20232458 rdev->wiphy.extended_capabilities_len,
....@@ -2032,6 +2467,30 @@
20322467 sizeof(*rdev->wiphy.vht_capa_mod_mask),
20332468 rdev->wiphy.vht_capa_mod_mask))
20342469 goto nla_put_failure;
2470
+
2471
+ if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
2472
+ rdev->wiphy.perm_addr))
2473
+ goto nla_put_failure;
2474
+
2475
+ if (!is_zero_ether_addr(rdev->wiphy.addr_mask) &&
2476
+ nla_put(msg, NL80211_ATTR_MAC_MASK, ETH_ALEN,
2477
+ rdev->wiphy.addr_mask))
2478
+ goto nla_put_failure;
2479
+
2480
+ if (rdev->wiphy.n_addresses > 1) {
2481
+ void *attr;
2482
+
2483
+ attr = nla_nest_start(msg, NL80211_ATTR_MAC_ADDRS);
2484
+ if (!attr)
2485
+ goto nla_put_failure;
2486
+
2487
+ for (i = 0; i < rdev->wiphy.n_addresses; i++)
2488
+ if (nla_put(msg, i + 1, ETH_ALEN,
2489
+ rdev->wiphy.addresses[i].addr))
2490
+ goto nla_put_failure;
2491
+
2492
+ nla_nest_end(msg, attr);
2493
+ }
20352494
20362495 state->split_start++;
20372496 break;
....@@ -2056,7 +2515,8 @@
20562515 const struct nl80211_vendor_cmd_info *info;
20572516 struct nlattr *nested;
20582517
2059
- nested = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
2518
+ nested = nla_nest_start_noflag(msg,
2519
+ NL80211_ATTR_VENDOR_DATA);
20602520 if (!nested)
20612521 goto nla_put_failure;
20622522
....@@ -2072,8 +2532,8 @@
20722532 const struct nl80211_vendor_cmd_info *info;
20732533 struct nlattr *nested;
20742534
2075
- nested = nla_nest_start(msg,
2076
- NL80211_ATTR_VENDOR_EVENTS);
2535
+ nested = nla_nest_start_noflag(msg,
2536
+ NL80211_ATTR_VENDOR_EVENTS);
20772537 if (!nested)
20782538 goto nla_put_failure;
20792539
....@@ -2110,7 +2570,8 @@
21102570 struct nlattr *nested;
21112571 u32 bss_select_support = rdev->wiphy.bss_select_support;
21122572
2113
- nested = nla_nest_start(msg, NL80211_ATTR_BSS_SELECT);
2573
+ nested = nla_nest_start_noflag(msg,
2574
+ NL80211_ATTR_BSS_SELECT);
21142575 if (!nested)
21152576 goto nla_put_failure;
21162577
....@@ -2132,8 +2593,8 @@
21322593 rdev->wiphy.iftype_ext_capab) {
21332594 struct nlattr *nested_ext_capab, *nested;
21342595
2135
- nested = nla_nest_start(msg,
2136
- NL80211_ATTR_IFTYPE_EXT_CAPA);
2596
+ nested = nla_nest_start_noflag(msg,
2597
+ NL80211_ATTR_IFTYPE_EXT_CAPA);
21372598 if (!nested)
21382599 goto nla_put_failure;
21392600
....@@ -2143,7 +2604,8 @@
21432604
21442605 capab = &rdev->wiphy.iftype_ext_capab[i];
21452606
2146
- nested_ext_capab = nla_nest_start(msg, i);
2607
+ nested_ext_capab = nla_nest_start_noflag(msg,
2608
+ i);
21472609 if (!nested_ext_capab ||
21482610 nla_put_u32(msg, NL80211_ATTR_IFTYPE,
21492611 capab->iftype) ||
....@@ -2192,7 +2654,25 @@
21922654 goto nla_put_failure;
21932655 }
21942656
2657
+ state->split_start++;
2658
+ break;
2659
+ case 14:
2660
+ if (nl80211_send_pmsr_capa(rdev, msg))
2661
+ goto nla_put_failure;
2662
+
2663
+ state->split_start++;
2664
+ break;
2665
+ case 15:
2666
+ if (rdev->wiphy.akm_suites &&
2667
+ nla_put(msg, NL80211_ATTR_AKM_SUITES,
2668
+ sizeof(u32) * rdev->wiphy.n_akm_suites,
2669
+ rdev->wiphy.akm_suites))
2670
+ goto nla_put_failure;
2671
+
21952672 if (nl80211_put_iftype_akm_suites(rdev, msg))
2673
+ goto nla_put_failure;
2674
+
2675
+ if (nl80211_put_tid_config_support(rdev, msg))
21962676 goto nla_put_failure;
21972677
21982678 /* done */
....@@ -2212,12 +2692,21 @@
22122692 struct netlink_callback *cb,
22132693 struct nl80211_dump_wiphy_state *state)
22142694 {
2215
- struct nlattr **tb = genl_family_attrbuf(&nl80211_fam);
2216
- int ret = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, tb,
2217
- nl80211_fam.maxattr, nl80211_policy, NULL);
2695
+ struct nlattr **tb = kcalloc(NUM_NL80211_ATTR, sizeof(*tb), GFP_KERNEL);
2696
+ int ret;
2697
+
2698
+ if (!tb)
2699
+ return -ENOMEM;
2700
+
2701
+ ret = nlmsg_parse_deprecated(cb->nlh,
2702
+ GENL_HDRLEN + nl80211_fam.hdrsize,
2703
+ tb, nl80211_fam.maxattr,
2704
+ nl80211_policy, NULL);
22182705 /* ignore parse errors for backward compatibility */
2219
- if (ret)
2220
- return 0;
2706
+ if (ret) {
2707
+ ret = 0;
2708
+ goto out;
2709
+ }
22212710
22222711 state->split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP];
22232712 if (tb[NL80211_ATTR_WIPHY])
....@@ -2230,8 +2719,10 @@
22302719 int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
22312720
22322721 netdev = __dev_get_by_index(sock_net(skb->sk), ifidx);
2233
- if (!netdev)
2234
- return -ENODEV;
2722
+ if (!netdev) {
2723
+ ret = -ENODEV;
2724
+ goto out;
2725
+ }
22352726 if (netdev->ieee80211_ptr) {
22362727 rdev = wiphy_to_rdev(
22372728 netdev->ieee80211_ptr->wiphy);
....@@ -2239,7 +2730,10 @@
22392730 }
22402731 }
22412732
2242
- return 0;
2733
+ ret = 0;
2734
+out:
2735
+ kfree(tb);
2736
+ return ret;
22432737 }
22442738
22452739 static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
....@@ -2395,33 +2889,41 @@
23952889 wdev->iftype == NL80211_IFTYPE_P2P_GO;
23962890 }
23972891
2398
-static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
2399
- struct genl_info *info,
2400
- struct cfg80211_chan_def *chandef)
2892
+int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
2893
+ struct genl_info *info,
2894
+ struct cfg80211_chan_def *chandef)
24012895 {
2896
+ struct netlink_ext_ack *extack = info->extack;
2897
+ struct nlattr **attrs = info->attrs;
24022898 u32 control_freq;
24032899
2404
- if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
2900
+ if (!attrs[NL80211_ATTR_WIPHY_FREQ])
24052901 return -EINVAL;
24062902
2407
- control_freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
2903
+ control_freq = MHZ_TO_KHZ(
2904
+ nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
2905
+ if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
2906
+ control_freq +=
2907
+ nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
24082908
24092909 memset(chandef, 0, sizeof(*chandef));
2410
-
2411
- chandef->chan = ieee80211_get_channel(&rdev->wiphy, control_freq);
2910
+ chandef->chan = ieee80211_get_channel_khz(&rdev->wiphy, control_freq);
24122911 chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
2413
- chandef->center_freq1 = control_freq;
2912
+ chandef->center_freq1 = KHZ_TO_MHZ(control_freq);
2913
+ chandef->freq1_offset = control_freq % 1000;
24142914 chandef->center_freq2 = 0;
24152915
24162916 /* Primary channel not allowed */
2417
- if (!chandef->chan || chandef->chan->flags & IEEE80211_CHAN_DISABLED)
2917
+ if (!chandef->chan || chandef->chan->flags & IEEE80211_CHAN_DISABLED) {
2918
+ NL_SET_ERR_MSG_ATTR(extack, attrs[NL80211_ATTR_WIPHY_FREQ],
2919
+ "Channel is disabled");
24182920 return -EINVAL;
2921
+ }
24192922
2420
- if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
2923
+ if (attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
24212924 enum nl80211_channel_type chantype;
24222925
2423
- chantype = nla_get_u32(
2424
- info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
2926
+ chantype = nla_get_u32(attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
24252927
24262928 switch (chantype) {
24272929 case NL80211_CHAN_NO_HT:
....@@ -2431,29 +2933,52 @@
24312933 cfg80211_chandef_create(chandef, chandef->chan,
24322934 chantype);
24332935 /* user input for center_freq is incorrect */
2434
- if (info->attrs[NL80211_ATTR_CENTER_FREQ1] &&
2435
- chandef->center_freq1 != nla_get_u32(
2436
- info->attrs[NL80211_ATTR_CENTER_FREQ1]))
2936
+ if (attrs[NL80211_ATTR_CENTER_FREQ1] &&
2937
+ chandef->center_freq1 != nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1])) {
2938
+ NL_SET_ERR_MSG_ATTR(extack,
2939
+ attrs[NL80211_ATTR_CENTER_FREQ1],
2940
+ "bad center frequency 1");
24372941 return -EINVAL;
2942
+ }
24382943 /* center_freq2 must be zero */
2439
- if (info->attrs[NL80211_ATTR_CENTER_FREQ2] &&
2440
- nla_get_u32(info->attrs[NL80211_ATTR_CENTER_FREQ2]))
2944
+ if (attrs[NL80211_ATTR_CENTER_FREQ2] &&
2945
+ nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2])) {
2946
+ NL_SET_ERR_MSG_ATTR(extack,
2947
+ attrs[NL80211_ATTR_CENTER_FREQ2],
2948
+ "center frequency 2 can't be used");
24412949 return -EINVAL;
2950
+ }
24422951 break;
24432952 default:
2953
+ NL_SET_ERR_MSG_ATTR(extack,
2954
+ attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
2955
+ "invalid channel type");
24442956 return -EINVAL;
24452957 }
2446
- } else if (info->attrs[NL80211_ATTR_CHANNEL_WIDTH]) {
2958
+ } else if (attrs[NL80211_ATTR_CHANNEL_WIDTH]) {
24472959 chandef->width =
2448
- nla_get_u32(info->attrs[NL80211_ATTR_CHANNEL_WIDTH]);
2449
- if (info->attrs[NL80211_ATTR_CENTER_FREQ1])
2960
+ nla_get_u32(attrs[NL80211_ATTR_CHANNEL_WIDTH]);
2961
+ if (chandef->chan->band == NL80211_BAND_S1GHZ) {
2962
+ /* User input error for channel width doesn't match channel */
2963
+ if (chandef->width != ieee80211_s1g_channel_width(chandef->chan)) {
2964
+ NL_SET_ERR_MSG_ATTR(extack,
2965
+ attrs[NL80211_ATTR_CHANNEL_WIDTH],
2966
+ "bad channel width");
2967
+ return -EINVAL;
2968
+ }
2969
+ }
2970
+ if (attrs[NL80211_ATTR_CENTER_FREQ1]) {
24502971 chandef->center_freq1 =
2451
- nla_get_u32(
2452
- info->attrs[NL80211_ATTR_CENTER_FREQ1]);
2453
- if (info->attrs[NL80211_ATTR_CENTER_FREQ2])
2972
+ nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1]);
2973
+ if (attrs[NL80211_ATTR_CENTER_FREQ1_OFFSET])
2974
+ chandef->freq1_offset = nla_get_u32(
2975
+ attrs[NL80211_ATTR_CENTER_FREQ1_OFFSET]);
2976
+ else
2977
+ chandef->freq1_offset = 0;
2978
+ }
2979
+ if (attrs[NL80211_ATTR_CENTER_FREQ2])
24542980 chandef->center_freq2 =
2455
- nla_get_u32(
2456
- info->attrs[NL80211_ATTR_CENTER_FREQ2]);
2981
+ nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2]);
24572982 }
24582983
24592984 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]) {
....@@ -2468,17 +2993,23 @@
24682993 chandef->edmg.channels = 0;
24692994 }
24702995
2471
- if (!cfg80211_chandef_valid(chandef))
2996
+ if (!cfg80211_chandef_valid(chandef)) {
2997
+ NL_SET_ERR_MSG(extack, "invalid channel definition");
24722998 return -EINVAL;
2999
+ }
24733000
24743001 if (!cfg80211_chandef_usable(&rdev->wiphy, chandef,
2475
- IEEE80211_CHAN_DISABLED))
3002
+ IEEE80211_CHAN_DISABLED)) {
3003
+ NL_SET_ERR_MSG(extack, "(extension) channel is disabled");
24763004 return -EINVAL;
3005
+ }
24773006
24783007 if ((chandef->width == NL80211_CHAN_WIDTH_5 ||
24793008 chandef->width == NL80211_CHAN_WIDTH_10) &&
2480
- !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ))
3009
+ !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ)) {
3010
+ NL_SET_ERR_MSG(extack, "5/10 MHz not supported");
24813011 return -EINVAL;
3012
+ }
24823013
24833014 return 0;
24843015 }
....@@ -2653,10 +3184,11 @@
26533184 nla_for_each_nested(nl_txq_params,
26543185 info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
26553186 rem_txq_params) {
2656
- result = nla_parse_nested(tb, NL80211_TXQ_ATTR_MAX,
2657
- nl_txq_params,
2658
- txq_params_policy,
2659
- info->extack);
3187
+ result = nla_parse_nested_deprecated(tb,
3188
+ NL80211_TXQ_ATTR_MAX,
3189
+ nl_txq_params,
3190
+ txq_params_policy,
3191
+ info->extack);
26603192 if (result)
26613193 return result;
26623194 result = parse_txq_params(tb, &txq_params);
....@@ -2738,8 +3270,6 @@
27383270 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {
27393271 retry_short = nla_get_u8(
27403272 info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]);
2741
- if (retry_short == 0)
2742
- return -EINVAL;
27433273
27443274 changed |= WIPHY_PARAM_RETRY_SHORT;
27453275 }
....@@ -2747,8 +3277,6 @@
27473277 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]) {
27483278 retry_long = nla_get_u8(
27493279 info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]);
2750
- if (retry_long == 0)
2751
- return -EINVAL;
27523280
27533281 changed |= WIPHY_PARAM_RETRY_LONG;
27543282 }
....@@ -2871,12 +3399,6 @@
28713399 return 0;
28723400 }
28733401
2874
-static inline u64 wdev_id(struct wireless_dev *wdev)
2875
-{
2876
- return (u64)wdev->identifier |
2877
- ((u64)wiphy_to_rdev(wdev->wiphy)->wiphy_idx << 32);
2878
-}
2879
-
28803402 static int nl80211_send_chandef(struct sk_buff *msg,
28813403 const struct cfg80211_chan_def *chandef)
28823404 {
....@@ -2885,6 +3407,9 @@
28853407
28863408 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
28873409 chandef->chan->center_freq))
3410
+ return -ENOBUFS;
3411
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
3412
+ chandef->chan->freq_offset))
28883413 return -ENOBUFS;
28893414 switch (chandef->width) {
28903415 case NL80211_CHAN_WIDTH_20_NOHT:
....@@ -2909,14 +3434,15 @@
29093434
29103435 static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags,
29113436 struct cfg80211_registered_device *rdev,
2912
- struct wireless_dev *wdev, bool removal)
3437
+ struct wireless_dev *wdev,
3438
+ enum nl80211_commands cmd)
29133439 {
29143440 struct net_device *dev = wdev->netdev;
2915
- u8 cmd = NL80211_CMD_NEW_INTERFACE;
29163441 void *hdr;
29173442
2918
- if (removal)
2919
- cmd = NL80211_CMD_DEL_INTERFACE;
3443
+ WARN_ON(cmd != NL80211_CMD_NEW_INTERFACE &&
3444
+ cmd != NL80211_CMD_DEL_INTERFACE &&
3445
+ cmd != NL80211_CMD_SET_INTERFACE);
29203446
29213447 hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
29223448 if (!hdr)
....@@ -2962,6 +3488,7 @@
29623488 wdev_lock(wdev);
29633489 switch (wdev->iftype) {
29643490 case NL80211_IFTYPE_AP:
3491
+ case NL80211_IFTYPE_P2P_GO:
29653492 if (wdev->ssid_len &&
29663493 nla_put(msg, NL80211_ATTR_SSID, wdev->ssid_len, wdev->ssid))
29673494 goto nla_put_failure_locked;
....@@ -3064,7 +3591,8 @@
30643591 }
30653592 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid,
30663593 cb->nlh->nlmsg_seq, NLM_F_MULTI,
3067
- rdev, wdev, false) < 0) {
3594
+ rdev, wdev,
3595
+ NL80211_CMD_NEW_INTERFACE) < 0) {
30683596 goto out;
30693597 }
30703598 if_idx++;
....@@ -3094,7 +3622,7 @@
30943622 return -ENOMEM;
30953623
30963624 if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0,
3097
- rdev, wdev, false) < 0) {
3625
+ rdev, wdev, NL80211_CMD_NEW_INTERFACE) < 0) {
30983626 nlmsg_free(msg);
30993627 return -ENOBUFS;
31003628 }
....@@ -3121,8 +3649,7 @@
31213649 if (!nla)
31223650 return -EINVAL;
31233651
3124
- if (nla_parse_nested(flags, NL80211_MNTR_FLAG_MAX, nla,
3125
- mntr_flags_policy, NULL))
3652
+ if (nla_parse_nested_deprecated(flags, NL80211_MNTR_FLAG_MAX, nla, mntr_flags_policy, NULL))
31263653 return -EINVAL;
31273654
31283655 for (flag = 1; flag <= NL80211_MNTR_FLAG_MAX; flag++)
....@@ -3202,7 +3729,7 @@
32023729 enum nl80211_iftype iftype)
32033730 {
32043731 if (!use_4addr) {
3205
- if (netdev && (netdev->priv_flags & IFF_BRIDGE_PORT))
3732
+ if (netdev && netif_is_bridge_port(netdev))
32063733 return -EBUSY;
32073734 return 0;
32083735 }
....@@ -3240,8 +3767,6 @@
32403767 ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
32413768 if (otype != ntype)
32423769 change = true;
3243
- if (ntype > NL80211_IFTYPE_MAX)
3244
- return -EINVAL;
32453770 }
32463771
32473772 if (info->attrs[NL80211_ATTR_MESH_ID]) {
....@@ -3286,6 +3811,12 @@
32863811 if (!err && params.use_4addr != -1)
32873812 dev->ieee80211_ptr->use_4addr = params.use_4addr;
32883813
3814
+ if (change && !err) {
3815
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
3816
+
3817
+ nl80211_notify_iface(rdev, wdev, NL80211_CMD_SET_INTERFACE);
3818
+ }
3819
+
32893820 return err;
32903821 }
32913822
....@@ -3306,11 +3837,8 @@
33063837 if (!info->attrs[NL80211_ATTR_IFNAME])
33073838 return -EINVAL;
33083839
3309
- if (info->attrs[NL80211_ATTR_IFTYPE]) {
3840
+ if (info->attrs[NL80211_ATTR_IFTYPE])
33103841 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
3311
- if (type > NL80211_IFTYPE_MAX)
3312
- return -EINVAL;
3313
- }
33143842
33153843 if (!rdev->ops->add_virtual_intf)
33163844 return -EOPNOTSUPP;
....@@ -3375,34 +3903,18 @@
33753903 * P2P Device and NAN do not have a netdev, so don't go
33763904 * through the netdev notifier and must be added here
33773905 */
3378
- mutex_init(&wdev->mtx);
3379
- INIT_LIST_HEAD(&wdev->event_list);
3380
- spin_lock_init(&wdev->event_lock);
3381
- INIT_LIST_HEAD(&wdev->mgmt_registrations);
3382
- spin_lock_init(&wdev->mgmt_registrations_lock);
3383
-
3384
- wdev->identifier = ++rdev->wdev_id;
3385
- list_add_rcu(&wdev->list, &rdev->wiphy.wdev_list);
3386
- rdev->devlist_generation++;
3906
+ cfg80211_init_wdev(wdev);
3907
+ cfg80211_register_wdev(rdev, wdev);
33873908 break;
33883909 default:
33893910 break;
33903911 }
33913912
33923913 if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0,
3393
- rdev, wdev, false) < 0) {
3914
+ rdev, wdev, NL80211_CMD_NEW_INTERFACE) < 0) {
33943915 nlmsg_free(msg);
33953916 return -ENOBUFS;
33963917 }
3397
-
3398
- /*
3399
- * For wdevs which have no associated netdev object (e.g. of type
3400
- * NL80211_IFTYPE_P2P_DEVICE), emit the NEW_INTERFACE event here.
3401
- * For all other types, the event will be generated from the
3402
- * netdev notifier
3403
- */
3404
- if (!wdev->netdev)
3405
- nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE);
34063918
34073919 return genlmsg_reply(msg, info);
34083920 }
....@@ -3467,7 +3979,7 @@
34673979 params->cipher)))
34683980 goto nla_put_failure;
34693981
3470
- key = nla_nest_start(cookie->msg, NL80211_ATTR_KEY);
3982
+ key = nla_nest_start_noflag(cookie->msg, NL80211_ATTR_KEY);
34713983 if (!key)
34723984 goto nla_put_failure;
34733985
....@@ -3505,18 +4017,26 @@
35054017 };
35064018 void *hdr;
35074019 struct sk_buff *msg;
4020
+ bool bigtk_support = false;
4021
+
4022
+ if (wiphy_ext_feature_isset(&rdev->wiphy,
4023
+ NL80211_EXT_FEATURE_BEACON_PROTECTION))
4024
+ bigtk_support = true;
4025
+
4026
+ if ((dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION ||
4027
+ dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
4028
+ wiphy_ext_feature_isset(&rdev->wiphy,
4029
+ NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT))
4030
+ bigtk_support = true;
35084031
35094032 if (info->attrs[NL80211_ATTR_KEY_IDX]) {
35104033 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
3511
- if (key_idx > 5 &&
3512
- !wiphy_ext_feature_isset(
3513
- &rdev->wiphy,
3514
- NL80211_EXT_FEATURE_BEACON_PROTECTION))
3515
- return -EINVAL;
3516
- }
35174034
3518
- if (key_idx > 5)
3519
- return -EINVAL;
4035
+ if (key_idx >= 6 && key_idx <= 7 && !bigtk_support) {
4036
+ GENL_SET_ERR_MSG(info, "BIGTK not supported");
4037
+ return -EINVAL;
4038
+ }
4039
+ }
35204040
35214041 if (info->attrs[NL80211_ATTR_MAC])
35224042 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
....@@ -3525,8 +4045,6 @@
35254045 if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
35264046 u32 kt = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
35274047
3528
- if (kt >= NUM_NL80211_KEYTYPES)
3529
- return -EINVAL;
35304048 if (kt != NL80211_KEYTYPE_GROUP &&
35314049 kt != NL80211_KEYTYPE_PAIRWISE)
35324050 return -EINVAL;
....@@ -3591,8 +4109,11 @@
35914109 if (key.idx < 0)
35924110 return -EINVAL;
35934111
3594
- /* only support setting default key */
3595
- if (!key.def && !key.defmgmt && !key.defbeacon)
4112
+ /* Only support setting default key and
4113
+ * Extended Key ID action NL80211_KEY_SET_TX.
4114
+ */
4115
+ if (!key.def && !key.defmgmt && !key.defbeacon &&
4116
+ !(key.p.mode == NL80211_KEY_SET_TX))
35964117 return -EINVAL;
35974118
35984119 wdev_lock(dev->ieee80211_ptr);
....@@ -3656,8 +4177,25 @@
36564177 err = rdev_set_default_beacon_key(rdev, dev, key.idx);
36574178 if (err)
36584179 goto out;
3659
- }
4180
+ } else if (key.p.mode == NL80211_KEY_SET_TX &&
4181
+ wiphy_ext_feature_isset(&rdev->wiphy,
4182
+ NL80211_EXT_FEATURE_EXT_KEY_ID)) {
4183
+ u8 *mac_addr = NULL;
36604184
4185
+ if (info->attrs[NL80211_ATTR_MAC])
4186
+ mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
4187
+
4188
+ if (!mac_addr || key.idx < 0 || key.idx > 1) {
4189
+ err = -EINVAL;
4190
+ goto out;
4191
+ }
4192
+
4193
+ err = rdev_add_key(rdev, dev, key.idx,
4194
+ NL80211_KEYTYPE_PAIRWISE,
4195
+ mac_addr, &key.p);
4196
+ } else {
4197
+ err = -EINVAL;
4198
+ }
36614199 out:
36624200 wdev_unlock(dev->ieee80211_ptr);
36634201
....@@ -3676,8 +4214,10 @@
36764214 if (err)
36774215 return err;
36784216
3679
- if (!key.p.key)
4217
+ if (!key.p.key) {
4218
+ GENL_SET_ERR_MSG(info, "no key");
36804219 return -EINVAL;
4220
+ }
36814221
36824222 if (info->attrs[NL80211_ATTR_MAC])
36834223 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
....@@ -3691,23 +4231,36 @@
36914231
36924232 /* for now */
36934233 if (key.type != NL80211_KEYTYPE_PAIRWISE &&
3694
- key.type != NL80211_KEYTYPE_GROUP)
4234
+ key.type != NL80211_KEYTYPE_GROUP) {
4235
+ GENL_SET_ERR_MSG(info, "key type not pairwise or group");
36954236 return -EINVAL;
4237
+ }
4238
+
4239
+ if (key.type == NL80211_KEYTYPE_GROUP &&
4240
+ info->attrs[NL80211_ATTR_VLAN_ID])
4241
+ key.p.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
36964242
36974243 if (!rdev->ops->add_key)
36984244 return -EOPNOTSUPP;
36994245
37004246 if (cfg80211_validate_key_settings(rdev, &key.p, key.idx,
37014247 key.type == NL80211_KEYTYPE_PAIRWISE,
3702
- mac_addr))
4248
+ mac_addr)) {
4249
+ GENL_SET_ERR_MSG(info, "key setting validation failed");
37034250 return -EINVAL;
4251
+ }
37044252
37054253 wdev_lock(dev->ieee80211_ptr);
37064254 err = nl80211_key_allowed(dev->ieee80211_ptr);
3707
- if (!err)
4255
+ if (err)
4256
+ GENL_SET_ERR_MSG(info, "key not allowed");
4257
+ if (!err) {
37084258 err = rdev_add_key(rdev, dev, key.idx,
37094259 key.type == NL80211_KEYTYPE_PAIRWISE,
37104260 mac_addr, &key.p);
4261
+ if (err)
4262
+ GENL_SET_ERR_MSG(info, "key addition failed");
4263
+ }
37114264 wdev_unlock(dev->ieee80211_ptr);
37124265
37134266 return err;
....@@ -3822,8 +4375,7 @@
38224375 if (n_entries > wiphy->max_acl_mac_addrs)
38234376 return ERR_PTR(-ENOTSUPP);
38244377
3825
- acl = kzalloc(sizeof(*acl) + (sizeof(struct mac_address) * n_entries),
3826
- GFP_KERNEL);
4378
+ acl = kzalloc(struct_size(acl, mac_addrs, n_entries), GFP_KERNEL);
38274379 if (!acl)
38284380 return ERR_PTR(-ENOMEM);
38294381
....@@ -3977,28 +4529,106 @@
39774529 return true;
39784530 }
39794531
3980
-static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = {
3981
- [NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY,
3982
- .len = NL80211_MAX_SUPP_RATES },
3983
- [NL80211_TXRATE_HT] = { .type = NLA_BINARY,
3984
- .len = NL80211_MAX_SUPP_HT_RATES },
3985
- [NL80211_TXRATE_VHT] = { .len = sizeof(struct nl80211_txrate_vht)},
3986
- [NL80211_TXRATE_GI] = { .type = NLA_U8 },
3987
-};
4532
+static u16 he_mcs_map_to_mcs_mask(u8 he_mcs_map)
4533
+{
4534
+ switch (he_mcs_map) {
4535
+ case IEEE80211_HE_MCS_NOT_SUPPORTED:
4536
+ return 0;
4537
+ case IEEE80211_HE_MCS_SUPPORT_0_7:
4538
+ return 0x00FF;
4539
+ case IEEE80211_HE_MCS_SUPPORT_0_9:
4540
+ return 0x03FF;
4541
+ case IEEE80211_HE_MCS_SUPPORT_0_11:
4542
+ return 0xFFF;
4543
+ default:
4544
+ break;
4545
+ }
4546
+ return 0;
4547
+}
4548
+
4549
+static void he_build_mcs_mask(u16 he_mcs_map,
4550
+ u16 he_mcs_mask[NL80211_HE_NSS_MAX])
4551
+{
4552
+ u8 nss;
4553
+
4554
+ for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++) {
4555
+ he_mcs_mask[nss] = he_mcs_map_to_mcs_mask(he_mcs_map & 0x03);
4556
+ he_mcs_map >>= 2;
4557
+ }
4558
+}
4559
+
4560
+static u16 he_get_txmcsmap(struct genl_info *info,
4561
+ const struct ieee80211_sta_he_cap *he_cap)
4562
+{
4563
+ struct net_device *dev = info->user_ptr[1];
4564
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
4565
+ __le16 tx_mcs;
4566
+
4567
+ switch (wdev->chandef.width) {
4568
+ case NL80211_CHAN_WIDTH_80P80:
4569
+ tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_80p80;
4570
+ break;
4571
+ case NL80211_CHAN_WIDTH_160:
4572
+ tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_160;
4573
+ break;
4574
+ default:
4575
+ tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_80;
4576
+ break;
4577
+ }
4578
+ return le16_to_cpu(tx_mcs);
4579
+}
4580
+
4581
+static bool he_set_mcs_mask(struct genl_info *info,
4582
+ struct wireless_dev *wdev,
4583
+ struct ieee80211_supported_band *sband,
4584
+ struct nl80211_txrate_he *txrate,
4585
+ u16 mcs[NL80211_HE_NSS_MAX])
4586
+{
4587
+ const struct ieee80211_sta_he_cap *he_cap;
4588
+ u16 tx_mcs_mask[NL80211_HE_NSS_MAX] = {};
4589
+ u16 tx_mcs_map = 0;
4590
+ u8 i;
4591
+
4592
+ he_cap = ieee80211_get_he_iftype_cap(sband, wdev->iftype);
4593
+ if (!he_cap)
4594
+ return false;
4595
+
4596
+ memset(mcs, 0, sizeof(u16) * NL80211_HE_NSS_MAX);
4597
+
4598
+ tx_mcs_map = he_get_txmcsmap(info, he_cap);
4599
+
4600
+ /* Build he_mcs_mask from HE capabilities */
4601
+ he_build_mcs_mask(tx_mcs_map, tx_mcs_mask);
4602
+
4603
+ for (i = 0; i < NL80211_HE_NSS_MAX; i++) {
4604
+ if ((tx_mcs_mask[i] & txrate->mcs[i]) == txrate->mcs[i])
4605
+ mcs[i] = txrate->mcs[i];
4606
+ else
4607
+ return false;
4608
+ }
4609
+
4610
+ return true;
4611
+}
39884612
39894613 static int nl80211_parse_tx_bitrate_mask(struct genl_info *info,
3990
- struct cfg80211_bitrate_mask *mask)
4614
+ struct nlattr *attrs[],
4615
+ enum nl80211_attrs attr,
4616
+ struct cfg80211_bitrate_mask *mask,
4617
+ struct net_device *dev)
39914618 {
39924619 struct nlattr *tb[NL80211_TXRATE_MAX + 1];
39934620 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4621
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
39944622 int rem, i;
39954623 struct nlattr *tx_rates;
39964624 struct ieee80211_supported_band *sband;
3997
- u16 vht_tx_mcs_map;
4625
+ u16 vht_tx_mcs_map, he_tx_mcs_map;
39984626
39994627 memset(mask, 0, sizeof(*mask));
40004628 /* Default to all rates enabled */
40014629 for (i = 0; i < NUM_NL80211_BANDS; i++) {
4630
+ const struct ieee80211_sta_he_cap *he_cap;
4631
+
40024632 sband = rdev->wiphy.bands[i];
40034633
40044634 if (!sband)
....@@ -4009,22 +4639,31 @@
40094639 sband->ht_cap.mcs.rx_mask,
40104640 sizeof(mask->control[i].ht_mcs));
40114641
4012
- if (!sband->vht_cap.vht_supported)
4642
+ if (sband->vht_cap.vht_supported) {
4643
+ vht_tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
4644
+ vht_build_mcs_mask(vht_tx_mcs_map, mask->control[i].vht_mcs);
4645
+ }
4646
+
4647
+ he_cap = ieee80211_get_he_iftype_cap(sband, wdev->iftype);
4648
+ if (!he_cap)
40134649 continue;
40144650
4015
- vht_tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
4016
- vht_build_mcs_mask(vht_tx_mcs_map, mask->control[i].vht_mcs);
4651
+ he_tx_mcs_map = he_get_txmcsmap(info, he_cap);
4652
+ he_build_mcs_mask(he_tx_mcs_map, mask->control[i].he_mcs);
4653
+
4654
+ mask->control[i].he_gi = 0xFF;
4655
+ mask->control[i].he_ltf = 0xFF;
40174656 }
40184657
40194658 /* if no rates are given set it back to the defaults */
4020
- if (!info->attrs[NL80211_ATTR_TX_RATES])
4659
+ if (!attrs[attr])
40214660 goto out;
40224661
40234662 /* The nested attribute uses enum nl80211_band as the index. This maps
40244663 * directly to the enum nl80211_band values used in cfg80211.
40254664 */
40264665 BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8);
4027
- nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) {
4666
+ nla_for_each_nested(tx_rates, attrs[attr], rem) {
40284667 enum nl80211_band band = nla_type(tx_rates);
40294668 int err;
40304669
....@@ -4033,8 +4672,10 @@
40334672 sband = rdev->wiphy.bands[band];
40344673 if (sband == NULL)
40354674 return -EINVAL;
4036
- err = nla_parse_nested(tb, NL80211_TXRATE_MAX, tx_rates,
4037
- nl80211_txattr_policy, info->extack);
4675
+ err = nla_parse_nested_deprecated(tb, NL80211_TXRATE_MAX,
4676
+ tx_rates,
4677
+ nl80211_txattr_policy,
4678
+ info->extack);
40384679 if (err)
40394680 return err;
40404681 if (tb[NL80211_TXRATE_LEGACY]) {
....@@ -4067,13 +4708,25 @@
40674708 if (mask->control[band].gi > NL80211_TXRATE_FORCE_LGI)
40684709 return -EINVAL;
40694710 }
4711
+ if (tb[NL80211_TXRATE_HE] &&
4712
+ !he_set_mcs_mask(info, wdev, sband,
4713
+ nla_data(tb[NL80211_TXRATE_HE]),
4714
+ mask->control[band].he_mcs))
4715
+ return -EINVAL;
4716
+ if (tb[NL80211_TXRATE_HE_GI])
4717
+ mask->control[band].he_gi =
4718
+ nla_get_u8(tb[NL80211_TXRATE_HE_GI]);
4719
+ if (tb[NL80211_TXRATE_HE_LTF])
4720
+ mask->control[band].he_ltf =
4721
+ nla_get_u8(tb[NL80211_TXRATE_HE_LTF]);
40704722
40714723 if (mask->control[band].legacy == 0) {
4072
- /* don't allow empty legacy rates if HT or VHT
4724
+ /* don't allow empty legacy rates if HT, VHT or HE
40734725 * are not even supported.
40744726 */
40754727 if (!(rdev->wiphy.bands[band]->ht_cap.ht_supported ||
4076
- rdev->wiphy.bands[band]->vht_cap.vht_supported))
4728
+ rdev->wiphy.bands[band]->vht_cap.vht_supported ||
4729
+ ieee80211_get_he_iftype_cap(sband, wdev->iftype)))
40774730 return -EINVAL;
40784731
40794732 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
....@@ -4082,6 +4735,10 @@
40824735
40834736 for (i = 0; i < NL80211_VHT_NSS_MAX; i++)
40844737 if (mask->control[band].vht_mcs[i])
4738
+ goto out;
4739
+
4740
+ for (i = 0; i < NL80211_HE_NSS_MAX; i++)
4741
+ if (mask->control[band].he_mcs[i])
40854742 goto out;
40864743
40874744 /* legacy and mcs rates may not be both empty */
....@@ -4149,26 +4806,16 @@
41494806 return 0;
41504807 }
41514808
4152
-static int nl80211_parse_beacon(struct nlattr *attrs[],
4809
+static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
4810
+ struct nlattr *attrs[],
41534811 struct cfg80211_beacon_data *bcn)
41544812 {
41554813 bool haveinfo = false;
4156
-
4157
- if (!is_valid_ie_attr(attrs[NL80211_ATTR_BEACON_TAIL]) ||
4158
- !is_valid_ie_attr(attrs[NL80211_ATTR_IE]) ||
4159
- !is_valid_ie_attr(attrs[NL80211_ATTR_IE_PROBE_RESP]) ||
4160
- !is_valid_ie_attr(attrs[NL80211_ATTR_IE_ASSOC_RESP]))
4161
- return -EINVAL;
4814
+ int err;
41624815
41634816 memset(bcn, 0, sizeof(*bcn));
41644817
41654818 if (attrs[NL80211_ATTR_BEACON_HEAD]) {
4166
- int ret = validate_beacon_head(attrs[NL80211_ATTR_BEACON_HEAD],
4167
- NULL);
4168
-
4169
- if (ret)
4170
- return ret;
4171
-
41724819 bcn->head = nla_data(attrs[NL80211_ATTR_BEACON_HEAD]);
41734820 bcn->head_len = nla_len(attrs[NL80211_ATTR_BEACON_HEAD]);
41744821 if (!bcn->head_len)
....@@ -4209,6 +4856,163 @@
42094856 bcn->probe_resp_len = nla_len(attrs[NL80211_ATTR_PROBE_RESP]);
42104857 }
42114858
4859
+ if (attrs[NL80211_ATTR_FTM_RESPONDER]) {
4860
+ struct nlattr *tb[NL80211_FTM_RESP_ATTR_MAX + 1];
4861
+
4862
+ err = nla_parse_nested_deprecated(tb,
4863
+ NL80211_FTM_RESP_ATTR_MAX,
4864
+ attrs[NL80211_ATTR_FTM_RESPONDER],
4865
+ NULL, NULL);
4866
+ if (err)
4867
+ return err;
4868
+
4869
+ if (tb[NL80211_FTM_RESP_ATTR_ENABLED] &&
4870
+ wiphy_ext_feature_isset(&rdev->wiphy,
4871
+ NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER))
4872
+ bcn->ftm_responder = 1;
4873
+ else
4874
+ return -EOPNOTSUPP;
4875
+
4876
+ if (tb[NL80211_FTM_RESP_ATTR_LCI]) {
4877
+ bcn->lci = nla_data(tb[NL80211_FTM_RESP_ATTR_LCI]);
4878
+ bcn->lci_len = nla_len(tb[NL80211_FTM_RESP_ATTR_LCI]);
4879
+ }
4880
+
4881
+ if (tb[NL80211_FTM_RESP_ATTR_CIVICLOC]) {
4882
+ bcn->civicloc = nla_data(tb[NL80211_FTM_RESP_ATTR_CIVICLOC]);
4883
+ bcn->civicloc_len = nla_len(tb[NL80211_FTM_RESP_ATTR_CIVICLOC]);
4884
+ }
4885
+ } else {
4886
+ bcn->ftm_responder = -1;
4887
+ }
4888
+
4889
+ return 0;
4890
+}
4891
+
4892
+static int nl80211_parse_he_obss_pd(struct nlattr *attrs,
4893
+ struct ieee80211_he_obss_pd *he_obss_pd)
4894
+{
4895
+ struct nlattr *tb[NL80211_HE_OBSS_PD_ATTR_MAX + 1];
4896
+ int err;
4897
+
4898
+ err = nla_parse_nested(tb, NL80211_HE_OBSS_PD_ATTR_MAX, attrs,
4899
+ he_obss_pd_policy, NULL);
4900
+ if (err)
4901
+ return err;
4902
+
4903
+ if (!tb[NL80211_HE_OBSS_PD_ATTR_SR_CTRL])
4904
+ return -EINVAL;
4905
+
4906
+ he_obss_pd->sr_ctrl = nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_SR_CTRL]);
4907
+
4908
+ if (tb[NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET])
4909
+ he_obss_pd->min_offset =
4910
+ nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET]);
4911
+ if (tb[NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET])
4912
+ he_obss_pd->max_offset =
4913
+ nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET]);
4914
+ if (tb[NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET])
4915
+ he_obss_pd->non_srg_max_offset =
4916
+ nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET]);
4917
+
4918
+ if (he_obss_pd->min_offset > he_obss_pd->max_offset)
4919
+ return -EINVAL;
4920
+
4921
+ if (tb[NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP])
4922
+ memcpy(he_obss_pd->bss_color_bitmap,
4923
+ nla_data(tb[NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP]),
4924
+ sizeof(he_obss_pd->bss_color_bitmap));
4925
+
4926
+ if (tb[NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP])
4927
+ memcpy(he_obss_pd->partial_bssid_bitmap,
4928
+ nla_data(tb[NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP]),
4929
+ sizeof(he_obss_pd->partial_bssid_bitmap));
4930
+
4931
+ he_obss_pd->enable = true;
4932
+
4933
+ return 0;
4934
+}
4935
+
4936
+static int nl80211_parse_he_bss_color(struct nlattr *attrs,
4937
+ struct cfg80211_he_bss_color *he_bss_color)
4938
+{
4939
+ struct nlattr *tb[NL80211_HE_BSS_COLOR_ATTR_MAX + 1];
4940
+ int err;
4941
+
4942
+ err = nla_parse_nested(tb, NL80211_HE_BSS_COLOR_ATTR_MAX, attrs,
4943
+ he_bss_color_policy, NULL);
4944
+ if (err)
4945
+ return err;
4946
+
4947
+ if (!tb[NL80211_HE_BSS_COLOR_ATTR_COLOR])
4948
+ return -EINVAL;
4949
+
4950
+ he_bss_color->color =
4951
+ nla_get_u8(tb[NL80211_HE_BSS_COLOR_ATTR_COLOR]);
4952
+ he_bss_color->enabled =
4953
+ !nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_DISABLED]);
4954
+ he_bss_color->partial =
4955
+ nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_PARTIAL]);
4956
+
4957
+ return 0;
4958
+}
4959
+
4960
+static int nl80211_parse_fils_discovery(struct cfg80211_registered_device *rdev,
4961
+ struct nlattr *attrs,
4962
+ struct cfg80211_ap_settings *params)
4963
+{
4964
+ struct nlattr *tb[NL80211_FILS_DISCOVERY_ATTR_MAX + 1];
4965
+ int ret;
4966
+ struct cfg80211_fils_discovery *fd = &params->fils_discovery;
4967
+
4968
+ if (!wiphy_ext_feature_isset(&rdev->wiphy,
4969
+ NL80211_EXT_FEATURE_FILS_DISCOVERY))
4970
+ return -EINVAL;
4971
+
4972
+ ret = nla_parse_nested(tb, NL80211_FILS_DISCOVERY_ATTR_MAX, attrs,
4973
+ NULL, NULL);
4974
+ if (ret)
4975
+ return ret;
4976
+
4977
+ if (!tb[NL80211_FILS_DISCOVERY_ATTR_INT_MIN] ||
4978
+ !tb[NL80211_FILS_DISCOVERY_ATTR_INT_MAX] ||
4979
+ !tb[NL80211_FILS_DISCOVERY_ATTR_TMPL])
4980
+ return -EINVAL;
4981
+
4982
+ fd->tmpl_len = nla_len(tb[NL80211_FILS_DISCOVERY_ATTR_TMPL]);
4983
+ fd->tmpl = nla_data(tb[NL80211_FILS_DISCOVERY_ATTR_TMPL]);
4984
+ fd->min_interval = nla_get_u32(tb[NL80211_FILS_DISCOVERY_ATTR_INT_MIN]);
4985
+ fd->max_interval = nla_get_u32(tb[NL80211_FILS_DISCOVERY_ATTR_INT_MAX]);
4986
+
4987
+ return 0;
4988
+}
4989
+
4990
+static int
4991
+nl80211_parse_unsol_bcast_probe_resp(struct cfg80211_registered_device *rdev,
4992
+ struct nlattr *attrs,
4993
+ struct cfg80211_ap_settings *params)
4994
+{
4995
+ struct nlattr *tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX + 1];
4996
+ int ret;
4997
+ struct cfg80211_unsol_bcast_probe_resp *presp =
4998
+ &params->unsol_bcast_probe_resp;
4999
+
5000
+ if (!wiphy_ext_feature_isset(&rdev->wiphy,
5001
+ NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP))
5002
+ return -EINVAL;
5003
+
5004
+ ret = nla_parse_nested(tb, NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX,
5005
+ attrs, NULL, NULL);
5006
+ if (ret)
5007
+ return ret;
5008
+
5009
+ if (!tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT] ||
5010
+ !tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL])
5011
+ return -EINVAL;
5012
+
5013
+ presp->tmpl = nla_data(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL]);
5014
+ presp->tmpl_len = nla_len(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL]);
5015
+ presp->interval = nla_get_u32(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT]);
42125016 return 0;
42135017 }
42145018
....@@ -4225,6 +5029,8 @@
42255029 params->ht_required = true;
42265030 if (rates[2 + i] == BSS_MEMBERSHIP_SELECTOR_VHT_PHY)
42275031 params->vht_required = true;
5032
+ if (rates[2 + i] == BSS_MEMBERSHIP_SELECTOR_HE_PHY)
5033
+ params->he_required = true;
42285034 }
42295035 }
42305036
....@@ -4253,6 +5059,12 @@
42535059 cap = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, ies, ies_len);
42545060 if (cap && cap[1] >= sizeof(*params->vht_cap))
42555061 params->vht_cap = (void *)(cap + 2);
5062
+ cap = cfg80211_find_ext_ie(WLAN_EID_EXT_HE_CAPABILITY, ies, ies_len);
5063
+ if (cap && cap[1] >= sizeof(*params->he_cap) + 1)
5064
+ params->he_cap = (void *)(cap + 3);
5065
+ cap = cfg80211_find_ext_ie(WLAN_EID_EXT_HE_OPERATION, ies, ies_len);
5066
+ if (cap && cap[1] >= sizeof(*params->he_oper) + 1)
5067
+ params->he_oper = (void *)(cap + 3);
42565068 }
42575069
42585070 static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
....@@ -4298,6 +5110,8 @@
42985110 return true;
42995111 case NL80211_CMD_CONNECT:
43005112 if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) &&
5113
+ !wiphy_ext_feature_isset(&rdev->wiphy,
5114
+ NL80211_EXT_FEATURE_SAE_OFFLOAD) &&
43015115 auth_type == NL80211_AUTHTYPE_SAE)
43025116 return false;
43035117
....@@ -4312,8 +5126,9 @@
43125126 return false;
43135127 return true;
43145128 case NL80211_CMD_START_AP:
4315
- /* SAE not supported yet */
4316
- if (auth_type == NL80211_AUTHTYPE_SAE)
5129
+ if (!wiphy_ext_feature_isset(&rdev->wiphy,
5130
+ NL80211_EXT_FEATURE_SAE_OFFLOAD_AP) &&
5131
+ auth_type == NL80211_AUTHTYPE_SAE)
43175132 return false;
43185133 /* FILS not supported yet */
43195134 if (auth_type == NL80211_AUTHTYPE_FILS_SK ||
....@@ -4352,7 +5167,7 @@
43525167 !info->attrs[NL80211_ATTR_BEACON_HEAD])
43535168 return -EINVAL;
43545169
4355
- err = nl80211_parse_beacon(info->attrs, &params.beacon);
5170
+ err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon);
43565171 if (err)
43575172 return err;
43585173
....@@ -4377,19 +5192,13 @@
43775192 params.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
43785193 params.ssid_len =
43795194 nla_len(info->attrs[NL80211_ATTR_SSID]);
4380
- if (params.ssid_len == 0 ||
4381
- params.ssid_len > IEEE80211_MAX_SSID_LEN)
5195
+ if (params.ssid_len == 0)
43825196 return -EINVAL;
43835197 }
43845198
4385
- if (info->attrs[NL80211_ATTR_HIDDEN_SSID]) {
5199
+ if (info->attrs[NL80211_ATTR_HIDDEN_SSID])
43865200 params.hidden_ssid = nla_get_u32(
43875201 info->attrs[NL80211_ATTR_HIDDEN_SSID]);
4388
- if (params.hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE &&
4389
- params.hidden_ssid != NL80211_HIDDEN_SSID_ZERO_LEN &&
4390
- params.hidden_ssid != NL80211_HIDDEN_SSID_ZERO_CONTENTS)
4391
- return -EINVAL;
4392
- }
43935202
43945203 params.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
43955204
....@@ -4419,8 +5228,6 @@
44195228 return -EINVAL;
44205229 params.p2p_ctwindow =
44215230 nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
4422
- if (params.p2p_ctwindow > 127)
4423
- return -EINVAL;
44245231 if (params.p2p_ctwindow != 0 &&
44255232 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
44265233 return -EINVAL;
....@@ -4432,8 +5239,6 @@
44325239 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
44335240 return -EINVAL;
44345241 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
4435
- if (tmp > 1)
4436
- return -EINVAL;
44375242 params.p2p_opp_ps = tmp;
44385243 if (params.p2p_opp_ps != 0 &&
44395244 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
....@@ -4454,7 +5259,10 @@
44545259 return -EINVAL;
44555260
44565261 if (info->attrs[NL80211_ATTR_TX_RATES]) {
4457
- err = nl80211_parse_tx_bitrate_mask(info, &params.beacon_rate);
5262
+ err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
5263
+ NL80211_ATTR_TX_RATES,
5264
+ &params.beacon_rate,
5265
+ dev);
44585266 if (err)
44595267 return err;
44605268
....@@ -4497,6 +5305,41 @@
44975305 return PTR_ERR(params.acl);
44985306 }
44995307
5308
+ params.twt_responder =
5309
+ nla_get_flag(info->attrs[NL80211_ATTR_TWT_RESPONDER]);
5310
+
5311
+ if (info->attrs[NL80211_ATTR_HE_OBSS_PD]) {
5312
+ err = nl80211_parse_he_obss_pd(
5313
+ info->attrs[NL80211_ATTR_HE_OBSS_PD],
5314
+ &params.he_obss_pd);
5315
+ if (err)
5316
+ goto out;
5317
+ }
5318
+
5319
+ if (info->attrs[NL80211_ATTR_HE_BSS_COLOR]) {
5320
+ err = nl80211_parse_he_bss_color(
5321
+ info->attrs[NL80211_ATTR_HE_BSS_COLOR],
5322
+ &params.he_bss_color);
5323
+ if (err)
5324
+ goto out;
5325
+ }
5326
+
5327
+ if (info->attrs[NL80211_ATTR_FILS_DISCOVERY]) {
5328
+ err = nl80211_parse_fils_discovery(rdev,
5329
+ info->attrs[NL80211_ATTR_FILS_DISCOVERY],
5330
+ &params);
5331
+ if (err)
5332
+ goto out;
5333
+ }
5334
+
5335
+ if (info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP]) {
5336
+ err = nl80211_parse_unsol_bcast_probe_resp(
5337
+ rdev, info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP],
5338
+ &params);
5339
+ if (err)
5340
+ goto out;
5341
+ }
5342
+
45005343 nl80211_calculate_ap_params(&params);
45015344
45025345 if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
....@@ -4516,6 +5359,7 @@
45165359 }
45175360 wdev_unlock(wdev);
45185361
5362
+out:
45195363 kfree(params.acl);
45205364
45215365 return err;
....@@ -4539,7 +5383,7 @@
45395383 if (!wdev->beacon_interval)
45405384 return -EINVAL;
45415385
4542
- err = nl80211_parse_beacon(info->attrs, &params);
5386
+ err = nl80211_parse_beacon(rdev, info->attrs, &params);
45435387 if (err)
45445388 return err;
45455389
....@@ -4599,8 +5443,7 @@
45995443 if (!nla)
46005444 return 0;
46015445
4602
- if (nla_parse_nested(flags, NL80211_STA_FLAG_MAX, nla,
4603
- sta_flags_policy, info->extack))
5446
+ if (nla_parse_nested_deprecated(flags, NL80211_STA_FLAG_MAX, nla, sta_flags_policy, info->extack))
46045447 return -EINVAL;
46055448
46065449 /*
....@@ -4645,15 +5488,14 @@
46455488 return 0;
46465489 }
46475490
4648
-static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info,
4649
- int attr)
5491
+bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr)
46505492 {
46515493 struct nlattr *rate;
46525494 u32 bitrate;
46535495 u16 bitrate_compat;
46545496 enum nl80211_rate_info rate_flg;
46555497
4656
- rate = nla_nest_start(msg, attr);
5498
+ rate = nla_nest_start_noflag(msg, attr);
46575499 if (!rate)
46585500 return false;
46595501
....@@ -4677,7 +5519,7 @@
46775519 break;
46785520 default:
46795521 WARN_ON(1);
4680
- /* fall through */
5522
+ fallthrough;
46815523 case RATE_INFO_BW_20:
46825524 rate_flg = 0;
46835525 break;
....@@ -4740,7 +5582,7 @@
47405582 if (!mask)
47415583 return true;
47425584
4743
- attr = nla_nest_start(msg, id);
5585
+ attr = nla_nest_start_noflag(msg, id);
47445586 if (!attr)
47455587 return false;
47465588
....@@ -4777,7 +5619,7 @@
47775619 nla_put_u32(msg, NL80211_ATTR_GENERATION, sinfo->generation))
47785620 goto nla_put_failure;
47795621
4780
- sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO);
5622
+ sinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_STA_INFO);
47815623 if (!sinfoattr)
47825624 goto nla_put_failure;
47835625
....@@ -4797,6 +5639,7 @@
47975639
47985640 PUT_SINFO(CONNECTED_TIME, connected_time, u32);
47995641 PUT_SINFO(INACTIVE_TIME, inactive_time, u32);
5642
+ PUT_SINFO_U64(ASSOC_AT_BOOTTIME, assoc_at);
48005643
48015644 if (sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES) |
48025645 BIT_ULL(NL80211_STA_INFO_RX_BYTES64)) &&
....@@ -4816,6 +5659,11 @@
48165659 PUT_SINFO(PLID, plid, u16);
48175660 PUT_SINFO(PLINK_STATE, plink_state, u8);
48185661 PUT_SINFO_U64(RX_DURATION, rx_duration);
5662
+ PUT_SINFO_U64(TX_DURATION, tx_duration);
5663
+
5664
+ if (wiphy_ext_feature_isset(&rdev->wiphy,
5665
+ NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
5666
+ PUT_SINFO(AIRTIME_WEIGHT, airtime_weight, u16);
48195667
48205668 switch (rdev->wiphy.signal_type) {
48215669 case CFG80211_SIGNAL_TYPE_MBM:
....@@ -4853,13 +5701,17 @@
48535701 PUT_SINFO(TX_RETRIES, tx_retries, u32);
48545702 PUT_SINFO(TX_FAILED, tx_failed, u32);
48555703 PUT_SINFO(EXPECTED_THROUGHPUT, expected_throughput, u32);
5704
+ PUT_SINFO(AIRTIME_LINK_METRIC, airtime_link_metric, u32);
48565705 PUT_SINFO(BEACON_LOSS, beacon_loss_count, u32);
48575706 PUT_SINFO(LOCAL_PM, local_pm, u32);
48585707 PUT_SINFO(PEER_PM, peer_pm, u32);
48595708 PUT_SINFO(NONPEER_PM, nonpeer_pm, u32);
5709
+ PUT_SINFO(CONNECTED_TO_GATE, connected_to_gate, u8);
5710
+ PUT_SINFO(CONNECTED_TO_AS, connected_to_as, u8);
48605711
48615712 if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_BSS_PARAM)) {
4862
- bss_param = nla_nest_start(msg, NL80211_STA_INFO_BSS_PARAM);
5713
+ bss_param = nla_nest_start_noflag(msg,
5714
+ NL80211_STA_INFO_BSS_PARAM);
48635715 if (!bss_param)
48645716 goto nla_put_failure;
48655717
....@@ -4887,12 +5739,13 @@
48875739 PUT_SINFO_U64(RX_DROP_MISC, rx_dropped_misc);
48885740 PUT_SINFO_U64(BEACON_RX, rx_beacon);
48895741 PUT_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8);
4890
- PUT_SINFO(ACK_SIGNAL, ack_signal, u8);
48915742 PUT_SINFO(RX_MPDUS, rx_mpdu_count, u32);
48925743 PUT_SINFO(FCS_ERROR_COUNT, fcs_err_count, u32);
48935744 if (wiphy_ext_feature_isset(&rdev->wiphy,
4894
- NL80211_EXT_FEATURE_DATA_ACK_SIGNAL_SUPPORT))
4895
- PUT_SINFO(DATA_ACK_SIGNAL_AVG, avg_ack_signal, s8);
5745
+ NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT)) {
5746
+ PUT_SINFO(ACK_SIGNAL, ack_signal, u8);
5747
+ PUT_SINFO(ACK_SIGNAL_AVG, avg_ack_signal, s8);
5748
+ }
48965749
48975750 #undef PUT_SINFO
48985751 #undef PUT_SINFO_U64
....@@ -4901,7 +5754,8 @@
49015754 struct nlattr *tidsattr;
49025755 int tid;
49035756
4904
- tidsattr = nla_nest_start(msg, NL80211_STA_INFO_TID_STATS);
5757
+ tidsattr = nla_nest_start_noflag(msg,
5758
+ NL80211_STA_INFO_TID_STATS);
49055759 if (!tidsattr)
49065760 goto nla_put_failure;
49075761
....@@ -4914,7 +5768,7 @@
49145768 if (!tidstats->filled)
49155769 continue;
49165770
4917
- tidattr = nla_nest_start(msg, tid + 1);
5771
+ tidattr = nla_nest_start_noflag(msg, tid + 1);
49185772 if (!tidattr)
49195773 goto nla_put_failure;
49205774
....@@ -4971,7 +5825,7 @@
49715825 int err;
49725826
49735827 rtnl_lock();
4974
- err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
5828
+ err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
49755829 if (err)
49765830 goto out_err;
49775831
....@@ -5262,8 +6116,9 @@
52626116 return 0;
52636117
52646118 nla = info->attrs[NL80211_ATTR_STA_WME];
5265
- err = nla_parse_nested(tb, NL80211_STA_WME_MAX, nla,
5266
- nl80211_sta_wme_policy, info->extack);
6119
+ err = nla_parse_nested_deprecated(tb, NL80211_STA_WME_MAX, nla,
6120
+ nl80211_sta_wme_policy,
6121
+ info->extack);
52676122 if (err)
52686123 return err;
52696124
....@@ -5294,11 +6149,9 @@
52946149 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
52956150 /*
52966151 * Need to include at least one (first channel, number of
5297
- * channels) tuple for each subband, and must have proper
5298
- * tuples for the rest of the data as well.
6152
+ * channels) tuple for each subband (checked in policy),
6153
+ * and must have proper tuples for the rest of the data as well.
52996154 */
5300
- if (params->supported_channels_len < 2)
5301
- return -EINVAL;
53026155 if (params->supported_channels_len % 2)
53036156 return -EINVAL;
53046157 }
....@@ -5308,13 +6161,6 @@
53086161 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
53096162 params->supported_oper_classes_len =
53106163 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
5311
- /*
5312
- * The value of the Length field of the Supported Operating
5313
- * Classes element is between 2 and 253.
5314
- */
5315
- if (params->supported_oper_classes_len < 2 ||
5316
- params->supported_oper_classes_len > 253)
5317
- return -EINVAL;
53186164 }
53196165 return 0;
53206166 }
....@@ -5337,9 +6183,6 @@
53376183 nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
53386184 params->he_capa_len =
53396185 nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
5340
-
5341
- if (params->he_capa_len < NL80211_HE_MIN_CAPABILITY_LEN)
5342
- return -EINVAL;
53436186 }
53446187
53456188 err = nl80211_parse_sta_channel_info(info, params);
....@@ -5347,6 +6190,36 @@
53476190 return err;
53486191
53496192 return nl80211_parse_sta_wme(info, params);
6193
+}
6194
+
6195
+static int nl80211_parse_sta_txpower_setting(struct genl_info *info,
6196
+ struct station_parameters *params)
6197
+{
6198
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
6199
+ int idx;
6200
+
6201
+ if (info->attrs[NL80211_ATTR_STA_TX_POWER_SETTING]) {
6202
+ if (!rdev->ops->set_tx_power ||
6203
+ !wiphy_ext_feature_isset(&rdev->wiphy,
6204
+ NL80211_EXT_FEATURE_STA_TX_PWR))
6205
+ return -EOPNOTSUPP;
6206
+
6207
+ idx = NL80211_ATTR_STA_TX_POWER_SETTING;
6208
+ params->txpwr.type = nla_get_u8(info->attrs[idx]);
6209
+
6210
+ if (params->txpwr.type == NL80211_TX_POWER_LIMITED) {
6211
+ idx = NL80211_ATTR_STA_TX_POWER;
6212
+
6213
+ if (info->attrs[idx])
6214
+ params->txpwr.power =
6215
+ nla_get_s16(info->attrs[idx]);
6216
+ else
6217
+ return -EINVAL;
6218
+ }
6219
+ params->sta_modify_mask |= STATION_PARAM_APPLY_STA_TXPOWER;
6220
+ }
6221
+
6222
+ return 0;
53506223 }
53516224
53526225 static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
....@@ -5370,23 +6243,20 @@
53706243 if (info->attrs[NL80211_ATTR_STA_AID])
53716244 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
53726245
6246
+ if (info->attrs[NL80211_ATTR_VLAN_ID])
6247
+ params.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
6248
+
53736249 if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
53746250 params.listen_interval =
53756251 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
53766252 else
53776253 params.listen_interval = -1;
53786254
5379
- if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) {
5380
- u8 tmp;
5381
-
5382
- tmp = nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
5383
- if (tmp >= NUM_NL80211_P2P_PS_STATUS)
5384
- return -EINVAL;
5385
-
5386
- params.support_p2p_ps = tmp;
5387
- } else {
6255
+ if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS])
6256
+ params.support_p2p_ps =
6257
+ nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
6258
+ else
53886259 params.support_p2p_ps = -1;
5389
- }
53906260
53916261 if (!info->attrs[NL80211_ATTR_MAC])
53926262 return -EINVAL;
....@@ -5416,43 +6286,45 @@
54166286 if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
54176287 return -EINVAL;
54186288
5419
- if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) {
6289
+ if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
54206290 params.plink_action =
54216291 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
5422
- if (params.plink_action >= NUM_NL80211_PLINK_ACTIONS)
5423
- return -EINVAL;
5424
- }
54256292
54266293 if (info->attrs[NL80211_ATTR_STA_PLINK_STATE]) {
54276294 params.plink_state =
54286295 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]);
5429
- if (params.plink_state >= NUM_NL80211_PLINK_STATES)
5430
- return -EINVAL;
5431
- if (info->attrs[NL80211_ATTR_MESH_PEER_AID]) {
6296
+ if (info->attrs[NL80211_ATTR_MESH_PEER_AID])
54326297 params.peer_aid = nla_get_u16(
54336298 info->attrs[NL80211_ATTR_MESH_PEER_AID]);
5434
- if (params.peer_aid > IEEE80211_MAX_AID)
5435
- return -EINVAL;
5436
- }
54376299 params.sta_modify_mask |= STATION_PARAM_APPLY_PLINK_STATE;
54386300 }
54396301
5440
- if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]) {
5441
- enum nl80211_mesh_power_mode pm = nla_get_u32(
6302
+ if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE])
6303
+ params.local_pm = nla_get_u32(
54426304 info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]);
5443
-
5444
- if (pm <= NL80211_MESH_POWER_UNKNOWN ||
5445
- pm > NL80211_MESH_POWER_MAX)
5446
- return -EINVAL;
5447
-
5448
- params.local_pm = pm;
5449
- }
54506305
54516306 if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
54526307 params.opmode_notif_used = true;
54536308 params.opmode_notif =
54546309 nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
54556310 }
6311
+
6312
+ if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
6313
+ params.he_6ghz_capa =
6314
+ nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
6315
+
6316
+ if (info->attrs[NL80211_ATTR_AIRTIME_WEIGHT])
6317
+ params.airtime_weight =
6318
+ nla_get_u16(info->attrs[NL80211_ATTR_AIRTIME_WEIGHT]);
6319
+
6320
+ if (params.airtime_weight &&
6321
+ !wiphy_ext_feature_isset(&rdev->wiphy,
6322
+ NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
6323
+ return -EOPNOTSUPP;
6324
+
6325
+ err = nl80211_parse_sta_txpower_setting(info, &params);
6326
+ if (err)
6327
+ return err;
54566328
54576329 /* Include parameters for TDLS peer (will check later) */
54586330 err = nl80211_set_station_tdls(info, &params);
....@@ -5523,14 +6395,12 @@
55236395 params.listen_interval =
55246396 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
55256397
6398
+ if (info->attrs[NL80211_ATTR_VLAN_ID])
6399
+ params.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
6400
+
55266401 if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) {
5527
- u8 tmp;
5528
-
5529
- tmp = nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
5530
- if (tmp >= NUM_NL80211_P2P_PS_STATUS)
5531
- return -EINVAL;
5532
-
5533
- params.support_p2p_ps = tmp;
6402
+ params.support_p2p_ps =
6403
+ nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
55346404 } else {
55356405 /*
55366406 * if not specified, assume it's supported for P2P GO interface,
....@@ -5544,8 +6414,6 @@
55446414 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
55456415 else
55466416 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
5547
- if (!params.aid || params.aid > IEEE80211_MAX_AID)
5548
- return -EINVAL;
55496417
55506418 if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
55516419 params.capability =
....@@ -5573,11 +6441,11 @@
55736441 nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
55746442 params.he_capa_len =
55756443 nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
5576
-
5577
- /* max len is validated in nla policy */
5578
- if (params.he_capa_len < NL80211_HE_MIN_CAPABILITY_LEN)
5579
- return -EINVAL;
55806444 }
6445
+
6446
+ if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
6447
+ params.he_6ghz_capa =
6448
+ nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
55816449
55826450 if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
55836451 params.opmode_notif_used = true;
....@@ -5585,12 +6453,22 @@
55856453 nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
55866454 }
55876455
5588
- if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) {
6456
+ if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
55896457 params.plink_action =
55906458 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
5591
- if (params.plink_action >= NUM_NL80211_PLINK_ACTIONS)
5592
- return -EINVAL;
5593
- }
6459
+
6460
+ if (info->attrs[NL80211_ATTR_AIRTIME_WEIGHT])
6461
+ params.airtime_weight =
6462
+ nla_get_u16(info->attrs[NL80211_ATTR_AIRTIME_WEIGHT]);
6463
+
6464
+ if (params.airtime_weight &&
6465
+ !wiphy_ext_feature_isset(&rdev->wiphy,
6466
+ NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
6467
+ return -EOPNOTSUPP;
6468
+
6469
+ err = nl80211_parse_sta_txpower_setting(info, &params);
6470
+ if (err)
6471
+ return err;
55946472
55956473 err = nl80211_parse_sta_channel_info(info, &params);
55966474 if (err)
....@@ -5613,9 +6491,13 @@
56136491 params.vht_capa = NULL;
56146492
56156493 /* HE requires WME */
5616
- if (params.he_capa_len)
6494
+ if (params.he_capa_len || params.he_6ghz_capa)
56176495 return -EINVAL;
56186496 }
6497
+
6498
+ /* Ensure that HT/VHT capabilities are not set for 6 GHz HE STA */
6499
+ if (params.he_6ghz_capa && (params.ht_capa || params.vht_capa))
6500
+ return -EINVAL;
56196501
56206502 /* When you run into this, adjust the code below for the new flag */
56216503 BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7);
....@@ -5723,11 +6605,22 @@
57236605 if (info->attrs[NL80211_ATTR_MAC])
57246606 params.mac = nla_data(info->attrs[NL80211_ATTR_MAC]);
57256607
5726
- if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
5727
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
5728
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
5729
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
6608
+ switch (dev->ieee80211_ptr->iftype) {
6609
+ case NL80211_IFTYPE_AP:
6610
+ case NL80211_IFTYPE_AP_VLAN:
6611
+ case NL80211_IFTYPE_MESH_POINT:
6612
+ case NL80211_IFTYPE_P2P_GO:
6613
+ /* always accept these */
6614
+ break;
6615
+ case NL80211_IFTYPE_ADHOC:
6616
+ /* conditionally accept */
6617
+ if (wiphy_ext_feature_isset(&rdev->wiphy,
6618
+ NL80211_EXT_FEATURE_DEL_IBSS_STA))
6619
+ break;
57306620 return -EINVAL;
6621
+ default:
6622
+ return -EINVAL;
6623
+ }
57316624
57326625 if (!rdev->ops->del_station)
57336626 return -EOPNOTSUPP;
....@@ -5774,7 +6667,7 @@
57746667 nla_put_u32(msg, NL80211_ATTR_GENERATION, pinfo->generation))
57756668 goto nla_put_failure;
57766669
5777
- pinfoattr = nla_nest_start(msg, NL80211_ATTR_MPATH_INFO);
6670
+ pinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_MPATH_INFO);
57786671 if (!pinfoattr)
57796672 goto nla_put_failure;
57806673 if ((pinfo->filled & MPATH_INFO_FRAME_QLEN) &&
....@@ -5797,7 +6690,13 @@
57976690 pinfo->discovery_timeout)) ||
57986691 ((pinfo->filled & MPATH_INFO_DISCOVERY_RETRIES) &&
57996692 nla_put_u8(msg, NL80211_MPATH_INFO_DISCOVERY_RETRIES,
5800
- pinfo->discovery_retries)))
6693
+ pinfo->discovery_retries)) ||
6694
+ ((pinfo->filled & MPATH_INFO_HOP_COUNT) &&
6695
+ nla_put_u8(msg, NL80211_MPATH_INFO_HOP_COUNT,
6696
+ pinfo->hop_count)) ||
6697
+ ((pinfo->filled & MPATH_INFO_PATH_CHANGE) &&
6698
+ nla_put_u32(msg, NL80211_MPATH_INFO_PATH_CHANGE,
6699
+ pinfo->path_change_count)))
58016700 goto nla_put_failure;
58026701
58036702 nla_nest_end(msg, pinfoattr);
....@@ -5822,7 +6721,7 @@
58226721 int err;
58236722
58246723 rtnl_lock();
5825
- err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
6724
+ err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
58266725 if (err)
58276726 goto out_err;
58286727
....@@ -6021,7 +6920,7 @@
60216920 int err;
60226921
60236922 rtnl_lock();
6024
- err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
6923
+ err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
60256924 if (err)
60266925 goto out_err;
60276926
....@@ -6103,9 +7002,7 @@
61037002 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
61047003 return -EINVAL;
61057004 params.p2p_ctwindow =
6106
- nla_get_s8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
6107
- if (params.p2p_ctwindow < 0)
6108
- return -EINVAL;
7005
+ nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
61097006 if (params.p2p_ctwindow != 0 &&
61107007 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
61117008 return -EINVAL;
....@@ -6117,8 +7014,6 @@
61177014 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
61187015 return -EINVAL;
61197016 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
6120
- if (tmp > 1)
6121
- return -EINVAL;
61227017 params.p2p_opp_ps = tmp;
61237018 if (params.p2p_opp_ps &&
61247019 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
....@@ -6226,7 +7121,7 @@
62267121 NL80211_CMD_GET_MESH_CONFIG);
62277122 if (!hdr)
62287123 goto out;
6229
- pinfoattr = nla_nest_start(msg, NL80211_ATTR_MESH_CONFIG);
7124
+ pinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_MESH_CONFIG);
62307125 if (!pinfoattr)
62317126 goto nla_put_failure;
62327127 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
....@@ -6285,7 +7180,13 @@
62857180 nla_put_u16(msg, NL80211_MESHCONF_AWAKE_WINDOW,
62867181 cur_params.dot11MeshAwakeWindowDuration) ||
62877182 nla_put_u32(msg, NL80211_MESHCONF_PLINK_TIMEOUT,
6288
- cur_params.plink_timeout))
7183
+ cur_params.plink_timeout) ||
7184
+ nla_put_u8(msg, NL80211_MESHCONF_CONNECTED_TO_GATE,
7185
+ cur_params.dot11MeshConnectedToMeshGate) ||
7186
+ nla_put_u8(msg, NL80211_MESHCONF_NOLEARN,
7187
+ cur_params.dot11MeshNolearn) ||
7188
+ nla_put_u8(msg, NL80211_MESHCONF_CONNECTED_TO_AS,
7189
+ cur_params.dot11MeshConnectedToAuthServer))
62897190 goto nla_put_failure;
62907191 nla_nest_end(msg, pinfoattr);
62917192 genlmsg_end(msg, hdr);
....@@ -6297,35 +7198,54 @@
62977198 return -ENOBUFS;
62987199 }
62997200
6300
-static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] = {
6301
- [NL80211_MESHCONF_RETRY_TIMEOUT] = { .type = NLA_U16 },
6302
- [NL80211_MESHCONF_CONFIRM_TIMEOUT] = { .type = NLA_U16 },
6303
- [NL80211_MESHCONF_HOLDING_TIMEOUT] = { .type = NLA_U16 },
6304
- [NL80211_MESHCONF_MAX_PEER_LINKS] = { .type = NLA_U16 },
6305
- [NL80211_MESHCONF_MAX_RETRIES] = { .type = NLA_U8 },
6306
- [NL80211_MESHCONF_TTL] = { .type = NLA_U8 },
6307
- [NL80211_MESHCONF_ELEMENT_TTL] = { .type = NLA_U8 },
6308
- [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = { .type = NLA_U8 },
6309
- [NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR] = { .type = NLA_U32 },
7201
+static const struct nla_policy
7202
+nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] = {
7203
+ [NL80211_MESHCONF_RETRY_TIMEOUT] =
7204
+ NLA_POLICY_RANGE(NLA_U16, 1, 255),
7205
+ [NL80211_MESHCONF_CONFIRM_TIMEOUT] =
7206
+ NLA_POLICY_RANGE(NLA_U16, 1, 255),
7207
+ [NL80211_MESHCONF_HOLDING_TIMEOUT] =
7208
+ NLA_POLICY_RANGE(NLA_U16, 1, 255),
7209
+ [NL80211_MESHCONF_MAX_PEER_LINKS] =
7210
+ NLA_POLICY_RANGE(NLA_U16, 0, 255),
7211
+ [NL80211_MESHCONF_MAX_RETRIES] = NLA_POLICY_MAX(NLA_U8, 16),
7212
+ [NL80211_MESHCONF_TTL] = NLA_POLICY_MIN(NLA_U8, 1),
7213
+ [NL80211_MESHCONF_ELEMENT_TTL] = NLA_POLICY_MIN(NLA_U8, 1),
7214
+ [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = NLA_POLICY_MAX(NLA_U8, 1),
7215
+ [NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR] =
7216
+ NLA_POLICY_RANGE(NLA_U32, 1, 255),
63107217 [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 },
63117218 [NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 },
6312
- [NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = { .type = NLA_U16 },
7219
+ [NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = NLA_POLICY_MIN(NLA_U16, 1),
63137220 [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 },
6314
- [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] = { .type = NLA_U16 },
6315
- [NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL] = { .type = NLA_U16 },
6316
- [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 },
6317
- [NL80211_MESHCONF_HWMP_ROOTMODE] = { .type = NLA_U8 },
6318
- [NL80211_MESHCONF_HWMP_RANN_INTERVAL] = { .type = NLA_U16 },
6319
- [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 },
6320
- [NL80211_MESHCONF_FORWARDING] = { .type = NLA_U8 },
6321
- [NL80211_MESHCONF_RSSI_THRESHOLD] = { .type = NLA_U32 },
7221
+ [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] =
7222
+ NLA_POLICY_MIN(NLA_U16, 1),
7223
+ [NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL] =
7224
+ NLA_POLICY_MIN(NLA_U16, 1),
7225
+ [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] =
7226
+ NLA_POLICY_MIN(NLA_U16, 1),
7227
+ [NL80211_MESHCONF_HWMP_ROOTMODE] = NLA_POLICY_MAX(NLA_U8, 4),
7228
+ [NL80211_MESHCONF_HWMP_RANN_INTERVAL] =
7229
+ NLA_POLICY_MIN(NLA_U16, 1),
7230
+ [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = NLA_POLICY_MAX(NLA_U8, 1),
7231
+ [NL80211_MESHCONF_FORWARDING] = NLA_POLICY_MAX(NLA_U8, 1),
7232
+ [NL80211_MESHCONF_RSSI_THRESHOLD] =
7233
+ NLA_POLICY_RANGE(NLA_S32, -255, 0),
63227234 [NL80211_MESHCONF_HT_OPMODE] = { .type = NLA_U16 },
63237235 [NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT] = { .type = NLA_U32 },
6324
- [NL80211_MESHCONF_HWMP_ROOT_INTERVAL] = { .type = NLA_U16 },
6325
- [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] = { .type = NLA_U16 },
6326
- [NL80211_MESHCONF_POWER_MODE] = { .type = NLA_U32 },
7236
+ [NL80211_MESHCONF_HWMP_ROOT_INTERVAL] =
7237
+ NLA_POLICY_MIN(NLA_U16, 1),
7238
+ [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] =
7239
+ NLA_POLICY_MIN(NLA_U16, 1),
7240
+ [NL80211_MESHCONF_POWER_MODE] =
7241
+ NLA_POLICY_RANGE(NLA_U32,
7242
+ NL80211_MESH_POWER_ACTIVE,
7243
+ NL80211_MESH_POWER_MAX),
63277244 [NL80211_MESHCONF_AWAKE_WINDOW] = { .type = NLA_U16 },
63287245 [NL80211_MESHCONF_PLINK_TIMEOUT] = { .type = NLA_U32 },
7246
+ [NL80211_MESHCONF_CONNECTED_TO_GATE] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
7247
+ [NL80211_MESHCONF_NOLEARN] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
7248
+ [NL80211_MESHCONF_CONNECTED_TO_AS] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
63297249 };
63307250
63317251 static const struct nla_policy
....@@ -6336,67 +7256,11 @@
63367256 [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG },
63377257 [NL80211_MESH_SETUP_AUTH_PROTOCOL] = { .type = NLA_U8 },
63387258 [NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG },
6339
- [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY,
6340
- .len = IEEE80211_MAX_DATA_LEN },
7259
+ [NL80211_MESH_SETUP_IE] =
7260
+ NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
7261
+ IEEE80211_MAX_DATA_LEN),
63417262 [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG },
63427263 };
6343
-
6344
-static int nl80211_check_bool(const struct nlattr *nla, u8 min, u8 max, bool *out)
6345
-{
6346
- u8 val = nla_get_u8(nla);
6347
- if (val < min || val > max)
6348
- return -EINVAL;
6349
- *out = val;
6350
- return 0;
6351
-}
6352
-
6353
-static int nl80211_check_u8(const struct nlattr *nla, u8 min, u8 max, u8 *out)
6354
-{
6355
- u8 val = nla_get_u8(nla);
6356
- if (val < min || val > max)
6357
- return -EINVAL;
6358
- *out = val;
6359
- return 0;
6360
-}
6361
-
6362
-static int nl80211_check_u16(const struct nlattr *nla, u16 min, u16 max, u16 *out)
6363
-{
6364
- u16 val = nla_get_u16(nla);
6365
- if (val < min || val > max)
6366
- return -EINVAL;
6367
- *out = val;
6368
- return 0;
6369
-}
6370
-
6371
-static int nl80211_check_u32(const struct nlattr *nla, u32 min, u32 max, u32 *out)
6372
-{
6373
- u32 val = nla_get_u32(nla);
6374
- if (val < min || val > max)
6375
- return -EINVAL;
6376
- *out = val;
6377
- return 0;
6378
-}
6379
-
6380
-static int nl80211_check_s32(const struct nlattr *nla, s32 min, s32 max, s32 *out)
6381
-{
6382
- s32 val = nla_get_s32(nla);
6383
- if (val < min || val > max)
6384
- return -EINVAL;
6385
- *out = val;
6386
- return 0;
6387
-}
6388
-
6389
-static int nl80211_check_power_mode(const struct nlattr *nla,
6390
- enum nl80211_mesh_power_mode min,
6391
- enum nl80211_mesh_power_mode max,
6392
- enum nl80211_mesh_power_mode *out)
6393
-{
6394
- u32 val = nla_get_u32(nla);
6395
- if (val < min || val > max)
6396
- return -EINVAL;
6397
- *out = val;
6398
- return 0;
6399
-}
64007264
64017265 static int nl80211_parse_mesh_config(struct genl_info *info,
64027266 struct mesh_config *cfg,
....@@ -6406,20 +7270,17 @@
64067270 u32 mask = 0;
64077271 u16 ht_opmode;
64087272
6409
-#define FILL_IN_MESH_PARAM_IF_SET(tb, cfg, param, min, max, mask, attr, fn) \
6410
-do { \
6411
- if (tb[attr]) { \
6412
- if (fn(tb[attr], min, max, &cfg->param)) \
6413
- return -EINVAL; \
6414
- mask |= (1 << (attr - 1)); \
6415
- } \
7273
+#define FILL_IN_MESH_PARAM_IF_SET(tb, cfg, param, mask, attr, fn) \
7274
+do { \
7275
+ if (tb[attr]) { \
7276
+ cfg->param = fn(tb[attr]); \
7277
+ mask |= BIT((attr) - 1); \
7278
+ } \
64167279 } while (0)
64177280
64187281 if (!info->attrs[NL80211_ATTR_MESH_CONFIG])
64197282 return -EINVAL;
6420
- if (nla_parse_nested(tb, NL80211_MESHCONF_ATTR_MAX,
6421
- info->attrs[NL80211_ATTR_MESH_CONFIG],
6422
- nl80211_meshconf_params_policy, info->extack))
7283
+ if (nla_parse_nested_deprecated(tb, NL80211_MESHCONF_ATTR_MAX, info->attrs[NL80211_ATTR_MESH_CONFIG], nl80211_meshconf_params_policy, info->extack))
64237284 return -EINVAL;
64247285
64257286 /* This makes sure that there aren't more than 32 mesh config
....@@ -6427,75 +7288,79 @@
64277288 BUILD_BUG_ON(NL80211_MESHCONF_ATTR_MAX > 32);
64287289
64297290 /* Fill in the params struct */
6430
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, 1, 255,
6431
- mask, NL80211_MESHCONF_RETRY_TIMEOUT,
6432
- nl80211_check_u16);
6433
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, 1, 255,
6434
- mask, NL80211_MESHCONF_CONFIRM_TIMEOUT,
6435
- nl80211_check_u16);
6436
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, 1, 255,
6437
- mask, NL80211_MESHCONF_HOLDING_TIMEOUT,
6438
- nl80211_check_u16);
6439
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, 0, 255,
6440
- mask, NL80211_MESHCONF_MAX_PEER_LINKS,
6441
- nl80211_check_u16);
6442
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, 0, 16,
6443
- mask, NL80211_MESHCONF_MAX_RETRIES,
6444
- nl80211_check_u8);
6445
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, 1, 255,
6446
- mask, NL80211_MESHCONF_TTL, nl80211_check_u8);
6447
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, 1, 255,
6448
- mask, NL80211_MESHCONF_ELEMENT_TTL,
6449
- nl80211_check_u8);
6450
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, 0, 1,
6451
- mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
6452
- nl80211_check_bool);
7291
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, mask,
7292
+ NL80211_MESHCONF_RETRY_TIMEOUT, nla_get_u16);
7293
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, mask,
7294
+ NL80211_MESHCONF_CONFIRM_TIMEOUT,
7295
+ nla_get_u16);
7296
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, mask,
7297
+ NL80211_MESHCONF_HOLDING_TIMEOUT,
7298
+ nla_get_u16);
7299
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, mask,
7300
+ NL80211_MESHCONF_MAX_PEER_LINKS,
7301
+ nla_get_u16);
7302
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, mask,
7303
+ NL80211_MESHCONF_MAX_RETRIES, nla_get_u8);
7304
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, mask,
7305
+ NL80211_MESHCONF_TTL, nla_get_u8);
7306
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, mask,
7307
+ NL80211_MESHCONF_ELEMENT_TTL, nla_get_u8);
7308
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, mask,
7309
+ NL80211_MESHCONF_AUTO_OPEN_PLINKS,
7310
+ nla_get_u8);
64537311 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor,
6454
- 1, 255, mask,
7312
+ mask,
64557313 NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
6456
- nl80211_check_u32);
6457
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, 0, 255,
6458
- mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
6459
- nl80211_check_u8);
6460
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, 1, 65535,
6461
- mask, NL80211_MESHCONF_PATH_REFRESH_TIME,
6462
- nl80211_check_u32);
6463
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, 1, 65535,
6464
- mask, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
6465
- nl80211_check_u16);
7314
+ nla_get_u32);
7315
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, mask,
7316
+ NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
7317
+ nla_get_u8);
7318
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, mask,
7319
+ NL80211_MESHCONF_PATH_REFRESH_TIME,
7320
+ nla_get_u32);
7321
+ if (mask & BIT(NL80211_MESHCONF_PATH_REFRESH_TIME) &&
7322
+ (cfg->path_refresh_time < 1 || cfg->path_refresh_time > 65535))
7323
+ return -EINVAL;
7324
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, mask,
7325
+ NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
7326
+ nla_get_u16);
64667327 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout,
6467
- 1, 65535, mask,
7328
+ mask,
64687329 NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
6469
- nl80211_check_u32);
6470
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval,
6471
- 1, 65535, mask,
7330
+ nla_get_u32);
7331
+ if (mask & BIT(NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT) &&
7332
+ (cfg->dot11MeshHWMPactivePathTimeout < 1 ||
7333
+ cfg->dot11MeshHWMPactivePathTimeout > 65535))
7334
+ return -EINVAL;
7335
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval, mask,
64727336 NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
6473
- nl80211_check_u16);
6474
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval,
6475
- 1, 65535, mask,
7337
+ nla_get_u16);
7338
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval, mask,
64767339 NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
6477
- nl80211_check_u16);
7340
+ nla_get_u16);
64787341 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
6479
- dot11MeshHWMPnetDiameterTraversalTime,
6480
- 1, 65535, mask,
7342
+ dot11MeshHWMPnetDiameterTraversalTime, mask,
64817343 NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
6482
- nl80211_check_u16);
6483
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, 0, 4,
6484
- mask, NL80211_MESHCONF_HWMP_ROOTMODE,
6485
- nl80211_check_u8);
6486
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, 1, 65535,
6487
- mask, NL80211_MESHCONF_HWMP_RANN_INTERVAL,
6488
- nl80211_check_u16);
6489
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
6490
- dot11MeshGateAnnouncementProtocol, 0, 1,
7344
+ nla_get_u16);
7345
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, mask,
7346
+ NL80211_MESHCONF_HWMP_ROOTMODE, nla_get_u8);
7347
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, mask,
7348
+ NL80211_MESHCONF_HWMP_RANN_INTERVAL,
7349
+ nla_get_u16);
7350
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshGateAnnouncementProtocol,
64917351 mask, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
6492
- nl80211_check_bool);
6493
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, 0, 1,
6494
- mask, NL80211_MESHCONF_FORWARDING,
6495
- nl80211_check_bool);
6496
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, -255, 0,
6497
- mask, NL80211_MESHCONF_RSSI_THRESHOLD,
6498
- nl80211_check_s32);
7352
+ nla_get_u8);
7353
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, mask,
7354
+ NL80211_MESHCONF_FORWARDING, nla_get_u8);
7355
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, mask,
7356
+ NL80211_MESHCONF_RSSI_THRESHOLD,
7357
+ nla_get_s32);
7358
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConnectedToMeshGate, mask,
7359
+ NL80211_MESHCONF_CONNECTED_TO_GATE,
7360
+ nla_get_u8);
7361
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConnectedToAuthServer, mask,
7362
+ NL80211_MESHCONF_CONNECTED_TO_AS,
7363
+ nla_get_u8);
64997364 /*
65007365 * Check HT operation mode based on
65017366 * IEEE 802.11-2016 9.4.2.57 HT Operation element.
....@@ -6514,29 +7379,29 @@
65147379 cfg->ht_opmode = ht_opmode;
65157380 mask |= (1 << (NL80211_MESHCONF_HT_OPMODE - 1));
65167381 }
6517
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathToRootTimeout,
6518
- 1, 65535, mask,
6519
- NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
6520
- nl80211_check_u32);
6521
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMProotInterval, 1, 65535,
6522
- mask, NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
6523
- nl80211_check_u16);
65247382 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
6525
- dot11MeshHWMPconfirmationInterval,
6526
- 1, 65535, mask,
7383
+ dot11MeshHWMPactivePathToRootTimeout, mask,
7384
+ NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
7385
+ nla_get_u32);
7386
+ if (mask & BIT(NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT) &&
7387
+ (cfg->dot11MeshHWMPactivePathToRootTimeout < 1 ||
7388
+ cfg->dot11MeshHWMPactivePathToRootTimeout > 65535))
7389
+ return -EINVAL;
7390
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMProotInterval, mask,
7391
+ NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
7392
+ nla_get_u16);
7393
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPconfirmationInterval,
7394
+ mask,
65277395 NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
6528
- nl80211_check_u16);
6529
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode,
6530
- NL80211_MESH_POWER_ACTIVE,
6531
- NL80211_MESH_POWER_MAX,
6532
- mask, NL80211_MESHCONF_POWER_MODE,
6533
- nl80211_check_power_mode);
6534
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration,
6535
- 0, 65535, mask,
6536
- NL80211_MESHCONF_AWAKE_WINDOW, nl80211_check_u16);
6537
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, 0, 0xffffffff,
6538
- mask, NL80211_MESHCONF_PLINK_TIMEOUT,
6539
- nl80211_check_u32);
7396
+ nla_get_u16);
7397
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode, mask,
7398
+ NL80211_MESHCONF_POWER_MODE, nla_get_u32);
7399
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration, mask,
7400
+ NL80211_MESHCONF_AWAKE_WINDOW, nla_get_u16);
7401
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, mask,
7402
+ NL80211_MESHCONF_PLINK_TIMEOUT, nla_get_u32);
7403
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNolearn, mask,
7404
+ NL80211_MESHCONF_NOLEARN, nla_get_u8);
65407405 if (mask_out)
65417406 *mask_out = mask;
65427407
....@@ -6553,9 +7418,7 @@
65537418
65547419 if (!info->attrs[NL80211_ATTR_MESH_SETUP])
65557420 return -EINVAL;
6556
- if (nla_parse_nested(tb, NL80211_MESH_SETUP_ATTR_MAX,
6557
- info->attrs[NL80211_ATTR_MESH_SETUP],
6558
- nl80211_mesh_setup_params_policy, info->extack))
7421
+ if (nla_parse_nested_deprecated(tb, NL80211_MESH_SETUP_ATTR_MAX, info->attrs[NL80211_ATTR_MESH_SETUP], nl80211_mesh_setup_params_policy, info->extack))
65597422 return -EINVAL;
65607423
65617424 if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC])
....@@ -6579,8 +7442,6 @@
65797442 if (tb[NL80211_MESH_SETUP_IE]) {
65807443 struct nlattr *ieattr =
65817444 tb[NL80211_MESH_SETUP_IE];
6582
- if (!is_valid_ie_attr(ieattr))
6583
- return -EINVAL;
65847445 setup->ie = nla_data(ieattr);
65857446 setup->ie_len = nla_len(ieattr);
65867447 }
....@@ -6646,7 +7507,7 @@
66467507 nla_put_u8(msg, NL80211_ATTR_DFS_REGION, regdom->dfs_region)))
66477508 goto nla_put_failure;
66487509
6649
- nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES);
7510
+ nl_reg_rules = nla_nest_start_noflag(msg, NL80211_ATTR_REG_RULES);
66507511 if (!nl_reg_rules)
66517512 goto nla_put_failure;
66527513
....@@ -6661,7 +7522,7 @@
66617522 freq_range = &reg_rule->freq_range;
66627523 power_rule = &reg_rule->power_rule;
66637524
6664
- nl_reg_rule = nla_nest_start(msg, i);
7525
+ nl_reg_rule = nla_nest_start_noflag(msg, i);
66657526 if (!nl_reg_rule)
66667527 goto nla_put_failure;
66677528
....@@ -6899,7 +7760,7 @@
68997760 struct nlattr *nl_reg_rule;
69007761 char *alpha2;
69017762 int rem_reg_rules, r;
6902
- u32 num_rules = 0, rule_idx = 0, size_of_regd;
7763
+ u32 num_rules = 0, rule_idx = 0;
69037764 enum nl80211_dfs_regions dfs_region = NL80211_DFS_UNSET;
69047765 struct ieee80211_regdomain *rd;
69057766
....@@ -6924,10 +7785,7 @@
69247785 if (!reg_is_valid_request(alpha2))
69257786 return -EINVAL;
69267787
6927
- size_of_regd = sizeof(struct ieee80211_regdomain) +
6928
- num_rules * sizeof(struct ieee80211_reg_rule);
6929
-
6930
- rd = kzalloc(size_of_regd, GFP_KERNEL);
7788
+ rd = kzalloc(struct_size(rd, reg_rules, num_rules), GFP_KERNEL);
69317789 if (!rd)
69327790 return -ENOMEM;
69337791
....@@ -6944,9 +7802,9 @@
69447802
69457803 nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
69467804 rem_reg_rules) {
6947
- r = nla_parse_nested(tb, NL80211_REG_RULE_ATTR_MAX,
6948
- nl_reg_rule, reg_rule_policy,
6949
- info->extack);
7805
+ r = nla_parse_nested_deprecated(tb, NL80211_REG_RULE_ATTR_MAX,
7806
+ nl_reg_rule, reg_rule_policy,
7807
+ info->extack);
69507808 if (r)
69517809 goto bad_reg;
69527810 r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]);
....@@ -7017,8 +7875,9 @@
70177875 if (!nla_ok(nest, nla_len(nest)))
70187876 return -EINVAL;
70197877
7020
- err = nla_parse_nested(attr, NL80211_BSS_SELECT_ATTR_MAX, nest,
7021
- nl80211_bss_select_policy, NULL);
7878
+ err = nla_parse_nested_deprecated(attr, NL80211_BSS_SELECT_ATTR_MAX,
7879
+ nest, nl80211_bss_select_policy,
7880
+ NULL);
70227881 if (err)
70237882 return err;
70247883
....@@ -7065,8 +7924,8 @@
70657924 return 0;
70667925 }
70677926
7068
-static int nl80211_parse_random_mac(struct nlattr **attrs,
7069
- u8 *mac_addr, u8 *mac_addr_mask)
7927
+int nl80211_parse_random_mac(struct nlattr **attrs,
7928
+ u8 *mac_addr, u8 *mac_addr_mask)
70707929 {
70717930 int i;
70727931
....@@ -7208,13 +8067,12 @@
72088067 struct cfg80211_registered_device *rdev = info->user_ptr[0];
72098068 struct wireless_dev *wdev = info->user_ptr[1];
72108069 struct cfg80211_scan_request *request;
8070
+ struct nlattr *scan_freqs = NULL;
8071
+ bool scan_freqs_khz = false;
72118072 struct nlattr *attr;
72128073 struct wiphy *wiphy;
72138074 int err, tmp, n_ssids = 0, n_channels, i;
72148075 size_t ie_len;
7215
-
7216
- if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
7217
- return -EINVAL;
72188076
72198077 wiphy = &rdev->wiphy;
72208078
....@@ -7224,18 +8082,22 @@
72248082 if (!rdev->ops->scan)
72258083 return -EOPNOTSUPP;
72268084
7227
- if (rdev->scan_req || rdev->scan_msg) {
7228
- err = -EBUSY;
7229
- goto unlock;
7230
- }
8085
+ if (rdev->scan_req || rdev->scan_msg)
8086
+ return -EBUSY;
72318087
7232
- if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
7233
- n_channels = validate_scan_freqs(
7234
- info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
7235
- if (!n_channels) {
7236
- err = -EINVAL;
7237
- goto unlock;
7238
- }
8088
+ if (info->attrs[NL80211_ATTR_SCAN_FREQ_KHZ]) {
8089
+ if (!wiphy_ext_feature_isset(wiphy,
8090
+ NL80211_EXT_FEATURE_SCAN_FREQ_KHZ))
8091
+ return -EOPNOTSUPP;
8092
+ scan_freqs = info->attrs[NL80211_ATTR_SCAN_FREQ_KHZ];
8093
+ scan_freqs_khz = true;
8094
+ } else if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES])
8095
+ scan_freqs = info->attrs[NL80211_ATTR_SCAN_FREQUENCIES];
8096
+
8097
+ if (scan_freqs) {
8098
+ n_channels = validate_scan_freqs(scan_freqs);
8099
+ if (!n_channels)
8100
+ return -EINVAL;
72398101 } else {
72408102 n_channels = ieee80211_get_num_supported_channels(wiphy);
72418103 }
....@@ -7244,29 +8106,23 @@
72448106 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp)
72458107 n_ssids++;
72468108
7247
- if (n_ssids > wiphy->max_scan_ssids) {
7248
- err = -EINVAL;
7249
- goto unlock;
7250
- }
8109
+ if (n_ssids > wiphy->max_scan_ssids)
8110
+ return -EINVAL;
72518111
72528112 if (info->attrs[NL80211_ATTR_IE])
72538113 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
72548114 else
72558115 ie_len = 0;
72568116
7257
- if (ie_len > wiphy->max_scan_ie_len) {
7258
- err = -EINVAL;
7259
- goto unlock;
7260
- }
8117
+ if (ie_len > wiphy->max_scan_ie_len)
8118
+ return -EINVAL;
72618119
72628120 request = kzalloc(sizeof(*request)
72638121 + sizeof(*request->ssids) * n_ssids
72648122 + sizeof(*request->channels) * n_channels
72658123 + ie_len, GFP_KERNEL);
7266
- if (!request) {
7267
- err = -ENOMEM;
7268
- goto unlock;
7269
- }
8124
+ if (!request)
8125
+ return -ENOMEM;
72708126
72718127 if (n_ssids)
72728128 request->ssids = (void *)&request->channels[n_channels];
....@@ -7279,13 +8135,16 @@
72798135 }
72808136
72818137 i = 0;
7282
- if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
8138
+ if (scan_freqs) {
72838139 /* user specified, bail out if channel not found */
7284
- nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_FREQUENCIES], tmp) {
8140
+ nla_for_each_nested(attr, scan_freqs, tmp) {
72858141 struct ieee80211_channel *chan;
8142
+ int freq = nla_get_u32(attr);
72868143
7287
- chan = ieee80211_get_channel(wiphy, nla_get_u32(attr));
8144
+ if (!scan_freqs_khz)
8145
+ freq = MHZ_TO_KHZ(freq);
72888146
8147
+ chan = ieee80211_get_channel_khz(wiphy, freq);
72898148 if (!chan) {
72908149 err = -EINVAL;
72918150 goto out_free;
....@@ -7440,19 +8299,21 @@
74408299 request->scan_start = jiffies;
74418300
74428301 rdev->scan_req = request;
7443
- err = rdev_scan(rdev, request);
8302
+ err = cfg80211_scan(rdev);
74448303
7445
- if (!err) {
7446
- nl80211_send_scan_start(rdev, wdev);
7447
- if (wdev->netdev)
7448
- dev_hold(wdev->netdev);
7449
- } else {
8304
+ if (err)
8305
+ goto out_free;
8306
+
8307
+ nl80211_send_scan_start(rdev, wdev);
8308
+ if (wdev->netdev)
8309
+ dev_hold(wdev->netdev);
8310
+
8311
+ return 0;
8312
+
74508313 out_free:
7451
- rdev->scan_req = NULL;
7452
- kfree(request);
7453
- }
8314
+ rdev->scan_req = NULL;
8315
+ kfree(request);
74548316
7455
- unlock:
74568317 return err;
74578318 }
74588319
....@@ -7514,8 +8375,10 @@
75148375 if (WARN_ON(i >= n_plans))
75158376 return -EINVAL;
75168377
7517
- err = nla_parse_nested(plan, NL80211_SCHED_SCAN_PLAN_MAX,
7518
- attr, nl80211_plan_policy, NULL);
8378
+ err = nla_parse_nested_deprecated(plan,
8379
+ NL80211_SCHED_SCAN_PLAN_MAX,
8380
+ attr, nl80211_plan_policy,
8381
+ NULL);
75198382 if (err)
75208383 return err;
75218384
....@@ -7557,6 +8420,41 @@
75578420 return 0;
75588421 }
75598422
8423
+static int
8424
+nl80211_parse_sched_scan_per_band_rssi(struct wiphy *wiphy,
8425
+ struct cfg80211_match_set *match_sets,
8426
+ struct nlattr *tb_band_rssi,
8427
+ s32 rssi_thold)
8428
+{
8429
+ struct nlattr *attr;
8430
+ int i, tmp, ret = 0;
8431
+
8432
+ if (!wiphy_ext_feature_isset(wiphy,
8433
+ NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD)) {
8434
+ if (tb_band_rssi)
8435
+ ret = -EOPNOTSUPP;
8436
+ else
8437
+ for (i = 0; i < NUM_NL80211_BANDS; i++)
8438
+ match_sets->per_band_rssi_thold[i] =
8439
+ NL80211_SCAN_RSSI_THOLD_OFF;
8440
+ return ret;
8441
+ }
8442
+
8443
+ for (i = 0; i < NUM_NL80211_BANDS; i++)
8444
+ match_sets->per_band_rssi_thold[i] = rssi_thold;
8445
+
8446
+ nla_for_each_nested(attr, tb_band_rssi, tmp) {
8447
+ enum nl80211_band band = nla_type(attr);
8448
+
8449
+ if (band < 0 || band >= NUM_NL80211_BANDS)
8450
+ return -EINVAL;
8451
+
8452
+ match_sets->per_band_rssi_thold[band] = nla_get_s32(attr);
8453
+ }
8454
+
8455
+ return 0;
8456
+}
8457
+
75608458 static struct cfg80211_sched_scan_request *
75618459 nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
75628460 struct nlattr **attrs, int max_match_sets)
....@@ -7568,9 +8466,6 @@
75688466 size_t ie_len;
75698467 struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
75708468 s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
7571
-
7572
- if (!is_valid_ie_attr(attrs[NL80211_ATTR_IE]))
7573
- return ERR_PTR(-EINVAL);
75748469
75758470 if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
75768471 n_channels = validate_scan_freqs(
....@@ -7604,10 +8499,11 @@
76048499 tmp) {
76058500 struct nlattr *rssi;
76068501
7607
- err = nla_parse_nested(tb,
7608
- NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
7609
- attr, nl80211_match_policy,
7610
- NULL);
8502
+ err = nla_parse_nested_deprecated(tb,
8503
+ NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
8504
+ attr,
8505
+ nl80211_match_policy,
8506
+ NULL);
76118507 if (err)
76128508 return ERR_PTR(err);
76138509
....@@ -7791,51 +8687,55 @@
77918687 tmp) {
77928688 struct nlattr *ssid, *bssid, *rssi;
77938689
7794
- err = nla_parse_nested(tb,
7795
- NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
7796
- attr, nl80211_match_policy,
7797
- NULL);
8690
+ err = nla_parse_nested_deprecated(tb,
8691
+ NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
8692
+ attr,
8693
+ nl80211_match_policy,
8694
+ NULL);
77988695 if (err)
77998696 goto out_free;
78008697 ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID];
78018698 bssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID];
7802
- if (ssid || bssid) {
7803
- if (WARN_ON(i >= n_match_sets)) {
7804
- /* this indicates a programming error,
7805
- * the loop above should have verified
7806
- * things properly
7807
- */
7808
- err = -EINVAL;
7809
- goto out_free;
7810
- }
78118699
7812
- if (ssid) {
7813
- if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) {
7814
- err = -EINVAL;
7815
- goto out_free;
7816
- }
7817
- memcpy(request->match_sets[i].ssid.ssid,
7818
- nla_data(ssid), nla_len(ssid));
7819
- request->match_sets[i].ssid.ssid_len =
7820
- nla_len(ssid);
7821
- }
7822
- if (bssid) {
7823
- if (nla_len(bssid) != ETH_ALEN) {
7824
- err = -EINVAL;
7825
- goto out_free;
7826
- }
7827
- memcpy(request->match_sets[i].bssid,
7828
- nla_data(bssid), ETH_ALEN);
7829
- }
7830
-
7831
- /* special attribute - old implementation w/a */
7832
- request->match_sets[i].rssi_thold =
7833
- default_match_rssi;
7834
- rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
7835
- if (rssi)
7836
- request->match_sets[i].rssi_thold =
7837
- nla_get_s32(rssi);
8700
+ if (!ssid && !bssid) {
8701
+ i++;
8702
+ continue;
78388703 }
8704
+
8705
+ if (WARN_ON(i >= n_match_sets)) {
8706
+ /* this indicates a programming error,
8707
+ * the loop above should have verified
8708
+ * things properly
8709
+ */
8710
+ err = -EINVAL;
8711
+ goto out_free;
8712
+ }
8713
+
8714
+ if (ssid) {
8715
+ memcpy(request->match_sets[i].ssid.ssid,
8716
+ nla_data(ssid), nla_len(ssid));
8717
+ request->match_sets[i].ssid.ssid_len =
8718
+ nla_len(ssid);
8719
+ }
8720
+ if (bssid)
8721
+ memcpy(request->match_sets[i].bssid,
8722
+ nla_data(bssid), ETH_ALEN);
8723
+
8724
+ /* special attribute - old implementation w/a */
8725
+ request->match_sets[i].rssi_thold = default_match_rssi;
8726
+ rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
8727
+ if (rssi)
8728
+ request->match_sets[i].rssi_thold =
8729
+ nla_get_s32(rssi);
8730
+
8731
+ /* Parse per band RSSI attribute */
8732
+ err = nl80211_parse_sched_scan_per_band_rssi(wiphy,
8733
+ &request->match_sets[i],
8734
+ tb[NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI],
8735
+ request->match_sets[i].rssi_thold);
8736
+ if (err)
8737
+ goto out_free;
8738
+
78398739 i++;
78408740 }
78418741
....@@ -7929,10 +8829,8 @@
79298829 /* leave request id zero for legacy request
79308830 * or if driver does not support multi-scheduled scan
79318831 */
7932
- if (want_multi && rdev->wiphy.max_sched_scan_reqs > 1) {
7933
- while (!sched_scan_req->reqid)
7934
- sched_scan_req->reqid = rdev->wiphy.cookie_counter++;
7935
- }
8832
+ if (want_multi && rdev->wiphy.max_sched_scan_reqs > 1)
8833
+ sched_scan_req->reqid = cfg80211_assign_cookie(rdev);
79368834
79378835 err = rdev_sched_scan_start(rdev, dev, sched_scan_req);
79388836 if (err)
....@@ -8038,6 +8936,60 @@
80388936 return err;
80398937 }
80408938
8939
+static int nl80211_notify_radar_detection(struct sk_buff *skb,
8940
+ struct genl_info *info)
8941
+{
8942
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
8943
+ struct net_device *dev = info->user_ptr[1];
8944
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
8945
+ struct wiphy *wiphy = wdev->wiphy;
8946
+ struct cfg80211_chan_def chandef;
8947
+ enum nl80211_dfs_regions dfs_region;
8948
+ int err;
8949
+
8950
+ dfs_region = reg_get_dfs_region(wiphy);
8951
+ if (dfs_region == NL80211_DFS_UNSET) {
8952
+ GENL_SET_ERR_MSG(info,
8953
+ "DFS Region is not set. Unexpected Radar indication");
8954
+ return -EINVAL;
8955
+ }
8956
+
8957
+ err = nl80211_parse_chandef(rdev, info, &chandef);
8958
+ if (err) {
8959
+ GENL_SET_ERR_MSG(info, "Unable to extract chandef info");
8960
+ return err;
8961
+ }
8962
+
8963
+ err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype);
8964
+ if (err < 0) {
8965
+ GENL_SET_ERR_MSG(info, "chandef is invalid");
8966
+ return err;
8967
+ }
8968
+
8969
+ if (err == 0) {
8970
+ GENL_SET_ERR_MSG(info,
8971
+ "Unexpected Radar indication for chandef/iftype");
8972
+ return -EINVAL;
8973
+ }
8974
+
8975
+ /* Do not process this notification if radar is already detected
8976
+ * by kernel on this channel, and return success.
8977
+ */
8978
+ if (chandef.chan->dfs_state == NL80211_DFS_UNAVAILABLE)
8979
+ return 0;
8980
+
8981
+ cfg80211_set_dfs_state(wiphy, &chandef, NL80211_DFS_UNAVAILABLE);
8982
+
8983
+ cfg80211_sched_dfs_chan_update(rdev);
8984
+
8985
+ rdev->radar_chandef = chandef;
8986
+
8987
+ /* Propagate this notification to other radios as well */
8988
+ queue_work(cfg80211_wq, &rdev->propagate_radar_detect_wk);
8989
+
8990
+ return 0;
8991
+}
8992
+
80418993 static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
80428994 {
80438995 struct cfg80211_registered_device *rdev = info->user_ptr[0];
....@@ -8086,6 +9038,7 @@
80869038 }
80879039
80889040 memset(&params, 0, sizeof(params));
9041
+ params.beacon_csa.ftm_responder = -1;
80899042
80909043 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
80919044 !info->attrs[NL80211_ATTR_CH_SWITCH_COUNT])
....@@ -8107,24 +9060,24 @@
81079060 if (!need_new_beacon)
81089061 goto skip_beacons;
81099062
8110
- err = nl80211_parse_beacon(info->attrs, &params.beacon_after);
9063
+ err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon_after);
81119064 if (err)
81129065 return err;
81139066
8114
- err = nla_parse_nested(csa_attrs, NL80211_ATTR_MAX,
8115
- info->attrs[NL80211_ATTR_CSA_IES],
8116
- nl80211_policy, info->extack);
9067
+ err = nla_parse_nested_deprecated(csa_attrs, NL80211_ATTR_MAX,
9068
+ info->attrs[NL80211_ATTR_CSA_IES],
9069
+ nl80211_policy, info->extack);
81179070 if (err)
81189071 return err;
81199072
8120
- err = nl80211_parse_beacon(csa_attrs, &params.beacon_csa);
9073
+ err = nl80211_parse_beacon(rdev, csa_attrs, &params.beacon_csa);
81219074 if (err)
81229075 return err;
81239076
8124
- if (!csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON])
9077
+ if (!csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON])
81259078 return -EINVAL;
81269079
8127
- len = nla_len(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]);
9080
+ len = nla_len(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
81289081 if (!len || (len % sizeof(u16)))
81299082 return -EINVAL;
81309083
....@@ -8135,7 +9088,7 @@
81359088 return -EINVAL;
81369089
81379090 params.counter_offsets_beacon =
8138
- nla_data(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]);
9091
+ nla_data(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
81399092
81409093 /* sanity checks - counters should fit and be the same */
81419094 for (i = 0; i < params.n_counter_offsets_beacon; i++) {
....@@ -8148,8 +9101,8 @@
81489101 return -EINVAL;
81499102 }
81509103
8151
- if (csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]) {
8152
- len = nla_len(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]);
9104
+ if (csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]) {
9105
+ len = nla_len(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
81539106 if (!len || (len % sizeof(u16)))
81549107 return -EINVAL;
81559108
....@@ -8160,7 +9113,7 @@
81609113 return -EINVAL;
81619114
81629115 params.counter_offsets_presp =
8163
- nla_data(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]);
9116
+ nla_data(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
81649117
81659118 /* sanity checks - counters should fit and be the same */
81669119 for (i = 0; i < params.n_counter_offsets_presp; i++) {
....@@ -8237,7 +9190,7 @@
82379190 NL80211_ATTR_PAD))
82389191 goto nla_put_failure;
82399192
8240
- bss = nla_nest_start(msg, NL80211_ATTR_BSS);
9193
+ bss = nla_nest_start_noflag(msg, NL80211_ATTR_BSS);
82419194 if (!bss)
82429195 goto nla_put_failure;
82439196 if ((!is_zero_ether_addr(res->bssid) &&
....@@ -8280,6 +9233,8 @@
82809233 goto nla_put_failure;
82819234 if (nla_put_u16(msg, NL80211_BSS_CAPABILITY, res->capability) ||
82829235 nla_put_u32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq) ||
9236
+ nla_put_u32(msg, NL80211_BSS_FREQUENCY_OFFSET,
9237
+ res->channel->freq_offset) ||
82839238 nla_put_u32(msg, NL80211_BSS_CHAN_WIDTH, res->scan_width) ||
82849239 nla_put_u32(msg, NL80211_BSS_SEEN_MS_AGO,
82859240 jiffies_to_msecs(jiffies - intbss->ts)))
....@@ -8354,7 +9309,7 @@
83549309 int err;
83559310
83569311 rtnl_lock();
8357
- err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
9312
+ err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
83589313 if (err) {
83599314 rtnl_unlock();
83609315 return err;
....@@ -8414,13 +9369,18 @@
84149369 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
84159370 goto nla_put_failure;
84169371
8417
- infoattr = nla_nest_start(msg, NL80211_ATTR_SURVEY_INFO);
9372
+ infoattr = nla_nest_start_noflag(msg, NL80211_ATTR_SURVEY_INFO);
84189373 if (!infoattr)
84199374 goto nla_put_failure;
84209375
84219376 if (survey->channel &&
84229377 nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY,
84239378 survey->channel->center_freq))
9379
+ goto nla_put_failure;
9380
+
9381
+ if (survey->channel && survey->channel->freq_offset &&
9382
+ nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY_OFFSET,
9383
+ survey->channel->freq_offset))
84249384 goto nla_put_failure;
84259385
84269386 if ((survey->filled & SURVEY_INFO_NOISE_DBM) &&
....@@ -8453,6 +9413,10 @@
84539413 nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_SCAN,
84549414 survey->time_scan, NL80211_SURVEY_INFO_PAD))
84559415 goto nla_put_failure;
9416
+ if ((survey->filled & SURVEY_INFO_TIME_BSS_RX) &&
9417
+ nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_BSS_RX,
9418
+ survey->time_bss_rx, NL80211_SURVEY_INFO_PAD))
9419
+ goto nla_put_failure;
84569420
84579421 nla_nest_end(msg, infoattr);
84589422
....@@ -8466,7 +9430,7 @@
84669430
84679431 static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
84689432 {
8469
- struct nlattr **attrbuf = genl_family_attrbuf(&nl80211_fam);
9433
+ struct nlattr **attrbuf;
84709434 struct survey_info survey;
84719435 struct cfg80211_registered_device *rdev;
84729436 struct wireless_dev *wdev;
....@@ -8474,8 +9438,12 @@
84749438 int res;
84759439 bool radio_stats;
84769440
9441
+ attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), GFP_KERNEL);
9442
+ if (!attrbuf)
9443
+ return -ENOMEM;
9444
+
84779445 rtnl_lock();
8478
- res = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
9446
+ res = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
84799447 if (res)
84809448 goto out_err;
84819449
....@@ -8518,6 +9486,7 @@
85189486 cb->args[2] = survey_idx;
85199487 res = skb->len;
85209488 out_err:
9489
+ kfree(attrbuf);
85219490 rtnl_unlock();
85229491 return res;
85239492 }
....@@ -8525,7 +9494,8 @@
85259494 static bool nl80211_valid_wpa_versions(u32 wpa_versions)
85269495 {
85279496 return !(wpa_versions & ~(NL80211_WPA_VERSION_1 |
8528
- NL80211_WPA_VERSION_2));
9497
+ NL80211_WPA_VERSION_2 |
9498
+ NL80211_WPA_VERSION_3));
85299499 }
85309500
85319501 static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
....@@ -8538,9 +9508,7 @@
85389508 enum nl80211_auth_type auth_type;
85399509 struct key_parse key;
85409510 bool local_state_change;
8541
-
8542
- if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
8543
- return -EINVAL;
9511
+ u32 freq;
85449512
85459513 if (!info->attrs[NL80211_ATTR_MAC])
85469514 return -EINVAL;
....@@ -8597,8 +9565,12 @@
85979565 return -EOPNOTSUPP;
85989566
85999567 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
8600
- chan = nl80211_get_valid_chan(&rdev->wiphy,
8601
- info->attrs[NL80211_ATTR_WIPHY_FREQ]);
9568
+ freq = MHZ_TO_KHZ(nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
9569
+ if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
9570
+ freq +=
9571
+ nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
9572
+
9573
+ chan = nl80211_get_valid_chan(&rdev->wiphy, freq);
86029574 if (!chan)
86039575 return -EINVAL;
86049576
....@@ -8629,9 +9601,6 @@
86299601 return -EINVAL;
86309602 auth_data = nla_data(info->attrs[NL80211_ATTR_AUTH_DATA]);
86319603 auth_data_len = nla_len(info->attrs[NL80211_ATTR_AUTH_DATA]);
8632
- /* need to include at least Auth Transaction and Status Code */
8633
- if (auth_data_len < 4)
8634
- return -EINVAL;
86359604 }
86369605
86379606 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
....@@ -8698,6 +9667,9 @@
86989667 return r;
86999668
87009669 settings->control_port_over_nl80211 = true;
9670
+
9671
+ if (info->attrs[NL80211_ATTR_CONTROL_PORT_NO_PREAUTH])
9672
+ settings->control_port_no_preauth = true;
87019673 }
87029674
87039675 if (info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]) {
....@@ -8759,10 +9731,30 @@
87599731 if (nla_len(info->attrs[NL80211_ATTR_PMK]) != WLAN_PMK_LEN)
87609732 return -EINVAL;
87619733 if (!wiphy_ext_feature_isset(&rdev->wiphy,
8762
- NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK))
9734
+ NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK) &&
9735
+ !wiphy_ext_feature_isset(&rdev->wiphy,
9736
+ NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK))
87639737 return -EINVAL;
87649738 settings->psk = nla_data(info->attrs[NL80211_ATTR_PMK]);
87659739 }
9740
+
9741
+ if (info->attrs[NL80211_ATTR_SAE_PASSWORD]) {
9742
+ if (!wiphy_ext_feature_isset(&rdev->wiphy,
9743
+ NL80211_EXT_FEATURE_SAE_OFFLOAD) &&
9744
+ !wiphy_ext_feature_isset(&rdev->wiphy,
9745
+ NL80211_EXT_FEATURE_SAE_OFFLOAD_AP))
9746
+ return -EINVAL;
9747
+ settings->sae_pwd =
9748
+ nla_data(info->attrs[NL80211_ATTR_SAE_PASSWORD]);
9749
+ settings->sae_pwd_len =
9750
+ nla_len(info->attrs[NL80211_ATTR_SAE_PASSWORD]);
9751
+ }
9752
+
9753
+ if (info->attrs[NL80211_ATTR_SAE_PWE])
9754
+ settings->sae_pwe =
9755
+ nla_get_u8(info->attrs[NL80211_ATTR_SAE_PWE]);
9756
+ else
9757
+ settings->sae_pwe = NL80211_SAE_PWE_UNSPECIFIED;
87669758
87679759 return 0;
87689760 }
....@@ -8775,13 +9767,11 @@
87759767 struct cfg80211_assoc_request req = {};
87769768 const u8 *bssid, *ssid;
87779769 int err, ssid_len = 0;
9770
+ u32 freq;
87789771
87799772 if (dev->ieee80211_ptr->conn_owner_nlportid &&
87809773 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
87819774 return -EPERM;
8782
-
8783
- if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
8784
- return -EINVAL;
87859775
87869776 if (!info->attrs[NL80211_ATTR_MAC] ||
87879777 !info->attrs[NL80211_ATTR_SSID] ||
....@@ -8797,8 +9787,11 @@
87979787
87989788 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
87999789
8800
- chan = nl80211_get_valid_chan(&rdev->wiphy,
8801
- info->attrs[NL80211_ATTR_WIPHY_FREQ]);
9790
+ freq = MHZ_TO_KHZ(nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
9791
+ if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
9792
+ freq +=
9793
+ nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
9794
+ chan = nl80211_get_valid_chan(&rdev->wiphy, freq);
88029795 if (!chan)
88039796 return -EINVAL;
88049797
....@@ -8873,6 +9866,22 @@
88739866 nla_data(info->attrs[NL80211_ATTR_FILS_NONCES]);
88749867 }
88759868
9869
+ if (info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK]) {
9870
+ if (!info->attrs[NL80211_ATTR_S1G_CAPABILITY])
9871
+ return -EINVAL;
9872
+ memcpy(&req.s1g_capa_mask,
9873
+ nla_data(info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK]),
9874
+ sizeof(req.s1g_capa_mask));
9875
+ }
9876
+
9877
+ if (info->attrs[NL80211_ATTR_S1G_CAPABILITY]) {
9878
+ if (!info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK])
9879
+ return -EINVAL;
9880
+ memcpy(&req.s1g_capa,
9881
+ nla_data(info->attrs[NL80211_ATTR_S1G_CAPABILITY]),
9882
+ sizeof(req.s1g_capa));
9883
+ }
9884
+
88769885 err = nl80211_crypto_settings(rdev, info, &req.crypto, 1);
88779886 if (!err) {
88789887 wdev_lock(dev->ieee80211_ptr);
....@@ -8905,9 +9914,6 @@
89059914 if (dev->ieee80211_ptr->conn_owner_nlportid &&
89069915 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
89079916 return -EPERM;
8908
-
8909
- if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
8910
- return -EINVAL;
89119917
89129918 if (!info->attrs[NL80211_ATTR_MAC])
89139919 return -EINVAL;
....@@ -8956,9 +9962,6 @@
89569962 if (dev->ieee80211_ptr->conn_owner_nlportid &&
89579963 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
89589964 return -EPERM;
8959
-
8960
- if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
8961
- return -EINVAL;
89629965
89639966 if (!info->attrs[NL80211_ATTR_MAC])
89649967 return -EINVAL;
....@@ -9033,9 +10036,6 @@
903310036 int err;
903410037
903510038 memset(&ibss, 0, sizeof(ibss));
9036
-
9037
- if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
9038
- return -EINVAL;
903910039
904010040 if (!info->attrs[NL80211_ATTR_SSID] ||
904110041 !nla_len(info->attrs[NL80211_ATTR_SSID]))
....@@ -9149,7 +10149,7 @@
914910149
915010150 if ((ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) &&
915110151 no_ht) {
9152
- kzfree(connkeys);
10152
+ kfree_sensitive(connkeys);
915310153 return -EINVAL;
915410154 }
915510155 }
....@@ -9161,7 +10161,7 @@
916110161 int r = validate_pae_over_nl80211(rdev, info);
916210162
916310163 if (r < 0) {
9164
- kzfree(connkeys);
10164
+ kfree_sensitive(connkeys);
916510165 return r;
916610166 }
916710167
....@@ -9174,7 +10174,7 @@
917410174 wdev_lock(dev->ieee80211_ptr);
917510175 err = __cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
917610176 if (err)
9177
- kzfree(connkeys);
10177
+ kfree_sensitive(connkeys);
917810178 else if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
917910179 dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
918010180 wdev_unlock(dev->ieee80211_ptr);
....@@ -9270,7 +10270,7 @@
927010270 goto nla_put_failure;
927110271 }
927210272
9273
- data = nla_nest_start(skb, attr);
10273
+ data = nla_nest_start_noflag(skb, attr);
927410274 if (!data)
927510275 goto nla_put_failure;
927610276
....@@ -9289,6 +10289,7 @@
928910289 struct wireless_dev *wdev,
929010290 enum nl80211_commands cmd,
929110291 enum nl80211_attrs attr,
10292
+ unsigned int portid,
929210293 int vendor_event_idx,
929310294 int approxlen, gfp_t gfp)
929410295 {
....@@ -9312,7 +10313,7 @@
931210313 return NULL;
931310314 }
931410315
9315
- return __cfg80211_alloc_vendor_skb(rdev, wdev, approxlen, 0, 0,
10316
+ return __cfg80211_alloc_vendor_skb(rdev, wdev, approxlen, portid, 0,
931610317 cmd, attr, info, gfp);
931710318 }
931810319 EXPORT_SYMBOL(__cfg80211_alloc_event_skb);
....@@ -9321,6 +10322,7 @@
932110322 {
932210323 struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
932310324 void *hdr = ((void **)skb->cb)[1];
10325
+ struct nlmsghdr *nlhdr = nlmsg_hdr(skb);
932410326 struct nlattr *data = ((void **)skb->cb)[2];
932510327 enum nl80211_multicast_groups mcgrp = NL80211_MCGRP_TESTMODE;
932610328
....@@ -9330,11 +10332,16 @@
933010332 nla_nest_end(skb, data);
933110333 genlmsg_end(skb, hdr);
933210334
9333
- if (data->nla_type == NL80211_ATTR_VENDOR_DATA)
9334
- mcgrp = NL80211_MCGRP_VENDOR;
10335
+ if (nlhdr->nlmsg_pid) {
10336
+ genlmsg_unicast(wiphy_net(&rdev->wiphy), skb,
10337
+ nlhdr->nlmsg_pid);
10338
+ } else {
10339
+ if (data->nla_type == NL80211_ATTR_VENDOR_DATA)
10340
+ mcgrp = NL80211_MCGRP_VENDOR;
933510341
9336
- genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), skb, 0,
9337
- mcgrp, gfp);
10342
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
10343
+ skb, 0, mcgrp, gfp);
10344
+ }
933810345 }
933910346 EXPORT_SYMBOL(__cfg80211_send_event_skb);
934010347
....@@ -9374,6 +10381,7 @@
937410381 struct netlink_callback *cb)
937510382 {
937610383 struct cfg80211_registered_device *rdev;
10384
+ struct nlattr **attrbuf = NULL;
937710385 int err;
937810386 long phy_idx;
937910387 void *data = NULL;
....@@ -9394,11 +10402,17 @@
939410402 goto out_err;
939510403 }
939610404 } else {
9397
- struct nlattr **attrbuf = genl_family_attrbuf(&nl80211_fam);
10405
+ attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf),
10406
+ GFP_KERNEL);
10407
+ if (!attrbuf) {
10408
+ err = -ENOMEM;
10409
+ goto out_err;
10410
+ }
939810411
9399
- err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
9400
- attrbuf, nl80211_fam.maxattr,
9401
- nl80211_policy, NULL);
10412
+ err = nlmsg_parse_deprecated(cb->nlh,
10413
+ GENL_HDRLEN + nl80211_fam.hdrsize,
10414
+ attrbuf, nl80211_fam.maxattr,
10415
+ nl80211_policy, NULL);
940210416 if (err)
940310417 goto out_err;
940410418
....@@ -9437,7 +10451,7 @@
943710451 break;
943810452 }
943910453
9440
- tmdata = nla_nest_start(skb, NL80211_ATTR_TESTDATA);
10454
+ tmdata = nla_nest_start_noflag(skb, NL80211_ATTR_TESTDATA);
944110455 if (!tmdata) {
944210456 genlmsg_cancel(skb, hdr);
944310457 break;
....@@ -9460,6 +10474,7 @@
946010474 /* see above */
946110475 cb->args[0] = phy_idx + 1;
946210476 out_err:
10477
+ kfree(attrbuf);
946310478 rtnl_unlock();
946410479 return err;
946510480 }
....@@ -9472,12 +10487,10 @@
947210487 struct cfg80211_connect_params connect;
947310488 struct wiphy *wiphy;
947410489 struct cfg80211_cached_keys *connkeys = NULL;
10490
+ u32 freq = 0;
947510491 int err;
947610492
947710493 memset(&connect, 0, sizeof(connect));
9478
-
9479
- if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
9480
- return -EINVAL;
948110494
948210495 if (!info->attrs[NL80211_ATTR_SSID] ||
948310496 !nla_len(info->attrs[NL80211_ATTR_SSID]))
....@@ -9537,11 +10550,6 @@
953710550 !wiphy_ext_feature_isset(&rdev->wiphy,
953810551 NL80211_EXT_FEATURE_MFP_OPTIONAL))
953910552 return -EOPNOTSUPP;
9540
-
9541
- if (connect.mfp != NL80211_MFP_REQUIRED &&
9542
- connect.mfp != NL80211_MFP_NO &&
9543
- connect.mfp != NL80211_MFP_OPTIONAL)
9544
- return -EINVAL;
954510553 } else {
954610554 connect.mfp = NL80211_MFP_NO;
954710555 }
....@@ -9550,14 +10558,21 @@
955010558 connect.prev_bssid =
955110559 nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
955210560
9553
- if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
9554
- connect.channel = nl80211_get_valid_chan(
9555
- wiphy, info->attrs[NL80211_ATTR_WIPHY_FREQ]);
10561
+ if (info->attrs[NL80211_ATTR_WIPHY_FREQ])
10562
+ freq = MHZ_TO_KHZ(nla_get_u32(
10563
+ info->attrs[NL80211_ATTR_WIPHY_FREQ]));
10564
+ if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
10565
+ freq +=
10566
+ nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
10567
+
10568
+ if (freq) {
10569
+ connect.channel = nl80211_get_valid_chan(wiphy, freq);
955610570 if (!connect.channel)
955710571 return -EINVAL;
955810572 } else if (info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]) {
9559
- connect.channel_hint = nl80211_get_valid_chan(
9560
- wiphy, info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]);
10573
+ freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]);
10574
+ freq = MHZ_TO_KHZ(freq);
10575
+ connect.channel_hint = nl80211_get_valid_chan(wiphy, freq);
956110576 if (!connect.channel_hint)
956210577 return -EINVAL;
956310578 }
....@@ -9568,7 +10583,7 @@
956810583
956910584 if (info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG])
957010585 connect.edmg.bw_config =
9571
- nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]);
10586
+ nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]);
957210587 }
957310588
957410589 if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) {
....@@ -9587,7 +10602,7 @@
958710602
958810603 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
958910604 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) {
9590
- kzfree(connkeys);
10605
+ kfree_sensitive(connkeys);
959110606 return -EINVAL;
959210607 }
959310608 memcpy(&connect.ht_capa,
....@@ -9605,7 +10620,7 @@
960510620
960610621 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) {
960710622 if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) {
9608
- kzfree(connkeys);
10623
+ kfree_sensitive(connkeys);
960910624 return -EINVAL;
961010625 }
961110626 memcpy(&connect.vht_capa,
....@@ -9619,7 +10634,7 @@
961910634 (rdev->wiphy.features & NL80211_FEATURE_QUIET)) &&
962010635 !wiphy_ext_feature_isset(&rdev->wiphy,
962110636 NL80211_EXT_FEATURE_RRM)) {
9622
- kzfree(connkeys);
10637
+ kfree_sensitive(connkeys);
962310638 return -EINVAL;
962410639 }
962510640 connect.flags |= ASSOC_REQ_USE_RRM;
....@@ -9627,21 +10642,21 @@
962710642
962810643 connect.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
962910644 if (connect.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) {
9630
- kzfree(connkeys);
10645
+ kfree_sensitive(connkeys);
963110646 return -EOPNOTSUPP;
963210647 }
963310648
963410649 if (info->attrs[NL80211_ATTR_BSS_SELECT]) {
963510650 /* bss selection makes no sense if bssid is set */
963610651 if (connect.bssid) {
9637
- kzfree(connkeys);
10652
+ kfree_sensitive(connkeys);
963810653 return -EINVAL;
963910654 }
964010655
964110656 err = parse_bss_select(info->attrs[NL80211_ATTR_BSS_SELECT],
964210657 wiphy, &connect.bss_select);
964310658 if (err) {
9644
- kzfree(connkeys);
10659
+ kfree_sensitive(connkeys);
964510660 return err;
964610661 }
964710662 }
....@@ -9671,13 +10686,13 @@
967110686 info->attrs[NL80211_ATTR_FILS_ERP_REALM] ||
967210687 info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] ||
967310688 info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
9674
- kzfree(connkeys);
10689
+ kfree_sensitive(connkeys);
967510690 return -EINVAL;
967610691 }
967710692
967810693 if (nla_get_flag(info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])) {
967910694 if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
9680
- kzfree(connkeys);
10695
+ kfree_sensitive(connkeys);
968110696 GENL_SET_ERR_MSG(info,
968210697 "external auth requires connection ownership");
968310698 return -EINVAL;
....@@ -9690,7 +10705,7 @@
969010705 err = cfg80211_connect(rdev, dev, &connect, connkeys,
969110706 connect.prev_bssid);
969210707 if (err)
9693
- kzfree(connkeys);
10708
+ kfree_sensitive(connkeys);
969410709
969510710 if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
969610711 dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
....@@ -9698,8 +10713,7 @@
969810713 memcpy(dev->ieee80211_ptr->disconnect_bssid,
969910714 connect.bssid, ETH_ALEN);
970010715 else
9701
- memset(dev->ieee80211_ptr->disconnect_bssid,
9702
- 0, ETH_ALEN);
10716
+ eth_zero_addr(dev->ieee80211_ptr->disconnect_bssid);
970310717 }
970410718
970510719 wdev_unlock(dev->ieee80211_ptr);
....@@ -9723,8 +10737,6 @@
972310737 return -EOPNOTSUPP;
972410738
972510739 if (info->attrs[NL80211_ATTR_IE]) {
9726
- if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
9727
- return -EINVAL;
972810740 connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
972910741 connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
973010742 changed |= UPDATE_ASSOC_IES;
....@@ -9883,8 +10895,20 @@
988310895 pmksa.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]);
988410896 }
988510897
10898
+ if (info->attrs[NL80211_ATTR_PMK_LIFETIME])
10899
+ pmksa.pmk_lifetime =
10900
+ nla_get_u32(info->attrs[NL80211_ATTR_PMK_LIFETIME]);
10901
+
10902
+ if (info->attrs[NL80211_ATTR_PMK_REAUTH_THRESHOLD])
10903
+ pmksa.pmk_reauth_threshold =
10904
+ nla_get_u8(
10905
+ info->attrs[NL80211_ATTR_PMK_REAUTH_THRESHOLD]);
10906
+
988610907 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
9887
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
10908
+ dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
10909
+ !(dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP &&
10910
+ wiphy_ext_feature_isset(&rdev->wiphy,
10911
+ NL80211_EXT_FEATURE_AP_PMKSA_CACHING)))
988810912 return -EOPNOTSUPP;
988910913
989010914 switch (info->genlhdr->cmd) {
....@@ -10081,16 +11105,23 @@
1008111105 struct cfg80211_bitrate_mask mask;
1008211106 struct cfg80211_registered_device *rdev = info->user_ptr[0];
1008311107 struct net_device *dev = info->user_ptr[1];
11108
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
1008411109 int err;
1008511110
1008611111 if (!rdev->ops->set_bitrate_mask)
1008711112 return -EOPNOTSUPP;
1008811113
10089
- err = nl80211_parse_tx_bitrate_mask(info, &mask);
11114
+ wdev_lock(wdev);
11115
+ err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
11116
+ NL80211_ATTR_TX_RATES, &mask,
11117
+ dev);
1009011118 if (err)
10091
- return err;
11119
+ goto out;
1009211120
10093
- return rdev_set_bitrate_mask(rdev, dev, NULL, &mask);
11121
+ err = rdev_set_bitrate_mask(rdev, dev, NULL, &mask);
11122
+out:
11123
+ wdev_unlock(wdev);
11124
+ return err;
1009411125 }
1009511126
1009611127 static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
....@@ -10124,9 +11155,19 @@
1012411155 if (!rdev->ops->mgmt_tx)
1012511156 return -EOPNOTSUPP;
1012611157
11158
+ if (info->attrs[NL80211_ATTR_RECEIVE_MULTICAST] &&
11159
+ !wiphy_ext_feature_isset(&rdev->wiphy,
11160
+ NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS)) {
11161
+ GENL_SET_ERR_MSG(info,
11162
+ "multicast RX registrations are not supported");
11163
+ return -EOPNOTSUPP;
11164
+ }
11165
+
1012711166 return cfg80211_mlme_register_mgmt(wdev, info->snd_portid, frame_type,
10128
- nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]),
10129
- nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]));
11167
+ nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]),
11168
+ nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]),
11169
+ info->attrs[NL80211_ATTR_RECEIVE_MULTICAST],
11170
+ info->extack);
1013011171 }
1013111172
1013211173 static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
....@@ -10308,9 +11349,6 @@
1030811349 return -EINVAL;
1030911350
1031011351 ps_state = nla_get_u32(info->attrs[NL80211_ATTR_PS_STATE]);
10311
-
10312
- if (ps_state != NL80211_PS_DISABLED && ps_state != NL80211_PS_ENABLED)
10313
- return -EINVAL;
1031411352
1031511353 wdev = dev->ieee80211_ptr;
1031611354
....@@ -10544,8 +11582,9 @@
1054411582 if (!cqm)
1054511583 return -EINVAL;
1054611584
10547
- err = nla_parse_nested(attrs, NL80211_ATTR_CQM_MAX, cqm,
10548
- nl80211_attr_cqm_policy, info->extack);
11585
+ err = nla_parse_nested_deprecated(attrs, NL80211_ATTR_CQM_MAX, cqm,
11586
+ nl80211_attr_cqm_policy,
11587
+ info->extack);
1054911588 if (err)
1055011589 return err;
1055111590
....@@ -10684,7 +11723,10 @@
1068411723 }
1068511724
1068611725 if (info->attrs[NL80211_ATTR_TX_RATES]) {
10687
- err = nl80211_parse_tx_bitrate_mask(info, &setup.beacon_rate);
11726
+ err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
11727
+ NL80211_ATTR_TX_RATES,
11728
+ &setup.beacon_rate,
11729
+ dev);
1068811730 if (err)
1068911731 return err;
1069011732
....@@ -10737,12 +11779,12 @@
1073711779 if (!wowlan->n_patterns)
1073811780 return 0;
1073911781
10740
- nl_pats = nla_nest_start(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN);
11782
+ nl_pats = nla_nest_start_noflag(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN);
1074111783 if (!nl_pats)
1074211784 return -ENOBUFS;
1074311785
1074411786 for (i = 0; i < wowlan->n_patterns; i++) {
10745
- nl_pat = nla_nest_start(msg, i + 1);
11787
+ nl_pat = nla_nest_start_noflag(msg, i + 1);
1074611788 if (!nl_pat)
1074711789 return -ENOBUFS;
1074811790 pat_len = wowlan->patterns[i].pattern_len;
....@@ -10768,7 +11810,8 @@
1076811810 if (!tcp)
1076911811 return 0;
1077011812
10771
- nl_tcp = nla_nest_start(msg, NL80211_WOWLAN_TRIG_TCP_CONNECTION);
11813
+ nl_tcp = nla_nest_start_noflag(msg,
11814
+ NL80211_WOWLAN_TRIG_TCP_CONNECTION);
1077211815 if (!nl_tcp)
1077311816 return -ENOBUFS;
1077411817
....@@ -10812,7 +11855,7 @@
1081211855 if (!req)
1081311856 return 0;
1081411857
10815
- nd = nla_nest_start(msg, NL80211_WOWLAN_TRIG_NET_DETECT);
11858
+ nd = nla_nest_start_noflag(msg, NL80211_WOWLAN_TRIG_NET_DETECT);
1081611859 if (!nd)
1081711860 return -ENOBUFS;
1081811861
....@@ -10838,7 +11881,7 @@
1083811881 return -ENOBUFS;
1083911882 }
1084011883
10841
- freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
11884
+ freqs = nla_nest_start_noflag(msg, NL80211_ATTR_SCAN_FREQUENCIES);
1084211885 if (!freqs)
1084311886 return -ENOBUFS;
1084411887
....@@ -10850,12 +11893,13 @@
1085011893 nla_nest_end(msg, freqs);
1085111894
1085211895 if (req->n_match_sets) {
10853
- matches = nla_nest_start(msg, NL80211_ATTR_SCHED_SCAN_MATCH);
11896
+ matches = nla_nest_start_noflag(msg,
11897
+ NL80211_ATTR_SCHED_SCAN_MATCH);
1085411898 if (!matches)
1085511899 return -ENOBUFS;
1085611900
1085711901 for (i = 0; i < req->n_match_sets; i++) {
10858
- match = nla_nest_start(msg, i);
11902
+ match = nla_nest_start_noflag(msg, i);
1085911903 if (!match)
1086011904 return -ENOBUFS;
1086111905
....@@ -10868,17 +11912,16 @@
1086811912 nla_nest_end(msg, matches);
1086911913 }
1087011914
10871
- scan_plans = nla_nest_start(msg, NL80211_ATTR_SCHED_SCAN_PLANS);
11915
+ scan_plans = nla_nest_start_noflag(msg, NL80211_ATTR_SCHED_SCAN_PLANS);
1087211916 if (!scan_plans)
1087311917 return -ENOBUFS;
1087411918
1087511919 for (i = 0; i < req->n_scan_plans; i++) {
10876
- scan_plan = nla_nest_start(msg, i + 1);
11920
+ scan_plan = nla_nest_start_noflag(msg, i + 1);
1087711921 if (!scan_plan)
1087811922 return -ENOBUFS;
1087911923
10880
- if (!scan_plan ||
10881
- nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_INTERVAL,
11924
+ if (nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_INTERVAL,
1088211925 req->scan_plans[i].interval) ||
1088311926 (req->scan_plans[i].iterations &&
1088411927 nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_ITERATIONS,
....@@ -10923,7 +11966,8 @@
1092311966 if (rdev->wiphy.wowlan_config) {
1092411967 struct nlattr *nl_wowlan;
1092511968
10926
- nl_wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS);
11969
+ nl_wowlan = nla_nest_start_noflag(msg,
11970
+ NL80211_ATTR_WOWLAN_TRIGGERS);
1092711971 if (!nl_wowlan)
1092811972 goto nla_put_failure;
1092911973
....@@ -10981,8 +12025,8 @@
1098112025 if (!rdev->wiphy.wowlan->tcp)
1098212026 return -EINVAL;
1098312027
10984
- err = nla_parse_nested(tb, MAX_NL80211_WOWLAN_TCP, attr,
10985
- nl80211_wowlan_tcp_policy, NULL);
12028
+ err = nla_parse_nested_deprecated(tb, MAX_NL80211_WOWLAN_TCP, attr,
12029
+ nl80211_wowlan_tcp_policy, NULL);
1098612030 if (err)
1098712031 return err;
1098812032
....@@ -11127,8 +12171,8 @@
1112712171 goto out;
1112812172 }
1112912173
11130
- err = nla_parse_nested(tb, NL80211_ATTR_MAX, attr, nl80211_policy,
11131
- NULL);
12174
+ err = nla_parse_nested_deprecated(tb, NL80211_ATTR_MAX, attr,
12175
+ nl80211_policy, NULL);
1113212176 if (err)
1113312177 goto out;
1113412178
....@@ -11163,9 +12207,9 @@
1116312207 goto set_wakeup;
1116412208 }
1116512209
11166
- err = nla_parse_nested(tb, MAX_NL80211_WOWLAN_TRIG,
11167
- info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS],
11168
- nl80211_wowlan_policy, info->extack);
12210
+ err = nla_parse_nested_deprecated(tb, MAX_NL80211_WOWLAN_TRIG,
12211
+ info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS],
12212
+ nl80211_wowlan_policy, info->extack);
1116912213 if (err)
1117012214 return err;
1117112215
....@@ -11247,9 +12291,11 @@
1124712291 rem) {
1124812292 u8 *mask_pat;
1124912293
11250
- err = nla_parse_nested(pat_tb, MAX_NL80211_PKTPAT, pat,
11251
- nl80211_packet_pattern_policy,
11252
- info->extack);
12294
+ err = nla_parse_nested_deprecated(pat_tb,
12295
+ MAX_NL80211_PKTPAT,
12296
+ pat,
12297
+ nl80211_packet_pattern_policy,
12298
+ info->extack);
1125312299 if (err)
1125412300 goto error;
1125512301
....@@ -11357,12 +12403,12 @@
1135712403 if (!rdev->coalesce->n_rules)
1135812404 return 0;
1135912405
11360
- nl_rules = nla_nest_start(msg, NL80211_ATTR_COALESCE_RULE);
12406
+ nl_rules = nla_nest_start_noflag(msg, NL80211_ATTR_COALESCE_RULE);
1136112407 if (!nl_rules)
1136212408 return -ENOBUFS;
1136312409
1136412410 for (i = 0; i < rdev->coalesce->n_rules; i++) {
11365
- nl_rule = nla_nest_start(msg, i + 1);
12411
+ nl_rule = nla_nest_start_noflag(msg, i + 1);
1136612412 if (!nl_rule)
1136712413 return -ENOBUFS;
1136812414
....@@ -11375,13 +12421,13 @@
1137512421 rule->condition))
1137612422 return -ENOBUFS;
1137712423
11378
- nl_pats = nla_nest_start(msg,
11379
- NL80211_ATTR_COALESCE_RULE_PKT_PATTERN);
12424
+ nl_pats = nla_nest_start_noflag(msg,
12425
+ NL80211_ATTR_COALESCE_RULE_PKT_PATTERN);
1138012426 if (!nl_pats)
1138112427 return -ENOBUFS;
1138212428
1138312429 for (j = 0; j < rule->n_patterns; j++) {
11384
- nl_pat = nla_nest_start(msg, j + 1);
12430
+ nl_pat = nla_nest_start_noflag(msg, j + 1);
1138512431 if (!nl_pat)
1138612432 return -ENOBUFS;
1138712433 pat_len = rule->patterns[j].pattern_len;
....@@ -11462,8 +12508,8 @@
1146212508 int rem, pat_len, mask_len, pkt_offset, n_patterns = 0;
1146312509 struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
1146412510
11465
- err = nla_parse_nested(tb, NL80211_ATTR_COALESCE_RULE_MAX, rule,
11466
- nl80211_coalesce_policy, NULL);
12511
+ err = nla_parse_nested_deprecated(tb, NL80211_ATTR_COALESCE_RULE_MAX,
12512
+ rule, nl80211_coalesce_policy, NULL);
1146712513 if (err)
1146812514 return err;
1146912515
....@@ -11476,9 +12522,6 @@
1147612522 if (tb[NL80211_ATTR_COALESCE_RULE_CONDITION])
1147712523 new_rule->condition =
1147812524 nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_CONDITION]);
11479
- if (new_rule->condition != NL80211_COALESCE_CONDITION_MATCH &&
11480
- new_rule->condition != NL80211_COALESCE_CONDITION_NO_MATCH)
11481
- return -EINVAL;
1148212525
1148312526 if (!tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN])
1148412527 return -EINVAL;
....@@ -11501,8 +12544,10 @@
1150112544 rem) {
1150212545 u8 *mask_pat;
1150312546
11504
- err = nla_parse_nested(pat_tb, MAX_NL80211_PKTPAT, pat,
11505
- nl80211_packet_pattern_policy, NULL);
12547
+ err = nla_parse_nested_deprecated(pat_tb, MAX_NL80211_PKTPAT,
12548
+ pat,
12549
+ nl80211_packet_pattern_policy,
12550
+ NULL);
1150612551 if (err)
1150712552 return err;
1150812553
....@@ -11624,37 +12669,31 @@
1162412669 if (!info->attrs[NL80211_ATTR_REKEY_DATA])
1162512670 return -EINVAL;
1162612671
11627
- err = nla_parse_nested(tb, MAX_NL80211_REKEY_DATA,
11628
- info->attrs[NL80211_ATTR_REKEY_DATA],
11629
- nl80211_rekey_policy, info->extack);
12672
+ err = nla_parse_nested_deprecated(tb, MAX_NL80211_REKEY_DATA,
12673
+ info->attrs[NL80211_ATTR_REKEY_DATA],
12674
+ nl80211_rekey_policy, info->extack);
1163012675 if (err)
1163112676 return err;
1163212677
1163312678 if (!tb[NL80211_REKEY_DATA_REPLAY_CTR] || !tb[NL80211_REKEY_DATA_KEK] ||
1163412679 !tb[NL80211_REKEY_DATA_KCK])
1163512680 return -EINVAL;
11636
- if (!tb[NL80211_REKEY_DATA_KEK] || !tb[NL80211_REKEY_DATA_REPLAY_CTR] ||
11637
- (!wiphy_ext_feature_isset(&rdev->wiphy,
11638
- NL80211_EXT_FEATURE_FILS_SK_OFFLOAD) &&
11639
- !wiphy_ext_feature_isset(&rdev->wiphy,
11640
- NL80211_EXT_FEATURE_FILS_STA) &&
11641
- !tb[NL80211_REKEY_DATA_KCK]))
11642
- return -EINVAL;
11643
-
11644
- if (nla_len(tb[NL80211_REKEY_DATA_REPLAY_CTR]) != NL80211_REPLAY_CTR_LEN)
12681
+ if (nla_len(tb[NL80211_REKEY_DATA_KEK]) != NL80211_KEK_LEN &&
12682
+ !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK &&
12683
+ nla_len(tb[NL80211_REKEY_DATA_KEK]) == NL80211_KEK_EXT_LEN))
1164512684 return -ERANGE;
11646
- if (nla_len(tb[NL80211_REKEY_DATA_KEK]) < NL80211_KEK_LEN)
11647
- return -ERANGE;
11648
- if (tb[NL80211_REKEY_DATA_KCK] &&
11649
- nla_len(tb[NL80211_REKEY_DATA_KCK]) != NL80211_KCK_LEN)
12685
+ if (nla_len(tb[NL80211_REKEY_DATA_KCK]) != NL80211_KCK_LEN &&
12686
+ !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK &&
12687
+ nla_len(tb[NL80211_REKEY_DATA_KCK]) == NL80211_KCK_EXT_LEN))
1165012688 return -ERANGE;
1165112689
11652
- memset(&rekey_data, 0, sizeof(rekey_data));
1165312690 rekey_data.kek = nla_data(tb[NL80211_REKEY_DATA_KEK]);
11654
- rekey_data.kek_len = nla_len(tb[NL80211_REKEY_DATA_KEK]);
11655
- if (tb[NL80211_REKEY_DATA_KCK])
11656
- rekey_data.kck = nla_data(tb[NL80211_REKEY_DATA_KCK]);
12691
+ rekey_data.kck = nla_data(tb[NL80211_REKEY_DATA_KCK]);
1165712692 rekey_data.replay_ctr = nla_data(tb[NL80211_REKEY_DATA_REPLAY_CTR]);
12693
+ rekey_data.kek_len = nla_len(tb[NL80211_REKEY_DATA_KEK]);
12694
+ rekey_data.kck_len = nla_len(tb[NL80211_REKEY_DATA_KCK]);
12695
+ if (tb[NL80211_REKEY_DATA_AKM])
12696
+ rekey_data.akm = nla_get_u32(tb[NL80211_REKEY_DATA_AKM]);
1165812697
1165912698 wdev_lock(wdev);
1166012699 if (!wdev->current_bss) {
....@@ -11843,8 +12882,6 @@
1184312882
1184412883 conf.master_pref =
1184512884 nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]);
11846
- if (!conf.master_pref)
11847
- return -EINVAL;
1184812885
1184912886 if (info->attrs[NL80211_ATTR_BANDS]) {
1185012887 u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]);
....@@ -11918,6 +12955,9 @@
1191812955 i = 0;
1191912956 nla_for_each_nested(attr, attr_filter, rem) {
1192012957 filter[i].filter = nla_memdup(attr, GFP_KERNEL);
12958
+ if (!filter[i].filter)
12959
+ goto err;
12960
+
1192112961 filter[i].len = nla_len(attr);
1192212962 i++;
1192312963 }
....@@ -11930,6 +12970,15 @@
1193012970 }
1193112971
1193212972 return 0;
12973
+
12974
+err:
12975
+ i = 0;
12976
+ nla_for_each_nested(attr, attr_filter, rem) {
12977
+ kfree(filter[i].filter);
12978
+ i++;
12979
+ }
12980
+ kfree(filter);
12981
+ return -ENOMEM;
1193312982 }
1193412983
1193512984 static int nl80211_nan_add_func(struct sk_buff *skb,
....@@ -11952,9 +13001,10 @@
1195213001 if (!info->attrs[NL80211_ATTR_NAN_FUNC])
1195313002 return -EINVAL;
1195413003
11955
- err = nla_parse_nested(tb, NL80211_NAN_FUNC_ATTR_MAX,
11956
- info->attrs[NL80211_ATTR_NAN_FUNC],
11957
- nl80211_nan_func_policy, info->extack);
13004
+ err = nla_parse_nested_deprecated(tb, NL80211_NAN_FUNC_ATTR_MAX,
13005
+ info->attrs[NL80211_ATTR_NAN_FUNC],
13006
+ nl80211_nan_func_policy,
13007
+ info->extack);
1195813008 if (err)
1195913009 return err;
1196013010
....@@ -11962,10 +13012,9 @@
1196213012 if (!func)
1196313013 return -ENOMEM;
1196413014
11965
- func->cookie = wdev->wiphy->cookie_counter++;
13015
+ func->cookie = cfg80211_assign_cookie(rdev);
1196613016
11967
- if (!tb[NL80211_NAN_FUNC_TYPE] ||
11968
- nla_get_u8(tb[NL80211_NAN_FUNC_TYPE]) > NL80211_NAN_FUNC_MAX_TYPE) {
13017
+ if (!tb[NL80211_NAN_FUNC_TYPE]) {
1196913018 err = -EINVAL;
1197013019 goto out;
1197113020 }
....@@ -12050,9 +13099,11 @@
1205013099 if (tb[NL80211_NAN_FUNC_SRF]) {
1205113100 struct nlattr *srf_tb[NUM_NL80211_NAN_SRF_ATTR];
1205213101
12053
- err = nla_parse_nested(srf_tb, NL80211_NAN_SRF_ATTR_MAX,
12054
- tb[NL80211_NAN_FUNC_SRF],
12055
- nl80211_nan_srf_policy, info->extack);
13102
+ err = nla_parse_nested_deprecated(srf_tb,
13103
+ NL80211_NAN_SRF_ATTR_MAX,
13104
+ tb[NL80211_NAN_FUNC_SRF],
13105
+ nl80211_nan_srf_policy,
13106
+ info->extack);
1205613107 if (err)
1205713108 goto out;
1205813109
....@@ -12150,7 +13201,7 @@
1215013201 NL80211_ATTR_PAD))
1215113202 goto nla_put_failure;
1215213203
12153
- func_attr = nla_nest_start(msg, NL80211_ATTR_NAN_FUNC);
13204
+ func_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_FUNC);
1215413205 if (!func_attr)
1215513206 goto nla_put_failure;
1215613207
....@@ -12267,11 +13318,12 @@
1226713318 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, match->addr))
1226813319 goto nla_put_failure;
1226913320
12270
- match_attr = nla_nest_start(msg, NL80211_ATTR_NAN_MATCH);
13321
+ match_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_MATCH);
1227113322 if (!match_attr)
1227213323 goto nla_put_failure;
1227313324
12274
- local_func_attr = nla_nest_start(msg, NL80211_NAN_MATCH_FUNC_LOCAL);
13325
+ local_func_attr = nla_nest_start_noflag(msg,
13326
+ NL80211_NAN_MATCH_FUNC_LOCAL);
1227513327 if (!local_func_attr)
1227613328 goto nla_put_failure;
1227713329
....@@ -12280,7 +13332,8 @@
1228013332
1228113333 nla_nest_end(msg, local_func_attr);
1228213334
12283
- peer_func_attr = nla_nest_start(msg, NL80211_NAN_MATCH_FUNC_PEER);
13335
+ peer_func_attr = nla_nest_start_noflag(msg,
13336
+ NL80211_NAN_MATCH_FUNC_PEER);
1228413337 if (!peer_func_attr)
1228513338 goto nla_put_failure;
1228613339
....@@ -12346,7 +13399,7 @@
1234613399 NL80211_ATTR_PAD))
1234713400 goto nla_put_failure;
1234813401
12349
- func_attr = nla_nest_start(msg, NL80211_ATTR_NAN_FUNC);
13402
+ func_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_FUNC);
1235013403 if (!func_attr)
1235113404 goto nla_put_failure;
1235213405
....@@ -12408,8 +13461,7 @@
1240813461 return -EOPNOTSUPP;
1240913462
1241013463 if (!info->attrs[NL80211_ATTR_MDID] ||
12411
- !info->attrs[NL80211_ATTR_IE] ||
12412
- !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
13464
+ !info->attrs[NL80211_ATTR_IE])
1241313465 return -EINVAL;
1241413466
1241513467 memset(&ft_params, 0, sizeof(ft_params));
....@@ -12452,9 +13504,6 @@
1245213504 duration =
1245313505 nla_get_u16(info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION]);
1245413506
12455
- if (duration > NL80211_CRIT_PROTO_MAX_DURATION)
12456
- return -ERANGE;
12457
-
1245813507 ret = rdev_crit_proto_start(rdev, wdev, proto, duration);
1245913508 if (!ret)
1246013509 rdev->crit_proto_nlportid = info->snd_portid;
....@@ -12476,6 +13525,28 @@
1247613525 rdev_crit_proto_stop(rdev, wdev);
1247713526 }
1247813527 return 0;
13528
+}
13529
+
13530
+static int nl80211_vendor_check_policy(const struct wiphy_vendor_command *vcmd,
13531
+ struct nlattr *attr,
13532
+ struct netlink_ext_ack *extack)
13533
+{
13534
+ if (vcmd->policy == VENDOR_CMD_RAW_DATA) {
13535
+ if (attr->nla_type & NLA_F_NESTED) {
13536
+ NL_SET_ERR_MSG_ATTR(extack, attr,
13537
+ "unexpected nested data");
13538
+ return -EINVAL;
13539
+ }
13540
+
13541
+ return 0;
13542
+ }
13543
+
13544
+ if (!(attr->nla_type & NLA_F_NESTED)) {
13545
+ NL_SET_ERR_MSG_ATTR(extack, attr, "expected nested data");
13546
+ return -EINVAL;
13547
+ }
13548
+
13549
+ return nla_validate_nested(attr, vcmd->maxattr, vcmd->policy, extack);
1247913550 }
1248013551
1248113552 static int nl80211_vendor_cmd(struct sk_buff *skb, struct genl_info *info)
....@@ -12536,11 +13607,16 @@
1253613607 if (info->attrs[NL80211_ATTR_VENDOR_DATA]) {
1253713608 data = nla_data(info->attrs[NL80211_ATTR_VENDOR_DATA]);
1253813609 len = nla_len(info->attrs[NL80211_ATTR_VENDOR_DATA]);
13610
+
13611
+ err = nl80211_vendor_check_policy(vcmd,
13612
+ info->attrs[NL80211_ATTR_VENDOR_DATA],
13613
+ info->extack);
13614
+ if (err)
13615
+ return err;
1253913616 }
1254013617
1254113618 rdev->cur_cmd_info = info;
12542
- err = rdev->wiphy.vendor_commands[i].doit(&rdev->wiphy, wdev,
12543
- data, len);
13619
+ err = vcmd->doit(&rdev->wiphy, wdev, data, len);
1254413620 rdev->cur_cmd_info = NULL;
1254513621 return err;
1254613622 }
....@@ -12553,7 +13629,7 @@
1255313629 struct cfg80211_registered_device **rdev,
1255413630 struct wireless_dev **wdev)
1255513631 {
12556
- struct nlattr **attrbuf = genl_family_attrbuf(&nl80211_fam);
13632
+ struct nlattr **attrbuf;
1255713633 u32 vid, subcmd;
1255813634 unsigned int i;
1255913635 int vcmd_idx = -1;
....@@ -12584,22 +13660,32 @@
1258413660 return 0;
1258513661 }
1258613662
12587
- err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, attrbuf,
12588
- nl80211_fam.maxattr, nl80211_policy, NULL);
13663
+ attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), GFP_KERNEL);
13664
+ if (!attrbuf)
13665
+ return -ENOMEM;
13666
+
13667
+ err = nlmsg_parse_deprecated(cb->nlh,
13668
+ GENL_HDRLEN + nl80211_fam.hdrsize,
13669
+ attrbuf, nl80211_fam.maxattr,
13670
+ nl80211_policy, NULL);
1258913671 if (err)
12590
- return err;
13672
+ goto out;
1259113673
1259213674 if (!attrbuf[NL80211_ATTR_VENDOR_ID] ||
12593
- !attrbuf[NL80211_ATTR_VENDOR_SUBCMD])
12594
- return -EINVAL;
13675
+ !attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) {
13676
+ err = -EINVAL;
13677
+ goto out;
13678
+ }
1259513679
1259613680 *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk), attrbuf);
1259713681 if (IS_ERR(*wdev))
1259813682 *wdev = NULL;
1259913683
1260013684 *rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
12601
- if (IS_ERR(*rdev))
12602
- return PTR_ERR(*rdev);
13685
+ if (IS_ERR(*rdev)) {
13686
+ err = PTR_ERR(*rdev);
13687
+ goto out;
13688
+ }
1260313689
1260413690 vid = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_ID]);
1260513691 subcmd = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_SUBCMD]);
....@@ -12612,19 +13698,30 @@
1261213698 if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd)
1261313699 continue;
1261413700
12615
- if (!vcmd->dumpit)
12616
- return -EOPNOTSUPP;
13701
+ if (!vcmd->dumpit) {
13702
+ err = -EOPNOTSUPP;
13703
+ goto out;
13704
+ }
1261713705
1261813706 vcmd_idx = i;
1261913707 break;
1262013708 }
1262113709
12622
- if (vcmd_idx < 0)
12623
- return -EOPNOTSUPP;
13710
+ if (vcmd_idx < 0) {
13711
+ err = -EOPNOTSUPP;
13712
+ goto out;
13713
+ }
1262413714
1262513715 if (attrbuf[NL80211_ATTR_VENDOR_DATA]) {
1262613716 data = nla_data(attrbuf[NL80211_ATTR_VENDOR_DATA]);
1262713717 data_len = nla_len(attrbuf[NL80211_ATTR_VENDOR_DATA]);
13718
+
13719
+ err = nl80211_vendor_check_policy(
13720
+ &(*rdev)->wiphy.vendor_commands[vcmd_idx],
13721
+ attrbuf[NL80211_ATTR_VENDOR_DATA],
13722
+ cb->extack);
13723
+ if (err)
13724
+ goto out;
1262813725 }
1262913726
1263013727 /* 0 is the first index - add 1 to parse only once */
....@@ -12636,7 +13733,10 @@
1263613733 cb->args[4] = data_len;
1263713734
1263813735 /* keep rtnl locked in successful case */
12639
- return 0;
13736
+ err = 0;
13737
+out:
13738
+ kfree(attrbuf);
13739
+ return err;
1264013740 }
1264113741
1264213742 static int nl80211_vendor_cmd_dump(struct sk_buff *skb,
....@@ -12696,7 +13796,8 @@
1269613796 break;
1269713797 }
1269813798
12699
- vendor_data = nla_nest_start(skb, NL80211_ATTR_VENDOR_DATA);
13799
+ vendor_data = nla_nest_start_noflag(skb,
13800
+ NL80211_ATTR_VENDOR_DATA);
1270013801 if (!vendor_data) {
1270113802 genlmsg_cancel(skb, hdr);
1270213803 break;
....@@ -12709,7 +13810,7 @@
1270913810 if (err == -ENOBUFS || err == -ENOENT) {
1271013811 genlmsg_cancel(skb, hdr);
1271113812 break;
12712
- } else if (err) {
13813
+ } else if (err <= 0) {
1271313814 genlmsg_cancel(skb, hdr);
1271413815 goto out;
1271513816 }
....@@ -12760,6 +13861,17 @@
1276013861 }
1276113862 EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_reply);
1276213863
13864
+unsigned int cfg80211_vendor_cmd_get_sender(struct wiphy *wiphy)
13865
+{
13866
+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
13867
+
13868
+ if (WARN_ON(!rdev->cur_cmd_info))
13869
+ return 0;
13870
+
13871
+ return rdev->cur_cmd_info->snd_portid;
13872
+}
13873
+EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_get_sender);
13874
+
1276313875 static int nl80211_set_qos_map(struct sk_buff *skb,
1276413876 struct genl_info *info)
1276513877 {
....@@ -12776,8 +13888,7 @@
1277613888 pos = nla_data(info->attrs[NL80211_ATTR_QOS_MAP]);
1277713889 len = nla_len(info->attrs[NL80211_ATTR_QOS_MAP]);
1277813890
12779
- if (len % 2 || len < IEEE80211_QOS_MAP_LEN_MIN ||
12780
- len > IEEE80211_QOS_MAP_LEN_MAX)
13891
+ if (len % 2)
1278113892 return -EINVAL;
1278213893
1278313894 qos_map = kzalloc(sizeof(struct cfg80211_qos_map), GFP_KERNEL);
....@@ -12829,12 +13940,7 @@
1282913940 return -EINVAL;
1283013941
1283113942 tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
12832
- if (tsid >= IEEE80211_NUM_TIDS)
12833
- return -EINVAL;
12834
-
1283513943 up = nla_get_u8(info->attrs[NL80211_ATTR_USER_PRIO]);
12836
- if (up >= IEEE80211_NUM_UPS)
12837
- return -EINVAL;
1283813944
1283913945 /* WMM uses TIDs 0-7 even for TSPEC */
1284013946 if (tsid >= IEEE80211_FIRST_TSPEC_TSID) {
....@@ -13050,17 +14156,9 @@
1305014156 goto out;
1305114157 }
1305214158
13053
- if (info->attrs[NL80211_ATTR_PMKR0_NAME]) {
13054
- int r0_name_len = nla_len(info->attrs[NL80211_ATTR_PMKR0_NAME]);
13055
-
13056
- if (r0_name_len != WLAN_PMK_NAME_LEN) {
13057
- ret = -EINVAL;
13058
- goto out;
13059
- }
13060
-
14159
+ if (info->attrs[NL80211_ATTR_PMKR0_NAME])
1306114160 pmk_conf.pmk_r0_name =
1306214161 nla_data(info->attrs[NL80211_ATTR_PMKR0_NAME]);
13063
- }
1306414162
1306514163 ret = rdev_set_pmk(rdev, dev, &pmk_conf);
1306614164 out:
....@@ -13119,8 +14217,7 @@
1311914217
1312014218 if (info->attrs[NL80211_ATTR_SSID]) {
1312114219 params.ssid.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
13122
- if (params.ssid.ssid_len == 0 ||
13123
- params.ssid.ssid_len > IEEE80211_MAX_SSID_LEN)
14220
+ if (params.ssid.ssid_len == 0)
1312414221 return -EINVAL;
1312514222 memcpy(params.ssid.ssid,
1312614223 nla_data(info->attrs[NL80211_ATTR_SSID]),
....@@ -13140,6 +14237,7 @@
1314014237
1314114238 static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
1314214239 {
14240
+ bool dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK];
1314314241 struct cfg80211_registered_device *rdev = info->user_ptr[0];
1314414242 struct net_device *dev = info->user_ptr[1];
1314514243 struct wireless_dev *wdev = dev->ieee80211_ptr;
....@@ -13148,6 +14246,7 @@
1314814246 u8 *dest;
1314914247 u16 proto;
1315014248 bool noencrypt;
14249
+ u64 cookie = 0;
1315114250 int err;
1315214251
1315314252 if (!wiphy_ext_feature_isset(&rdev->wiphy,
....@@ -13192,12 +14291,86 @@
1319214291 noencrypt =
1319314292 nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]);
1319414293
13195
- return rdev_tx_control_port(rdev, dev, buf, len,
13196
- dest, cpu_to_be16(proto), noencrypt);
13197
-
14294
+ err = rdev_tx_control_port(rdev, dev, buf, len,
14295
+ dest, cpu_to_be16(proto), noencrypt,
14296
+ dont_wait_for_ack ? NULL : &cookie);
14297
+ if (!err && !dont_wait_for_ack)
14298
+ nl_set_extack_cookie_u64(info->extack, cookie);
14299
+ return err;
1319814300 out:
1319914301 wdev_unlock(wdev);
1320014302 return err;
14303
+}
14304
+
14305
+static int nl80211_get_ftm_responder_stats(struct sk_buff *skb,
14306
+ struct genl_info *info)
14307
+{
14308
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
14309
+ struct net_device *dev = info->user_ptr[1];
14310
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
14311
+ struct cfg80211_ftm_responder_stats ftm_stats = {};
14312
+ struct sk_buff *msg;
14313
+ void *hdr;
14314
+ struct nlattr *ftm_stats_attr;
14315
+ int err;
14316
+
14317
+ if (wdev->iftype != NL80211_IFTYPE_AP || !wdev->beacon_interval)
14318
+ return -EOPNOTSUPP;
14319
+
14320
+ err = rdev_get_ftm_responder_stats(rdev, dev, &ftm_stats);
14321
+ if (err)
14322
+ return err;
14323
+
14324
+ if (!ftm_stats.filled)
14325
+ return -ENODATA;
14326
+
14327
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
14328
+ if (!msg)
14329
+ return -ENOMEM;
14330
+
14331
+ hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
14332
+ NL80211_CMD_GET_FTM_RESPONDER_STATS);
14333
+ if (!hdr)
14334
+ goto nla_put_failure;
14335
+
14336
+ if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
14337
+ goto nla_put_failure;
14338
+
14339
+ ftm_stats_attr = nla_nest_start_noflag(msg,
14340
+ NL80211_ATTR_FTM_RESPONDER_STATS);
14341
+ if (!ftm_stats_attr)
14342
+ goto nla_put_failure;
14343
+
14344
+#define SET_FTM(field, name, type) \
14345
+ do { if ((ftm_stats.filled & BIT(NL80211_FTM_STATS_ ## name)) && \
14346
+ nla_put_ ## type(msg, NL80211_FTM_STATS_ ## name, \
14347
+ ftm_stats.field)) \
14348
+ goto nla_put_failure; } while (0)
14349
+#define SET_FTM_U64(field, name) \
14350
+ do { if ((ftm_stats.filled & BIT(NL80211_FTM_STATS_ ## name)) && \
14351
+ nla_put_u64_64bit(msg, NL80211_FTM_STATS_ ## name, \
14352
+ ftm_stats.field, NL80211_FTM_STATS_PAD)) \
14353
+ goto nla_put_failure; } while (0)
14354
+
14355
+ SET_FTM(success_num, SUCCESS_NUM, u32);
14356
+ SET_FTM(partial_num, PARTIAL_NUM, u32);
14357
+ SET_FTM(failed_num, FAILED_NUM, u32);
14358
+ SET_FTM(asap_num, ASAP_NUM, u32);
14359
+ SET_FTM(non_asap_num, NON_ASAP_NUM, u32);
14360
+ SET_FTM_U64(total_duration_ms, TOTAL_DURATION_MSEC);
14361
+ SET_FTM(unknown_triggers_num, UNKNOWN_TRIGGERS_NUM, u32);
14362
+ SET_FTM(reschedule_requests_num, RESCHEDULE_REQUESTS_NUM, u32);
14363
+ SET_FTM(out_of_window_triggers_num, OUT_OF_WINDOW_TRIGGERS_NUM, u32);
14364
+#undef SET_FTM
14365
+
14366
+ nla_nest_end(msg, ftm_stats_attr);
14367
+
14368
+ genlmsg_end(msg, hdr);
14369
+ return genlmsg_reply(msg, info);
14370
+
14371
+nla_put_failure:
14372
+ nlmsg_free(msg);
14373
+ return -ENOBUFS;
1320114374 }
1320214375
1320314376 static int nl80211_update_owe_info(struct sk_buff *skb, struct genl_info *info)
....@@ -13223,6 +14396,204 @@
1322314396 }
1322414397
1322514398 return rdev_update_owe_info(rdev, dev, &owe_info);
14399
+}
14400
+
14401
+static int nl80211_probe_mesh_link(struct sk_buff *skb, struct genl_info *info)
14402
+{
14403
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
14404
+ struct net_device *dev = info->user_ptr[1];
14405
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
14406
+ struct station_info sinfo = {};
14407
+ const u8 *buf;
14408
+ size_t len;
14409
+ u8 *dest;
14410
+ int err;
14411
+
14412
+ if (!rdev->ops->probe_mesh_link || !rdev->ops->get_station)
14413
+ return -EOPNOTSUPP;
14414
+
14415
+ if (!info->attrs[NL80211_ATTR_MAC] ||
14416
+ !info->attrs[NL80211_ATTR_FRAME]) {
14417
+ GENL_SET_ERR_MSG(info, "Frame or MAC missing");
14418
+ return -EINVAL;
14419
+ }
14420
+
14421
+ if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
14422
+ return -EOPNOTSUPP;
14423
+
14424
+ dest = nla_data(info->attrs[NL80211_ATTR_MAC]);
14425
+ buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
14426
+ len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
14427
+
14428
+ if (len < sizeof(struct ethhdr))
14429
+ return -EINVAL;
14430
+
14431
+ if (!ether_addr_equal(buf, dest) || is_multicast_ether_addr(buf) ||
14432
+ !ether_addr_equal(buf + ETH_ALEN, dev->dev_addr))
14433
+ return -EINVAL;
14434
+
14435
+ err = rdev_get_station(rdev, dev, dest, &sinfo);
14436
+ if (err)
14437
+ return err;
14438
+
14439
+ cfg80211_sinfo_release_content(&sinfo);
14440
+
14441
+ return rdev_probe_mesh_link(rdev, dev, dest, buf, len);
14442
+}
14443
+
14444
+static int parse_tid_conf(struct cfg80211_registered_device *rdev,
14445
+ struct nlattr *attrs[], struct net_device *dev,
14446
+ struct cfg80211_tid_cfg *tid_conf,
14447
+ struct genl_info *info, const u8 *peer)
14448
+{
14449
+ struct netlink_ext_ack *extack = info->extack;
14450
+ u64 mask;
14451
+ int err;
14452
+
14453
+ if (!attrs[NL80211_TID_CONFIG_ATTR_TIDS])
14454
+ return -EINVAL;
14455
+
14456
+ tid_conf->config_override =
14457
+ nla_get_flag(attrs[NL80211_TID_CONFIG_ATTR_OVERRIDE]);
14458
+ tid_conf->tids = nla_get_u16(attrs[NL80211_TID_CONFIG_ATTR_TIDS]);
14459
+
14460
+ if (tid_conf->config_override) {
14461
+ if (rdev->ops->reset_tid_config) {
14462
+ err = rdev_reset_tid_config(rdev, dev, peer,
14463
+ tid_conf->tids);
14464
+ if (err)
14465
+ return err;
14466
+ } else {
14467
+ return -EINVAL;
14468
+ }
14469
+ }
14470
+
14471
+ if (attrs[NL80211_TID_CONFIG_ATTR_NOACK]) {
14472
+ tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_NOACK);
14473
+ tid_conf->noack =
14474
+ nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_NOACK]);
14475
+ }
14476
+
14477
+ if (attrs[NL80211_TID_CONFIG_ATTR_RETRY_SHORT]) {
14478
+ tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RETRY_SHORT);
14479
+ tid_conf->retry_short =
14480
+ nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RETRY_SHORT]);
14481
+
14482
+ if (tid_conf->retry_short > rdev->wiphy.max_data_retry_count)
14483
+ return -EINVAL;
14484
+ }
14485
+
14486
+ if (attrs[NL80211_TID_CONFIG_ATTR_RETRY_LONG]) {
14487
+ tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RETRY_LONG);
14488
+ tid_conf->retry_long =
14489
+ nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RETRY_LONG]);
14490
+
14491
+ if (tid_conf->retry_long > rdev->wiphy.max_data_retry_count)
14492
+ return -EINVAL;
14493
+ }
14494
+
14495
+ if (attrs[NL80211_TID_CONFIG_ATTR_AMPDU_CTRL]) {
14496
+ tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL);
14497
+ tid_conf->ampdu =
14498
+ nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_AMPDU_CTRL]);
14499
+ }
14500
+
14501
+ if (attrs[NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL]) {
14502
+ tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL);
14503
+ tid_conf->rtscts =
14504
+ nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL]);
14505
+ }
14506
+
14507
+ if (attrs[NL80211_TID_CONFIG_ATTR_AMSDU_CTRL]) {
14508
+ tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_AMSDU_CTRL);
14509
+ tid_conf->amsdu =
14510
+ nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_AMSDU_CTRL]);
14511
+ }
14512
+
14513
+ if (attrs[NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE]) {
14514
+ u32 idx = NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE, attr;
14515
+
14516
+ tid_conf->txrate_type = nla_get_u8(attrs[idx]);
14517
+
14518
+ if (tid_conf->txrate_type != NL80211_TX_RATE_AUTOMATIC) {
14519
+ attr = NL80211_TID_CONFIG_ATTR_TX_RATE;
14520
+ err = nl80211_parse_tx_bitrate_mask(info, attrs, attr,
14521
+ &tid_conf->txrate_mask, dev);
14522
+ if (err)
14523
+ return err;
14524
+
14525
+ tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_TX_RATE);
14526
+ }
14527
+ tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE);
14528
+ }
14529
+
14530
+ if (peer)
14531
+ mask = rdev->wiphy.tid_config_support.peer;
14532
+ else
14533
+ mask = rdev->wiphy.tid_config_support.vif;
14534
+
14535
+ if (tid_conf->mask & ~mask) {
14536
+ NL_SET_ERR_MSG(extack, "unsupported TID configuration");
14537
+ return -ENOTSUPP;
14538
+ }
14539
+
14540
+ return 0;
14541
+}
14542
+
14543
+static int nl80211_set_tid_config(struct sk_buff *skb,
14544
+ struct genl_info *info)
14545
+{
14546
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
14547
+ struct nlattr *attrs[NL80211_TID_CONFIG_ATTR_MAX + 1];
14548
+ struct net_device *dev = info->user_ptr[1];
14549
+ struct cfg80211_tid_config *tid_config;
14550
+ struct nlattr *tid;
14551
+ int conf_idx = 0, rem_conf;
14552
+ int ret = -EINVAL;
14553
+ u32 num_conf = 0;
14554
+
14555
+ if (!info->attrs[NL80211_ATTR_TID_CONFIG])
14556
+ return -EINVAL;
14557
+
14558
+ if (!rdev->ops->set_tid_config)
14559
+ return -EOPNOTSUPP;
14560
+
14561
+ nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
14562
+ rem_conf)
14563
+ num_conf++;
14564
+
14565
+ tid_config = kzalloc(struct_size(tid_config, tid_conf, num_conf),
14566
+ GFP_KERNEL);
14567
+ if (!tid_config)
14568
+ return -ENOMEM;
14569
+
14570
+ tid_config->n_tid_conf = num_conf;
14571
+
14572
+ if (info->attrs[NL80211_ATTR_MAC])
14573
+ tid_config->peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
14574
+
14575
+ nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
14576
+ rem_conf) {
14577
+ ret = nla_parse_nested(attrs, NL80211_TID_CONFIG_ATTR_MAX,
14578
+ tid, NULL, NULL);
14579
+
14580
+ if (ret)
14581
+ goto bad_tid_conf;
14582
+
14583
+ ret = parse_tid_conf(rdev, attrs, dev,
14584
+ &tid_config->tid_conf[conf_idx],
14585
+ info, tid_config->peer);
14586
+ if (ret)
14587
+ goto bad_tid_conf;
14588
+
14589
+ conf_idx++;
14590
+ }
14591
+
14592
+ ret = rdev_set_tid_config(rdev, dev, tid_config);
14593
+
14594
+bad_tid_conf:
14595
+ kfree(tid_config);
14596
+ return ret;
1322614597 }
1322714598
1322814599 #define NL80211_FLAG_NEED_WIPHY 0x01
....@@ -13331,66 +14702,69 @@
1333114702 static const struct genl_ops nl80211_ops[] = {
1333214703 {
1333314704 .cmd = NL80211_CMD_GET_WIPHY,
14705
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1333414706 .doit = nl80211_get_wiphy,
1333514707 .dumpit = nl80211_dump_wiphy,
1333614708 .done = nl80211_dump_wiphy_done,
13337
- .policy = nl80211_policy,
1333814709 /* can be retrieved by unprivileged users */
1333914710 .internal_flags = NL80211_FLAG_NEED_WIPHY |
1334014711 NL80211_FLAG_NEED_RTNL,
1334114712 },
14713
+};
14714
+
14715
+static const struct genl_small_ops nl80211_small_ops[] = {
1334214716 {
1334314717 .cmd = NL80211_CMD_SET_WIPHY,
14718
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1334414719 .doit = nl80211_set_wiphy,
13345
- .policy = nl80211_policy,
1334614720 .flags = GENL_UNS_ADMIN_PERM,
1334714721 .internal_flags = NL80211_FLAG_NEED_RTNL,
1334814722 },
1334914723 {
1335014724 .cmd = NL80211_CMD_GET_INTERFACE,
14725
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1335114726 .doit = nl80211_get_interface,
1335214727 .dumpit = nl80211_dump_interface,
13353
- .policy = nl80211_policy,
1335414728 /* can be retrieved by unprivileged users */
1335514729 .internal_flags = NL80211_FLAG_NEED_WDEV |
1335614730 NL80211_FLAG_NEED_RTNL,
1335714731 },
1335814732 {
1335914733 .cmd = NL80211_CMD_SET_INTERFACE,
14734
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1336014735 .doit = nl80211_set_interface,
13361
- .policy = nl80211_policy,
1336214736 .flags = GENL_UNS_ADMIN_PERM,
1336314737 .internal_flags = NL80211_FLAG_NEED_NETDEV |
1336414738 NL80211_FLAG_NEED_RTNL,
1336514739 },
1336614740 {
1336714741 .cmd = NL80211_CMD_NEW_INTERFACE,
14742
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1336814743 .doit = nl80211_new_interface,
13369
- .policy = nl80211_policy,
1337014744 .flags = GENL_UNS_ADMIN_PERM,
1337114745 .internal_flags = NL80211_FLAG_NEED_WIPHY |
1337214746 NL80211_FLAG_NEED_RTNL,
1337314747 },
1337414748 {
1337514749 .cmd = NL80211_CMD_DEL_INTERFACE,
14750
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1337614751 .doit = nl80211_del_interface,
13377
- .policy = nl80211_policy,
1337814752 .flags = GENL_UNS_ADMIN_PERM,
1337914753 .internal_flags = NL80211_FLAG_NEED_WDEV |
1338014754 NL80211_FLAG_NEED_RTNL,
1338114755 },
1338214756 {
1338314757 .cmd = NL80211_CMD_GET_KEY,
14758
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1338414759 .doit = nl80211_get_key,
13385
- .policy = nl80211_policy,
1338614760 .flags = GENL_UNS_ADMIN_PERM,
1338714761 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1338814762 NL80211_FLAG_NEED_RTNL,
1338914763 },
1339014764 {
1339114765 .cmd = NL80211_CMD_SET_KEY,
14766
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1339214767 .doit = nl80211_set_key,
13393
- .policy = nl80211_policy,
1339414768 .flags = GENL_UNS_ADMIN_PERM,
1339514769 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1339614770 NL80211_FLAG_NEED_RTNL |
....@@ -13398,8 +14772,8 @@
1339814772 },
1339914773 {
1340014774 .cmd = NL80211_CMD_NEW_KEY,
14775
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1340114776 .doit = nl80211_new_key,
13402
- .policy = nl80211_policy,
1340314777 .flags = GENL_UNS_ADMIN_PERM,
1340414778 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1340514779 NL80211_FLAG_NEED_RTNL |
....@@ -13407,15 +14781,15 @@
1340714781 },
1340814782 {
1340914783 .cmd = NL80211_CMD_DEL_KEY,
14784
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1341014785 .doit = nl80211_del_key,
13411
- .policy = nl80211_policy,
1341214786 .flags = GENL_UNS_ADMIN_PERM,
1341314787 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1341414788 NL80211_FLAG_NEED_RTNL,
1341514789 },
1341614790 {
1341714791 .cmd = NL80211_CMD_SET_BEACON,
13418
- .policy = nl80211_policy,
14792
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1341914793 .flags = GENL_UNS_ADMIN_PERM,
1342014794 .doit = nl80211_set_beacon,
1342114795 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
....@@ -13423,7 +14797,7 @@
1342314797 },
1342414798 {
1342514799 .cmd = NL80211_CMD_START_AP,
13426
- .policy = nl80211_policy,
14800
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1342714801 .flags = GENL_UNS_ADMIN_PERM,
1342814802 .doit = nl80211_start_ap,
1342914803 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
....@@ -13431,7 +14805,7 @@
1343114805 },
1343214806 {
1343314807 .cmd = NL80211_CMD_STOP_AP,
13434
- .policy = nl80211_policy,
14808
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1343514809 .flags = GENL_UNS_ADMIN_PERM,
1343614810 .doit = nl80211_stop_ap,
1343714811 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
....@@ -13439,172 +14813,172 @@
1343914813 },
1344014814 {
1344114815 .cmd = NL80211_CMD_GET_STATION,
14816
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1344214817 .doit = nl80211_get_station,
1344314818 .dumpit = nl80211_dump_station,
13444
- .policy = nl80211_policy,
1344514819 .internal_flags = NL80211_FLAG_NEED_NETDEV |
1344614820 NL80211_FLAG_NEED_RTNL,
1344714821 },
1344814822 {
1344914823 .cmd = NL80211_CMD_SET_STATION,
14824
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1345014825 .doit = nl80211_set_station,
13451
- .policy = nl80211_policy,
1345214826 .flags = GENL_UNS_ADMIN_PERM,
1345314827 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1345414828 NL80211_FLAG_NEED_RTNL,
1345514829 },
1345614830 {
1345714831 .cmd = NL80211_CMD_NEW_STATION,
14832
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1345814833 .doit = nl80211_new_station,
13459
- .policy = nl80211_policy,
1346014834 .flags = GENL_UNS_ADMIN_PERM,
1346114835 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1346214836 NL80211_FLAG_NEED_RTNL,
1346314837 },
1346414838 {
1346514839 .cmd = NL80211_CMD_DEL_STATION,
14840
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1346614841 .doit = nl80211_del_station,
13467
- .policy = nl80211_policy,
1346814842 .flags = GENL_UNS_ADMIN_PERM,
1346914843 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1347014844 NL80211_FLAG_NEED_RTNL,
1347114845 },
1347214846 {
1347314847 .cmd = NL80211_CMD_GET_MPATH,
14848
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1347414849 .doit = nl80211_get_mpath,
1347514850 .dumpit = nl80211_dump_mpath,
13476
- .policy = nl80211_policy,
1347714851 .flags = GENL_UNS_ADMIN_PERM,
1347814852 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1347914853 NL80211_FLAG_NEED_RTNL,
1348014854 },
1348114855 {
1348214856 .cmd = NL80211_CMD_GET_MPP,
14857
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1348314858 .doit = nl80211_get_mpp,
1348414859 .dumpit = nl80211_dump_mpp,
13485
- .policy = nl80211_policy,
1348614860 .flags = GENL_UNS_ADMIN_PERM,
1348714861 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1348814862 NL80211_FLAG_NEED_RTNL,
1348914863 },
1349014864 {
1349114865 .cmd = NL80211_CMD_SET_MPATH,
14866
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1349214867 .doit = nl80211_set_mpath,
13493
- .policy = nl80211_policy,
1349414868 .flags = GENL_UNS_ADMIN_PERM,
1349514869 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1349614870 NL80211_FLAG_NEED_RTNL,
1349714871 },
1349814872 {
1349914873 .cmd = NL80211_CMD_NEW_MPATH,
14874
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1350014875 .doit = nl80211_new_mpath,
13501
- .policy = nl80211_policy,
1350214876 .flags = GENL_UNS_ADMIN_PERM,
1350314877 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1350414878 NL80211_FLAG_NEED_RTNL,
1350514879 },
1350614880 {
1350714881 .cmd = NL80211_CMD_DEL_MPATH,
14882
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1350814883 .doit = nl80211_del_mpath,
13509
- .policy = nl80211_policy,
1351014884 .flags = GENL_UNS_ADMIN_PERM,
1351114885 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1351214886 NL80211_FLAG_NEED_RTNL,
1351314887 },
1351414888 {
1351514889 .cmd = NL80211_CMD_SET_BSS,
14890
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1351614891 .doit = nl80211_set_bss,
13517
- .policy = nl80211_policy,
1351814892 .flags = GENL_UNS_ADMIN_PERM,
1351914893 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1352014894 NL80211_FLAG_NEED_RTNL,
1352114895 },
1352214896 {
1352314897 .cmd = NL80211_CMD_GET_REG,
14898
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1352414899 .doit = nl80211_get_reg_do,
1352514900 .dumpit = nl80211_get_reg_dump,
13526
- .policy = nl80211_policy,
1352714901 .internal_flags = NL80211_FLAG_NEED_RTNL,
1352814902 /* can be retrieved by unprivileged users */
1352914903 },
1353014904 #ifdef CONFIG_CFG80211_CRDA_SUPPORT
1353114905 {
1353214906 .cmd = NL80211_CMD_SET_REG,
14907
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1353314908 .doit = nl80211_set_reg,
13534
- .policy = nl80211_policy,
1353514909 .flags = GENL_ADMIN_PERM,
1353614910 .internal_flags = NL80211_FLAG_NEED_RTNL,
1353714911 },
1353814912 #endif
1353914913 {
1354014914 .cmd = NL80211_CMD_REQ_SET_REG,
14915
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1354114916 .doit = nl80211_req_set_reg,
13542
- .policy = nl80211_policy,
1354314917 .flags = GENL_ADMIN_PERM,
1354414918 },
1354514919 {
1354614920 .cmd = NL80211_CMD_RELOAD_REGDB,
14921
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1354714922 .doit = nl80211_reload_regdb,
13548
- .policy = nl80211_policy,
1354914923 .flags = GENL_ADMIN_PERM,
1355014924 },
1355114925 {
1355214926 .cmd = NL80211_CMD_GET_MESH_CONFIG,
14927
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1355314928 .doit = nl80211_get_mesh_config,
13554
- .policy = nl80211_policy,
1355514929 /* can be retrieved by unprivileged users */
1355614930 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1355714931 NL80211_FLAG_NEED_RTNL,
1355814932 },
1355914933 {
1356014934 .cmd = NL80211_CMD_SET_MESH_CONFIG,
14935
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1356114936 .doit = nl80211_update_mesh_config,
13562
- .policy = nl80211_policy,
1356314937 .flags = GENL_UNS_ADMIN_PERM,
1356414938 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1356514939 NL80211_FLAG_NEED_RTNL,
1356614940 },
1356714941 {
1356814942 .cmd = NL80211_CMD_TRIGGER_SCAN,
14943
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1356914944 .doit = nl80211_trigger_scan,
13570
- .policy = nl80211_policy,
1357114945 .flags = GENL_UNS_ADMIN_PERM,
1357214946 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
1357314947 NL80211_FLAG_NEED_RTNL,
1357414948 },
1357514949 {
1357614950 .cmd = NL80211_CMD_ABORT_SCAN,
14951
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1357714952 .doit = nl80211_abort_scan,
13578
- .policy = nl80211_policy,
1357914953 .flags = GENL_UNS_ADMIN_PERM,
1358014954 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
1358114955 NL80211_FLAG_NEED_RTNL,
1358214956 },
1358314957 {
1358414958 .cmd = NL80211_CMD_GET_SCAN,
13585
- .policy = nl80211_policy,
14959
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1358614960 .dumpit = nl80211_dump_scan,
1358714961 },
1358814962 {
1358914963 .cmd = NL80211_CMD_START_SCHED_SCAN,
14964
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1359014965 .doit = nl80211_start_sched_scan,
13591
- .policy = nl80211_policy,
1359214966 .flags = GENL_UNS_ADMIN_PERM,
1359314967 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1359414968 NL80211_FLAG_NEED_RTNL,
1359514969 },
1359614970 {
1359714971 .cmd = NL80211_CMD_STOP_SCHED_SCAN,
14972
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1359814973 .doit = nl80211_stop_sched_scan,
13599
- .policy = nl80211_policy,
1360014974 .flags = GENL_UNS_ADMIN_PERM,
1360114975 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1360214976 NL80211_FLAG_NEED_RTNL,
1360314977 },
1360414978 {
1360514979 .cmd = NL80211_CMD_AUTHENTICATE,
14980
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1360614981 .doit = nl80211_authenticate,
13607
- .policy = nl80211_policy,
1360814982 .flags = GENL_UNS_ADMIN_PERM,
1360914983 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1361014984 NL80211_FLAG_NEED_RTNL |
....@@ -13612,8 +14986,8 @@
1361214986 },
1361314987 {
1361414988 .cmd = NL80211_CMD_ASSOCIATE,
14989
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1361514990 .doit = nl80211_associate,
13616
- .policy = nl80211_policy,
1361714991 .flags = GENL_UNS_ADMIN_PERM,
1361814992 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1361914993 NL80211_FLAG_NEED_RTNL |
....@@ -13621,32 +14995,32 @@
1362114995 },
1362214996 {
1362314997 .cmd = NL80211_CMD_DEAUTHENTICATE,
14998
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1362414999 .doit = nl80211_deauthenticate,
13625
- .policy = nl80211_policy,
1362615000 .flags = GENL_UNS_ADMIN_PERM,
1362715001 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1362815002 NL80211_FLAG_NEED_RTNL,
1362915003 },
1363015004 {
1363115005 .cmd = NL80211_CMD_DISASSOCIATE,
15006
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1363215007 .doit = nl80211_disassociate,
13633
- .policy = nl80211_policy,
1363415008 .flags = GENL_UNS_ADMIN_PERM,
1363515009 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1363615010 NL80211_FLAG_NEED_RTNL,
1363715011 },
1363815012 {
1363915013 .cmd = NL80211_CMD_JOIN_IBSS,
15014
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1364015015 .doit = nl80211_join_ibss,
13641
- .policy = nl80211_policy,
1364215016 .flags = GENL_UNS_ADMIN_PERM,
1364315017 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1364415018 NL80211_FLAG_NEED_RTNL,
1364515019 },
1364615020 {
1364715021 .cmd = NL80211_CMD_LEAVE_IBSS,
15022
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1364815023 .doit = nl80211_leave_ibss,
13649
- .policy = nl80211_policy,
1365015024 .flags = GENL_UNS_ADMIN_PERM,
1365115025 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1365215026 NL80211_FLAG_NEED_RTNL,
....@@ -13654,9 +15028,9 @@
1365415028 #ifdef CONFIG_NL80211_TESTMODE
1365515029 {
1365615030 .cmd = NL80211_CMD_TESTMODE,
15031
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1365715032 .doit = nl80211_testmode_do,
1365815033 .dumpit = nl80211_testmode_dump,
13659
- .policy = nl80211_policy,
1366015034 .flags = GENL_UNS_ADMIN_PERM,
1366115035 .internal_flags = NL80211_FLAG_NEED_WIPHY |
1366215036 NL80211_FLAG_NEED_RTNL,
....@@ -13664,8 +15038,8 @@
1366415038 #endif
1366515039 {
1366615040 .cmd = NL80211_CMD_CONNECT,
15041
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1366715042 .doit = nl80211_connect,
13668
- .policy = nl80211_policy,
1366915043 .flags = GENL_UNS_ADMIN_PERM,
1367015044 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1367115045 NL80211_FLAG_NEED_RTNL |
....@@ -13673,8 +15047,8 @@
1367315047 },
1367415048 {
1367515049 .cmd = NL80211_CMD_UPDATE_CONNECT_PARAMS,
15050
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1367615051 .doit = nl80211_update_connect_params,
13677
- .policy = nl80211_policy,
1367815052 .flags = GENL_ADMIN_PERM,
1367915053 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1368015054 NL80211_FLAG_NEED_RTNL |
....@@ -13682,29 +15056,29 @@
1368215056 },
1368315057 {
1368415058 .cmd = NL80211_CMD_DISCONNECT,
15059
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1368515060 .doit = nl80211_disconnect,
13686
- .policy = nl80211_policy,
1368715061 .flags = GENL_UNS_ADMIN_PERM,
1368815062 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1368915063 NL80211_FLAG_NEED_RTNL,
1369015064 },
1369115065 {
1369215066 .cmd = NL80211_CMD_SET_WIPHY_NETNS,
15067
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1369315068 .doit = nl80211_wiphy_netns,
13694
- .policy = nl80211_policy,
1369515069 .flags = GENL_UNS_ADMIN_PERM,
1369615070 .internal_flags = NL80211_FLAG_NEED_WIPHY |
1369715071 NL80211_FLAG_NEED_RTNL,
1369815072 },
1369915073 {
1370015074 .cmd = NL80211_CMD_GET_SURVEY,
13701
- .policy = nl80211_policy,
15075
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1370215076 .dumpit = nl80211_dump_survey,
1370315077 },
1370415078 {
1370515079 .cmd = NL80211_CMD_SET_PMKSA,
15080
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1370615081 .doit = nl80211_setdel_pmksa,
13707
- .policy = nl80211_policy,
1370815082 .flags = GENL_UNS_ADMIN_PERM,
1370915083 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1371015084 NL80211_FLAG_NEED_RTNL |
....@@ -13712,136 +15086,136 @@
1371215086 },
1371315087 {
1371415088 .cmd = NL80211_CMD_DEL_PMKSA,
15089
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1371515090 .doit = nl80211_setdel_pmksa,
13716
- .policy = nl80211_policy,
1371715091 .flags = GENL_UNS_ADMIN_PERM,
1371815092 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1371915093 NL80211_FLAG_NEED_RTNL,
1372015094 },
1372115095 {
1372215096 .cmd = NL80211_CMD_FLUSH_PMKSA,
15097
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1372315098 .doit = nl80211_flush_pmksa,
13724
- .policy = nl80211_policy,
1372515099 .flags = GENL_UNS_ADMIN_PERM,
1372615100 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1372715101 NL80211_FLAG_NEED_RTNL,
1372815102 },
1372915103 {
1373015104 .cmd = NL80211_CMD_REMAIN_ON_CHANNEL,
15105
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1373115106 .doit = nl80211_remain_on_channel,
13732
- .policy = nl80211_policy,
1373315107 .flags = GENL_UNS_ADMIN_PERM,
1373415108 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
1373515109 NL80211_FLAG_NEED_RTNL,
1373615110 },
1373715111 {
1373815112 .cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
15113
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1373915114 .doit = nl80211_cancel_remain_on_channel,
13740
- .policy = nl80211_policy,
1374115115 .flags = GENL_UNS_ADMIN_PERM,
1374215116 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
1374315117 NL80211_FLAG_NEED_RTNL,
1374415118 },
1374515119 {
1374615120 .cmd = NL80211_CMD_SET_TX_BITRATE_MASK,
15121
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1374715122 .doit = nl80211_set_tx_bitrate_mask,
13748
- .policy = nl80211_policy,
1374915123 .flags = GENL_UNS_ADMIN_PERM,
1375015124 .internal_flags = NL80211_FLAG_NEED_NETDEV |
1375115125 NL80211_FLAG_NEED_RTNL,
1375215126 },
1375315127 {
1375415128 .cmd = NL80211_CMD_REGISTER_FRAME,
15129
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1375515130 .doit = nl80211_register_mgmt,
13756
- .policy = nl80211_policy,
1375715131 .flags = GENL_UNS_ADMIN_PERM,
1375815132 .internal_flags = NL80211_FLAG_NEED_WDEV |
1375915133 NL80211_FLAG_NEED_RTNL,
1376015134 },
1376115135 {
1376215136 .cmd = NL80211_CMD_FRAME,
15137
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1376315138 .doit = nl80211_tx_mgmt,
13764
- .policy = nl80211_policy,
1376515139 .flags = GENL_UNS_ADMIN_PERM,
1376615140 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
1376715141 NL80211_FLAG_NEED_RTNL,
1376815142 },
1376915143 {
1377015144 .cmd = NL80211_CMD_FRAME_WAIT_CANCEL,
15145
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1377115146 .doit = nl80211_tx_mgmt_cancel_wait,
13772
- .policy = nl80211_policy,
1377315147 .flags = GENL_UNS_ADMIN_PERM,
1377415148 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
1377515149 NL80211_FLAG_NEED_RTNL,
1377615150 },
1377715151 {
1377815152 .cmd = NL80211_CMD_SET_POWER_SAVE,
15153
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1377915154 .doit = nl80211_set_power_save,
13780
- .policy = nl80211_policy,
1378115155 .flags = GENL_UNS_ADMIN_PERM,
1378215156 .internal_flags = NL80211_FLAG_NEED_NETDEV |
1378315157 NL80211_FLAG_NEED_RTNL,
1378415158 },
1378515159 {
1378615160 .cmd = NL80211_CMD_GET_POWER_SAVE,
15161
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1378715162 .doit = nl80211_get_power_save,
13788
- .policy = nl80211_policy,
1378915163 /* can be retrieved by unprivileged users */
1379015164 .internal_flags = NL80211_FLAG_NEED_NETDEV |
1379115165 NL80211_FLAG_NEED_RTNL,
1379215166 },
1379315167 {
1379415168 .cmd = NL80211_CMD_SET_CQM,
15169
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1379515170 .doit = nl80211_set_cqm,
13796
- .policy = nl80211_policy,
1379715171 .flags = GENL_UNS_ADMIN_PERM,
1379815172 .internal_flags = NL80211_FLAG_NEED_NETDEV |
1379915173 NL80211_FLAG_NEED_RTNL,
1380015174 },
1380115175 {
1380215176 .cmd = NL80211_CMD_SET_CHANNEL,
15177
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1380315178 .doit = nl80211_set_channel,
13804
- .policy = nl80211_policy,
1380515179 .flags = GENL_UNS_ADMIN_PERM,
1380615180 .internal_flags = NL80211_FLAG_NEED_NETDEV |
1380715181 NL80211_FLAG_NEED_RTNL,
1380815182 },
1380915183 {
1381015184 .cmd = NL80211_CMD_SET_WDS_PEER,
15185
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1381115186 .doit = nl80211_set_wds_peer,
13812
- .policy = nl80211_policy,
1381315187 .flags = GENL_UNS_ADMIN_PERM,
1381415188 .internal_flags = NL80211_FLAG_NEED_NETDEV |
1381515189 NL80211_FLAG_NEED_RTNL,
1381615190 },
1381715191 {
1381815192 .cmd = NL80211_CMD_JOIN_MESH,
15193
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1381915194 .doit = nl80211_join_mesh,
13820
- .policy = nl80211_policy,
1382115195 .flags = GENL_UNS_ADMIN_PERM,
1382215196 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1382315197 NL80211_FLAG_NEED_RTNL,
1382415198 },
1382515199 {
1382615200 .cmd = NL80211_CMD_LEAVE_MESH,
15201
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1382715202 .doit = nl80211_leave_mesh,
13828
- .policy = nl80211_policy,
1382915203 .flags = GENL_UNS_ADMIN_PERM,
1383015204 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1383115205 NL80211_FLAG_NEED_RTNL,
1383215206 },
1383315207 {
1383415208 .cmd = NL80211_CMD_JOIN_OCB,
15209
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1383515210 .doit = nl80211_join_ocb,
13836
- .policy = nl80211_policy,
1383715211 .flags = GENL_UNS_ADMIN_PERM,
1383815212 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1383915213 NL80211_FLAG_NEED_RTNL,
1384015214 },
1384115215 {
1384215216 .cmd = NL80211_CMD_LEAVE_OCB,
15217
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1384315218 .doit = nl80211_leave_ocb,
13844
- .policy = nl80211_policy,
1384515219 .flags = GENL_UNS_ADMIN_PERM,
1384615220 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1384715221 NL80211_FLAG_NEED_RTNL,
....@@ -13849,16 +15223,16 @@
1384915223 #ifdef CONFIG_PM
1385015224 {
1385115225 .cmd = NL80211_CMD_GET_WOWLAN,
15226
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1385215227 .doit = nl80211_get_wowlan,
13853
- .policy = nl80211_policy,
1385415228 /* can be retrieved by unprivileged users */
1385515229 .internal_flags = NL80211_FLAG_NEED_WIPHY |
1385615230 NL80211_FLAG_NEED_RTNL,
1385715231 },
1385815232 {
1385915233 .cmd = NL80211_CMD_SET_WOWLAN,
15234
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1386015235 .doit = nl80211_set_wowlan,
13861
- .policy = nl80211_policy,
1386215236 .flags = GENL_UNS_ADMIN_PERM,
1386315237 .internal_flags = NL80211_FLAG_NEED_WIPHY |
1386415238 NL80211_FLAG_NEED_RTNL,
....@@ -13866,8 +15240,8 @@
1386615240 #endif
1386715241 {
1386815242 .cmd = NL80211_CMD_SET_REKEY_OFFLOAD,
15243
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1386915244 .doit = nl80211_set_rekey_data,
13870
- .policy = nl80211_policy,
1387115245 .flags = GENL_UNS_ADMIN_PERM,
1387215246 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1387315247 NL80211_FLAG_NEED_RTNL |
....@@ -13875,189 +15249,189 @@
1387515249 },
1387615250 {
1387715251 .cmd = NL80211_CMD_TDLS_MGMT,
15252
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1387815253 .doit = nl80211_tdls_mgmt,
13879
- .policy = nl80211_policy,
1388015254 .flags = GENL_UNS_ADMIN_PERM,
1388115255 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1388215256 NL80211_FLAG_NEED_RTNL,
1388315257 },
1388415258 {
1388515259 .cmd = NL80211_CMD_TDLS_OPER,
15260
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1388615261 .doit = nl80211_tdls_oper,
13887
- .policy = nl80211_policy,
1388815262 .flags = GENL_UNS_ADMIN_PERM,
1388915263 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1389015264 NL80211_FLAG_NEED_RTNL,
1389115265 },
1389215266 {
1389315267 .cmd = NL80211_CMD_UNEXPECTED_FRAME,
15268
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1389415269 .doit = nl80211_register_unexpected_frame,
13895
- .policy = nl80211_policy,
1389615270 .flags = GENL_UNS_ADMIN_PERM,
1389715271 .internal_flags = NL80211_FLAG_NEED_NETDEV |
1389815272 NL80211_FLAG_NEED_RTNL,
1389915273 },
1390015274 {
1390115275 .cmd = NL80211_CMD_PROBE_CLIENT,
15276
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1390215277 .doit = nl80211_probe_client,
13903
- .policy = nl80211_policy,
1390415278 .flags = GENL_UNS_ADMIN_PERM,
1390515279 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1390615280 NL80211_FLAG_NEED_RTNL,
1390715281 },
1390815282 {
1390915283 .cmd = NL80211_CMD_REGISTER_BEACONS,
15284
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1391015285 .doit = nl80211_register_beacons,
13911
- .policy = nl80211_policy,
1391215286 .flags = GENL_UNS_ADMIN_PERM,
1391315287 .internal_flags = NL80211_FLAG_NEED_WIPHY |
1391415288 NL80211_FLAG_NEED_RTNL,
1391515289 },
1391615290 {
1391715291 .cmd = NL80211_CMD_SET_NOACK_MAP,
15292
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1391815293 .doit = nl80211_set_noack_map,
13919
- .policy = nl80211_policy,
1392015294 .flags = GENL_UNS_ADMIN_PERM,
1392115295 .internal_flags = NL80211_FLAG_NEED_NETDEV |
1392215296 NL80211_FLAG_NEED_RTNL,
1392315297 },
1392415298 {
1392515299 .cmd = NL80211_CMD_START_P2P_DEVICE,
15300
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1392615301 .doit = nl80211_start_p2p_device,
13927
- .policy = nl80211_policy,
1392815302 .flags = GENL_UNS_ADMIN_PERM,
1392915303 .internal_flags = NL80211_FLAG_NEED_WDEV |
1393015304 NL80211_FLAG_NEED_RTNL,
1393115305 },
1393215306 {
1393315307 .cmd = NL80211_CMD_STOP_P2P_DEVICE,
15308
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1393415309 .doit = nl80211_stop_p2p_device,
13935
- .policy = nl80211_policy,
1393615310 .flags = GENL_UNS_ADMIN_PERM,
1393715311 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
1393815312 NL80211_FLAG_NEED_RTNL,
1393915313 },
1394015314 {
1394115315 .cmd = NL80211_CMD_START_NAN,
15316
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1394215317 .doit = nl80211_start_nan,
13943
- .policy = nl80211_policy,
1394415318 .flags = GENL_ADMIN_PERM,
1394515319 .internal_flags = NL80211_FLAG_NEED_WDEV |
1394615320 NL80211_FLAG_NEED_RTNL,
1394715321 },
1394815322 {
1394915323 .cmd = NL80211_CMD_STOP_NAN,
15324
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1395015325 .doit = nl80211_stop_nan,
13951
- .policy = nl80211_policy,
1395215326 .flags = GENL_ADMIN_PERM,
1395315327 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
1395415328 NL80211_FLAG_NEED_RTNL,
1395515329 },
1395615330 {
1395715331 .cmd = NL80211_CMD_ADD_NAN_FUNCTION,
15332
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1395815333 .doit = nl80211_nan_add_func,
13959
- .policy = nl80211_policy,
1396015334 .flags = GENL_ADMIN_PERM,
1396115335 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
1396215336 NL80211_FLAG_NEED_RTNL,
1396315337 },
1396415338 {
1396515339 .cmd = NL80211_CMD_DEL_NAN_FUNCTION,
15340
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1396615341 .doit = nl80211_nan_del_func,
13967
- .policy = nl80211_policy,
1396815342 .flags = GENL_ADMIN_PERM,
1396915343 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
1397015344 NL80211_FLAG_NEED_RTNL,
1397115345 },
1397215346 {
1397315347 .cmd = NL80211_CMD_CHANGE_NAN_CONFIG,
15348
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1397415349 .doit = nl80211_nan_change_config,
13975
- .policy = nl80211_policy,
1397615350 .flags = GENL_ADMIN_PERM,
1397715351 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
1397815352 NL80211_FLAG_NEED_RTNL,
1397915353 },
1398015354 {
1398115355 .cmd = NL80211_CMD_SET_MCAST_RATE,
15356
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1398215357 .doit = nl80211_set_mcast_rate,
13983
- .policy = nl80211_policy,
1398415358 .flags = GENL_UNS_ADMIN_PERM,
1398515359 .internal_flags = NL80211_FLAG_NEED_NETDEV |
1398615360 NL80211_FLAG_NEED_RTNL,
1398715361 },
1398815362 {
1398915363 .cmd = NL80211_CMD_SET_MAC_ACL,
15364
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1399015365 .doit = nl80211_set_mac_acl,
13991
- .policy = nl80211_policy,
1399215366 .flags = GENL_UNS_ADMIN_PERM,
1399315367 .internal_flags = NL80211_FLAG_NEED_NETDEV |
1399415368 NL80211_FLAG_NEED_RTNL,
1399515369 },
1399615370 {
1399715371 .cmd = NL80211_CMD_RADAR_DETECT,
15372
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1399815373 .doit = nl80211_start_radar_detection,
13999
- .policy = nl80211_policy,
1400015374 .flags = GENL_UNS_ADMIN_PERM,
1400115375 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1400215376 NL80211_FLAG_NEED_RTNL,
1400315377 },
1400415378 {
1400515379 .cmd = NL80211_CMD_GET_PROTOCOL_FEATURES,
15380
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1400615381 .doit = nl80211_get_protocol_features,
14007
- .policy = nl80211_policy,
1400815382 },
1400915383 {
1401015384 .cmd = NL80211_CMD_UPDATE_FT_IES,
15385
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1401115386 .doit = nl80211_update_ft_ies,
14012
- .policy = nl80211_policy,
1401315387 .flags = GENL_UNS_ADMIN_PERM,
1401415388 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1401515389 NL80211_FLAG_NEED_RTNL,
1401615390 },
1401715391 {
1401815392 .cmd = NL80211_CMD_CRIT_PROTOCOL_START,
15393
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1401915394 .doit = nl80211_crit_protocol_start,
14020
- .policy = nl80211_policy,
1402115395 .flags = GENL_UNS_ADMIN_PERM,
1402215396 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
1402315397 NL80211_FLAG_NEED_RTNL,
1402415398 },
1402515399 {
1402615400 .cmd = NL80211_CMD_CRIT_PROTOCOL_STOP,
15401
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1402715402 .doit = nl80211_crit_protocol_stop,
14028
- .policy = nl80211_policy,
1402915403 .flags = GENL_UNS_ADMIN_PERM,
1403015404 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
1403115405 NL80211_FLAG_NEED_RTNL,
1403215406 },
1403315407 {
1403415408 .cmd = NL80211_CMD_GET_COALESCE,
15409
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1403515410 .doit = nl80211_get_coalesce,
14036
- .policy = nl80211_policy,
1403715411 .internal_flags = NL80211_FLAG_NEED_WIPHY |
1403815412 NL80211_FLAG_NEED_RTNL,
1403915413 },
1404015414 {
1404115415 .cmd = NL80211_CMD_SET_COALESCE,
15416
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1404215417 .doit = nl80211_set_coalesce,
14043
- .policy = nl80211_policy,
1404415418 .flags = GENL_UNS_ADMIN_PERM,
1404515419 .internal_flags = NL80211_FLAG_NEED_WIPHY |
1404615420 NL80211_FLAG_NEED_RTNL,
1404715421 },
1404815422 {
1404915423 .cmd = NL80211_CMD_CHANNEL_SWITCH,
15424
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1405015425 .doit = nl80211_channel_switch,
14051
- .policy = nl80211_policy,
1405215426 .flags = GENL_UNS_ADMIN_PERM,
1405315427 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1405415428 NL80211_FLAG_NEED_RTNL,
1405515429 },
1405615430 {
1405715431 .cmd = NL80211_CMD_VENDOR,
15432
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1405815433 .doit = nl80211_vendor_cmd,
1405915434 .dumpit = nl80211_vendor_cmd_dump,
14060
- .policy = nl80211_policy,
1406115435 .flags = GENL_UNS_ADMIN_PERM,
1406215436 .internal_flags = NL80211_FLAG_NEED_WIPHY |
1406315437 NL80211_FLAG_NEED_RTNL |
....@@ -14065,79 +15439,102 @@
1406515439 },
1406615440 {
1406715441 .cmd = NL80211_CMD_SET_QOS_MAP,
15442
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1406815443 .doit = nl80211_set_qos_map,
14069
- .policy = nl80211_policy,
1407015444 .flags = GENL_UNS_ADMIN_PERM,
1407115445 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1407215446 NL80211_FLAG_NEED_RTNL,
1407315447 },
1407415448 {
1407515449 .cmd = NL80211_CMD_ADD_TX_TS,
15450
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1407615451 .doit = nl80211_add_tx_ts,
14077
- .policy = nl80211_policy,
1407815452 .flags = GENL_UNS_ADMIN_PERM,
1407915453 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1408015454 NL80211_FLAG_NEED_RTNL,
1408115455 },
1408215456 {
1408315457 .cmd = NL80211_CMD_DEL_TX_TS,
15458
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1408415459 .doit = nl80211_del_tx_ts,
14085
- .policy = nl80211_policy,
1408615460 .flags = GENL_UNS_ADMIN_PERM,
1408715461 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1408815462 NL80211_FLAG_NEED_RTNL,
1408915463 },
1409015464 {
1409115465 .cmd = NL80211_CMD_TDLS_CHANNEL_SWITCH,
15466
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1409215467 .doit = nl80211_tdls_channel_switch,
14093
- .policy = nl80211_policy,
1409415468 .flags = GENL_UNS_ADMIN_PERM,
1409515469 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1409615470 NL80211_FLAG_NEED_RTNL,
1409715471 },
1409815472 {
1409915473 .cmd = NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH,
15474
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1410015475 .doit = nl80211_tdls_cancel_channel_switch,
14101
- .policy = nl80211_policy,
1410215476 .flags = GENL_UNS_ADMIN_PERM,
1410315477 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1410415478 NL80211_FLAG_NEED_RTNL,
1410515479 },
1410615480 {
1410715481 .cmd = NL80211_CMD_SET_MULTICAST_TO_UNICAST,
15482
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1410815483 .doit = nl80211_set_multicast_to_unicast,
14109
- .policy = nl80211_policy,
1411015484 .flags = GENL_UNS_ADMIN_PERM,
1411115485 .internal_flags = NL80211_FLAG_NEED_NETDEV |
1411215486 NL80211_FLAG_NEED_RTNL,
1411315487 },
1411415488 {
1411515489 .cmd = NL80211_CMD_SET_PMK,
15490
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1411615491 .doit = nl80211_set_pmk,
14117
- .policy = nl80211_policy,
1411815492 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1411915493 NL80211_FLAG_NEED_RTNL |
1412015494 NL80211_FLAG_CLEAR_SKB,
1412115495 },
1412215496 {
1412315497 .cmd = NL80211_CMD_DEL_PMK,
15498
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1412415499 .doit = nl80211_del_pmk,
14125
- .policy = nl80211_policy,
1412615500 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1412715501 NL80211_FLAG_NEED_RTNL,
1412815502 },
1412915503 {
1413015504 .cmd = NL80211_CMD_EXTERNAL_AUTH,
15505
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1413115506 .doit = nl80211_external_auth,
14132
- .policy = nl80211_policy,
1413315507 .flags = GENL_ADMIN_PERM,
1413415508 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1413515509 NL80211_FLAG_NEED_RTNL,
1413615510 },
1413715511 {
1413815512 .cmd = NL80211_CMD_CONTROL_PORT_FRAME,
15513
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1413915514 .doit = nl80211_tx_control_port,
14140
- .policy = nl80211_policy,
15515
+ .flags = GENL_UNS_ADMIN_PERM,
15516
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15517
+ NL80211_FLAG_NEED_RTNL,
15518
+ },
15519
+ {
15520
+ .cmd = NL80211_CMD_GET_FTM_RESPONDER_STATS,
15521
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
15522
+ .doit = nl80211_get_ftm_responder_stats,
15523
+ .internal_flags = NL80211_FLAG_NEED_NETDEV |
15524
+ NL80211_FLAG_NEED_RTNL,
15525
+ },
15526
+ {
15527
+ .cmd = NL80211_CMD_PEER_MEASUREMENT_START,
15528
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
15529
+ .doit = nl80211_pmsr_start,
15530
+ .flags = GENL_UNS_ADMIN_PERM,
15531
+ .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
15532
+ NL80211_FLAG_NEED_RTNL,
15533
+ },
15534
+ {
15535
+ .cmd = NL80211_CMD_NOTIFY_RADAR,
15536
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
15537
+ .doit = nl80211_notify_radar_detection,
1414115538 .flags = GENL_UNS_ADMIN_PERM,
1414215539 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1414315540 NL80211_FLAG_NEED_RTNL,
....@@ -14149,6 +15546,20 @@
1414915546 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1415015547 NL80211_FLAG_NEED_RTNL,
1415115548 },
15549
+ {
15550
+ .cmd = NL80211_CMD_PROBE_MESH_LINK,
15551
+ .doit = nl80211_probe_mesh_link,
15552
+ .flags = GENL_UNS_ADMIN_PERM,
15553
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15554
+ NL80211_FLAG_NEED_RTNL,
15555
+ },
15556
+ {
15557
+ .cmd = NL80211_CMD_SET_TID_CONFIG,
15558
+ .doit = nl80211_set_tid_config,
15559
+ .flags = GENL_UNS_ADMIN_PERM,
15560
+ .internal_flags = NL80211_FLAG_NEED_NETDEV |
15561
+ NL80211_FLAG_NEED_RTNL,
15562
+ },
1415215563 };
1415315564
1415415565 static struct genl_family nl80211_fam __ro_after_init = {
....@@ -14156,14 +15567,18 @@
1415615567 .hdrsize = 0, /* no private header */
1415715568 .version = 1, /* no particular meaning now */
1415815569 .maxattr = NL80211_ATTR_MAX,
15570
+ .policy = nl80211_policy,
1415915571 .netnsok = true,
1416015572 .pre_doit = nl80211_pre_doit,
1416115573 .post_doit = nl80211_post_doit,
1416215574 .module = THIS_MODULE,
1416315575 .ops = nl80211_ops,
1416415576 .n_ops = ARRAY_SIZE(nl80211_ops),
15577
+ .small_ops = nl80211_small_ops,
15578
+ .n_small_ops = ARRAY_SIZE(nl80211_small_ops),
1416515579 .mcgrps = nl80211_mcgrps,
1416615580 .n_mcgrps = ARRAY_SIZE(nl80211_mcgrps),
15581
+ .parallel_ops = true,
1416715582 };
1416815583
1416915584 /* notification functions */
....@@ -14196,15 +15611,11 @@
1419615611 {
1419715612 struct sk_buff *msg;
1419815613
14199
- WARN_ON(cmd != NL80211_CMD_NEW_INTERFACE &&
14200
- cmd != NL80211_CMD_DEL_INTERFACE);
14201
-
1420215614 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1420315615 if (!msg)
1420415616 return;
1420515617
14206
- if (nl80211_send_iface(msg, 0, 0, 0, rdev, wdev,
14207
- cmd == NL80211_CMD_DEL_INTERFACE) < 0) {
15618
+ if (nl80211_send_iface(msg, 0, 0, 0, rdev, wdev, cmd) < 0) {
1420815619 nlmsg_free(msg);
1420915620 return;
1421015621 }
....@@ -14219,11 +15630,12 @@
1421915630 struct cfg80211_scan_request *req = rdev->scan_req;
1422015631 struct nlattr *nest;
1422115632 int i;
15633
+ struct cfg80211_scan_info *info;
1422215634
1422315635 if (WARN_ON(!req))
1422415636 return 0;
1422515637
14226
- nest = nla_nest_start(msg, NL80211_ATTR_SCAN_SSIDS);
15638
+ nest = nla_nest_start_noflag(msg, NL80211_ATTR_SCAN_SSIDS);
1422715639 if (!nest)
1422815640 goto nla_put_failure;
1422915641 for (i = 0; i < req->n_ssids; i++) {
....@@ -14232,14 +15644,27 @@
1423215644 }
1423315645 nla_nest_end(msg, nest);
1423415646
14235
- nest = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
14236
- if (!nest)
14237
- goto nla_put_failure;
14238
- for (i = 0; i < req->n_channels; i++) {
14239
- if (nla_put_u32(msg, i, req->channels[i]->center_freq))
15647
+ if (req->flags & NL80211_SCAN_FLAG_FREQ_KHZ) {
15648
+ nest = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQ_KHZ);
15649
+ if (!nest)
1424015650 goto nla_put_failure;
15651
+ for (i = 0; i < req->n_channels; i++) {
15652
+ if (nla_put_u32(msg, i,
15653
+ ieee80211_channel_to_khz(req->channels[i])))
15654
+ goto nla_put_failure;
15655
+ }
15656
+ nla_nest_end(msg, nest);
15657
+ } else {
15658
+ nest = nla_nest_start_noflag(msg,
15659
+ NL80211_ATTR_SCAN_FREQUENCIES);
15660
+ if (!nest)
15661
+ goto nla_put_failure;
15662
+ for (i = 0; i < req->n_channels; i++) {
15663
+ if (nla_put_u32(msg, i, req->channels[i]->center_freq))
15664
+ goto nla_put_failure;
15665
+ }
15666
+ nla_nest_end(msg, nest);
1424115667 }
14242
- nla_nest_end(msg, nest);
1424315668
1424415669 if (req->ie &&
1424515670 nla_put(msg, NL80211_ATTR_IE, req->ie_len, req->ie))
....@@ -14249,11 +15674,13 @@
1424915674 nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags))
1425015675 goto nla_put_failure;
1425115676
14252
- if (req->info.scan_start_tsf &&
15677
+ info = rdev->int_scan_req ? &rdev->int_scan_req->info :
15678
+ &rdev->scan_req->info;
15679
+ if (info->scan_start_tsf &&
1425315680 (nla_put_u64_64bit(msg, NL80211_ATTR_SCAN_START_TIME_TSF,
14254
- req->info.scan_start_tsf, NL80211_BSS_PAD) ||
15681
+ info->scan_start_tsf, NL80211_BSS_PAD) ||
1425515682 nla_put(msg, NL80211_ATTR_SCAN_START_TIME_TSF_BSSID, ETH_ALEN,
14256
- req->info.tsf_bssid)))
15683
+ info->tsf_bssid)))
1425715684 goto nla_put_failure;
1425815685
1425915686 return 0;
....@@ -14444,12 +15871,10 @@
1444415871 return;
1444515872
1444615873 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd_id);
14447
- if (!hdr) {
14448
- nlmsg_free(msg);
14449
- return;
14450
- }
15874
+ if (!hdr)
15875
+ goto nla_put_failure;
1445115876
14452
- if (nl80211_reg_change_event_fill(msg, request) == false)
15877
+ if (!nl80211_reg_change_event_fill(msg, request))
1445315878 goto nla_put_failure;
1445415879
1445515880 genlmsg_end(msg, hdr);
....@@ -14469,12 +15894,13 @@
1446915894 struct net_device *netdev,
1447015895 const u8 *buf, size_t len,
1447115896 enum nl80211_commands cmd, gfp_t gfp,
14472
- int uapsd_queues)
15897
+ int uapsd_queues, const u8 *req_ies,
15898
+ size_t req_ies_len)
1447315899 {
1447415900 struct sk_buff *msg;
1447515901 void *hdr;
1447615902
14477
- msg = nlmsg_new(100 + len, gfp);
15903
+ msg = nlmsg_new(100 + len + req_ies_len, gfp);
1447815904 if (!msg)
1447915905 return;
1448015906
....@@ -14486,12 +15912,14 @@
1448615912
1448715913 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
1448815914 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
14489
- nla_put(msg, NL80211_ATTR_FRAME, len, buf))
15915
+ nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
15916
+ (req_ies &&
15917
+ nla_put(msg, NL80211_ATTR_REQ_IE, req_ies_len, req_ies)))
1449015918 goto nla_put_failure;
1449115919
1449215920 if (uapsd_queues >= 0) {
1449315921 struct nlattr *nla_wmm =
14494
- nla_nest_start(msg, NL80211_ATTR_STA_WME);
15922
+ nla_nest_start_noflag(msg, NL80211_ATTR_STA_WME);
1449515923 if (!nla_wmm)
1449615924 goto nla_put_failure;
1449715925
....@@ -14517,15 +15945,17 @@
1451715945 size_t len, gfp_t gfp)
1451815946 {
1451915947 nl80211_send_mlme_event(rdev, netdev, buf, len,
14520
- NL80211_CMD_AUTHENTICATE, gfp, -1);
15948
+ NL80211_CMD_AUTHENTICATE, gfp, -1, NULL, 0);
1452115949 }
1452215950
1452315951 void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
1452415952 struct net_device *netdev, const u8 *buf,
14525
- size_t len, gfp_t gfp, int uapsd_queues)
15953
+ size_t len, gfp_t gfp, int uapsd_queues,
15954
+ const u8 *req_ies, size_t req_ies_len)
1452615955 {
1452715956 nl80211_send_mlme_event(rdev, netdev, buf, len,
14528
- NL80211_CMD_ASSOCIATE, gfp, uapsd_queues);
15957
+ NL80211_CMD_ASSOCIATE, gfp, uapsd_queues,
15958
+ req_ies, req_ies_len);
1452915959 }
1453015960
1453115961 void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
....@@ -14533,7 +15963,7 @@
1453315963 size_t len, gfp_t gfp)
1453415964 {
1453515965 nl80211_send_mlme_event(rdev, netdev, buf, len,
14536
- NL80211_CMD_DEAUTHENTICATE, gfp, -1);
15966
+ NL80211_CMD_DEAUTHENTICATE, gfp, -1, NULL, 0);
1453715967 }
1453815968
1453915969 void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
....@@ -14541,7 +15971,7 @@
1454115971 size_t len, gfp_t gfp)
1454215972 {
1454315973 nl80211_send_mlme_event(rdev, netdev, buf, len,
14544
- NL80211_CMD_DISASSOCIATE, gfp, -1);
15974
+ NL80211_CMD_DISASSOCIATE, gfp, -1, NULL, 0);
1454515975 }
1454615976
1454715977 void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf,
....@@ -14556,13 +15986,23 @@
1455615986 if (WARN_ON(len < 2))
1455715987 return;
1455815988
14559
- if (ieee80211_is_deauth(mgmt->frame_control))
15989
+ if (ieee80211_is_deauth(mgmt->frame_control)) {
1456015990 cmd = NL80211_CMD_UNPROT_DEAUTHENTICATE;
14561
- else
15991
+ } else if (ieee80211_is_disassoc(mgmt->frame_control)) {
1456215992 cmd = NL80211_CMD_UNPROT_DISASSOCIATE;
15993
+ } else if (ieee80211_is_beacon(mgmt->frame_control)) {
15994
+ if (wdev->unprot_beacon_reported &&
15995
+ elapsed_jiffies_msecs(wdev->unprot_beacon_reported) < 10000)
15996
+ return;
15997
+ cmd = NL80211_CMD_UNPROT_BEACON;
15998
+ wdev->unprot_beacon_reported = jiffies;
15999
+ } else {
16000
+ return;
16001
+ }
1456316002
1456416003 trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len);
14565
- nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1);
16004
+ nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1,
16005
+ NULL, 0);
1456616006 }
1456716007 EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt);
1456816008
....@@ -14741,7 +16181,9 @@
1474116181 return;
1474216182 }
1474316183
14744
- if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
16184
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
16185
+ nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
16186
+ nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
1474516187 goto nla_put_failure;
1474616188
1474716189 genlmsg_end(msg, hdr);
....@@ -14823,7 +16265,8 @@
1482316265 }
1482416266
1482516267 void cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr,
14826
- const u8* ie, u8 ie_len, gfp_t gfp)
16268
+ const u8 *ie, u8 ie_len,
16269
+ int sig_dbm, gfp_t gfp)
1482716270 {
1482816271 struct wireless_dev *wdev = dev->ieee80211_ptr;
1482916272 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
....@@ -14849,7 +16292,9 @@
1484916292 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
1485016293 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
1485116294 (ie_len && ie &&
14852
- nla_put(msg, NL80211_ATTR_IE, ie_len , ie)))
16295
+ nla_put(msg, NL80211_ATTR_IE, ie_len, ie)) ||
16296
+ (sig_dbm &&
16297
+ nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)))
1485316298 goto nla_put_failure;
1485416299
1485516300 genlmsg_end(msg, hdr);
....@@ -14926,7 +16371,7 @@
1492616371 goto nla_put_failure;
1492716372
1492816373 /* Before */
14929
- nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_BEFORE);
16374
+ nl_freq = nla_nest_start_noflag(msg, NL80211_ATTR_FREQ_BEFORE);
1493016375 if (!nl_freq)
1493116376 goto nla_put_failure;
1493216377
....@@ -14935,7 +16380,7 @@
1493516380 nla_nest_end(msg, nl_freq);
1493616381
1493716382 /* After */
14938
- nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_AFTER);
16383
+ nl_freq = nla_nest_start_noflag(msg, NL80211_ATTR_FREQ_AFTER);
1493916384 if (!nl_freq)
1494016385 goto nla_put_failure;
1494116386
....@@ -15027,6 +16472,19 @@
1502716472 rdev, wdev, cookie, chan, 0, gfp);
1502816473 }
1502916474 EXPORT_SYMBOL(cfg80211_remain_on_channel_expired);
16475
+
16476
+void cfg80211_tx_mgmt_expired(struct wireless_dev *wdev, u64 cookie,
16477
+ struct ieee80211_channel *chan,
16478
+ gfp_t gfp)
16479
+{
16480
+ struct wiphy *wiphy = wdev->wiphy;
16481
+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
16482
+
16483
+ trace_cfg80211_tx_mgmt_expired(wdev, cookie, chan);
16484
+ nl80211_send_remain_on_chan_event(NL80211_CMD_FRAME_WAIT_CANCEL,
16485
+ rdev, wdev, cookie, chan, 0, gfp);
16486
+}
16487
+EXPORT_SYMBOL(cfg80211_tx_mgmt_expired);
1503016488
1503116489 void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
1503216490 struct station_info *sinfo, gfp_t gfp)
....@@ -15219,7 +16677,8 @@
1521916677 netdev->ifindex)) ||
1522016678 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
1522116679 NL80211_ATTR_PAD) ||
15222
- nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) ||
16680
+ nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, KHZ_TO_MHZ(freq)) ||
16681
+ nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET, freq % 1000) ||
1522316682 (sig_dbm &&
1522416683 nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||
1522516684 nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
....@@ -15236,8 +16695,9 @@
1523616695 return -ENOBUFS;
1523716696 }
1523816697
15239
-void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
15240
- const u8 *buf, size_t len, bool ack, gfp_t gfp)
16698
+static void nl80211_frame_tx_status(struct wireless_dev *wdev, u64 cookie,
16699
+ const u8 *buf, size_t len, bool ack,
16700
+ gfp_t gfp, enum nl80211_commands command)
1524116701 {
1524216702 struct wiphy *wiphy = wdev->wiphy;
1524316703 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
....@@ -15245,13 +16705,16 @@
1524516705 struct sk_buff *msg;
1524616706 void *hdr;
1524716707
15248
- trace_cfg80211_mgmt_tx_status(wdev, cookie, ack);
16708
+ if (command == NL80211_CMD_FRAME_TX_STATUS)
16709
+ trace_cfg80211_mgmt_tx_status(wdev, cookie, ack);
16710
+ else
16711
+ trace_cfg80211_control_port_tx_status(wdev, cookie, ack);
1524916712
1525016713 msg = nlmsg_new(100 + len, gfp);
1525116714 if (!msg)
1525216715 return;
1525316716
15254
- hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME_TX_STATUS);
16717
+ hdr = nl80211hdr_put(msg, 0, 0, 0, command);
1525516718 if (!hdr) {
1525616719 nlmsg_free(msg);
1525716720 return;
....@@ -15274,8 +16737,24 @@
1527416737 NL80211_MCGRP_MLME, gfp);
1527516738 return;
1527616739
15277
- nla_put_failure:
16740
+nla_put_failure:
1527816741 nlmsg_free(msg);
16742
+}
16743
+
16744
+void cfg80211_control_port_tx_status(struct wireless_dev *wdev, u64 cookie,
16745
+ const u8 *buf, size_t len, bool ack,
16746
+ gfp_t gfp)
16747
+{
16748
+ nl80211_frame_tx_status(wdev, cookie, buf, len, ack, gfp,
16749
+ NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS);
16750
+}
16751
+EXPORT_SYMBOL(cfg80211_control_port_tx_status);
16752
+
16753
+void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
16754
+ const u8 *buf, size_t len, bool ack, gfp_t gfp)
16755
+{
16756
+ nl80211_frame_tx_status(wdev, cookie, buf, len, ack, gfp,
16757
+ NL80211_CMD_FRAME_TX_STATUS);
1527916758 }
1528016759 EXPORT_SYMBOL(cfg80211_mgmt_tx_status);
1528116760
....@@ -15369,7 +16848,7 @@
1536916848 if (mac && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac))
1537016849 goto nla_put_failure;
1537116850
15372
- cb[1] = nla_nest_start(msg, NL80211_ATTR_CQM);
16851
+ cb[1] = nla_nest_start_noflag(msg, NL80211_ATTR_CQM);
1537316852 if (!cb[1])
1537416853 goto nla_put_failure;
1537516854
....@@ -15530,7 +17009,7 @@
1553017009 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
1553117010 goto nla_put_failure;
1553217011
15533
- rekey_attr = nla_nest_start(msg, NL80211_ATTR_REKEY_DATA);
17012
+ rekey_attr = nla_nest_start_noflag(msg, NL80211_ATTR_REKEY_DATA);
1553417013 if (!rekey_attr)
1553517014 goto nla_put_failure;
1553617015
....@@ -15585,7 +17064,7 @@
1558517064 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
1558617065 goto nla_put_failure;
1558717066
15588
- attr = nla_nest_start(msg, NL80211_ATTR_PMKSA_CANDIDATE);
17067
+ attr = nla_nest_start_noflag(msg, NL80211_ATTR_PMKSA_CANDIDATE);
1558917068 if (!attr)
1559017069 goto nla_put_failure;
1559117070
....@@ -15673,9 +17152,12 @@
1567317152 wdev->chandef = *chandef;
1567417153 wdev->preset_chandef = *chandef;
1567517154
15676
- if (wdev->iftype == NL80211_IFTYPE_STATION &&
17155
+ if ((wdev->iftype == NL80211_IFTYPE_STATION ||
17156
+ wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
1567717157 !WARN_ON(!wdev->current_bss))
15678
- wdev->current_bss->pub.channel = chandef->chan;
17158
+ cfg80211_update_assoc_bss_entry(wdev, chandef->chan);
17159
+
17160
+ cfg80211_sched_dfs_chan_update(rdev);
1567917161
1568017162 nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
1568117163 NL80211_CMD_CH_SWITCH_NOTIFY, 0);
....@@ -15843,9 +17325,8 @@
1584317325 }
1584417326 EXPORT_SYMBOL(cfg80211_probe_status);
1584517327
15846
-void cfg80211_report_obss_beacon(struct wiphy *wiphy,
15847
- const u8 *frame, size_t len,
15848
- int freq, int sig_dbm)
17328
+void cfg80211_report_obss_beacon_khz(struct wiphy *wiphy, const u8 *frame,
17329
+ size_t len, int freq, int sig_dbm)
1584917330 {
1585017331 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
1585117332 struct sk_buff *msg;
....@@ -15868,7 +17349,10 @@
1586817349
1586917350 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
1587017351 (freq &&
15871
- nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq)) ||
17352
+ (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
17353
+ KHZ_TO_MHZ(freq)) ||
17354
+ nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
17355
+ freq % 1000))) ||
1587217356 (sig_dbm &&
1587317357 nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||
1587417358 nla_put(msg, NL80211_ATTR_FRAME, len, frame))
....@@ -15885,7 +17369,7 @@
1588517369 spin_unlock_bh(&rdev->beacon_registrations_lock);
1588617370 nlmsg_free(msg);
1588717371 }
15888
-EXPORT_SYMBOL(cfg80211_report_obss_beacon);
17372
+EXPORT_SYMBOL(cfg80211_report_obss_beacon_khz);
1588917373
1589017374 #ifdef CONFIG_PM
1589117375 static int cfg80211_net_detect_results(struct sk_buff *msg,
....@@ -15895,15 +17379,15 @@
1589517379 struct nlattr *nl_results, *nl_match, *nl_freqs;
1589617380 int i, j;
1589717381
15898
- nl_results = nla_nest_start(
15899
- msg, NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS);
17382
+ nl_results = nla_nest_start_noflag(msg,
17383
+ NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS);
1590017384 if (!nl_results)
1590117385 return -EMSGSIZE;
1590217386
1590317387 for (i = 0; i < nd->n_matches; i++) {
1590417388 struct cfg80211_wowlan_nd_match *match = nd->matches[i];
1590517389
15906
- nl_match = nla_nest_start(msg, i);
17390
+ nl_match = nla_nest_start_noflag(msg, i);
1590717391 if (!nl_match)
1590817392 break;
1590917393
....@@ -15921,8 +17405,8 @@
1592117405 }
1592217406
1592317407 if (match->n_channels) {
15924
- nl_freqs = nla_nest_start(
15925
- msg, NL80211_ATTR_SCAN_FREQUENCIES);
17408
+ nl_freqs = nla_nest_start_noflag(msg,
17409
+ NL80211_ATTR_SCAN_FREQUENCIES);
1592617410 if (!nl_freqs) {
1592717411 nla_nest_cancel(msg, nl_match);
1592817412 goto out;
....@@ -15981,7 +17465,8 @@
1598117465 if (wakeup) {
1598217466 struct nlattr *reasons;
1598317467
15984
- reasons = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS);
17468
+ reasons = nla_nest_start_noflag(msg,
17469
+ NL80211_ATTR_WOWLAN_TRIGGERS);
1598517470 if (!reasons)
1598617471 goto free_msg;
1598717472
....@@ -16137,6 +17622,8 @@
1613717622 } else if (wdev->conn_owner_nlportid == notify->portid) {
1613817623 schedule_work(&wdev->disconnect_wk);
1613917624 }
17625
+
17626
+ cfg80211_release_pmsr(wdev, notify->portid);
1614017627 }
1614117628
1614217629 spin_lock_bh(&rdev->beacon_registrations_lock);
....@@ -16246,16 +17733,6 @@
1624617733 nlmsg_free(msg);
1624717734 }
1624817735 EXPORT_SYMBOL(cfg80211_crit_proto_stopped);
16249
-
16250
-void cfg80211_ap_stopped(struct net_device *netdev, gfp_t gfp)
16251
-{
16252
- struct wireless_dev *wdev = netdev->ieee80211_ptr;
16253
- struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
16254
-
16255
- nl80211_send_mlme_event(rdev, netdev, NULL, 0,
16256
- NL80211_CMD_STOP_AP, gfp, -1);
16257
-}
16258
-EXPORT_SYMBOL(cfg80211_ap_stopped);
1625917736
1626017737 void nl80211_send_ap_stopped(struct wireless_dev *wdev)
1626117738 {