--- zzzz-none-000/linux-4.1.52/net/wireless/nl80211.c 2018-05-28 02:26:45.000000000 +0000 +++ bcm63-7530ax-731/linux-4.1.52/net/wireless/nl80211.c 2022-03-02 11:37:14.000000000 +0000 @@ -209,6 +209,37 @@ return __cfg80211_rdev_from_attrs(netns, info->attrs); } +#ifdef CONFIG_BCM_KF_CFG80211_BACKPORT +static int validate_beacon_head(const struct nlattr *attr) +{ + const u8 *data = nla_data(attr); + unsigned int len = nla_len(attr); + const struct element *elem; + const struct ieee80211_mgmt *mgmt = (void *)data; + unsigned int fixedlen = offsetof(struct ieee80211_mgmt, + u.beacon.variable); + + if (len < fixedlen) + goto err; + + if (ieee80211_hdrlen(mgmt->frame_control) != + offsetof(struct ieee80211_mgmt, u.beacon)) + goto err; + + data += fixedlen; + len -= fixedlen; + + for_each_element(elem, data, len) { + /* nothing */ + } + + if (for_each_element_completed(elem, data, len)) + return 0; + +err: + return -EINVAL; +} +#endif /* policy for the attributes */ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, @@ -247,8 +278,14 @@ [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 }, [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 }, +#ifndef CONFIG_BCM_KF_CFG80211_BACKPORT [NL80211_ATTR_BEACON_HEAD] = { .type = NLA_BINARY, .len = IEEE80211_MAX_DATA_LEN }, +#else + [NL80211_ATTR_BEACON_HEAD] = + NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_beacon_head, + IEEE80211_MAX_DATA_LEN), +#endif [NL80211_ATTR_BEACON_TAIL] = { .type = NLA_BINARY, .len = IEEE80211_MAX_DATA_LEN }, [NL80211_ATTR_STA_AID] = { .type = NLA_U16 }, @@ -668,6 +705,9 @@ int idx; int type; bool def, defmgmt; +#ifdef CONFIG_BCM_KF_CFG80211_BACKPORT + bool defbeacon; +#endif /* CONFIG_BCM_KF_CFG80211_BACKPORT */ bool def_uni, def_multi; }; @@ -681,13 +721,21 @@ k->def = !!tb[NL80211_KEY_DEFAULT]; k->defmgmt = !!tb[NL80211_KEY_DEFAULT_MGMT]; +#ifdef CONFIG_BCM_KF_CFG80211_BACKPORT + k->defbeacon = !!tb[NL80211_KEY_DEFAULT_BEACON]; +#endif /* CONFIG_BCM_KF_CFG80211_BACKPORT */ if (k->def) { k->def_uni = true; k->def_multi = true; } +#ifndef CONFIG_BCM_KF_CFG80211_BACKPORT if (k->defmgmt) k->def_multi = true; +#else + if (k->defmgmt || k->defbeacon) + k->def_multi = true; +#endif /* CONFIG_BCM_KF_CFG80211_BACKPORT */ if (tb[NL80211_KEY_IDX]) k->idx = nla_get_u8(tb[NL80211_KEY_IDX]); @@ -792,6 +840,7 @@ if (err) return err; +#ifndef CONFIG_BCM_KF_CFG80211_BACKPORT if (k->def && k->defmgmt) return -EINVAL; @@ -799,16 +848,35 @@ if (k->def_uni || !k->def_multi) return -EINVAL; } +#else + if ((k->def ? 1 : 0) + (k->defmgmt ? 1 : 0) + + (k->defbeacon ? 1 : 0) > 1) + return -EINVAL; + + if (k->defmgmt || k->defbeacon) { + if (k->def_uni || !k->def_multi) + return -EINVAL; + } +#endif /* CONFIG_BCM_KF_CFG80211_BACKPORT */ if (k->idx != -1) { if (k->defmgmt) { if (k->idx < 4 || k->idx > 5) return -EINVAL; +#ifdef CONFIG_BCM_KF_CFG80211_BACKPORT + } else if (k->defbeacon) { + if (k->idx < 6 || k->idx > 7) + return -EINVAL; +#endif /* CONFIG_BCM_KF_CFG80211_BACKPORT */ } else if (k->def) { if (k->idx < 0 || k->idx > 3) return -EINVAL; } else { +#ifndef CONFIG_BCM_KF_CFG80211_BACKPORT if (k->idx < 0 || k->idx > 5) +#else + if (k->idx < 0 || k->idx > 7) +#endif /* CONFIG_BCM_KF_CFG80211_BACKPORT */ return -EINVAL; } } @@ -887,6 +955,9 @@ break; case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_STATION: +#if defined(CONFIG_BCM_KF_WL_HOSTAPD) + case NL80211_IFTYPE_WDS: +#endif case NL80211_IFTYPE_P2P_CLIENT: if (!wdev->current_bss) return -ENOLINK; @@ -895,7 +966,9 @@ case NL80211_IFTYPE_OCB: case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_P2P_DEVICE: +#if !defined(CONFIG_BCM_KF_WL_HOSTAPD) case NL80211_IFTYPE_WDS: +#endif case NUM_NL80211_IFTYPES: return -EINVAL; } @@ -2525,6 +2598,9 @@ return 0; break; case NL80211_IFTYPE_STATION: +#if defined(CONFIG_BCM_KF_WL_HOSTAPD) + case NL80211_IFTYPE_WDS: +#endif if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_STATION) return 0; break; @@ -2932,7 +3008,11 @@ return -EINVAL; /* only support setting default key */ +#ifndef CONFIG_BCM_KF_CFG80211_BACKPORT if (!key.def && !key.defmgmt) +#else + if (!key.def && !key.defmgmt && !key.defbeacon) +#endif /* CONFIG_BCM_KF_CFG80211_BACKPORT */ return -EINVAL; wdev_lock(dev->ieee80211_ptr); @@ -3274,6 +3354,12 @@ return false; return true; case NL80211_CMD_CONNECT: +#ifdef CONFIG_BCM_KF_CFG80211_BACKPORT + if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) && + auth_type == NL80211_AUTHTYPE_SAE) + return false; + return true; +#endif case NL80211_CMD_START_AP: /* SAE not supported yet */ if (auth_type == NL80211_AUTHTYPE_SAE) @@ -4299,6 +4385,9 @@ case NL80211_IFTYPE_P2P_GO: case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_STATION: +#if defined(CONFIG_BCM_KF_WL_HOSTAPD) + case NL80211_IFTYPE_WDS: +#endif case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_MESH_POINT: break; @@ -6344,6 +6433,11 @@ if (!cfg80211_chandef_dfs_usable(wdev->wiphy, &chandef)) return -EINVAL; +#ifdef CONFIG_BCM_KF_CFG80211_BACKPORT + /* CAC start is offloaded to HW and can't be started manually */ + if (wiphy_ext_feature_isset(wdev->wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD)) + return -EOPNOTSUPP; +#endif /* CONFIG_BCM_KF_CFG80211_BACKPORT */ if (!rdev->ops->start_radar_detection) return -EOPNOTSUPP; @@ -7688,6 +7782,9 @@ return err; if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && +#if defined(CONFIG_BCM_KF_WL_HOSTAPD) + dev->ieee80211_ptr->iftype != NL80211_IFTYPE_WDS && +#endif dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) return -EOPNOTSUPP; @@ -7809,6 +7906,9 @@ return -EINVAL; if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && +#if defined(CONFIG_BCM_KF_WL_HOSTAPD) + dev->ieee80211_ptr->iftype != NL80211_IFTYPE_WDS && +#endif dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) return -EOPNOTSUPP; @@ -7869,6 +7969,9 @@ pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && +#if defined(CONFIG_BCM_KF_WL_HOSTAPD) + dev->ieee80211_ptr->iftype != NL80211_IFTYPE_WDS && +#endif dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) return -EOPNOTSUPP; @@ -7896,6 +7999,9 @@ struct net_device *dev = info->user_ptr[1]; if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && +#if defined(CONFIG_BCM_KF_WL_HOSTAPD) + dev->ieee80211_ptr->iftype != NL80211_IFTYPE_WDS && +#endif dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) return -EOPNOTSUPP; @@ -10229,6 +10335,43 @@ return 0; } +#ifdef CONFIG_BCM_KF_CFG80211_BACKPORT +static int nl80211_external_auth(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_external_auth_params params; + + if (!rdev->ops->external_auth) + return -EOPNOTSUPP; + + if (!info->attrs[NL80211_ATTR_SSID]) + return -EINVAL; + + if (!info->attrs[NL80211_ATTR_BSSID]) + return -EINVAL; + + if (!info->attrs[NL80211_ATTR_STATUS_CODE]) + return -EINVAL; + + memset(¶ms, 0, sizeof(params)); + + params.ssid.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); + if (params.ssid.ssid_len == 0 || + params.ssid.ssid_len > IEEE80211_MAX_SSID_LEN) + return -EINVAL; + memcpy(params.ssid.ssid, nla_data(info->attrs[NL80211_ATTR_SSID]), + params.ssid.ssid_len); + + memcpy(params.bssid, nla_data(info->attrs[NL80211_ATTR_BSSID]), + ETH_ALEN); + + params.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]); + + return rdev_external_auth(rdev, dev, ¶ms); +} + +#endif #define NL80211_FLAG_NEED_WIPHY 0x01 #define NL80211_FLAG_NEED_NETDEV 0x02 #define NL80211_FLAG_NEED_RTNL 0x04 @@ -11044,6 +11187,16 @@ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | NL80211_FLAG_NEED_RTNL, }, +#ifdef CONFIG_BCM_KF_CFG80211_BACKPORT + { + .cmd = NL80211_CMD_EXTERNAL_AUTH, + .doit = nl80211_external_auth, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NEED_RTNL, + }, +#endif }; /* notification functions */ @@ -12963,6 +13116,46 @@ out: nlmsg_free(msg); } +#ifdef CONFIG_BCM_KF_CFG80211_BACKPORT +int cfg80211_external_auth_request(struct net_device *dev, + struct cfg80211_external_auth_params *params, + gfp_t gfp) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); + struct sk_buff *msg; + void *hdr; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); + if (!msg) + return -ENOMEM; + + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_EXTERNAL_AUTH); + if (!hdr) + goto nla_put_failure; + + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || + nla_put_u32(msg, NL80211_ATTR_AKM_SUITES, params->key_mgmt_suite) || + 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)) + goto nla_put_failure; + + genlmsg_end(msg, hdr); + + genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, + NL80211_MCGRP_MLME, gfp); + return 0; + + nla_put_failure: + nlmsg_free(msg); + return -ENOBUFS; +} +EXPORT_SYMBOL(cfg80211_external_auth_request); +#endif /* initialisation/exit functions */