Skip to content

Commit 3699589

Browse files
nxptestKalle Valo
authored andcommitted
wifi: mwifiex: add host mlme for client mode
Add host based MLME to enable WPA3 functionalities in client mode. This feature required a firmware with the corresponding V2 Key API support. The feature (WPA3) is currently enabled and verified only on IW416. Also, verified no regression with change when host MLME is disabled. Signed-off-by: David Lin <[email protected]> Reviewed-by: Francesco Dolcini <[email protected]> Acked-by: Brian Norris <[email protected]> Signed-off-by: Kalle Valo <[email protected]> Link: https://patch.msgid.link/[email protected]
1 parent e8b7d0c commit 3699589

File tree

15 files changed

+683
-14
lines changed

15 files changed

+683
-14
lines changed

drivers/net/wireless/marvell/mwifiex/cfg80211.c

Lines changed: 318 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,8 @@ mwifiex_cfg80211_update_mgmt_frame_registrations(struct wiphy *wiphy,
268268

269269
if (mask != priv->mgmt_frame_mask) {
270270
priv->mgmt_frame_mask = mask;
271+
if (priv->host_mlme_reg)
272+
priv->mgmt_frame_mask |= HOST_MLME_MGMT_MASK;
271273
mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,
272274
HostCmd_ACT_GEN_SET, 0,
273275
&priv->mgmt_frame_mask, false);
@@ -848,6 +850,7 @@ static int mwifiex_deinit_priv_params(struct mwifiex_private *priv)
848850
struct mwifiex_adapter *adapter = priv->adapter;
849851
unsigned long flags;
850852

853+
priv->host_mlme_reg = false;
851854
priv->mgmt_frame_mask = 0;
852855
if (mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,
853856
HostCmd_ACT_GEN_SET, 0,
@@ -3633,6 +3636,9 @@ static int mwifiex_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
36333636
if (!ISSUPP_FIRMWARE_SUPPLICANT(priv->adapter->fw_cap_info))
36343637
return -EOPNOTSUPP;
36353638

3639+
if (priv->adapter->host_mlme_enabled)
3640+
return 0;
3641+
36363642
return mwifiex_send_cmd(priv, HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG,
36373643
HostCmd_ACT_GEN_SET, 0, data, true);
36383644
}
@@ -4206,6 +4212,305 @@ mwifiex_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev,
42064212
return ret;
42074213
}
42084214

