Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

wifi: nl80211: Add more configuration options for NAN commands

Current NAN APIs have only basic configuration for master
preference and operating bands. Add and parse additional parameters
which provide more control over NAN synchronization. The newly added
attributes allow to publish additional NAN attributes and vendor
elements in NAN beacons, control scan and discovery beacons
periodicity, enable/disable DW notifications etc.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
tested: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20250908140015.a4779492bf8e.I375feb919bd72358173766b9fe10010c40796b33@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Andrei Otcheretianski and committed by
Johannes Berg
01b4a306 4f8ea79a

+431 -37
+60
include/net/cfg80211.h
··· 3913 3913 }; 3914 3914 3915 3915 /** 3916 + * struct cfg80211_nan_band_config - NAN band specific configuration 3917 + * 3918 + * @chan: Pointer to the IEEE 802.11 channel structure. The channel to be used 3919 + * for NAN operations on this band. For 2.4 GHz band, this is always 3920 + * channel 6. For 5 GHz band, the channel is either 44 or 149, according 3921 + * to the regulatory constraints. If chan pointer is NULL the entire band 3922 + * configuration entry is considered invalid and should not be used. 3923 + * @rssi_close: RSSI close threshold used for NAN state transition algorithm 3924 + * as described in chapters 3.3.6 and 3.3.7 "NAN Device Role and State 3925 + * Transition" of Wi-Fi Aware Specification v4.0. If not 3926 + * specified (set to 0), default device value is used. The value should 3927 + * be greater than -60 dBm. 3928 + * @rssi_middle: RSSI middle threshold used for NAN state transition algorithm. 3929 + * as described in chapters 3.3.6 and 3.3.7 "NAN Device Role and State 3930 + * Transition" of Wi-Fi Aware Specification v4.0. If not 3931 + * specified (set to 0), default device value is used. The value should be 3932 + * greater than -75 dBm and less than rssi_close. 3933 + * @awake_dw_interval: Committed DW interval. Valid values range: 0-5. 0 3934 + * indicates no wakeup for DW and can't be used on 2.4GHz band, otherwise 3935 + * 2^(n-1). 3936 + * @disable_scan: If true, the device will not scan this band for cluster 3937 + * merge. Disabling scan on 2.4 GHz band is not allowed. 3938 + */ 3939 + struct cfg80211_nan_band_config { 3940 + struct ieee80211_channel *chan; 3941 + s8 rssi_close; 3942 + s8 rssi_middle; 3943 + u8 awake_dw_interval; 3944 + bool disable_scan; 3945 + }; 3946 + 3947 + /** 3916 3948 * struct cfg80211_nan_conf - NAN configuration 3917 3949 * 3918 3950 * This struct defines NAN configuration parameters ··· 3953 3921 * @bands: operating bands, a bitmap of &enum nl80211_band values. 3954 3922 * For instance, for NL80211_BAND_2GHZ, bit 0 would be set 3955 3923 * (i.e. BIT(NL80211_BAND_2GHZ)). 3924 + * @cluster_id: cluster ID used for NAN synchronization. This is a MAC address 3925 + * that can take a value from 50-6F-9A-01-00-00 to 50-6F-9A-01-FF-FF. 3926 + * If NULL, the device will pick a random Cluster ID. 3927 + * @scan_period: period (in seconds) between NAN scans. 3928 + * @scan_dwell_time: dwell time (in milliseconds) for NAN scans. 3929 + * @discovery_beacon_interval: interval (in TUs) for discovery beacons. 3930 + * @band_cfgs: array of band specific configurations, indexed by 3931 + * &enum nl80211_band values. 3932 + * @extra_nan_attrs: pointer to additional NAN attributes. 3933 + * @extra_nan_attrs_len: length of the additional NAN attributes. 3934 + * @vendor_elems: pointer to vendor-specific elements. 3935 + * @vendor_elems_len: length of the vendor-specific elements. 3956 3936 */ 3957 3937 struct cfg80211_nan_conf { 3958 3938 u8 master_pref; 3959 3939 u8 bands; 3940 + const u8 *cluster_id; 3941 + u16 scan_period; 3942 + u16 scan_dwell_time; 3943 + u8 discovery_beacon_interval; 3944 + struct cfg80211_nan_band_config band_cfgs[NUM_NL80211_BANDS]; 3945 + const u8 *extra_nan_attrs; 3946 + u16 extra_nan_attrs_len; 3947 + const u8 *vendor_elems; 3948 + u16 vendor_elems_len; 3960 3949 }; 3961 3950 3962 3951 /** ··· 3986 3933 * 3987 3934 * @CFG80211_NAN_CONF_CHANGED_PREF: master preference 3988 3935 * @CFG80211_NAN_CONF_CHANGED_BANDS: operating bands 3936 + * @CFG80211_NAN_CONF_CHANGED_CONFIG: changed additional configuration. 3937 + * When this flag is set, it indicates that some additional attribute(s) 3938 + * (other then master_pref and bands) have been changed. In this case, 3939 + * all the unchanged attributes will be properly configured to their 3940 + * previous values. The driver doesn't need to store any 3941 + * previous configuration besides master_pref and bands. 3989 3942 */ 3990 3943 enum cfg80211_nan_conf_changes { 3991 3944 CFG80211_NAN_CONF_CHANGED_PREF = BIT(0), 3992 3945 CFG80211_NAN_CONF_CHANGED_BANDS = BIT(1), 3946 + CFG80211_NAN_CONF_CHANGED_CONFIG = BIT(2), 3993 3947 }; 3994 3948 3995 3949 /**
+108 -2
include/uapi/linux/nl80211.h
··· 1085 1085 * %NL80211_ATTR_NAN_MASTER_PREF attribute and optional 1086 1086 * %NL80211_ATTR_BANDS attributes. If %NL80211_ATTR_BANDS is 1087 1087 * omitted or set to 0, it means don't-care and the device will 1088 - * decide what to use. After this command NAN functions can be 1089 - * added. 1088 + * decide what to use. Additional cluster configuration may be 1089 + * optionally provided with %NL80211_ATTR_NAN_CONFIG. 1090 + * After this command NAN functions can be added. 1090 1091 * @NL80211_CMD_STOP_NAN: Stop the NAN operation, identified by 1091 1092 * its %NL80211_ATTR_WDEV interface. 1092 1093 * @NL80211_CMD_ADD_NAN_FUNCTION: Add a NAN function. The function is defined ··· 1116 1115 * current configuration is not changed. If it is present but 1117 1116 * set to zero, the configuration is changed to don't-care 1118 1117 * (i.e. the device can decide what to do). 1118 + * Additional parameters may be provided with 1119 + * %NL80211_ATTR_NAN_CONFIG. User space should provide all previously 1120 + * configured nested attributes under %NL80211_ATTR_NAN_CONFIG, even if 1121 + * only a subset was changed. 1119 1122 * @NL80211_CMD_NAN_MATCH: Notification sent when a match is reported. 1120 1123 * This will contain a %NL80211_ATTR_NAN_MATCH nested attribute and 1121 1124 * %NL80211_ATTR_COOKIE. ··· 2941 2936 * indicate that it wants strict checking on the BSS parameters to be 2942 2937 * modified. 2943 2938 * 2939 + * @NL80211_ATTR_NAN_CONFIG: Nested attribute for 2940 + * extended NAN cluster configuration. This is used with 2941 + * %NL80211_CMD_START_NAN and %NL80211_CMD_CHANGE_NAN_CONFIG. 2942 + * See &enum nl80211_nan_conf_attributes for details. 2943 + * This attribute is optional. 2944 + * 2944 2945 * @NUM_NL80211_ATTR: total number of nl80211_attrs available 2945 2946 * @NL80211_ATTR_MAX: highest attribute number currently defined 2946 2947 * @__NL80211_ATTR_AFTER_LAST: internal use ··· 3509 3498 NL80211_ATTR_S1G_LONG_BEACON_PERIOD, 3510 3499 NL80211_ATTR_S1G_SHORT_BEACON, 3511 3500 NL80211_ATTR_BSS_PARAM, 3501 + NL80211_ATTR_NAN_CONFIG, 3512 3502 3513 3503 /* add attributes here, update the policy in nl80211.c */ 3514 3504 ··· 7333 7321 /* keep last */ 7334 7322 NUM_NL80211_NAN_MATCH_ATTR, 7335 7323 NL80211_NAN_MATCH_ATTR_MAX = NUM_NL80211_NAN_MATCH_ATTR - 1 7324 + }; 7325 + 7326 + /** 7327 + * enum nl80211_nan_band_conf_attributes - NAN band configuration attributes 7328 + * @__NL80211_NAN_BAND_CONF_INVALID: Invalid. 7329 + * @NL80211_NAN_BAND_CONF_BAND: Band for which the configuration is 7330 + * being set. The value is according to &enum nl80211_band (u8). 7331 + * @NL80211_NAN_BAND_CONF_FREQ: Discovery frequency. This attribute shall not 7332 + * be present on 2.4 GHZ band. On 5 GHz band its presence is optional. 7333 + * The allowed values are 5220 (channel 44) or 5745 (channel 149). 7334 + * If not present, channel 149 is used if allowed, otherwise channel 44 7335 + * will be selected. The value is in MHz (u16). 7336 + * @NL80211_NAN_BAND_CONF_RSSI_CLOSE: RSSI close threshold used for NAN state 7337 + * transition algorithm as described in chapters 3.3.6 and 3.3.7 "NAN 7338 + * Device Role and State Transition" of Wi-Fi Aware (TM) Specification 7339 + * v4.0. If not specified, default device value is used. The value should 7340 + * be greater than -60 dBm (s8). 7341 + * @NL80211_NAN_BAND_CONF_RSSI_MIDDLE: RSSI middle threshold used for NAN state 7342 + * transition algorithm as described in chapters 3.3.6 and 3.3.7 "NAN 7343 + * Device Role and State Transition" of Wi-Fi Aware (TM) Specification 7344 + * v4.0. If not present, default device value is used. The value should be 7345 + * greater than -75 dBm and less than %NL80211_NAN_BAND_CONF_RSSI_CLOSE 7346 + * (s8). 7347 + * @NL80211_NAN_BAND_CONF_WAKE_DW: Committed DW information (values 0-5). 7348 + * Value 0 means that the device will not wake up during the 7349 + * discovery window. Values 1-5 mean that the device will wake up 7350 + * during each 2^(n - 1) discovery window, where n is the value of 7351 + * this attribute. Setting this attribute to 0 is not allowed on 7352 + * 2.4 GHz band (u8). This is an optional parameter (default is 1). 7353 + * @NL80211_NAN_BAND_CONF_DISABLE_SCAN: Optional flag attribute to disable 7354 + * scanning (for cluster merge) on the band. If set, the device will not 7355 + * scan on this band anymore. Disabling scanning on 2.4 GHz band is not 7356 + * allowed. 7357 + * @NUM_NL80211_NAN_BAND_CONF_ATTR: Internal. 7358 + * @NL80211_NAN_BAND_CONF_ATTR_MAX: Highest NAN band configuration attribute. 7359 + * 7360 + * These attributes are used to configure NAN band-specific parameters. Note, 7361 + * that both RSSI attributes should be configured (or both left unset). 7362 + */ 7363 + enum nl80211_nan_band_conf_attributes { 7364 + __NL80211_NAN_BAND_CONF_INVALID, 7365 + NL80211_NAN_BAND_CONF_BAND, 7366 + NL80211_NAN_BAND_CONF_FREQ, 7367 + NL80211_NAN_BAND_CONF_RSSI_CLOSE, 7368 + NL80211_NAN_BAND_CONF_RSSI_MIDDLE, 7369 + NL80211_NAN_BAND_CONF_WAKE_DW, 7370 + NL80211_NAN_BAND_CONF_DISABLE_SCAN, 7371 + 7372 + /* keep last */ 7373 + NUM_NL80211_NAN_BAND_CONF_ATTR, 7374 + NL80211_NAN_BAND_CONF_ATTR_MAX = NUM_NL80211_NAN_BAND_CONF_ATTR - 1, 7375 + }; 7376 + 7377 + /** 7378 + * enum nl80211_nan_conf_attributes - NAN configuration attributes 7379 + * @__NL80211_NAN_CONF_INVALID: Invalid attribute, used for validation. 7380 + * @NL80211_NAN_CONF_CLUSTER_ID: ID for the NAN cluster. This is a MAC 7381 + * address that can take values from 50-6F-9A-01-00-00 to 7382 + * 50-6F-9A-01-FF-FF. This attribute is optional. If not present, 7383 + * a random Cluster ID will be chosen. 7384 + * @NL80211_NAN_CONF_EXTRA_ATTRS: Additional NAN attributes to be 7385 + * published in the beacons. This is an optional byte array. 7386 + * @NL80211_NAN_CONF_VENDOR_ELEMS: Vendor-specific elements that will 7387 + * be published in the beacons. This is an optional byte array. 7388 + * @NL80211_NAN_CONF_BAND_CONFIGS: This is a nested array attribute, 7389 + * containing multiple entries for each supported band. Each band 7390 + * configuration consists of &enum nl80211_nan_band_conf_attributes. 7391 + * @NL80211_NAN_CONF_SCAN_PERIOD: Scan period in seconds. If not configured, 7392 + * device default is used. Zero value will disable scanning. 7393 + * This is u16 (optional). 7394 + * @NL80211_NAN_CONF_SCAN_DWELL_TIME: Scan dwell time in TUs per channel. 7395 + * Only non-zero values are valid. If not configured the device default 7396 + * value is used. This is u16 (optional) 7397 + * @NL80211_NAN_CONF_DISCOVERY_BEACON_INTERVAL: Discovery beacon interval 7398 + * in TUs. Valid range is 50-200 TUs. If not configured the device default 7399 + * value is used. This is u8 (optional) 7400 + * @NUM_NL80211_NAN_CONF_ATTR: Internal. 7401 + * @NL80211_NAN_CONF_ATTR_MAX: Highest NAN configuration attribute. 7402 + * 7403 + * These attributes are used to configure NAN-specific parameters. 7404 + */ 7405 + enum nl80211_nan_conf_attributes { 7406 + __NL80211_NAN_CONF_INVALID, 7407 + NL80211_NAN_CONF_CLUSTER_ID, 7408 + NL80211_NAN_CONF_EXTRA_ATTRS, 7409 + NL80211_NAN_CONF_VENDOR_ELEMS, 7410 + NL80211_NAN_CONF_BAND_CONFIGS, 7411 + NL80211_NAN_CONF_SCAN_PERIOD, 7412 + NL80211_NAN_CONF_SCAN_DWELL_TIME, 7413 + NL80211_NAN_CONF_DISCOVERY_BEACON_INTERVAL, 7414 + 7415 + /* keep last */ 7416 + NUM_NL80211_NAN_CONF_ATTR, 7417 + NL80211_NAN_CONF_ATTR_MAX = NUM_NL80211_NAN_CONF_ATTR - 1, 7336 7418 }; 7337 7419 7338 7420 /**
+263 -35
net/wireless/nl80211.c
··· 312 312 return 0; 313 313 } 314 314 315 + static int validate_nan_cluster_id(const struct nlattr *attr, 316 + struct netlink_ext_ack *extack) 317 + { 318 + const u8 *data = nla_data(attr); 319 + unsigned int len = nla_len(attr); 320 + static const u8 cluster_id_prefix[4] = {0x50, 0x6f, 0x9a, 0x1}; 321 + 322 + if (len != ETH_ALEN) { 323 + NL_SET_ERR_MSG_ATTR(extack, attr, "bad cluster id length"); 324 + return -EINVAL; 325 + } 326 + 327 + if (memcmp(data, cluster_id_prefix, sizeof(cluster_id_prefix))) { 328 + NL_SET_ERR_MSG_ATTR(extack, attr, "invalid cluster id prefix"); 329 + return -EINVAL; 330 + } 331 + 332 + return 0; 333 + } 334 + 315 335 /* policy for the attributes */ 316 336 static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR]; 317 337 ··· 518 498 [NL80211_S1G_SHORT_BEACON_ATTR_TAIL] = 519 499 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr, 520 500 IEEE80211_MAX_DATA_LEN), 501 + }; 502 + 503 + static const struct nla_policy 504 + nl80211_nan_band_conf_policy[NL80211_NAN_BAND_CONF_ATTR_MAX + 1] = { 505 + [NL80211_NAN_BAND_CONF_BAND] = NLA_POLICY_MAX(NLA_U8, 506 + NUM_NL80211_BANDS - 1), 507 + [NL80211_NAN_BAND_CONF_FREQ] = { .type = NLA_U16 }, 508 + [NL80211_NAN_BAND_CONF_RSSI_CLOSE] = NLA_POLICY_MIN(NLA_S8, -59), 509 + [NL80211_NAN_BAND_CONF_RSSI_MIDDLE] = NLA_POLICY_MIN(NLA_S8, -74), 510 + [NL80211_NAN_BAND_CONF_WAKE_DW] = NLA_POLICY_MAX(NLA_U8, 5), 511 + [NL80211_NAN_BAND_CONF_DISABLE_SCAN] = { .type = NLA_FLAG }, 512 + }; 513 + 514 + static const struct nla_policy 515 + nl80211_nan_conf_policy[NL80211_NAN_CONF_ATTR_MAX + 1] = { 516 + [NL80211_NAN_CONF_CLUSTER_ID] = 517 + NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_nan_cluster_id, 518 + ETH_ALEN), 519 + [NL80211_NAN_CONF_EXTRA_ATTRS] = { .type = NLA_BINARY, 520 + .len = IEEE80211_MAX_DATA_LEN}, 521 + [NL80211_NAN_CONF_VENDOR_ELEMS] = 522 + NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr, 523 + IEEE80211_MAX_DATA_LEN), 524 + [NL80211_NAN_CONF_BAND_CONFIGS] = 525 + NLA_POLICY_NESTED_ARRAY(nl80211_nan_band_conf_policy), 526 + [NL80211_NAN_CONF_SCAN_PERIOD] = { .type = NLA_U16 }, 527 + [NL80211_NAN_CONF_SCAN_DWELL_TIME] = NLA_POLICY_RANGE(NLA_U16, 50, 512), 528 + [NL80211_NAN_CONF_DISCOVERY_BEACON_INTERVAL] = 529 + NLA_POLICY_RANGE(NLA_U8, 50, 200), 521 530 }; 522 531 523 532 static const struct netlink_range_validation nl80211_punct_bitmap_range = { ··· 818 769 [NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN), 819 770 [NL80211_ATTR_NAN_MASTER_PREF] = NLA_POLICY_MIN(NLA_U8, 1), 820 771 [NL80211_ATTR_BANDS] = { .type = NLA_U32 }, 772 + [NL80211_ATTR_NAN_CONFIG] = NLA_POLICY_NESTED(nl80211_nan_conf_policy), 821 773 [NL80211_ATTR_NAN_FUNC] = { .type = NLA_NESTED }, 822 774 [NL80211_ATTR_FILS_KEK] = { .type = NLA_BINARY, 823 775 .len = FILS_MAX_KEK_LEN }, ··· 15448 15398 return 0; 15449 15399 } 15450 15400 15401 + static struct ieee80211_channel *nl80211_get_nan_channel(struct wiphy *wiphy, 15402 + int freq) 15403 + { 15404 + struct ieee80211_channel *chan; 15405 + struct cfg80211_chan_def def; 15406 + 15407 + /* Check if the frequency is valid for NAN */ 15408 + if (freq != 5220 && freq != 5745 && freq != 2437) 15409 + return NULL; 15410 + 15411 + chan = ieee80211_get_channel(wiphy, freq); 15412 + if (!chan) 15413 + return NULL; 15414 + 15415 + cfg80211_chandef_create(&def, chan, NL80211_CHAN_NO_HT); 15416 + 15417 + /* Check if the channel is allowed */ 15418 + if (cfg80211_reg_can_beacon(wiphy, &def, NL80211_IFTYPE_NAN)) 15419 + return chan; 15420 + 15421 + return NULL; 15422 + } 15423 + 15424 + static int nl80211_parse_nan_band_config(struct wiphy *wiphy, 15425 + struct nlattr **tb, 15426 + struct cfg80211_nan_band_config *cfg, 15427 + enum nl80211_band band) 15428 + { 15429 + if (BIT(band) & ~(u32)wiphy->nan_supported_bands) 15430 + return -EINVAL; 15431 + 15432 + if (tb[NL80211_NAN_BAND_CONF_FREQ]) { 15433 + u16 freq = nla_get_u16(tb[NL80211_NAN_BAND_CONF_FREQ]); 15434 + 15435 + if (band != NL80211_BAND_5GHZ) 15436 + return -EINVAL; 15437 + 15438 + cfg->chan = nl80211_get_nan_channel(wiphy, freq); 15439 + if (!cfg->chan) 15440 + return -EINVAL; 15441 + } 15442 + 15443 + if (tb[NL80211_NAN_BAND_CONF_RSSI_CLOSE]) { 15444 + cfg->rssi_close = 15445 + nla_get_s8(tb[NL80211_NAN_BAND_CONF_RSSI_CLOSE]); 15446 + if (!tb[NL80211_NAN_BAND_CONF_RSSI_MIDDLE]) 15447 + return -EINVAL; 15448 + } 15449 + 15450 + if (tb[NL80211_NAN_BAND_CONF_RSSI_MIDDLE]) { 15451 + cfg->rssi_middle = 15452 + nla_get_s8(tb[NL80211_NAN_BAND_CONF_RSSI_MIDDLE]); 15453 + if (!cfg->rssi_close || cfg->rssi_middle >= cfg->rssi_close) 15454 + return -EINVAL; 15455 + } 15456 + 15457 + if (tb[NL80211_NAN_BAND_CONF_WAKE_DW]) { 15458 + cfg->awake_dw_interval = 15459 + nla_get_u8(tb[NL80211_NAN_BAND_CONF_WAKE_DW]); 15460 + 15461 + if (band == NL80211_BAND_2GHZ && cfg->awake_dw_interval == 0) 15462 + return -EINVAL; 15463 + } 15464 + 15465 + cfg->disable_scan = 15466 + nla_get_flag(tb[NL80211_NAN_BAND_CONF_DISABLE_SCAN]); 15467 + return 0; 15468 + } 15469 + 15470 + static int nl80211_parse_nan_conf(struct wiphy *wiphy, 15471 + struct genl_info *info, 15472 + struct cfg80211_nan_conf *conf, 15473 + u32 *changed_flags) 15474 + { 15475 + struct nlattr *attrs[NL80211_NAN_CONF_ATTR_MAX + 1]; 15476 + int err, rem; 15477 + u32 changed = 0; 15478 + struct nlattr *band_config; 15479 + 15480 + if (info->attrs[NL80211_ATTR_NAN_MASTER_PREF]) { 15481 + conf->master_pref = 15482 + nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]); 15483 + 15484 + changed |= CFG80211_NAN_CONF_CHANGED_PREF; 15485 + } 15486 + 15487 + if (info->attrs[NL80211_ATTR_BANDS]) { 15488 + u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]); 15489 + 15490 + if (bands & ~(u32)wiphy->nan_supported_bands) 15491 + return -EOPNOTSUPP; 15492 + 15493 + if (bands && !(bands & BIT(NL80211_BAND_2GHZ))) 15494 + return -EINVAL; 15495 + 15496 + conf->bands = bands; 15497 + changed |= CFG80211_NAN_CONF_CHANGED_BANDS; 15498 + } 15499 + 15500 + conf->band_cfgs[NL80211_BAND_2GHZ].awake_dw_interval = 1; 15501 + if (conf->bands & BIT(NL80211_BAND_5GHZ) || !conf->bands) 15502 + conf->band_cfgs[NL80211_BAND_5GHZ].awake_dw_interval = 1; 15503 + 15504 + /* On 2.4 GHz band use channel 6 */ 15505 + conf->band_cfgs[NL80211_BAND_2GHZ].chan = 15506 + nl80211_get_nan_channel(wiphy, 2437); 15507 + if (!conf->band_cfgs[NL80211_BAND_2GHZ].chan) 15508 + return -EINVAL; 15509 + 15510 + if (!info->attrs[NL80211_ATTR_NAN_CONFIG]) 15511 + goto out; 15512 + 15513 + err = nla_parse_nested(attrs, NL80211_NAN_CONF_ATTR_MAX, 15514 + info->attrs[NL80211_ATTR_NAN_CONFIG], NULL, 15515 + info->extack); 15516 + if (err) 15517 + return err; 15518 + 15519 + changed |= CFG80211_NAN_CONF_CHANGED_CONFIG; 15520 + if (attrs[NL80211_NAN_CONF_CLUSTER_ID]) 15521 + conf->cluster_id = 15522 + nla_data(attrs[NL80211_NAN_CONF_CLUSTER_ID]); 15523 + 15524 + if (attrs[NL80211_NAN_CONF_EXTRA_ATTRS]) { 15525 + conf->extra_nan_attrs = 15526 + nla_data(attrs[NL80211_NAN_CONF_EXTRA_ATTRS]); 15527 + conf->extra_nan_attrs_len = 15528 + nla_len(attrs[NL80211_NAN_CONF_EXTRA_ATTRS]); 15529 + } 15530 + 15531 + if (attrs[NL80211_NAN_CONF_VENDOR_ELEMS]) { 15532 + conf->vendor_elems = 15533 + nla_data(attrs[NL80211_NAN_CONF_VENDOR_ELEMS]); 15534 + conf->vendor_elems_len = 15535 + nla_len(attrs[NL80211_NAN_CONF_VENDOR_ELEMS]); 15536 + } 15537 + 15538 + if (attrs[NL80211_NAN_CONF_BAND_CONFIGS]) { 15539 + nla_for_each_nested(band_config, 15540 + attrs[NL80211_NAN_CONF_BAND_CONFIGS], 15541 + rem) { 15542 + enum nl80211_band band; 15543 + struct cfg80211_nan_band_config *cfg; 15544 + struct nlattr *tb[NL80211_NAN_BAND_CONF_ATTR_MAX + 1]; 15545 + 15546 + err = nla_parse_nested(tb, 15547 + NL80211_NAN_BAND_CONF_ATTR_MAX, 15548 + band_config, NULL, 15549 + info->extack); 15550 + if (err) 15551 + return err; 15552 + 15553 + if (!tb[NL80211_NAN_BAND_CONF_BAND]) 15554 + return -EINVAL; 15555 + 15556 + band = nla_get_u8(tb[NL80211_NAN_BAND_CONF_BAND]); 15557 + if (conf->bands && !(conf->bands & BIT(band))) 15558 + return -EINVAL; 15559 + 15560 + cfg = &conf->band_cfgs[band]; 15561 + 15562 + err = nl80211_parse_nan_band_config(wiphy, tb, cfg, 15563 + band); 15564 + if (err) 15565 + return err; 15566 + } 15567 + } 15568 + 15569 + if (attrs[NL80211_NAN_CONF_SCAN_PERIOD]) 15570 + conf->scan_period = 15571 + nla_get_u16(attrs[NL80211_NAN_CONF_SCAN_PERIOD]); 15572 + 15573 + if (attrs[NL80211_NAN_CONF_SCAN_DWELL_TIME]) 15574 + conf->scan_dwell_time = 15575 + nla_get_u16(attrs[NL80211_NAN_CONF_SCAN_DWELL_TIME]); 15576 + 15577 + if (attrs[NL80211_NAN_CONF_DISCOVERY_BEACON_INTERVAL]) 15578 + conf->discovery_beacon_interval = 15579 + nla_get_u8(attrs[NL80211_NAN_CONF_DISCOVERY_BEACON_INTERVAL]); 15580 + out: 15581 + if (!conf->band_cfgs[NL80211_BAND_5GHZ].chan && 15582 + (!conf->bands || conf->bands & BIT(NL80211_BAND_5GHZ))) { 15583 + /* If no 5GHz channel is specified use default, if possible */ 15584 + conf->band_cfgs[NL80211_BAND_5GHZ].chan = 15585 + nl80211_get_nan_channel(wiphy, 5745); 15586 + if (!conf->band_cfgs[NL80211_BAND_5GHZ].chan) 15587 + conf->band_cfgs[NL80211_BAND_5GHZ].chan = 15588 + nl80211_get_nan_channel(wiphy, 5220); 15589 + 15590 + /* Return error if user space asked explicitly for 5 GHz */ 15591 + if (!conf->band_cfgs[NL80211_BAND_5GHZ].chan && 15592 + conf->bands & BIT(NL80211_BAND_5GHZ)) { 15593 + NL_SET_ERR_MSG_ATTR(info->extack, 15594 + info->attrs[NL80211_ATTR_BANDS], 15595 + "5 GHz band operation is not allowed"); 15596 + return -EINVAL; 15597 + } 15598 + } 15599 + 15600 + if (changed_flags) 15601 + *changed_flags = changed; 15602 + 15603 + return 0; 15604 + } 15605 + 15451 15606 static int nl80211_start_nan(struct sk_buff *skb, struct genl_info *info) 15452 15607 { 15453 15608 struct cfg80211_registered_device *rdev = info->user_ptr[0]; ··· 15669 15414 if (rfkill_blocked(rdev->wiphy.rfkill)) 15670 15415 return -ERFKILL; 15671 15416 15417 + /* Master preference is mandatory for START_NAN */ 15672 15418 if (!info->attrs[NL80211_ATTR_NAN_MASTER_PREF]) 15673 15419 return -EINVAL; 15674 15420 15675 - conf.master_pref = 15676 - nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]); 15677 - 15678 - if (info->attrs[NL80211_ATTR_BANDS]) { 15679 - u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]); 15680 - 15681 - if (bands & ~(u32)wdev->wiphy->nan_supported_bands) 15682 - return -EOPNOTSUPP; 15683 - 15684 - if (bands && !(bands & BIT(NL80211_BAND_2GHZ))) 15685 - return -EINVAL; 15686 - 15687 - conf.bands = bands; 15688 - } 15421 + err = nl80211_parse_nan_conf(&rdev->wiphy, info, &conf, NULL); 15422 + if (err) 15423 + return err; 15689 15424 15690 15425 err = rdev_start_nan(rdev, wdev, &conf); 15691 15426 if (err) ··· 16031 15786 struct wireless_dev *wdev = info->user_ptr[1]; 16032 15787 struct cfg80211_nan_conf conf = {}; 16033 15788 u32 changed = 0; 15789 + int err; 16034 15790 16035 15791 if (wdev->iftype != NL80211_IFTYPE_NAN) 16036 15792 return -EOPNOTSUPP; ··· 16039 15793 if (!wdev_running(wdev)) 16040 15794 return -ENOTCONN; 16041 15795 16042 - if (info->attrs[NL80211_ATTR_NAN_MASTER_PREF]) { 16043 - conf.master_pref = 16044 - nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]); 16045 - if (conf.master_pref <= 1 || conf.master_pref == 255) 16046 - return -EINVAL; 16047 - 16048 - changed |= CFG80211_NAN_CONF_CHANGED_PREF; 16049 - } 16050 - 16051 - if (info->attrs[NL80211_ATTR_BANDS]) { 16052 - u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]); 16053 - 16054 - if (bands & ~(u32)wdev->wiphy->nan_supported_bands) 16055 - return -EOPNOTSUPP; 16056 - 16057 - if (bands && !(bands & BIT(NL80211_BAND_2GHZ))) 16058 - return -EINVAL; 16059 - 16060 - conf.bands = bands; 16061 - changed |= CFG80211_NAN_CONF_CHANGED_BANDS; 16062 - } 15796 + err = nl80211_parse_nan_conf(&rdev->wiphy, info, &conf, &changed); 15797 + if (err) 15798 + return err; 16063 15799 16064 15800 if (!changed) 16065 15801 return -EINVAL;