diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 5f1032fb1..d80fb0821 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -3773,6 +3773,28 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "dpp_csign_expiry") == 0) { bss->dpp_csign_expiry = strtol(pos, NULL, 0); #endif /* CONFIG_DPP */ +#ifdef CONFIG_OWE + } else if (os_strcmp(buf, "owe_transition_bssid") == 0) { + if (hwaddr_aton(pos, bss->owe_transition_bssid)) { + wpa_printf(MSG_ERROR, + "Line %d: invalid owe_transition_bssid", + line); + return 1; + } + } else if (os_strcmp(buf, "owe_transition_ssid") == 0) { + size_t slen; + char *str = wpa_config_parse_string(pos, &slen); + + if (!str || slen < 1 || slen > SSID_MAX_LEN) { + wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'", + line, pos); + os_free(str); + return 1; + } + os_memcpy(bss->owe_transition_ssid, str, slen); + bss->owe_transition_ssid_len = slen; + os_free(str); +#endif /* CONFIG_OWE */ } else { wpa_printf(MSG_ERROR, "Line %d: unknown configuration item '%s'", diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 7ad320648..2c5fa7cb0 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -1407,6 +1407,12 @@ own_ip_addr=127.0.0.1 # 1-65535 DH Group to use for FILS PFS #fils_dh_group=0 +# OWE transition mode configuration +# Pointer to the matching open/OWE BSS +#owe_transition_bssid= +# SSID in same format as ssid2 described above. +#owe_transition_ssid= + # DHCP server for FILS HLP # If configured, hostapd will act as a DHCP relay for all FILS HLP requests # that include a DHCPDISCOVER message and send them to the specific DHCP diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 48d4280ed..02164e16e 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -644,6 +644,12 @@ struct hostapd_bss_config { struct wpabuf *dpp_csign; unsigned int dpp_csign_expiry; #endif /* CONFIG_DPP */ + +#ifdef CONFIG_OWE + macaddr owe_transition_bssid; + u8 owe_transition_ssid[SSID_MAX_LEN]; + size_t owe_transition_ssid_len; +#endif /* CONFIG_OWE */ }; /** diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 18374f678..542575829 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -363,6 +363,63 @@ static u8 * hostapd_eid_supported_op_classes(struct hostapd_data *hapd, u8 *eid) } +#ifdef CONFIG_OWE +static int hostapd_eid_owe_trans_enabled(struct hostapd_data *hapd) +{ + return hapd->conf->owe_transition_ssid_len > 0 && + !is_zero_ether_addr(hapd->conf->owe_transition_bssid); +} +#endif /* CONFIG_OWE */ + + +static size_t hostapd_eid_owe_trans_len(struct hostapd_data *hapd) +{ +#ifdef CONFIG_OWE + if (!hostapd_eid_owe_trans_enabled(hapd)) + return 0; + return 6 + ETH_ALEN + 1 + hapd->conf->owe_transition_ssid_len; +#else /* CONFIG_OWE */ + return 0; +#endif /* CONFIG_OWE */ +} + + +static u8 * hostapd_eid_owe_trans(struct hostapd_data *hapd, u8 *eid, + size_t len) +{ +#ifdef CONFIG_OWE + u8 *pos = eid; + size_t elen; + + if (!hostapd_eid_owe_trans_enabled(hapd)) + return pos; + + elen = hostapd_eid_owe_trans_len(hapd); + if (len < elen) { + wpa_printf(MSG_DEBUG, + "OWE: Not enough room in the buffer for OWE IE"); + return pos; + } + + *pos++ = WLAN_EID_VENDOR_SPECIFIC; + *pos++ = elen - 2; + WPA_PUT_BE24(pos, OUI_WFA); + pos += 3; + *pos++ = OWE_OUI_TYPE; + os_memcpy(pos, hapd->conf->owe_transition_bssid, ETH_ALEN); + pos += ETH_ALEN; + *pos++ = hapd->conf->owe_transition_ssid_len; + os_memcpy(pos, hapd->conf->owe_transition_ssid, + hapd->conf->owe_transition_ssid_len); + pos += hapd->conf->owe_transition_ssid_len; + + return pos; +#else /* CONFIG_OWE */ + return eid; +#endif /* CONFIG_OWE */ +} + + static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, const struct ieee80211_mgmt *req, int is_p2p, size_t *resp_len) @@ -400,6 +457,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, #endif /* CONFIG_IEEE80211AX */ buflen += hostapd_mbo_ie_len(hapd); + buflen += hostapd_eid_owe_trans_len(hapd); resp = os_zalloc(buflen); if (resp == NULL) @@ -545,6 +603,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, #endif /* CONFIG_HS20 */ pos = hostapd_eid_mbo(hapd, pos, (u8 *) resp + buflen - pos); + pos = hostapd_eid_owe_trans(hapd, pos, (u8 *) resp + buflen - pos); if (hapd->conf->vendor_elements) { os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements), @@ -1062,6 +1121,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, #endif /* CONFIG_IEEE80211AX */ tail_len += hostapd_mbo_ie_len(hapd); + tail_len += hostapd_eid_owe_trans_len(hapd); tailpos = tail = os_malloc(tail_len); if (head == NULL || tail == NULL) { @@ -1229,6 +1289,8 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, #endif /* CONFIG_HS20 */ tailpos = hostapd_eid_mbo(hapd, tailpos, tail + tail_len - tailpos); + tailpos = hostapd_eid_owe_trans(hapd, tailpos, + tail + tail_len - tailpos); if (hapd->conf->vendor_elements) { os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements), diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 2444c7d4e..b7fa5633f 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -1196,6 +1196,8 @@ struct ieee80211_ampe_ie { #define OSEN_IE_VENDOR_TYPE 0x506f9a12 #define MBO_IE_VENDOR_TYPE 0x506f9a16 #define MBO_OUI_TYPE 22 +#define OWE_IE_VENDOR_TYPE 0x506f9a1c +#define OWE_OUI_TYPE 28 #define WMM_OUI_TYPE 2 #define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0