4215+
static int
4216+
mwifiex_cfg80211_authenticate(struct wiphy *wiphy,
4217+
struct net_device *dev,
4218+
struct cfg80211_auth_request *req)
4219+
{
4220+
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
4221+
struct mwifiex_adapter *adapter = priv->adapter;
4222+
struct sk_buff *skb;
4223+
u16 pkt_len, auth_alg;
4224+
int ret;
4225+
struct mwifiex_ieee80211_mgmt *mgmt;
4226+
struct mwifiex_txinfo *tx_info;
4227+
u32 tx_control = 0, pkt_type = PKT_TYPE_MGMT;
4228+
u8 trans = 1, status_code = 0;
4229+
u8 *varptr;
4230+
4231+
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
4232+
mwifiex_dbg(priv->adapter, ERROR, "Interface role is AP\n");
4233+
return -EFAULT;
4234+
}
4235+
4236+
if (priv->wdev.iftype != NL80211_IFTYPE_STATION) {
4237+
mwifiex_dbg(priv->adapter, ERROR,
4238+
"Interface type is not correct (type %d)\n",
4239+
priv->wdev.iftype);
4240+
return -EINVAL;
4241+
}
4242+
4243+
if (priv->auth_alg != WLAN_AUTH_SAE &&
4244+
(priv->auth_flag & HOST_MLME_AUTH_PENDING)) {
4245+
mwifiex_dbg(priv->adapter, ERROR, "Pending auth on going\n");
4246+
return -EBUSY;
4247+
}
4248+
4249+
if (!priv->host_mlme_reg) {
4250+
priv->host_mlme_reg = true;
4251+
priv->mgmt_frame_mask |= HOST_MLME_MGMT_MASK;
4252+
mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,
4253+
HostCmd_ACT_GEN_SET, 0,
4254+
&priv->mgmt_frame_mask, false);
4255+
}
4256+
4257+
switch (req->auth_type) {
4258+
case NL80211_AUTHTYPE_OPEN_SYSTEM:
4259+
auth_alg = WLAN_AUTH_OPEN;
4260+
break;
4261+
case NL80211_AUTHTYPE_SHARED_KEY:
4262+
auth_alg = WLAN_AUTH_SHARED_KEY;
4263+
break;
4264+
case NL80211_AUTHTYPE_FT:
4265+
auth_alg = WLAN_AUTH_FT;
4266+
break;
4267+
case NL80211_AUTHTYPE_NETWORK_EAP:
4268+
auth_alg = WLAN_AUTH_LEAP;
4269+
break;
4270+
case NL80211_AUTHTYPE_SAE:
4271+
auth_alg = WLAN_AUTH_SAE;
4272+
break;
4273+
default:
4274+
mwifiex_dbg(priv->adapter, ERROR,
4275+
"unsupported auth type=%d\n", req->auth_type);
4276+
return -EOPNOTSUPP;
4277+
}
4278+
4279+
if (!priv->auth_flag) {
4280+
ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_SET,
4281+
req->bss->channel,
4282+
AUTH_TX_DEFAULT_WAIT_TIME);
4283+
4284+
if (!ret) {
4285+
priv->roc_cfg.cookie = get_random_u32() | 1;
4286+
priv->roc_cfg.chan = *req->bss->channel;
4287+
} else {
4288+
return -EFAULT;
4289+
}
4290+
}
4291+
4292+
priv->sec_info.authentication_mode = auth_alg;
4293+
4294+
mwifiex_cancel_scan(adapter);
4295+
4296+
pkt_len = (u16)req->ie_len + req->auth_data_len +
4297+
MWIFIEX_MGMT_HEADER_LEN + MWIFIEX_AUTH_BODY_LEN;
4298+
if (req->auth_data_len >= 4)
4299+
pkt_len -= 4;
4300+
4301+
skb = dev_alloc_skb(MWIFIEX_MIN_DATA_HEADER_LEN +
4302+
MWIFIEX_MGMT_FRAME_HEADER_SIZE +
4303+
pkt_len + sizeof(pkt_len));
4304+
if (!skb) {
4305+
mwifiex_dbg(priv->adapter, ERROR,
4306+
"allocate skb failed for management frame\n");
4307+
return -ENOMEM;
4308+
}
4309+
4310+
tx_info = MWIFIEX_SKB_TXCB(skb);
4311+
memset(tx_info, 0, sizeof(*tx_info));
4312+
tx_info->bss_num = priv->bss_num;
4313+
tx_info->bss_type = priv->bss_type;
4314+
tx_info->pkt_len = pkt_len;
4315+
4316+
skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN +
4317+
MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
4318+
memcpy(skb_push(skb, sizeof(pkt_len)), &pkt_len, sizeof(pkt_len));
4319+
memcpy(skb_push(skb, sizeof(tx_control)),
4320+
&tx_control, sizeof(tx_control));
4321+
memcpy(skb_push(skb, sizeof(pkt_type)), &pkt_type, sizeof(pkt_type));
4322+
4323+
mgmt = (struct mwifiex_ieee80211_mgmt *)skb_put(skb, pkt_len);
4324+
memset(mgmt, 0, pkt_len);
4325+
mgmt->frame_control =
4326+
cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
4327+
memcpy(mgmt->da, req->bss->bssid, ETH_ALEN);
4328+
memcpy(mgmt->sa, priv->curr_addr, ETH_ALEN);
4329+
memcpy(mgmt->bssid, req->bss->bssid, ETH_ALEN);
4330+
eth_broadcast_addr(mgmt->addr4);
4331+
4332+
if (req->auth_data_len >= 4) {
4333+
if (req->auth_type == NL80211_AUTHTYPE_SAE) {
4334+
__le16 *pos = (__le16 *)req->auth_data;
4335+
4336+
trans = le16_to_cpu(pos[0]);
4337+
status_code = le16_to_cpu(pos[1]);
4338+
}
4339+
memcpy((u8 *)(&mgmt->auth.variable), req->auth_data + 4,
4340+
req->auth_data_len - 4);
4341+
varptr = (u8 *)&mgmt->auth.variable +
4342+
(req->auth_data_len - 4);
4343+
}
4344+
4345+
mgmt->auth.auth_alg = cpu_to_le16(auth_alg);
4346+
mgmt->auth.auth_transaction = cpu_to_le16(trans);
4347+
mgmt->auth.status_code = cpu_to_le16(status_code);
4348+
4349+
if (req->ie && req->ie_len) {
4350+
if (!varptr)
4351+
varptr = (u8 *)&mgmt->auth.variable;
4352+
memcpy((u8 *)varptr, req->ie, req->ie_len);
4353+
}
4354+
4355+
priv->auth_flag = HOST_MLME_AUTH_PENDING;
4356+
priv->auth_alg = auth_alg;
4357+
4358+
skb->priority = WMM_HIGHEST_PRIORITY;
4359+
__net_timestamp(skb);
4360+
4361+
mwifiex_dbg(priv->adapter, MSG,
4362+
"auth: send authentication to %pM\n", req->bss->bssid);
4363+
4364+
mwifiex_queue_tx_pkt(priv, skb);
4365+
4366+
return 0;
4367+
}
4368+
4369+
static int
4370+
mwifiex_cfg80211_associate(struct wiphy *wiphy, struct net_device *dev,
4371+
struct cfg80211_assoc_request *req)
4372+
{
4373+
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
4374+
struct mwifiex_adapter *adapter = priv->adapter;
4375+
int ret;
4376+
struct cfg80211_ssid req_ssid;
4377+
const u8 *ssid_ie;
4378+
4379+
if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) {
4380+
mwifiex_dbg(adapter, ERROR,
4381+
"%s: reject infra assoc request in non-STA role\n",
4382+
dev->name);
4383+
return -EINVAL;
4384+
}
4385+
4386+
if (test_bit(MWIFIEX_SURPRISE_REMOVED, &adapter->work_flags) ||
4387+
test_bit(MWIFIEX_IS_CMD_TIMEDOUT, &adapter->work_flags)) {
4388+
mwifiex_dbg(adapter, ERROR,
4389+
"%s: Ignore association.\t"
4390+
"Card removed or FW in bad state\n",
4391+
dev->name);
4392+
return -EFAULT;
4393+
}
4394+
4395+
if (priv->auth_alg == WLAN_AUTH_SAE)
4396+
priv->auth_flag = HOST_MLME_AUTH_DONE;
4397+
4398+
if (priv->auth_flag && !(priv->auth_flag & HOST_MLME_AUTH_DONE))
4399+
return -EBUSY;
4400+
4401+
if (priv->roc_cfg.cookie) {
4402+
ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_REMOVE,
4403+
&priv->roc_cfg.chan, 0);
4404+
if (!ret)
4405+
memset(&priv->roc_cfg, 0,
4406+
sizeof(struct mwifiex_roc_cfg));
4407+
else
4408+
return -EFAULT;
4409+
}
4410+
4411+
if (!mwifiex_stop_bg_scan(priv))
4412+
cfg80211_sched_scan_stopped_locked(priv->wdev.wiphy, 0);
4413+
4414+
memset(&req_ssid, 0, sizeof(struct cfg80211_ssid));
4415+
rcu_read_lock();
4416+
ssid_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
4417+
4418+
if (!ssid_ie)
4419+
goto ssid_err;
4420+
4421+
req_ssid.ssid_len = ssid_ie[1];
4422+
if (req_ssid.ssid_len > IEEE80211_MAX_SSID_LEN) {
4423+
mwifiex_dbg(adapter, ERROR, "invalid SSID - aborting\n");
4424+
goto ssid_err;
4425+
}
4426+
4427+
memcpy(req_ssid.ssid, ssid_ie + 2, req_ssid.ssid_len);
4428+
if (!req_ssid.ssid_len || req_ssid.ssid[0] < 0x20) {
4429+
mwifiex_dbg(adapter, ERROR, "invalid SSID - aborting\n");
4430+
goto ssid_err;
4431+
}
4432+
rcu_read_unlock();
4433+
4434+
/* As this is new association, clear locally stored
4435+
* keys and security related flags
4436+
*/
4437+
priv->sec_info.wpa_enabled = false;
4438+
priv->sec_info.wpa2_enabled = false;
4439+
priv->wep_key_curr_index = 0;
4440+
priv->sec_info.encryption_mode = 0;
4441+
priv->sec_info.is_authtype_auto = 0;
4442+
if (mwifiex_set_encode(priv, NULL, NULL, 0, 0, NULL, 1)) {
4443+
mwifiex_dbg(priv->adapter, ERROR, "deleting the crypto keys\n");
4444+
return -EFAULT;
4445+
}
4446+
4447+
if (req->crypto.n_ciphers_pairwise)
4448+
priv->sec_info.encryption_mode =
4449+
req->crypto.ciphers_pairwise[0];
4450+
4451+
if (req->crypto.cipher_group)
4452+
priv->sec_info.encryption_mode = req->crypto.cipher_group;
4453+
4454+
if (req->ie)
4455+
mwifiex_set_gen_ie(priv, req->ie, req->ie_len);
4456+
4457+
memcpy(priv->cfg_bssid, req->bss->bssid, ETH_ALEN);
4458+
4459+
mwifiex_dbg(adapter, MSG,
4460+
"assoc: send association to %pM\n", req->bss->bssid);
4461+
4462+
cfg80211_ref_bss(adapter->wiphy, req->bss);
4463+
ret = mwifiex_bss_start(priv, req->bss, &req_ssid);
4464+
if (ret) {
4465+
priv->auth_flag = 0;
4466+
priv->auth_alg = WLAN_AUTH_NONE;
4467+
eth_zero_addr(priv->cfg_bssid);
4468+
}
4469+
4470+
if (priv->assoc_rsp_size) {
4471+
priv->req_bss = req->bss;
4472+
adapter->assoc_resp_received = true;
4473+
queue_work(adapter->host_mlme_workqueue,
4474+
&adapter->host_mlme_work);
4475+
}
4476+
4477+
cfg80211_put_bss(priv->adapter->wiphy, req->bss);
4478+
4479+
return 0;
4480+
4481+
ssid_err:
4482+
rcu_read_unlock();
4483+
return -EFAULT;
4484+
}
4485+
4486+
static int
4487+
mwifiex_cfg80211_deauthenticate(struct wiphy *wiphy,
4488+
struct net_device *dev,
4489+
struct cfg80211_deauth_request *req)
4490+
{
4491+
return mwifiex_cfg80211_disconnect(wiphy, dev, req->reason_code);
4492+
}
4493+
4494+
static int
4495+
mwifiex_cfg80211_disassociate(struct wiphy *wiphy,
4496+
struct net_device *dev,
4497+
struct cfg80211_disassoc_request *req)
4498+
{
4499+
return mwifiex_cfg80211_disconnect(wiphy, dev, req->reason_code);
4500+
}
4501+
4502+
static int
4503+
mwifiex_cfg80211_probe_client(struct wiphy *wiphy,
4504+
struct net_device *dev, const u8 *peer,
4505+
u64 *cookie)
4506+
{
4507+
/* hostapd looks for NL80211_CMD_PROBE_CLIENT support; otherwise,
4508+
* it requires monitor-mode support (which mwifiex doesn't support).
4509+
* Provide fake probe_client support to work around this.
4510+
*/
4511+
return -EOPNOTSUPP;
4512+
}
4513+
42094514
/* station cfg80211 operations */
42104515
static struct cfg80211_ops mwifiex_cfg80211_ops = {
42114516
.add_virtual_intf = mwifiex_add_virtual_intf,
@@ -4351,6 +4656,16 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
43514656
"%s: creating new wiphy\n", __func__);
43524657
return -ENOMEM;
43534658
}
4659+
if (adapter->host_mlme_enabled) {
4660+
mwifiex_cfg80211_ops.auth = mwifiex_cfg80211_authenticate;
4661+
mwifiex_cfg80211_ops.assoc = mwifiex_cfg80211_associate;
4662+
mwifiex_cfg80211_ops.deauth = mwifiex_cfg80211_deauthenticate;
4663+
mwifiex_cfg80211_ops.disassoc = mwifiex_cfg80211_disassociate;
4664+
mwifiex_cfg80211_ops.disconnect = NULL;
4665+
mwifiex_cfg80211_ops.connect = NULL;
4666+
mwifiex_cfg80211_ops.probe_client =
4667+
mwifiex_cfg80211_probe_client;
4668+
}
43544669
wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH;
43554670
wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN;
43564671
wiphy->mgmt_stypes = mwifiex_mgmt_stypes;
@@ -4434,6 +4749,9 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
44344749
NL80211_FEATURE_LOW_PRIORITY_SCAN |
44354750
NL80211_FEATURE_NEED_OBSS_SCAN;
44364751

