diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c index 75ee0f775..44859396c 100644 --- a/wpa_supplicant/mesh_mpm.c +++ b/wpa_supplicant/mesh_mpm.c @@ -12,6 +12,7 @@ #include "utils/eloop.h" #include "common/ieee802_11_defs.h" #include "common/hw_features_common.h" +#include "common/ocv.h" #include "ap/hostapd.h" #include "ap/sta_info.h" #include "ap/ieee802_11.h" @@ -246,6 +247,11 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s, #endif /* CONFIG_IEEE80211AC */ if (type != PLINK_CLOSE) buf_len += conf->rsn_ie_len; /* RSN IE */ +#ifdef CONFIG_OCV + /* OCI is included even when the other STA doesn't support OCV */ + if (type != PLINK_CLOSE && conf->ocv) + buf_len += OCV_OCI_EXTENDED_LEN; +#endif /* CONFIG_OCV */ buf = wpabuf_alloc(buf_len); if (!buf) @@ -357,6 +363,22 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s, } #endif /* CONFIG_IEEE80211AC */ +#ifdef CONFIG_OCV + if (type != PLINK_CLOSE && conf->ocv) { + struct wpa_channel_info ci; + + if (wpa_drv_channel_info(wpa_s, &ci) != 0) { + wpa_printf(MSG_WARNING, + "Mesh MPM: Failed to get channel info for OCI element"); + goto fail; + } + + pos = wpabuf_put(buf, OCV_OCI_EXTENDED_LEN); + if (ocv_insert_extended_oci(&ci, pos) < 0) + goto fail; + } +#endif /* CONFIG_OCV */ + if (ampe && mesh_rsn_protect_frame(wpa_s->mesh_rsn, sta, cat, buf)) { wpa_msg(wpa_s, MSG_INFO, "Mesh MPM: failed to add AMPE and MIC IE"); @@ -1197,6 +1219,56 @@ void mesh_mpm_action_rx(struct wpa_supplicant *wpa_s, } return; } + +#ifdef CONFIG_OCV + if (action_field == PLINK_OPEN && elems.rsn_ie) { + struct wpa_state_machine *sm = sta->wpa_sm; + struct wpa_ie_data data; + + res = wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2, + elems.rsn_ie_len + 2, + &data); + if (res) { + wpa_printf(MSG_DEBUG, + "Failed to parse RSN IE (res=%d)", + res); + wpa_hexdump(MSG_DEBUG, "RSN IE", elems.rsn_ie, + elems.rsn_ie_len); + return; + } + + wpa_auth_set_ocv(sm, mconf->ocv && + (data.capabilities & + WPA_CAPABILITY_OCVC)); + } + + if (action_field != PLINK_CLOSE && + wpa_auth_uses_ocv(sta->wpa_sm)) { + struct wpa_channel_info ci; + int tx_chanwidth; + int tx_seg1_idx; + + if (wpa_drv_channel_info(wpa_s, &ci) != 0) { + wpa_printf(MSG_WARNING, + "MPM: Failed to get channel info to validate received OCI in MPM Confirm"); + return; + } + + if (get_tx_parameters( + sta, channel_width_to_int(ci.chanwidth), + ci.seg1_idx, &tx_chanwidth, + &tx_seg1_idx) < 0) + return; + + if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, + tx_chanwidth, tx_seg1_idx) != + 0) { + wpa_printf(MSG_WARNING, "MPM: %s", + ocv_errorstr); + return; + } + } +#endif /* CONFIG_OCV */ } if (sta->plink_state == PLINK_BLOCKED) {