--- zzzz-none-000/linux-5.15.111/net/wireless/nl80211.c 2023-05-11 14:00:40.000000000 +0000 +++ puma7-atom-6670-761/linux-5.15.111/net/wireless/nl80211.c 2024-02-07 10:23:31.000000000 +0000 @@ -764,6 +764,19 @@ [NL80211_ATTR_COLOR_CHANGE_COUNT] = { .type = NLA_U8 }, [NL80211_ATTR_COLOR_CHANGE_COLOR] = { .type = NLA_U8 }, [NL80211_ATTR_COLOR_CHANGE_ELEMS] = NLA_POLICY_NESTED(nl80211_policy), + [NL80211_ATTR_EHT_CAPABILITY] = + NLA_POLICY_RANGE(NLA_BINARY, + NL80211_EHT_MIN_CAPABILITY_LEN, + NL80211_EHT_MAX_CAPABILITY_LEN), + [NL80211_ATTR_EHT_PUNCTURE_BITMAP] = { .type = NLA_U32 }, + [NL80211_ATTR_MLD_MAC] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN), + [NL80211_ATTR_MLD_REFERENCE] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 }, + [NL80211_ATTR_MLD_LINK_MACS] = { .type = NLA_NESTED }, + [NL80211_ATTR_MLD_LINK_IDS] = { .type = NLA_NESTED }, + [NL80211_ATTR_RECONFIG] = { .type = NLA_FLAG }, + [NL80211_ATTR_MLO_LINK_ID] = + NLA_POLICY_RANGE(NLA_U8, 0, NL80211_MLD_MAX_NUM_LINKS), + }; /* policy for the key attributes */ @@ -1149,6 +1162,9 @@ } } + if (nla_put_u16(msg, NL80211_FREQUENCY_ATTR_CHANNEL, chan->hw_value)) + goto nla_put_failure; + return 0; nla_put_failure: @@ -1459,12 +1475,9 @@ case NL80211_IFTYPE_AP_VLAN: case NL80211_IFTYPE_P2P_GO: case NL80211_IFTYPE_MESH_POINT: - break; case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_P2P_CLIENT: - if (!wdev->current_bss) - return -ENOLINK; break; case NL80211_IFTYPE_UNSPECIFIED: case NL80211_IFTYPE_OCB: @@ -1714,6 +1727,9 @@ const struct ieee80211_sband_iftype_data *iftdata) { const struct ieee80211_sta_he_cap *he_cap = &iftdata->he_cap; +#ifdef CFG80211_PROP_MULTI_LINK_SUPPORT + const struct ieee80211_sta_eht_cap *eht_cap = &iftdata->eht_cap; +#endif /* CFG80211_PROP_MULTI_LINK_SUPPORT */ if (nl80211_put_iftypes(msg, NL80211_BAND_IFTYPE_ATTR_IFTYPES, iftdata->types_mask)) @@ -1745,6 +1761,21 @@ iftdata->vendor_elems.len, iftdata->vendor_elems.data)) return -ENOBUFS; +#ifdef CFG80211_PROP_MULTI_LINK_SUPPORT + if (eht_cap->has_eht) { + if (nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC, + sizeof(eht_cap->eht_cap_elem.mac_cap_info), + eht_cap->eht_cap_elem.mac_cap_info) || + nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY, + sizeof(eht_cap->eht_cap_elem.phy_cap_info), + eht_cap->eht_cap_elem.phy_cap_info) || + nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET, + sizeof(eht_cap->eht_mcs_nss_supp), + &eht_cap->eht_mcs_nss_supp)) + return -ENOBUFS; + } +#endif /* CFG80211_PROP_MULTI_LINK_SUPPORT */ + return 0; } @@ -3115,6 +3146,15 @@ chandef->edmg.channels = 0; } +#ifdef CFG80211_PROP_MULTI_LINK_SUPPORT + if (info->attrs[NL80211_ATTR_EHT_PUNCTURE_BITMAP]) { + chandef->puncture_bitmap = + nla_get_u32(attrs[NL80211_ATTR_EHT_PUNCTURE_BITMAP]); + } else { + chandef->puncture_bitmap = IEEE80211_EHT_PUNCTURE_BITMAP_DEFAULT; + } +#endif /* CFG80211_PROP_MULTI_LINK_SUPPORT */ + if (!cfg80211_chandef_valid(chandef)) { NL_SET_ERR_MSG(extack, "invalid channel definition"); return -EINVAL; @@ -3567,6 +3607,10 @@ if (chandef->center_freq2 && nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2, chandef->center_freq2)) return -ENOBUFS; +#ifdef CFG80211_PROP_MULTI_LINK_SUPPORT + if (nla_put_u32(msg, NL80211_ATTR_EHT_PUNCTURE_BITMAP, chandef->puncture_bitmap)) + return -ENOBUFS; +#endif return 0; } @@ -3602,6 +3646,13 @@ nla_put_u8(msg, NL80211_ATTR_4ADDR, wdev->use_4addr)) goto nla_put_failure; +#ifdef CFG80211_PROP_MULTI_LINK_SUPPORT + if (wiphy_ext_feature_isset(&rdev->wiphy, NL80211_EXT_FEATURE_MLO)) { + if (nla_put(msg, NL80211_ATTR_MLD_MAC, ETH_ALEN, wdev->mld_address)) + goto nla_put_failure; + } +#endif /* CFG80211_PROP_MULTI_LINK_SUPPORT */ + if (rdev->ops->get_channel) { int ret; struct cfg80211_chan_def chandef = {}; @@ -4001,6 +4052,27 @@ if (err < 0) return err; +#ifdef CFG80211_PROP_MULTI_LINK_SUPPORT + if (info->attrs[NL80211_ATTR_MLD_MAC]) { + if (wiphy_ext_feature_isset(&rdev->wiphy, NL80211_EXT_FEATURE_MLO)) { + nla_memcpy(params.mld_macaddr, info->attrs[NL80211_ATTR_MLD_MAC], + ETH_ALEN); + if (!is_valid_ether_addr(params.mld_macaddr)) + return -EADDRNOTAVAIL; + } else { + return -EOPNOTSUPP; + } + } + + if (info->attrs[NL80211_ATTR_MLD_REFERENCE]) { + if (wiphy_ext_feature_isset(&rdev->wiphy, NL80211_EXT_FEATURE_MLO)) + params.mld_reference = + nla_data(info->attrs[NL80211_ATTR_MLD_REFERENCE]); + else + return -EOPNOTSUPP; + } +#endif /* CFG80211_PROP_MULTI_LINK_SUPPORT */ + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return -ENOMEM; @@ -5257,6 +5329,11 @@ cap = cfg80211_find_ext_ie(WLAN_EID_EXT_HE_OPERATION, ies, ies_len); if (cap && cap[1] >= sizeof(*params->he_oper) + 1) params->he_oper = (void *)(cap + 3); +#ifdef CFG80211_PROP_MULTI_LINK_SUPPORT + cap = cfg80211_find_ext_ie(WLAN_EID_EXT_EHT_CAPABILITY, ies, ies_len); + if (cap && cap[1] >= sizeof(*params->eht_cap) + 1) + params->eht_cap = (void *)(cap + 3); +#endif /* CFG80211_PROP_MULTI_LINK_SUPPORT */ } static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev, @@ -5340,6 +5417,11 @@ struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_ap_settings params; int err; +#ifdef CFG80211_PROP_MULTI_LINK_SUPPORT + struct cfg80211_mlo_info *ml_info = NULL; + struct nlattr *attr; + int i; +#endif /* CFG80211_PROP_MULTI_LINK_SUPPORT */ if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) @@ -5524,6 +5606,41 @@ goto out; } +#ifdef CFG80211_PROP_MULTI_LINK_SUPPORT + i = 0; + ml_info = ¶ms.mlo_info; + if (info->attrs[NL80211_ATTR_MLD_LINK_IDS]) { + int tmp; + + nla_for_each_nested(attr, + info->attrs[NL80211_ATTR_MLD_LINK_IDS], + tmp) { + ml_info->mlo_link_ids[i] = nla_get_u32(attr); + i++; + } + ml_info->num_mlo_links = i; + } + + i = 0; + if (info->attrs[NL80211_ATTR_MLD_LINK_MACS]) { + int tmp; + + err = validate_acl_mac_addrs(info->attrs[NL80211_ATTR_MLD_LINK_MACS]); + if (err <= 0) + goto out; + + nla_for_each_nested(attr, + info->attrs[NL80211_ATTR_MLD_LINK_MACS], + tmp) { + memcpy(ml_info->mlo_mac_addrs[i].addr, nla_data(attr), ETH_ALEN); + i++; + } + } + + params.mlo_info.reconfig = + nla_get_flag(info->attrs[NL80211_ATTR_RECONFIG]); +#endif /* CFG80211_PROP_MULTI_LINK_SUPPORT */ + if (info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP]) { err = nl80211_parse_unsol_bcast_probe_resp( rdev, info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP], @@ -5591,7 +5708,7 @@ struct cfg80211_registered_device *rdev = info->user_ptr[0]; struct net_device *dev = info->user_ptr[1]; - return cfg80211_stop_ap(rdev, dev, false); + return cfg80211_stop_ap(rdev, dev, false, info); } static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { @@ -6378,6 +6495,15 @@ nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]); } +#ifdef CFG80211_PROP_MULTI_LINK_SUPPORT + if (info->attrs[NL80211_ATTR_EHT_CAPABILITY]) { + params->eht_capa = + nla_data(info->attrs[NL80211_ATTR_EHT_CAPABILITY]); + params->eht_capa_len = + nla_len(info->attrs[NL80211_ATTR_EHT_CAPABILITY]); + } +#endif /* CFG80211_PROP_MULTI_LINK_SUPPORT */ + err = nl80211_parse_sta_channel_info(info, params); if (err) return err; @@ -6639,6 +6765,15 @@ params.he_6ghz_capa = nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]); +#ifdef CFG80211_PROP_MULTI_LINK_SUPPORT + if (info->attrs[NL80211_ATTR_EHT_CAPABILITY]) { + params.eht_capa = + nla_data(info->attrs[NL80211_ATTR_EHT_CAPABILITY]); + params.eht_capa_len = + nla_len(info->attrs[NL80211_ATTR_EHT_CAPABILITY]); + } +#endif /* CFG80211_PROP_MULTI_LINK_SUPPORT */ + if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) { params.opmode_notif_used = true; params.opmode_notif = @@ -9879,9 +10014,13 @@ proto = nla_get_u16( info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]); settings->control_port_ethertype = cpu_to_be16(proto); +#ifndef ETH_P_WAI +#define ETH_P_WAI 0x88B4 +#endif if (!(rdev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) && - proto != ETH_P_PAE) + ((proto != ETH_P_PAE) && (proto != ETH_P_WAI))) return -EINVAL; +#undef ETH_P_WAI if (info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]) settings->control_port_no_encrypt = true; } else @@ -10930,8 +11069,6 @@ if (nla_get_flag(info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])) { if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) { kfree_sensitive(connkeys); - GENL_SET_ERR_MSG(info, - "external auth requires connection ownership"); return -EINVAL; } connect.flags |= CONNECT_REQ_EXTERNAL_AUTH_SUPPORT; @@ -14936,6 +15073,29 @@ return err; } +static int nl80211_set_fils_aad(struct sk_buff *skb, + struct genl_info *info) +{ + struct cfg80211_registered_device *rdev = info->user_ptr[0]; + struct net_device *dev = info->user_ptr[1]; + struct cfg80211_fils_aad fils_aad = {}; + u8 *nonces; + + if (!info->attrs[NL80211_ATTR_MAC] || + !info->attrs[NL80211_ATTR_FILS_KEK] || + !info->attrs[NL80211_ATTR_FILS_NONCES]) + return -EINVAL; + + fils_aad.macaddr = nla_data(info->attrs[NL80211_ATTR_MAC]); + fils_aad.kek_len = nla_len(info->attrs[NL80211_ATTR_FILS_KEK]); + fils_aad.kek = nla_data(info->attrs[NL80211_ATTR_FILS_KEK]); + nonces = nla_data(info->attrs[NL80211_ATTR_FILS_NONCES]); + fils_aad.snonce = nonces; + fils_aad.anonce = nonces + FILS_NONCE_LEN; + + return rdev_set_fils_aad(rdev, dev, &fils_aad); +} + #define NL80211_FLAG_NEED_WIPHY 0x01 #define NL80211_FLAG_NEED_NETDEV 0x02 #define NL80211_FLAG_NEED_RTNL 0x04 @@ -15938,6 +16098,13 @@ .flags = GENL_UNS_ADMIN_PERM, .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, }, + { + .cmd = NL80211_CMD_SET_FILS_AAD, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = nl80211_set_fils_aad, + .flags = GENL_UNS_ADMIN_PERM, + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + }, }; static struct genl_family nl80211_fam __ro_after_init = { @@ -16580,9 +16747,16 @@ nlmsg_free(msg); } +#ifndef CFG80211_PROP_MULTI_LINK_SUPPORT void nl80211_send_disconnected(struct cfg80211_registered_device *rdev, struct net_device *netdev, u16 reason, const u8 *ie, size_t ie_len, bool from_ap) +#else /* CFG80211_PROP_MULTI_LINK_SUPPORT */ +void nl80211_send_disconnected(struct cfg80211_registered_device *rdev, + struct net_device *netdev, u16 reason, + const u8 *ie, size_t ie_len, bool from_ap, + int link_id) +#endif /* CFG80211_PROP_MULTI_LINK_SUPPORT */ { struct sk_buff *msg; void *hdr; @@ -16603,6 +16777,10 @@ nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason)) || (from_ap && nla_put_flag(msg, NL80211_ATTR_DISCONNECTED_BY_AP)) || +#ifdef CFG80211_PROP_MULTI_LINK_SUPPORT + (link_id >= 0 && link_id <= NL80211_MLD_MAX_NUM_LINKS && + nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id)) || +#endif /* CFG80211_PROP_MULTI_LINK_SUPPORT */ (ie && nla_put(msg, NL80211_ATTR_IE, ie_len, ie))) goto nla_put_failure; @@ -18224,8 +18402,9 @@ nla_put_u32(msg, NL80211_ATTR_EXTERNAL_AUTH_ACTION, params->action) || nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, params->bssid) || - nla_put(msg, NL80211_ATTR_SSID, params->ssid.ssid_len, - params->ssid.ssid)) + (params->ssid.ssid_len && + nla_put(msg, NL80211_ATTR_SSID, params->ssid.ssid_len, + params->ssid.ssid))) goto nla_put_failure; genlmsg_end(msg, hdr);