4752+
if (adapter->host_mlme_enabled)
4753+
wiphy->features |= NL80211_FEATURE_SAE;
4754+
44374755
if (ISSUPP_ADHOC_ENABLED(adapter->fw_cap_info))
44384756
wiphy->features |= NL80211_FEATURE_HT_IBSS;
44394757

drivers/net/wireless/marvell/mwifiex/cmdevt.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,24 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
924924
return ret;
925925
}
926926

927+
void mwifiex_process_assoc_resp(struct mwifiex_adapter *adapter)
928+
{
929+
struct cfg80211_rx_assoc_resp_data assoc_resp = {
930+
.uapsd_queues = -1,
931+
};
932+
struct mwifiex_private *priv =
933+
mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);
934+
935+
if (priv->assoc_rsp_size) {
936+
assoc_resp.links[0].bss = priv->req_bss;
937+
assoc_resp.buf = priv->assoc_rsp_buf;
938+
assoc_resp.len = priv->assoc_rsp_size;
939+
cfg80211_rx_assoc_resp(priv->netdev,
940+
&assoc_resp);
941+
priv->assoc_rsp_size = 0;
942+
}
943+
}
944+
927945
/*
928946
* This function handles the timeout of command sending.
929947
*
@@ -1672,6 +1690,13 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
16721690
if (adapter->fw_api_ver == MWIFIEX_FW_V15)
16731691
adapter->scan_chan_gap_enabled = true;
16741692

1693+
if (adapter->key_api_major_ver != KEY_API_VER_MAJOR_V2)
1694+
adapter->host_mlme_enabled = false;
1695+
1696+
mwifiex_dbg(adapter, MSG, "host_mlme: %s, key_api: %d\n",
1697+
adapter->host_mlme_enabled ? "enable" : "disable",
1698+
adapter->key_api_major_ver);
1699+
16751700
return 0;
16761701
}
16771702

0 commit comments

Comments
 (0)