|
89 | 89 |
|
90 | 90 | #define BRCMF_PS_MAX_TIMEOUT_MS 2000
|
91 | 91 |
|
| 92 | +#define MGMT_AUTH_FRAME_DWELL_TIME 4000 |
| 93 | +#define MGMT_AUTH_FRAME_WAIT_TIME (MGMT_AUTH_FRAME_DWELL_TIME + 100) |
| 94 | + |
92 | 95 | /* Dump obss definitions */
|
93 | 96 | #define ACS_MSRMNT_DELAY 80
|
94 | 97 | #define CHAN_NOISE_DUMMY (-80)
|
@@ -1958,14 +1961,18 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev,
|
1958 | 1961 | s32 val = 0;
|
1959 | 1962 | s32 err = 0;
|
1960 | 1963 |
|
1961 |
| - if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) |
| 1964 | + if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) { |
1962 | 1965 | val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
|
1963 |
| - else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) |
1964 |
| - val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED; |
1965 |
| - else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_3) |
| 1966 | + } else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) { |
| 1967 | + if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_SAE) |
| 1968 | + val = WPA3_AUTH_SAE_PSK; |
| 1969 | + else |
| 1970 | + val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED; |
| 1971 | + } else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_3) { |
1966 | 1972 | val = WPA3_AUTH_SAE_PSK;
|
1967 |
| - else |
| 1973 | + } else { |
1968 | 1974 | val = WPA_AUTH_DISABLED;
|
| 1975 | + } |
1969 | 1976 | brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val);
|
1970 | 1977 | err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", val);
|
1971 | 1978 | if (err) {
|
@@ -2230,7 +2237,7 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
|
2230 | 2237 | brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "mfp", mfp);
|
2231 | 2238 |
|
2232 | 2239 | skip_mfp_config:
|
2233 |
| - brcmf_dbg(CONN, "setting wpa_auth to %d\n", val); |
| 2240 | + brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val); |
2234 | 2241 | err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth", val);
|
2235 | 2242 | if (err) {
|
2236 | 2243 | bphy_err(drvr, "could not set wpa_auth (%d)\n", err);
|
@@ -5525,9 +5532,12 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
5525 | 5532 | s32 ie_len;
|
5526 | 5533 | struct brcmf_fil_action_frame_le *action_frame;
|
5527 | 5534 | struct brcmf_fil_af_params_le *af_params;
|
5528 |
| - bool ack; |
| 5535 | + bool ack = false; |
5529 | 5536 | s32 chan_nr;
|
5530 | 5537 | u32 freq;
|
| 5538 | + struct brcmf_mf_params_le *mf_params; |
| 5539 | + u32 mf_params_len; |
| 5540 | + s32 timeout; |
5531 | 5541 |
|
5532 | 5542 | brcmf_dbg(TRACE, "Enter\n");
|
5533 | 5543 |
|
@@ -5608,6 +5618,71 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
5608 | 5618 | cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, ack,
|
5609 | 5619 | GFP_KERNEL);
|
5610 | 5620 | kfree(af_params);
|
| 5621 | + } else if (ieee80211_is_auth(mgmt->frame_control)) { |
| 5622 | + reinit_completion(&vif->mgmt_tx); |
| 5623 | + clear_bit(BRCMF_MGMT_TX_ACK, &vif->mgmt_tx_status); |
| 5624 | + clear_bit(BRCMF_MGMT_TX_NOACK, &vif->mgmt_tx_status); |
| 5625 | + clear_bit(BRCMF_MGMT_TX_OFF_CHAN_COMPLETED, |
| 5626 | + &vif->mgmt_tx_status); |
| 5627 | + |
| 5628 | + mf_params_len = offsetof(struct brcmf_mf_params_le, data) + |
| 5629 | + (len - DOT11_MGMT_HDR_LEN); |
| 5630 | + mf_params = kzalloc(mf_params_len, GFP_KERNEL); |
| 5631 | + if (!mf_params) { |
| 5632 | + err = -ENOMEM; |
| 5633 | + goto exit; |
| 5634 | + } |
| 5635 | + |
| 5636 | + mf_params->dwell_time = cpu_to_le32(MGMT_AUTH_FRAME_DWELL_TIME); |
| 5637 | + mf_params->len = cpu_to_le16(len - DOT11_MGMT_HDR_LEN); |
| 5638 | + mf_params->frame_control = mgmt->frame_control; |
| 5639 | + |
| 5640 | + if (chan) |
| 5641 | + freq = chan->center_freq; |
| 5642 | + else |
| 5643 | + brcmf_fil_cmd_int_get(vif->ifp, BRCMF_C_GET_CHANNEL, |
| 5644 | + &freq); |
| 5645 | + chan_nr = ieee80211_frequency_to_channel(freq); |
| 5646 | + mf_params->channel = cpu_to_le32(chan_nr); |
| 5647 | + memcpy(&mf_params->da[0], &mgmt->da[0], ETH_ALEN); |
| 5648 | + memcpy(&mf_params->bssid[0], &mgmt->bssid[0], ETH_ALEN); |
| 5649 | + mf_params->packet_id = cpu_to_le32(*cookie); |
| 5650 | + memcpy(mf_params->data, &buf[DOT11_MGMT_HDR_LEN], |
| 5651 | + le16_to_cpu(mf_params->len)); |
| 5652 | + |
| 5653 | + brcmf_dbg(TRACE, "Auth frame, cookie=%d, fc=%04x, len=%d, channel=%d\n", |
| 5654 | + le32_to_cpu(mf_params->packet_id), |
| 5655 | + le16_to_cpu(mf_params->frame_control), |
| 5656 | + le16_to_cpu(mf_params->len), |
| 5657 | + le32_to_cpu(mf_params->channel)); |
| 5658 | + |
| 5659 | + vif->mgmt_tx_id = le32_to_cpu(mf_params->packet_id); |
| 5660 | + set_bit(BRCMF_MGMT_TX_SEND_FRAME, &vif->mgmt_tx_status); |
| 5661 | + |
| 5662 | + err = brcmf_fil_bsscfg_data_set(vif->ifp, "mgmt_frame", |
| 5663 | + mf_params, mf_params_len); |
| 5664 | + if (err) { |
| 5665 | + bphy_err(drvr, "Failed to send Auth frame: err=%d\n", |
| 5666 | + err); |
| 5667 | + goto tx_status; |
| 5668 | + } |
| 5669 | + |
| 5670 | + timeout = |
| 5671 | + wait_for_completion_timeout(&vif->mgmt_tx, |
| 5672 | + MGMT_AUTH_FRAME_WAIT_TIME); |
| 5673 | + if (test_bit(BRCMF_MGMT_TX_ACK, &vif->mgmt_tx_status)) { |
| 5674 | + brcmf_dbg(TRACE, "TX Auth frame operation is success\n"); |
| 5675 | + ack = true; |
| 5676 | + } else { |
| 5677 | + bphy_err(drvr, "TX Auth frame operation is failed: status=%ld)\n", |
| 5678 | + vif->mgmt_tx_status); |
| 5679 | + } |
| 5680 | + |
| 5681 | +tx_status: |
| 5682 | + cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, ack, |
| 5683 | + GFP_KERNEL); |
| 5684 | + kfree(mf_params); |
| 5685 | + |
5611 | 5686 | } else {
|
5612 | 5687 | brcmf_dbg(TRACE, "Unhandled, fc=%04x!!\n", mgmt->frame_control);
|
5613 | 5688 | brcmf_dbg_hex_dump(true, buf, len, "payload, len=%zu\n", len);
|
@@ -5931,6 +6006,40 @@ static int brcmf_cfg80211_del_pmk(struct wiphy *wiphy, struct net_device *dev,
|
5931 | 6006 | return brcmf_set_pmk(ifp, NULL, 0);
|
5932 | 6007 | }
|
5933 | 6008 |
|
| 6009 | +static int |
| 6010 | +brcmf_cfg80211_external_auth(struct wiphy *wiphy, struct net_device *dev, |
| 6011 | + struct cfg80211_external_auth_params *params) |
| 6012 | +{ |
| 6013 | + struct brcmf_if *ifp; |
| 6014 | + struct brcmf_pub *drvr; |
| 6015 | + struct brcmf_auth_req_status_le auth_status; |
| 6016 | + int ret = 0; |
| 6017 | + |
| 6018 | + brcmf_dbg(TRACE, "Enter\n"); |
| 6019 | + |
| 6020 | + ifp = netdev_priv(dev); |
| 6021 | + drvr = ifp->drvr; |
| 6022 | + if (params->status == WLAN_STATUS_SUCCESS) { |
| 6023 | + auth_status.flags = cpu_to_le16(BRCMF_EXTAUTH_SUCCESS); |
| 6024 | + } else { |
| 6025 | + bphy_err(drvr, "External authentication failed: status=%d\n", |
| 6026 | + params->status); |
| 6027 | + auth_status.flags = cpu_to_le16(BRCMF_EXTAUTH_FAIL); |
| 6028 | + } |
| 6029 | + |
| 6030 | + memcpy(auth_status.peer_mac, params->bssid, ETH_ALEN); |
| 6031 | + auth_status.ssid_len = cpu_to_le32(min_t(u8, params->ssid.ssid_len, |
| 6032 | + IEEE80211_MAX_SSID_LEN)); |
| 6033 | + memcpy(auth_status.ssid, params->ssid.ssid, auth_status.ssid_len); |
| 6034 | + |
| 6035 | + ret = brcmf_fil_iovar_data_set(ifp, "auth_status", &auth_status, |
| 6036 | + sizeof(auth_status)); |
| 6037 | + if (ret < 0) |
| 6038 | + bphy_err(drvr, "auth_status iovar failed: ret=%d\n", ret); |
| 6039 | + |
| 6040 | + return ret; |
| 6041 | +} |
| 6042 | + |
5934 | 6043 | static struct cfg80211_ops brcmf_cfg80211_ops = {
|
5935 | 6044 | .add_virtual_intf = brcmf_cfg80211_add_iface,
|
5936 | 6045 | .del_virtual_intf = brcmf_cfg80211_del_iface,
|
@@ -5978,6 +6087,7 @@ static struct cfg80211_ops brcmf_cfg80211_ops = {
|
5978 | 6087 | .update_connect_params = brcmf_cfg80211_update_conn_params,
|
5979 | 6088 | .set_pmk = brcmf_cfg80211_set_pmk,
|
5980 | 6089 | .del_pmk = brcmf_cfg80211_del_pmk,
|
| 6090 | + .external_auth = brcmf_cfg80211_external_auth, |
5981 | 6091 | };
|
5982 | 6092 |
|
5983 | 6093 | struct cfg80211_ops *brcmf_cfg80211_get_ops(struct brcmf_mp_device *settings)
|
@@ -6024,6 +6134,7 @@ struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
|
6024 | 6134 | vif->mbss = mbss;
|
6025 | 6135 | }
|
6026 | 6136 |
|
| 6137 | + init_completion(&vif->mgmt_tx); |
6027 | 6138 | list_add_tail(&vif->list, &cfg->vif_list);
|
6028 | 6139 | return vif;
|
6029 | 6140 | }
|
@@ -6715,6 +6826,122 @@ static s32 brcmf_notify_vif_event(struct brcmf_if *ifp,
|
6715 | 6826 | return -EINVAL;
|
6716 | 6827 | }
|
6717 | 6828 |
|
| 6829 | +static s32 |
| 6830 | +brcmf_notify_ext_auth_request(struct brcmf_if *ifp, |
| 6831 | + const struct brcmf_event_msg *e, void *data) |
| 6832 | +{ |
| 6833 | + struct brcmf_pub *drvr = ifp->drvr; |
| 6834 | + struct cfg80211_external_auth_params params; |
| 6835 | + struct brcmf_auth_req_status_le *auth_req = |
| 6836 | + (struct brcmf_auth_req_status_le *)data; |
| 6837 | + s32 err = 0; |
| 6838 | + |
| 6839 | + brcmf_dbg(INFO, "Enter: event %s (%d) received\n", |
| 6840 | + brcmf_fweh_event_name(e->event_code), e->event_code); |
| 6841 | + |
| 6842 | + if (e->datalen < sizeof(*auth_req)) { |
| 6843 | + bphy_err(drvr, "Event %s (%d) data too small. Ignore\n", |
| 6844 | + brcmf_fweh_event_name(e->event_code), e->event_code); |
| 6845 | + return -EINVAL; |
| 6846 | + } |
| 6847 | + |
| 6848 | + memset(¶ms, 0, sizeof(params)); |
| 6849 | + params.action = NL80211_EXTERNAL_AUTH_START; |
| 6850 | + params.key_mgmt_suite = ntohl(WLAN_AKM_SUITE_SAE); |
| 6851 | + params.status = WLAN_STATUS_SUCCESS; |
| 6852 | + params.ssid.ssid_len = min_t(u32, 32, le32_to_cpu(auth_req->ssid_len)); |
| 6853 | + memcpy(params.ssid.ssid, auth_req->ssid, params.ssid.ssid_len); |
| 6854 | + memcpy(params.bssid, auth_req->peer_mac, ETH_ALEN); |
| 6855 | + |
| 6856 | + err = cfg80211_external_auth_request(ifp->ndev, ¶ms, GFP_ATOMIC); |
| 6857 | + if (err) |
| 6858 | + bphy_err(drvr, "Ext Auth request to supplicant failed (%d)\n", |
| 6859 | + err); |
| 6860 | + |
| 6861 | + return err; |
| 6862 | +} |
| 6863 | + |
| 6864 | +static s32 |
| 6865 | +brcmf_notify_auth_frame_rx(struct brcmf_if *ifp, |
| 6866 | + const struct brcmf_event_msg *e, void *data) |
| 6867 | +{ |
| 6868 | + struct brcmf_pub *drvr = ifp->drvr; |
| 6869 | + struct brcmf_cfg80211_info *cfg = drvr->config; |
| 6870 | + struct wireless_dev *wdev; |
| 6871 | + u32 mgmt_frame_len = e->datalen - sizeof(struct brcmf_rx_mgmt_data); |
| 6872 | + struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data; |
| 6873 | + u8 *frame = (u8 *)(rxframe + 1); |
| 6874 | + struct brcmu_chan ch; |
| 6875 | + struct ieee80211_mgmt *mgmt_frame; |
| 6876 | + s32 freq; |
| 6877 | + |
| 6878 | + brcmf_dbg(INFO, "Enter: event %s (%d) received\n", |
| 6879 | + brcmf_fweh_event_name(e->event_code), e->event_code); |
| 6880 | + |
| 6881 | + if (e->datalen < sizeof(*rxframe)) { |
| 6882 | + bphy_err(drvr, "Event %s (%d) data too small. Ignore\n", |
| 6883 | + brcmf_fweh_event_name(e->event_code), e->event_code); |
| 6884 | + return -EINVAL; |
| 6885 | + } |
| 6886 | + |
| 6887 | + wdev = &ifp->vif->wdev; |
| 6888 | + WARN_ON(!wdev); |
| 6889 | + |
| 6890 | + ch.chspec = be16_to_cpu(rxframe->chanspec); |
| 6891 | + cfg->d11inf.decchspec(&ch); |
| 6892 | + |
| 6893 | + mgmt_frame = kzalloc(mgmt_frame_len, GFP_KERNEL); |
| 6894 | + if (!mgmt_frame) |
| 6895 | + return -ENOMEM; |
| 6896 | + |
| 6897 | + mgmt_frame->frame_control = cpu_to_le16(IEEE80211_STYPE_AUTH); |
| 6898 | + memcpy(mgmt_frame->da, ifp->mac_addr, ETH_ALEN); |
| 6899 | + memcpy(mgmt_frame->sa, e->addr, ETH_ALEN); |
| 6900 | + brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSSID, mgmt_frame->bssid, |
| 6901 | + ETH_ALEN); |
| 6902 | + frame += offsetof(struct ieee80211_mgmt, u); |
| 6903 | + memcpy(&mgmt_frame->u, frame, |
| 6904 | + mgmt_frame_len - offsetof(struct ieee80211_mgmt, u)); |
| 6905 | + |
| 6906 | + freq = ieee80211_channel_to_frequency(ch.control_ch_num, |
| 6907 | + ch.band == BRCMU_CHAN_BAND_2G ? |
| 6908 | + NL80211_BAND_2GHZ : |
| 6909 | + NL80211_BAND_5GHZ); |
| 6910 | + |
| 6911 | + cfg80211_rx_mgmt(wdev, freq, 0, (u8 *)mgmt_frame, mgmt_frame_len, |
| 6912 | + NL80211_RXMGMT_FLAG_EXTERNAL_AUTH); |
| 6913 | + kfree(mgmt_frame); |
| 6914 | + return 0; |
| 6915 | +} |
| 6916 | + |
| 6917 | +static s32 |
| 6918 | +brcmf_notify_mgmt_tx_status(struct brcmf_if *ifp, |
| 6919 | + const struct brcmf_event_msg *e, void *data) |
| 6920 | +{ |
| 6921 | + struct brcmf_cfg80211_vif *vif = ifp->vif; |
| 6922 | + u32 *packet_id = (u32 *)data; |
| 6923 | + |
| 6924 | + brcmf_dbg(INFO, "Enter: event %s (%d), status=%d\n", |
| 6925 | + brcmf_fweh_event_name(e->event_code), e->event_code, |
| 6926 | + e->status); |
| 6927 | + |
| 6928 | + if (!test_bit(BRCMF_MGMT_TX_SEND_FRAME, &vif->mgmt_tx_status) || |
| 6929 | + (*packet_id != vif->mgmt_tx_id)) |
| 6930 | + return 0; |
| 6931 | + |
| 6932 | + if (e->event_code == BRCMF_E_MGMT_FRAME_TXSTATUS) { |
| 6933 | + if (e->status == BRCMF_E_STATUS_SUCCESS) |
| 6934 | + set_bit(BRCMF_MGMT_TX_ACK, &vif->mgmt_tx_status); |
| 6935 | + else |
| 6936 | + set_bit(BRCMF_MGMT_TX_NOACK, &vif->mgmt_tx_status); |
| 6937 | + } else { |
| 6938 | + set_bit(BRCMF_MGMT_TX_OFF_CHAN_COMPLETED, &vif->mgmt_tx_status); |
| 6939 | + } |
| 6940 | + |
| 6941 | + complete(&vif->mgmt_tx); |
| 6942 | + return 0; |
| 6943 | +} |
| 6944 | + |
6718 | 6945 | static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
|
6719 | 6946 | {
|
6720 | 6947 | conf->frag_threshold = (u32)-1;
|
@@ -6759,7 +6986,16 @@ static void brcmf_register_event_handlers(struct brcmf_cfg80211_info *cfg)
|
6759 | 6986 | brcmf_p2p_notify_action_tx_complete);
|
6760 | 6987 | brcmf_fweh_register(cfg->pub, BRCMF_E_PSK_SUP,
|
6761 | 6988 | brcmf_notify_connect_status);
|
6762 |
| - brcmf_fweh_register(cfg->pub, BRCMF_E_RSSI, brcmf_notify_rssi); |
| 6989 | + brcmf_fweh_register(cfg->pub, BRCMF_E_RSSI, |
| 6990 | + brcmf_notify_rssi); |
| 6991 | + brcmf_fweh_register(cfg->pub, BRCMF_E_EXT_AUTH_REQ, |
| 6992 | + brcmf_notify_ext_auth_request); |
| 6993 | + brcmf_fweh_register(cfg->pub, BRCMF_E_EXT_AUTH_FRAME_RX, |
| 6994 | + brcmf_notify_auth_frame_rx); |
| 6995 | + brcmf_fweh_register(cfg->pub, BRCMF_E_MGMT_FRAME_TXSTATUS, |
| 6996 | + brcmf_notify_mgmt_tx_status); |
| 6997 | + brcmf_fweh_register(cfg->pub, BRCMF_E_MGMT_FRAME_OFF_CHAN_COMPLETE, |
| 6998 | + brcmf_notify_mgmt_tx_status); |
6763 | 6999 | }
|
6764 | 7000 |
|
6765 | 7001 | static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_info *cfg)
|
@@ -7347,6 +7583,7 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
|
7347 | 7583 | [NL80211_IFTYPE_STATION] = {
|
7348 | 7584 | .tx = 0xffff,
|
7349 | 7585 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
|
| 7586 | + BIT(IEEE80211_STYPE_AUTH >> 4) | |
7350 | 7587 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
|
7351 | 7588 | },
|
7352 | 7589 | [NL80211_IFTYPE_P2P_CLIENT] = {
|
@@ -7652,6 +7889,8 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
|
7652 | 7889 | wiphy_ext_feature_set(wiphy,
|
7653 | 7890 | NL80211_EXT_FEATURE_SAE_OFFLOAD_AP);
|
7654 | 7891 | }
|
| 7892 | + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SAE_EXT)) |
| 7893 | + wiphy->features |= NL80211_FEATURE_SAE; |
7655 | 7894 | wiphy->mgmt_stypes = brcmf_txrx_stypes;
|
7656 | 7895 | wiphy->max_remain_on_channel_duration = 5000;
|
7657 | 7896 | if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO)) {
|
|
0 commit comments