} else {
wpa_hexdump_link(MSG_DEBUG, i, "RSN: Set AP RSNE",
ie, len);
- sm->mlo.links[i].ap_rsne = os_memdup(ie, len);
- if (!sm->mlo.links[i].ap_rsne) {
- sm->mlo.links[i].ap_rsne_len = 0;
- return -1;
+ if (ie[0] == WLAN_EID_VENDOR_SPECIFIC && len > 2 + 4) {
+ sm->mlo.links[i].ap_rsne = os_malloc(len - 4);
+ if (!sm->mlo.links[i].ap_rsne)
+ return -1;
+ sm->mlo.links[i].ap_rsne[0] = WLAN_EID_RSN;
+ sm->mlo.links[i].ap_rsne[1] = len - 2 - 4;
+ os_memcpy(&sm->mlo.links[i].ap_rsne[2],
+ ie + 2 + 4, len - 2 - 4);
+ sm->mlo.links[i].ap_rsne_len = len - 4;
+ wpa_hexdump(MSG_DEBUG,
+ "RSN: Converted RSNE override to RSNE",
+ sm->mlo.links[i].ap_rsne,
+ sm->mlo.links[i].ap_rsne_len);
+ } else {
+ sm->mlo.links[i].ap_rsne = os_memdup(ie, len);
+ if (!sm->mlo.links[i].ap_rsne) {
+ sm->mlo.links[i].ap_rsne_len = 0;
+ return -1;
+ }
+ sm->mlo.links[i].ap_rsne_len = len;
}
- sm->mlo.links[i].ap_rsne_len = len;
}
ie = mlo->links[i].ap_rsnxe;
} else {
wpa_hexdump_link(MSG_DEBUG, i, "RSN: Set AP RSNXE", ie,
len);
- sm->mlo.links[i].ap_rsnxe = os_memdup(ie, len);
- if (!sm->mlo.links[i].ap_rsnxe) {
- sm->mlo.links[i].ap_rsnxe_len = 0;
- return -1;
+ if (ie[0] == WLAN_EID_VENDOR_SPECIFIC && len > 2 + 4) {
+ sm->mlo.links[i].ap_rsnxe = os_malloc(len - 4);
+ if (!sm->mlo.links[i].ap_rsnxe)
+ return -1;
+ sm->mlo.links[i].ap_rsnxe[0] = WLAN_EID_RSNX;
+ sm->mlo.links[i].ap_rsnxe[1] = len - 2 - 4;
+ os_memcpy(&sm->mlo.links[i].ap_rsnxe[2],
+ ie + 2 + 4, len - 2 - 4);
+ sm->mlo.links[i].ap_rsnxe_len = len - 4;
+ wpa_hexdump(MSG_DEBUG,
+ "RSN: Converted RSNXE override to RSNXE",
+ sm->mlo.links[i].ap_rsnxe,
+ sm->mlo.links[i].ap_rsnxe_len);
+ } else {
+ sm->mlo.links[i].ap_rsnxe = os_memdup(ie, len);
+ if (!sm->mlo.links[i].ap_rsnxe) {
+ sm->mlo.links[i].ap_rsnxe_len = 0;
+ return -1;
+ }
+ sm->mlo.links[i].ap_rsnxe_len = len;
}
- sm->mlo.links[i].ap_rsnxe_len = len;
}
}
sm->ap_rsn_ie_len = 0;
} else {
wpa_hexdump(MSG_DEBUG, "WPA: set AP RSN IE", ie, len);
- sm->ap_rsn_ie = os_memdup(ie, len);
- if (sm->ap_rsn_ie == NULL)
- return -1;
+ if (ie[0] == WLAN_EID_VENDOR_SPECIFIC && len > 2 + 4) {
+ sm->ap_rsn_ie = os_malloc(len - 4);
+ if (!sm->ap_rsn_ie)
+ return -1;
+ sm->ap_rsn_ie[0] = WLAN_EID_RSN;
+ sm->ap_rsn_ie[1] = len - 2 - 4;
+ os_memcpy(&sm->ap_rsn_ie[2], ie + 2 + 4, len - 2 - 4);
+ sm->ap_rsn_ie_len = len - 4;
+ wpa_hexdump(MSG_DEBUG,
+ "RSN: Converted RSNE override to RSNE",
+ sm->ap_rsn_ie, sm->ap_rsn_ie_len);
+ } else {
+ sm->ap_rsn_ie = os_memdup(ie, len);
+ if (sm->ap_rsn_ie == NULL)
+ return -1;
- sm->ap_rsn_ie_len = len;
+ sm->ap_rsn_ie_len = len;
+ }
}
return 0;
sm->ap_rsnxe_len = 0;
} else {
wpa_hexdump(MSG_DEBUG, "WPA: set AP RSNXE", ie, len);
- sm->ap_rsnxe = os_memdup(ie, len);
- if (!sm->ap_rsnxe)
- return -1;
+ if (ie[0] == WLAN_EID_VENDOR_SPECIFIC && len > 2 + 4) {
+ sm->ap_rsnxe = os_malloc(len - 4);
+ if (!sm->ap_rsnxe)
+ return -1;
+ sm->ap_rsnxe[0] = WLAN_EID_RSNX;
+ sm->ap_rsnxe[1] = len - 2 - 4;
+ os_memcpy(&sm->ap_rsnxe[2], ie + 2 + 4, len - 2 - 4);
+ sm->ap_rsnxe_len = len - 4;
+ wpa_hexdump(MSG_DEBUG,
+ "RSN: Converted RSNXE override to RSNXE",
+ sm->ap_rsnxe, sm->ap_rsnxe_len);
+ } else {
+ sm->ap_rsnxe = os_memdup(ie, len);
+ if (!sm->ap_rsnxe)
+ return -1;
- sm->ap_rsnxe_len = len;
+ sm->ap_rsnxe_len = len;
+ }
}
return 0;
if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC &&
wpa_ie[1] >= 4 && WPA_GET_BE32(&wpa_ie[2]) == OSEN_IE_VENDOR_TYPE)
return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
- else
- return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data);
+ if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC &&
+ wpa_ie[1] >= 4 &&
+ WPA_GET_BE32(&wpa_ie[2]) == RSNE_OVERRIDE_IE_VENDOR_TYPE)
+ return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
+ if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC &&
+ wpa_ie[1] >= 4 &&
+ WPA_GET_BE32(&wpa_ie[2]) == RSNE_OVERRIDE_2_IE_VENDOR_TYPE)
+ return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
+ return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data);
}
if (ssid) {
struct wpa_ie_data ie;
-
- if (!elems.rsn_ie ||
- wpa_parse_wpa_ie(elems.rsn_ie - 2, 2 + elems.rsn_ie_len,
- &ie)) {
+ const u8 *rsne;
+ size_t rsne_len;
+
+ if (elems.rsne_override_2 && wpas_rsn_overriding(wpa_s)) {
+ rsne = elems.rsne_override_2;
+ rsne_len = elems.rsne_override_2_len;
+ } else if (elems.rsne_override &&
+ wpas_rsn_overriding(wpa_s)) {
+ rsne = elems.rsne_override;
+ rsne_len = elems.rsne_override_len;
+ } else {
+ rsne = elems.rsn_ie;
+ rsne_len = elems.rsn_ie_len;
+ }
+ if (!rsne ||
+ wpa_parse_wpa_ie(rsne - 2, 2 + rsne_len, &ie)) {
wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No RSN element");
goto out;
}
}
+static bool wpa_bss_supported_cipher(struct wpa_supplicant *wpa_s,
+ int pairwise_cipher)
+{
+ if (!wpa_s->drv_enc)
+ return true;
+
+ if ((pairwise_cipher & WPA_CIPHER_CCMP) &&
+ (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_CCMP))
+ return true;
+
+ if ((pairwise_cipher & WPA_CIPHER_GCMP) &&
+ (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_GCMP))
+ return true;
+
+ if ((pairwise_cipher & WPA_CIPHER_CCMP_256) &&
+ (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_CCMP_256))
+ return true;
+
+ if ((pairwise_cipher & WPA_CIPHER_GCMP_256) &&
+ (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_GCMP_256))
+ return true;
+
+ return false;
+}
+
+
+static bool wpa_bss_supported_key_mgmt(struct wpa_supplicant *wpa_s,
+ int key_mgmt)
+{
+ if (!wpa_s->drv_key_mgmt)
+ return true;
+
+ if ((key_mgmt & WPA_KEY_MGMT_IEEE8021X) &&
+ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA2))
+ return true;
+ if ((key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) &&
+ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_802_1X_SHA256))
+ return true;
+ if ((key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) &&
+ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT))
+ return true;
+ if ((key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
+ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_802_1X_SHA384))
+ return true;
+ if ((key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) &&
+ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B))
+ return true;
+ if ((key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) &&
+ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192))
+ return true;
+ if ((key_mgmt & WPA_KEY_MGMT_PSK) &&
+ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK))
+ return true;
+ if ((key_mgmt & WPA_KEY_MGMT_FT_PSK) &&
+ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK))
+ return true;
+ if ((key_mgmt & WPA_KEY_MGMT_PSK_SHA256) &&
+ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_PSK_SHA256))
+ return true;
+ if ((key_mgmt & WPA_KEY_MGMT_SAE) &&
+ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE))
+ return true;
+ if ((key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) &&
+ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE_EXT_KEY))
+ return true;
+ if ((key_mgmt & WPA_KEY_MGMT_FT_SAE) &&
+ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE))
+ return true;
+ if ((key_mgmt & WPA_KEY_MGMT_FT_SAE_EXT_KEY) &&
+ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE_EXT_KEY))
+ return true;
+ if ((key_mgmt & WPA_KEY_MGMT_OWE) &&
+ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE))
+ return true;
+ if ((key_mgmt & WPA_KEY_MGMT_DPP) &&
+ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP))
+ return true;
+ if ((key_mgmt & WPA_KEY_MGMT_FILS_SHA256) &&
+ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256))
+ return true;
+ if ((key_mgmt & WPA_KEY_MGMT_FILS_SHA384) &&
+ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384))
+ return true;
+ if ((key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) &&
+ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256))
+ return true;
+ if ((key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) &&
+ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384))
+ return true;
+
+ return false;
+}
+
+
+static bool wpa_bss_supported_rsne(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid, const u8 *ie)
+{
+ struct wpa_ie_data data;
+
+ if (wpa_parse_wpa_ie_rsn(ie, 2 + ie[1], &data) < 0)
+ return false;
+
+ /* Check that there is a supported AKM and pairwise cipher based on
+ * overall capabilities */
+ if (!data.pairwise_cipher || !data.key_mgmt)
+ return false;
+
+ if (wpa_s->drv_capa_known) {
+ if (!wpa_bss_supported_cipher(wpa_s, data.pairwise_cipher) ||
+ !wpa_bss_supported_key_mgmt(wpa_s, data.key_mgmt))
+ return false;
+ }
+
+ if (ssid) {
+ /* Check that there is a supported AKM and pairwise cipher
+ * based on the specific network profile. */
+ if ((ssid->pairwise_cipher & data.pairwise_cipher) == 0)
+ return false;
+ if ((ssid->key_mgmt & data.key_mgmt) == 0)
+ return false;
+ }
+
+ return true;
+}
+
+
const u8 * wpa_bss_get_rsne(struct wpa_supplicant *wpa_s,
const struct wpa_bss *bss, struct wpa_ssid *ssid,
bool mlo)
{
+ const u8 *ie;
+
+ if (wpas_rsn_overriding(wpa_s)) {
+ if (!ssid)
+ ssid = wpa_s->current_ssid;
+
+ /* MLO cases for RSN overriding are required to use RSNE
+ * Override 2 element and RSNXE Override element together. */
+ ie = wpa_bss_get_vendor_ie(bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
+ if (mlo && ie &&
+ !wpa_bss_get_vendor_ie(bss,
+ RSNXE_OVERRIDE_IE_VENDOR_TYPE)) {
+ wpa_printf(MSG_DEBUG, "BSS " MACSTR
+ " advertises RSNE Override 2 element without RSNXE Override element - ignore RSNE Override 2 element for MLO",
+ MAC2STR(bss->bssid));
+ } else if (ie && wpa_bss_supported_rsne(wpa_s, ssid, ie)) {
+ return ie;
+ }
+
+ if (!mlo) {
+ ie = wpa_bss_get_vendor_ie(
+ bss, RSNE_OVERRIDE_IE_VENDOR_TYPE);
+ if (ie && wpa_bss_supported_rsne(wpa_s, ssid, ie))
+ return ie;
+ }
+ }
+
return wpa_bss_get_ie(bss, WLAN_EID_RSN);
}
const struct wpa_bss *bss, struct wpa_ssid *ssid,
bool mlo)
{
+ const u8 *ie;
+
+ if (wpas_rsn_overriding(wpa_s)) {
+ ie = wpa_bss_get_vendor_ie(bss, RSNXE_OVERRIDE_IE_VENDOR_TYPE);
+ if (ie) {
+ const u8 *tmp;
+
+ tmp = wpa_bss_get_rsne(wpa_s, bss, ssid, mlo);
+ if (!tmp || tmp[0] == WLAN_EID_RSN) {
+ /* An acceptable RSNE override element was not
+ * found, so need to ignore RSNXE overriding. */
+ return NULL;
+ }
+
+ return ie;
+ }
+
+ /* MLO cases for RSN overriding are required to use RSNE
+ * Override 2 element and RSNXE Override element together. */
+ if (mlo && wpa_bss_get_vendor_ie(
+ bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE)) {
+ wpa_printf(MSG_DEBUG, "BSS " MACSTR
+ " advertises RSNXE Override element without RSNE Override 2 element - ignore RSNXE Override element for MLO",
+ MAC2STR(bss->bssid));
+ return NULL;
+ }
+ }
+
return wpa_bss_get_ie(bss, WLAN_EID_RSNX);
}
{ INT_RANGE(extended_key_id, 0, 1), 0 },
#endif /* CONFIG_WNM */
{ INT_RANGE(wowlan_disconnect_on_deinit, 0, 1), 0},
+ { INT_RANGE(rsn_overriding, 0, 2), 0},
#ifdef CONFIG_PASN
#ifdef CONFIG_TESTING_OPTIONS
{ INT_RANGE(force_kdk_derivation, 0, 1), 0 },
*/
int wowlan_disconnect_on_deinit;
+ /**
+ * rsn_overriding - RSN overriding
+ *
+ * 0 = Disabled
+ * 1 = Enabled automatically if the driver indicates support
+ * 2 = Forced to be enabled even without driver capability indication
+ */
+ enum rsn_overriding {
+ RSN_OVERRIDING_DISABLED = 0,
+ RSN_OVERRIDING_AUTO = 1,
+ RSN_OVERRIDING_ENABLED = 2,
+ } rsn_overriding;
+
#ifdef CONFIG_PASN
#ifdef CONFIG_TESTING_OPTIONS
/*
if (config->wowlan_disconnect_on_deinit)
fprintf(f, "wowlan_disconnect_on_deinit=%d\n",
config->wowlan_disconnect_on_deinit);
+ if (config->rsn_overriding)
+ fprintf(f, "rsn_overriding=%d\n", config->rsn_overriding);
#ifdef CONFIG_TESTING_OPTIONS
if (config->mld_force_single_link)
fprintf(f, "mld_force_single_link=1\n");
#ifdef CONFIG_SAE
ie = wpa_bss_get_rsnxe(wpa_s, bss, ssid, false);
- if (ie && ie[1] >= 1)
+ if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4 + 1)
+ rsnxe_capa = ie[4 + 2];
+ else if (ie && ie[1] >= 1)
rsnxe_capa = ie[2];
#endif /* CONFIG_SAE */
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, p, len);
}
+ if (wpas_rsn_overriding(wpa_s) &&
+ p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
+ WPA_GET_BE32(&p[2]) == RSNE_OVERRIDE_2_IE_VENDOR_TYPE) {
+ rsn_found = 1;
+ wpa_sm_set_ap_rsn_ie(wpa_s->wpa, p, len);
+ }
+
+ if (!rsn_found &&
+ wpas_rsn_overriding(wpa_s) &&
+ p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
+ WPA_GET_BE32(&p[2]) == RSNE_OVERRIDE_IE_VENDOR_TYPE) {
+ rsn_found = 1;
+ wpa_sm_set_ap_rsn_ie(wpa_s->wpa, p, len);
+ }
+
if (p[0] == WLAN_EID_RSNX && p[1] >= 1)
wpa_sm_set_ap_rsnxe(wpa_s->wpa, p, len);
+ if (wpas_rsn_overriding(wpa_s) &&
+ p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
+ WPA_GET_BE32(&p[2]) == RSNXE_OVERRIDE_IE_VENDOR_TYPE)
+ wpa_sm_set_ap_rsnxe(wpa_s->wpa, p, len);
+
l -= len;
p += len;
}
const u8 *rsnxe;
rsnxe = wpa_bss_get_rsnxe(wpa_s, bss, ssid, false);
- if (rsnxe && rsnxe[1] >= 1)
+ if (rsnxe && rsnxe[0] == WLAN_EID_VENDOR_SPECIFIC &&
+ rsnxe[1] >= 1 + 4)
+ rsnxe_capa = rsnxe[2 + 4];
+ else if (rsnxe && rsnxe[1] >= 1)
rsnxe_capa = rsnxe[2];
}
wpa_s->sme.assoc_req_ie_len += multi_ap_ie_len;
}
+ if (wpas_rsn_overriding(wpa_s) &&
+ wpas_ap_supports_rsn_overriding(wpa_s, wpa_s->current_bss) &&
+ wpa_s->sme.assoc_req_ie_len + 2 + 4 <=
+ sizeof(wpa_s->sme.assoc_req_ie)) {
+ u8 *pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
+ u32 type = 0;
+ const u8 *ie;
+
+ ie = wpa_bss_get_rsne(wpa_s, wpa_s->current_bss, ssid,
+ wpa_s->valid_links);
+ if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4)
+ type = WPA_GET_BE32(&ie[2]);
+
+ if (type) {
+ /* Indicate support for RSN overriding */
+ *pos++ = WLAN_EID_VENDOR_SPECIFIC;
+ *pos++ = 4;
+ WPA_PUT_BE32(pos, type);
+ wpa_s->sme.assoc_req_ie_len += 2 + 4;
+ }
+ }
+
params.bssid = bssid;
params.ssid = wpa_s->sme.ssid;
params.ssid_len = wpa_s->sme.ssid_len;
wpa_ie_len += multi_ap_ie_len;
}
+ if (!wpas_driver_bss_selection(wpa_s) &&
+ wpas_rsn_overriding(wpa_s) &&
+ wpas_ap_supports_rsn_overriding(wpa_s, bss) &&
+ wpa_ie_len + 2 + 4 <= max_wpa_ie_len) {
+ u8 *pos = wpa_ie + wpa_ie_len;
+ u32 type = 0;
+ const u8 *ie;
+
+ ie = wpa_bss_get_rsne(wpa_s, bss, ssid, wpa_s->valid_links);
+ if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4)
+ type = WPA_GET_BE32(&ie[2]);
+
+ if (type) {
+ /* Indicate support for RSN overriding */
+ *pos++ = WLAN_EID_VENDOR_SPECIFIC;
+ *pos++ = 4;
+ WPA_PUT_BE32(pos, type);
+ pos += 4;
+ wpa_hexdump(MSG_MSGDUMP, "RSNE Override", wpa_ie,
+ pos - wpa_ie);
+ wpa_ie_len += 2 + 4;
+ }
+ }
+
+ if (wpas_driver_bss_selection(wpa_s) &&
+ wpas_rsn_overriding(wpa_s)) {
+ if (wpa_ie_len + 2 + 4 <= max_wpa_ie_len) {
+ u8 *pos = wpa_ie + wpa_ie_len;
+
+ *pos++ = WLAN_EID_VENDOR_SPECIFIC;
+ *pos++ = 4;
+ WPA_PUT_BE32(pos, RSNE_OVERRIDE_IE_VENDOR_TYPE);
+ pos += 4;
+ wpa_hexdump(MSG_MSGDUMP, "RSNE Override", wpa_ie,
+ pos - wpa_ie);
+ wpa_ie_len += 2 + 4;
+ }
+
+ if (wpa_ie_len + 2 + 4 <= max_wpa_ie_len) {
+ u8 *pos = wpa_ie + wpa_ie_len;
+
+ *pos++ = WLAN_EID_VENDOR_SPECIFIC;
+ *pos++ = 4;
+ WPA_PUT_BE32(pos, RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
+ pos += 4;
+ wpa_hexdump(MSG_MSGDUMP, "RSNE Override 2",
+ wpa_ie, pos - wpa_ie);
+ wpa_ie_len += 2 + 4;
+ }
+ }
+
params->wpa_ie = wpa_ie;
params->wpa_ie_len = wpa_ie_len;
params->auth_alg = algs;
}
+static bool wpas_driver_rsn_override(struct wpa_supplicant *wpa_s)
+{
+ return !!(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_RSN_OVERRIDE_STA);
+}
+
+
+bool wpas_rsn_overriding(struct wpa_supplicant *wpa_s)
+{
+ if (wpa_s->conf->rsn_overriding == RSN_OVERRIDING_DISABLED)
+ return false;
+
+ if (wpa_s->conf->rsn_overriding == RSN_OVERRIDING_ENABLED)
+ return true;
+
+ if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
+ wpas_driver_bss_selection(wpa_s))
+ return wpas_driver_rsn_override(wpa_s);
+
+ return true;
+}
+
+
#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid,
return false;
}
+
+
+bool wpas_ap_supports_rsn_overriding(struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss)
+{
+ int i;
+
+ if (!bss)
+ return false;
+ if (wpa_bss_get_vendor_ie(bss, RSNE_OVERRIDE_IE_VENDOR_TYPE) ||
+ wpa_bss_get_vendor_ie(bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE))
+ return true;
+
+ if (!wpa_s->valid_links)
+ return false;
+
+ for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+ if (!(wpa_s->valid_links & BIT(i)))
+ continue;
+ if (wpa_s->links[i].bss &&
+ (wpa_bss_get_vendor_ie(wpa_s->links[i].bss,
+ RSNE_OVERRIDE_IE_VENDOR_TYPE) ||
+ wpa_bss_get_vendor_ie(wpa_s->links[i].bss,
+ RSNE_OVERRIDE_2_IE_VENDOR_TYPE)))
+ return true;
+ }
+
+ return false;
+}
+
+
+bool wpas_ap_supports_rsn_overriding_2(struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss)
+{
+ int i;
+
+ if (!bss)
+ return false;
+ if (wpa_bss_get_vendor_ie(bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE))
+ return true;
+
+ if (!wpa_s->valid_links)
+ return false;
+
+ for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+ if (!(wpa_s->valid_links & BIT(i)))
+ continue;
+ if (wpa_s->links[i].bss &&
+ wpa_bss_get_vendor_ie(wpa_s->links[i].bss,
+ RSNE_OVERRIDE_2_IE_VENDOR_TYPE))
+ return true;
+ }
+
+ return false;
+}
# 1 = auto: Activate Extended Key ID support if the driver supports it
#extended_key_id=0
+# RSN overriding
+# NOTE: The protocol used for this mechanism is still subject to change and as
+# such, this should not yet be enabled for production uses to avoid issues if
+# something were to change.
+# 0 = Disabled (default)
+# 1 = Enabled automatically if the driver indicates support
+# 2 = Forced to be enabled even without driver capability indication
+#rsn_overriding=0
+
# network block
#
# Each network (usually AP's sharing the same SSID) is configured as a separate
void fils_connection_failure(struct wpa_supplicant *wpa_s);
void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s);
int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s);
+bool wpas_rsn_overriding(struct wpa_supplicant *wpa_s);
int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s);
void wpas_auth_failed(struct wpa_supplicant *wpa_s, const char *reason,
const u8 *bssid);
bool wpa_is_non_eht_scs_traffic_desc_supported(struct wpa_bss *bss);
bool wpas_ap_link_address(struct wpa_supplicant *wpa_s, const u8 *addr);
+bool wpas_ap_supports_rsn_overriding(struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss);
+bool wpas_ap_supports_rsn_overriding_2(struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss);
#endif /* WPA_SUPPLICANT_I_H */