|
90 | 90 |
|
91 | 91 | #define BRCMF_PS_MAX_TIMEOUT_MS 2000
|
92 | 92 |
|
| 93 | +#define MGMT_AUTH_FRAME_DWELL_TIME 4000 |
| 94 | +#define MGMT_AUTH_FRAME_WAIT_TIME (MGMT_AUTH_FRAME_DWELL_TIME + 100) |
| 95 | + |
93 | 96 | /* Dump obss definitions */
|
94 | 97 | #define ACS_MSRMNT_DELAY 80
|
95 | 98 | #define CHAN_NOISE_DUMMY (-80)
|
@@ -1949,14 +1952,18 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev,
|
1949 | 1952 | s32 val = 0;
|
1950 | 1953 | s32 err = 0;
|
1951 | 1954 |
|
1952 |
| - if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) |
| 1955 | + if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) { |
1953 | 1956 | val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
|
1954 |
| - else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) |
1955 |
| - val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED; |
1956 |
| - else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_3) |
| 1957 | + } else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) { |
| 1958 | + if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_SAE) |
| 1959 | + val = WPA3_AUTH_SAE_PSK; |
| 1960 | + else |
| 1961 | + val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED; |
| 1962 | + } else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_3) { |
1957 | 1963 | val = WPA3_AUTH_SAE_PSK;
|
1958 |
| - else |
| 1964 | + } else { |
1959 | 1965 | val = WPA_AUTH_DISABLED;
|
| 1966 | + } |
1960 | 1967 | brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val);
|
1961 | 1968 | err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", val);
|
1962 | 1969 | if (err) {
|
@@ -2222,7 +2229,7 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
|
2222 | 2229 | brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "mfp", mfp);
|
2223 | 2230 |
|
2224 | 2231 | skip_mfp_config:
|
2225 |
| - brcmf_dbg(CONN, "setting wpa_auth to %d\n", val); |
| 2232 | + brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val); |
2226 | 2233 | err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth", val);
|
2227 | 2234 | if (err) {
|
2228 | 2235 | bphy_err(drvr, "could not set wpa_auth (%d)\n", err);
|
@@ -5534,9 +5541,12 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
5534 | 5541 | s32 ie_len;
|
5535 | 5542 | struct brcmf_fil_action_frame_le *action_frame;
|
5536 | 5543 | struct brcmf_fil_af_params_le *af_params;
|
5537 |
| - bool ack; |
| 5544 | + bool ack = false; |
5538 | 5545 | s32 chan_nr;
|
5539 | 5546 | u32 freq;
|
| 5547 | + struct brcmf_mf_params_le *mf_params; |
| 5548 | + u32 mf_params_len; |
| 5549 | + s32 timeout; |
5540 | 5550 |
|
5541 | 5551 | brcmf_dbg(TRACE, "Enter\n");
|
5542 | 5552 |
|
@@ -5617,6 +5627,71 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
5617 | 5627 | cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, ack,
|
5618 | 5628 | GFP_KERNEL);
|
5619 | 5629 | kfree(af_params);
|
| 5630 | + } else if (ieee80211_is_auth(mgmt->frame_control)) { |
| 5631 | + reinit_completion(&vif->mgmt_tx); |
| 5632 | + clear_bit(BRCMF_MGMT_TX_ACK, &vif->mgmt_tx_status); |
| 5633 | + clear_bit(BRCMF_MGMT_TX_NOACK, &vif->mgmt_tx_status); |
| 5634 | + clear_bit(BRCMF_MGMT_TX_OFF_CHAN_COMPLETED, |
| 5635 | + &vif->mgmt_tx_status); |
| 5636 | + |
| 5637 | + mf_params_len = offsetof(struct brcmf_mf_params_le, data) + |
| 5638 | + (len - DOT11_MGMT_HDR_LEN); |
| 5639 | + mf_params = kzalloc(mf_params_len, GFP_KERNEL); |
| 5640 | + if (!mf_params) { |
| 5641 | + err = -ENOMEM; |
| 5642 | + goto exit; |
| 5643 | + } |
| 5644 | + |
| 5645 | + mf_params->dwell_time = cpu_to_le32(MGMT_AUTH_FRAME_DWELL_TIME); |
| 5646 | + mf_params->len = cpu_to_le16(len - DOT11_MGMT_HDR_LEN); |
| 5647 | + mf_params->frame_control = mgmt->frame_control; |
| 5648 | + |
| 5649 | + if (chan) |
| 5650 | + freq = chan->center_freq; |
| 5651 | + else |
| 5652 | + brcmf_fil_cmd_int_get(vif->ifp, BRCMF_C_GET_CHANNEL, |
| 5653 | + &freq); |
| 5654 | + chan_nr = ieee80211_frequency_to_channel(freq); |
| 5655 | + mf_params->channel = cpu_to_le32(chan_nr); |
| 5656 | + memcpy(&mf_params->da[0], &mgmt->da[0], ETH_ALEN); |
| 5657 | + memcpy(&mf_params->bssid[0], &mgmt->bssid[0], ETH_ALEN); |
| 5658 | + mf_params->packet_id = cpu_to_le32(*cookie); |
| 5659 | + memcpy(mf_params->data, &buf[DOT11_MGMT_HDR_LEN], |
| 5660 | + le16_to_cpu(mf_params->len)); |
| 5661 | + |
| 5662 | + brcmf_dbg(TRACE, "Auth frame, cookie=%d, fc=%04x, len=%d, channel=%d\n", |
| 5663 | + le32_to_cpu(mf_params->packet_id), |
| 5664 | + le16_to_cpu(mf_params->frame_control), |
| 5665 | + le16_to_cpu(mf_params->len), |
| 5666 | + le32_to_cpu(mf_params->channel)); |
| 5667 | + |
| 5668 | + vif->mgmt_tx_id = le32_to_cpu(mf_params->packet_id); |
| 5669 | + set_bit(BRCMF_MGMT_TX_SEND_FRAME, &vif->mgmt_tx_status); |
| 5670 | + |
| 5671 | + err = brcmf_fil_bsscfg_data_set(vif->ifp, "mgmt_frame", |
| 5672 | + mf_params, mf_params_len); |
| 5673 | + if (err) { |
| 5674 | + bphy_err(drvr, "Failed to send Auth frame: err=%d\n", |
| 5675 | + err); |
| 5676 | + goto tx_status; |
| 5677 | + } |
| 5678 | + |
| 5679 | + timeout = |
| 5680 | + wait_for_completion_timeout(&vif->mgmt_tx, |
| 5681 | + MGMT_AUTH_FRAME_WAIT_TIME); |
| 5682 | + if (test_bit(BRCMF_MGMT_TX_ACK, &vif->mgmt_tx_status)) { |
| 5683 | + brcmf_dbg(TRACE, "TX Auth frame operation is success\n"); |
| 5684 | + ack = true; |
| 5685 | + } else { |
| 5686 | + bphy_err(drvr, "TX Auth frame operation is failed: status=%ld)\n", |
| 5687 | + vif->mgmt_tx_status); |
| 5688 | + } |
| 5689 | + |
| 5690 | +tx_status: |
| 5691 | + cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, ack, |
| 5692 | + GFP_KERNEL); |
| 5693 | + kfree(mf_params); |
| 5694 | + |
5620 | 5695 | } else {
|
5621 | 5696 | brcmf_dbg(TRACE, "Unhandled, fc=%04x!!\n", mgmt->frame_control);
|
5622 | 5697 | brcmf_dbg_hex_dump(true, buf, len, "payload, len=%zu\n", len);
|
@@ -5940,6 +6015,40 @@ static int brcmf_cfg80211_del_pmk(struct wiphy *wiphy, struct net_device *dev,
|
5940 | 6015 | return brcmf_set_pmk(ifp, NULL, 0);
|
5941 | 6016 | }
|
5942 | 6017 |
|
| 6018 | +static int |
| 6019 | +brcmf_cfg80211_external_auth(struct wiphy *wiphy, struct net_device *dev, |
| 6020 | + struct cfg80211_external_auth_params *params) |
| 6021 | +{ |
| 6022 | + struct brcmf_if *ifp; |
| 6023 | + struct brcmf_pub *drvr; |
| 6024 | + struct brcmf_auth_req_status_le auth_status; |
| 6025 | + int ret = 0; |
| 6026 | + |
| 6027 | + brcmf_dbg(TRACE, "Enter\n"); |
| 6028 | + |
| 6029 | + ifp = netdev_priv(dev); |
| 6030 | + drvr = ifp->drvr; |
| 6031 | + if (params->status == WLAN_STATUS_SUCCESS) { |
| 6032 | + auth_status.flags = cpu_to_le16(BRCMF_EXTAUTH_SUCCESS); |
| 6033 | + } else { |
| 6034 | + bphy_err(drvr, "External authentication failed: status=%d\n", |
| 6035 | + params->status); |
| 6036 | + auth_status.flags = cpu_to_le16(BRCMF_EXTAUTH_FAIL); |
| 6037 | + } |
| 6038 | + |
| 6039 | + memcpy(auth_status.peer_mac, params->bssid, ETH_ALEN); |
| 6040 | + auth_status.ssid_len = cpu_to_le32(min_t(u8, params->ssid.ssid_len, |
| 6041 | + IEEE80211_MAX_SSID_LEN)); |
| 6042 | + memcpy(auth_status.ssid, params->ssid.ssid, auth_status.ssid_len); |
| 6043 | + |
| 6044 | + ret = brcmf_fil_iovar_data_set(ifp, "auth_status", &auth_status, |
| 6045 | + sizeof(auth_status)); |
| 6046 | + if (ret < 0) |
| 6047 | + bphy_err(drvr, "auth_status iovar failed: ret=%d\n", ret); |
| 6048 | + |
| 6049 | + return ret; |
| 6050 | +} |
| 6051 | + |
5943 | 6052 | static struct cfg80211_ops brcmf_cfg80211_ops = {
|
5944 | 6053 | .add_virtual_intf = brcmf_cfg80211_add_iface,
|
5945 | 6054 | .del_virtual_intf = brcmf_cfg80211_del_iface,
|
@@ -5987,6 +6096,7 @@ static struct cfg80211_ops brcmf_cfg80211_ops = {
|
5987 | 6096 | .update_connect_params = brcmf_cfg80211_update_conn_params,
|
5988 | 6097 | .set_pmk = brcmf_cfg80211_set_pmk,
|
5989 | 6098 | .del_pmk = brcmf_cfg80211_del_pmk,
|
| 6099 | + .external_auth = brcmf_cfg80211_external_auth, |
5990 | 6100 | };
|
5991 | 6101 |
|
5992 | 6102 | struct cfg80211_ops *brcmf_cfg80211_get_ops(struct brcmf_mp_device *settings)
|
@@ -6033,6 +6143,7 @@ struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
|
6033 | 6143 | vif->mbss = mbss;
|
6034 | 6144 | }
|
6035 | 6145 |
|
| 6146 | + init_completion(&vif->mgmt_tx); |
6036 | 6147 | list_add_tail(&vif->list, &cfg->vif_list);
|
6037 | 6148 | return vif;
|
6038 | 6149 | }
|
@@ -6724,6 +6835,122 @@ static s32 brcmf_notify_vif_event(struct brcmf_if *ifp,
|
6724 | 6835 | return -EINVAL;
|
6725 | 6836 | }
|
6726 | 6837 |
|
| 6838 | +static s32 |
| 6839 | +brcmf_notify_ext_auth_request(struct brcmf_if *ifp, |
| 6840 | + const struct brcmf_event_msg *e, void *data) |
| 6841 | +{ |
| 6842 | + struct brcmf_pub *drvr = ifp->drvr; |
| 6843 | + struct cfg80211_external_auth_params params; |
| 6844 | + struct brcmf_auth_req_status_le *auth_req = |
| 6845 | + (struct brcmf_auth_req_status_le *)data; |
| 6846 | + s32 err = 0; |
| 6847 | + |
| 6848 | + brcmf_dbg(INFO, "Enter: event %s (%d) received\n", |
| 6849 | + brcmf_fweh_event_name(e->event_code), e->event_code); |
| 6850 | + |
| 6851 | + if (e->datalen < sizeof(*auth_req)) { |
| 6852 | + bphy_err(drvr, "Event %s (%d) data too small. Ignore\n", |
| 6853 | + brcmf_fweh_event_name(e->event_code), e->event_code); |
| 6854 | + return -EINVAL; |
| 6855 | + } |
| 6856 | + |
| 6857 | + memset(¶ms, 0, sizeof(params)); |
| 6858 | + params.action = NL80211_EXTERNAL_AUTH_START; |
| 6859 | + params.key_mgmt_suite = ntohl(WLAN_AKM_SUITE_SAE); |
| 6860 | + params.status = WLAN_STATUS_SUCCESS; |
| 6861 | + params.ssid.ssid_len = min_t(u32, 32, le32_to_cpu(auth_req->ssid_len)); |
| 6862 | + memcpy(params.ssid.ssid, auth_req->ssid, params.ssid.ssid_len); |
| 6863 | + memcpy(params.bssid, auth_req->peer_mac, ETH_ALEN); |
| 6864 | + |
| 6865 | + err = cfg80211_external_auth_request(ifp->ndev, ¶ms, GFP_ATOMIC); |
| 6866 | + if (err) |
| 6867 | + bphy_err(drvr, "Ext Auth request to supplicant failed (%d)\n", |
| 6868 | + err); |
| 6869 | + |
| 6870 | + return err; |
| 6871 | +} |
| 6872 | + |
| 6873 | +static s32 |
| 6874 | +brcmf_notify_auth_frame_rx(struct brcmf_if *ifp, |
| 6875 | + const struct brcmf_event_msg *e, void *data) |
| 6876 | +{ |
| 6877 | + struct brcmf_pub *drvr = ifp->drvr; |
| 6878 | + struct brcmf_cfg80211_info *cfg = drvr->config; |
| 6879 | + struct wireless_dev *wdev; |
| 6880 | + u32 mgmt_frame_len = e->datalen - sizeof(struct brcmf_rx_mgmt_data); |
| 6881 | + struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data; |
| 6882 | + u8 *frame = (u8 *)(rxframe + 1); |
| 6883 | + struct brcmu_chan ch; |
| 6884 | + struct ieee80211_mgmt *mgmt_frame; |
| 6885 | + s32 freq; |
| 6886 | + |
| 6887 | + brcmf_dbg(INFO, "Enter: event %s (%d) received\n", |
| 6888 | + brcmf_fweh_event_name(e->event_code), e->event_code); |
| 6889 | + |
| 6890 | + if (e->datalen < sizeof(*rxframe)) { |
| 6891 | + bphy_err(drvr, "Event %s (%d) data too small. Ignore\n", |
| 6892 | + brcmf_fweh_event_name(e->event_code), e->event_code); |
| 6893 | + return -EINVAL; |
| 6894 | + } |
| 6895 | + |
| 6896 | + wdev = &ifp->vif->wdev; |
| 6897 | + WARN_ON(!wdev); |
| 6898 | + |
| 6899 | + ch.chspec = be16_to_cpu(rxframe->chanspec); |
| 6900 | + cfg->d11inf.decchspec(&ch); |
| 6901 | + |
| 6902 | + mgmt_frame = kzalloc(mgmt_frame_len, GFP_KERNEL); |
| 6903 | + if (!mgmt_frame) |
| 6904 | + return -ENOMEM; |
| 6905 | + |
| 6906 | + mgmt_frame->frame_control = cpu_to_le16(IEEE80211_STYPE_AUTH); |
| 6907 | + memcpy(mgmt_frame->da, ifp->mac_addr, ETH_ALEN); |
| 6908 | + memcpy(mgmt_frame->sa, e->addr, ETH_ALEN); |
| 6909 | + brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSSID, mgmt_frame->bssid, |
| 6910 | + ETH_ALEN); |
| 6911 | + frame += offsetof(struct ieee80211_mgmt, u); |
| 6912 | + memcpy(&mgmt_frame->u, frame, |
| 6913 | + mgmt_frame_len - offsetof(struct ieee80211_mgmt, u)); |
| 6914 | + |
| 6915 | + freq = ieee80211_channel_to_frequency(ch.control_ch_num, |
| 6916 | + ch.band == BRCMU_CHAN_BAND_2G ? |
| 6917 | + NL80211_BAND_2GHZ : |
| 6918 | + NL80211_BAND_5GHZ); |
| 6919 | + |
| 6920 | + cfg80211_rx_mgmt(wdev, freq, 0, (u8 *)mgmt_frame, mgmt_frame_len, |
| 6921 | + NL80211_RXMGMT_FLAG_EXTERNAL_AUTH); |
| 6922 | + kfree(mgmt_frame); |
| 6923 | + return 0; |
| 6924 | +} |
| 6925 | + |
| 6926 | +static s32 |
| 6927 | +brcmf_notify_mgmt_tx_status(struct brcmf_if *ifp, |
| 6928 | + const struct brcmf_event_msg *e, void *data) |
| 6929 | +{ |
| 6930 | + struct brcmf_cfg80211_vif *vif = ifp->vif; |
| 6931 | + u32 *packet_id = (u32 *)data; |
| 6932 | + |
| 6933 | + brcmf_dbg(INFO, "Enter: event %s (%d), status=%d\n", |
| 6934 | + brcmf_fweh_event_name(e->event_code), e->event_code, |
| 6935 | + e->status); |
| 6936 | + |
| 6937 | + if (!test_bit(BRCMF_MGMT_TX_SEND_FRAME, &vif->mgmt_tx_status) || |
| 6938 | + (*packet_id != vif->mgmt_tx_id)) |
| 6939 | + return 0; |
| 6940 | + |
| 6941 | + if (e->event_code == BRCMF_E_MGMT_FRAME_TXSTATUS) { |
| 6942 | + if (e->status == BRCMF_E_STATUS_SUCCESS) |
| 6943 | + set_bit(BRCMF_MGMT_TX_ACK, &vif->mgmt_tx_status); |
| 6944 | + else |
| 6945 | + set_bit(BRCMF_MGMT_TX_NOACK, &vif->mgmt_tx_status); |
| 6946 | + } else { |
| 6947 | + set_bit(BRCMF_MGMT_TX_OFF_CHAN_COMPLETED, &vif->mgmt_tx_status); |
| 6948 | + } |
| 6949 | + |
| 6950 | + complete(&vif->mgmt_tx); |
| 6951 | + return 0; |
| 6952 | +} |
| 6953 | + |
6727 | 6954 | static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
|
6728 | 6955 | {
|
6729 | 6956 | conf->frag_threshold = (u32)-1;
|
@@ -6768,7 +6995,16 @@ static void brcmf_register_event_handlers(struct brcmf_cfg80211_info *cfg)
|
6768 | 6995 | brcmf_p2p_notify_action_tx_complete);
|
6769 | 6996 | brcmf_fweh_register(cfg->pub, BRCMF_E_PSK_SUP,
|
6770 | 6997 | brcmf_notify_connect_status);
|
6771 |
| - brcmf_fweh_register(cfg->pub, BRCMF_E_RSSI, brcmf_notify_rssi); |
| 6998 | + brcmf_fweh_register(cfg->pub, BRCMF_E_RSSI, |
| 6999 | + brcmf_notify_rssi); |
| 7000 | + brcmf_fweh_register(cfg->pub, BRCMF_E_EXT_AUTH_REQ, |
| 7001 | + brcmf_notify_ext_auth_request); |
| 7002 | + brcmf_fweh_register(cfg->pub, BRCMF_E_EXT_AUTH_FRAME_RX, |
| 7003 | + brcmf_notify_auth_frame_rx); |
| 7004 | + brcmf_fweh_register(cfg->pub, BRCMF_E_MGMT_FRAME_TXSTATUS, |
| 7005 | + brcmf_notify_mgmt_tx_status); |
| 7006 | + brcmf_fweh_register(cfg->pub, BRCMF_E_MGMT_FRAME_OFF_CHAN_COMPLETE, |
| 7007 | + brcmf_notify_mgmt_tx_status); |
6772 | 7008 | }
|
6773 | 7009 |
|
6774 | 7010 | static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_info *cfg)
|
@@ -7355,6 +7591,7 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
|
7355 | 7591 | [NL80211_IFTYPE_STATION] = {
|
7356 | 7592 | .tx = 0xffff,
|
7357 | 7593 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
|
| 7594 | + BIT(IEEE80211_STYPE_AUTH >> 4) | |
7358 | 7595 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
|
7359 | 7596 | },
|
7360 | 7597 | [NL80211_IFTYPE_P2P_CLIENT] = {
|
@@ -7662,6 +7899,8 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
|
7662 | 7899 | wiphy_ext_feature_set(wiphy,
|
7663 | 7900 | NL80211_EXT_FEATURE_SAE_OFFLOAD_AP);
|
7664 | 7901 | }
|
| 7902 | + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SAE_EXT)) |
| 7903 | + wiphy->features |= NL80211_FEATURE_SAE; |
7665 | 7904 | wiphy->mgmt_stypes = brcmf_txrx_stypes;
|
7666 | 7905 | wiphy->max_remain_on_channel_duration = 5000;
|
7667 | 7906 | if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO)) {
|
|
0 commit comments