FILS: Add generation of FILS Discovery frame template
Add hostapd configuration parameters for FILS Discovery frame transmission interval and prepare a template for FILS Discovery frame for the driver interface. The actual driver interface changes are not included in this commit. Signed-off-by: Aloka Dixit <alokad@codeaurora.org>
This commit is contained in:
parent
c4c529e9cb
commit
9c02a0f5a6
8 changed files with 369 additions and 0 deletions
|
@ -4423,6 +4423,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
bss->dhcp_server_port = atoi(pos);
|
||||
} else if (os_strcmp(buf, "dhcp_relay_port") == 0) {
|
||||
bss->dhcp_relay_port = atoi(pos);
|
||||
} else if (os_strcmp(buf, "fils_discovery_min_interval") == 0) {
|
||||
bss->fils_discovery_min_int = atoi(pos);
|
||||
} else if (os_strcmp(buf, "fils_discovery_max_interval") == 0) {
|
||||
bss->fils_discovery_max_int = atoi(pos);
|
||||
#endif /* CONFIG_FILS */
|
||||
} else if (os_strcmp(buf, "multicast_to_unicast") == 0) {
|
||||
bss->multicast_to_unicast = atoi(pos);
|
||||
|
|
|
@ -1987,6 +1987,13 @@ own_ip_addr=127.0.0.1
|
|||
# default: 30 TUs (= 30.72 milliseconds)
|
||||
#fils_hlp_wait_time=30
|
||||
|
||||
# FILS Discovery frame transmission minimum and maximum interval settings.
|
||||
# If fils_discovery_max_interval is non-zero, the AP enables FILS Discovery
|
||||
# frame transmission. These values use TUs as the unit and have allowed range
|
||||
# of 0-10000. fils_discovery_min_interval defaults to 20.
|
||||
#fils_discovery_min_interval=20
|
||||
#fils_discovery_max_interval=0
|
||||
|
||||
# Transition Disable indication
|
||||
# The AP can notify authenticated stations to disable transition mode in their
|
||||
# network profiles when the network has completed transition steps, i.e., once
|
||||
|
|
|
@ -131,6 +131,7 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
|
|||
bss->fils_hlp_wait_time = 30;
|
||||
bss->dhcp_server_port = DHCP_SERVER_PORT;
|
||||
bss->dhcp_relay_port = DHCP_SERVER_PORT;
|
||||
bss->fils_discovery_min_int = 20;
|
||||
#endif /* CONFIG_FILS */
|
||||
|
||||
bss->broadcast_deauth = 1;
|
||||
|
|
|
@ -730,6 +730,8 @@ struct hostapd_bss_config {
|
|||
unsigned int fils_hlp_wait_time;
|
||||
u16 dhcp_server_port;
|
||||
u16 dhcp_relay_port;
|
||||
u32 fils_discovery_min_int;
|
||||
u32 fils_discovery_max_int;
|
||||
#endif /* CONFIG_FILS */
|
||||
|
||||
int multicast_to_unicast;
|
||||
|
|
245
src/ap/beacon.c
245
src/ap/beacon.c
|
@ -1134,6 +1134,243 @@ void sta_track_del(struct hostapd_sta_info *info)
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_FILS
|
||||
|
||||
static u16 hostapd_fils_discovery_cap(struct hostapd_data *hapd)
|
||||
{
|
||||
u16 cap_info, phy_index = 0;
|
||||
u8 chwidth = FD_CAP_BSS_CHWIDTH_20, mcs_nss_size = 4;
|
||||
struct hostapd_hw_modes *mode = hapd->iface->current_mode;
|
||||
|
||||
cap_info = FD_CAP_ESS;
|
||||
if (hapd->conf->wpa)
|
||||
cap_info |= FD_CAP_PRIVACY;
|
||||
|
||||
if (is_6ghz_op_class(hapd->iconf->op_class)) {
|
||||
phy_index = FD_CAP_PHY_INDEX_HE;
|
||||
|
||||
switch (hapd->iconf->op_class) {
|
||||
case 135:
|
||||
mcs_nss_size += 4;
|
||||
/* fallthrough */
|
||||
case 134:
|
||||
mcs_nss_size += 4;
|
||||
chwidth = FD_CAP_BSS_CHWIDTH_160_80_80;
|
||||
break;
|
||||
case 133:
|
||||
chwidth = FD_CAP_BSS_CHWIDTH_80;
|
||||
break;
|
||||
case 132:
|
||||
chwidth = FD_CAP_BSS_CHWIDTH_40;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (hostapd_get_oper_chwidth(hapd->iconf)) {
|
||||
case CHANWIDTH_80P80MHZ:
|
||||
mcs_nss_size += 4;
|
||||
/* fallthrough */
|
||||
case CHANWIDTH_160MHZ:
|
||||
mcs_nss_size += 4;
|
||||
chwidth = FD_CAP_BSS_CHWIDTH_160_80_80;
|
||||
break;
|
||||
case CHANWIDTH_80MHZ:
|
||||
chwidth = FD_CAP_BSS_CHWIDTH_80;
|
||||
break;
|
||||
case CHANWIDTH_USE_HT:
|
||||
if (hapd->iconf->secondary_channel)
|
||||
chwidth = FD_CAP_BSS_CHWIDTH_40;
|
||||
else
|
||||
chwidth = FD_CAP_BSS_CHWIDTH_20;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax)
|
||||
phy_index = FD_CAP_PHY_INDEX_HE;
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
#ifdef CONFIG_IEEE80211AC
|
||||
if (!phy_index &&
|
||||
hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac)
|
||||
phy_index = FD_CAP_PHY_INDEX_VHT;
|
||||
#endif /* CONFIG_IEEE80211AC */
|
||||
if (!phy_index &&
|
||||
hapd->iconf->ieee80211n && !hapd->conf->disable_11n)
|
||||
phy_index = FD_CAP_PHY_INDEX_HT;
|
||||
}
|
||||
|
||||
cap_info |= phy_index << FD_CAP_PHY_INDEX_SHIFT;
|
||||
cap_info |= chwidth << FD_CAP_BSS_CHWIDTH_SHIFT;
|
||||
|
||||
if (mode) {
|
||||
u16 *mcs = (u16 *) mode->he_capab[IEEE80211_MODE_AP].mcs;
|
||||
int i;
|
||||
u16 nss = 0;
|
||||
|
||||
for (i = 0; i < HE_NSS_MAX_STREAMS; i++) {
|
||||
u16 nss_mask = 0x3 << (i * 2);
|
||||
|
||||
if (mcs_nss_size == 4 &&
|
||||
(((mcs[0] & nss_mask) == nss_mask) ||
|
||||
((mcs[1] & nss_mask) == nss_mask)))
|
||||
continue;
|
||||
|
||||
if (mcs_nss_size == 8 &&
|
||||
(((mcs[2] & nss_mask) == nss_mask) ||
|
||||
((mcs[3] & nss_mask) == nss_mask)))
|
||||
continue;
|
||||
|
||||
if (mcs_nss_size == 12 &&
|
||||
(((mcs[4] & nss_mask) == nss_mask) ||
|
||||
((mcs[5] & nss_mask) == nss_mask)))
|
||||
continue;
|
||||
|
||||
nss++;
|
||||
}
|
||||
|
||||
if (nss > 4)
|
||||
cap_info |= FD_CAP_NSS_5_8 << FD_CAP_NSS_SHIFT;
|
||||
else if (nss)
|
||||
cap_info |= (nss - 1) << FD_CAP_NSS_SHIFT;
|
||||
}
|
||||
|
||||
return cap_info;
|
||||
}
|
||||
|
||||
|
||||
static u8 * hostapd_gen_fils_discovery(struct hostapd_data *hapd, size_t *len)
|
||||
{
|
||||
struct ieee80211_mgmt *head;
|
||||
const u8 *mobility_domain;
|
||||
u8 *pos, *length_pos, buf[200];
|
||||
u16 ctl = 0;
|
||||
u8 fd_rsn_info[5];
|
||||
size_t total_len, buf_len;
|
||||
|
||||
total_len = 24 + 2 + 12;
|
||||
|
||||
/* FILS Discovery Frame Control */
|
||||
ctl = (sizeof(hapd->conf->ssid.short_ssid) - 1) |
|
||||
FD_FRAME_CTL_SHORT_SSID_PRESENT |
|
||||
FD_FRAME_CTL_LENGTH_PRESENT |
|
||||
FD_FRAME_CTL_CAP_PRESENT;
|
||||
total_len += 4 + 1 + 2;
|
||||
|
||||
/* Check for optional subfields and calculate length */
|
||||
if (wpa_auth_write_fd_rsn_info(hapd->wpa_auth, fd_rsn_info)) {
|
||||
ctl |= FD_FRAME_CTL_RSN_INFO_PRESENT;
|
||||
total_len += sizeof(fd_rsn_info);
|
||||
}
|
||||
|
||||
mobility_domain = hostapd_wpa_ie(hapd, WLAN_EID_MOBILITY_DOMAIN);
|
||||
if (mobility_domain) {
|
||||
ctl |= FD_FRAME_CTL_MD_PRESENT;
|
||||
total_len += 3;
|
||||
}
|
||||
|
||||
pos = hostapd_eid_fils_indic(hapd, buf, 0);
|
||||
buf_len = pos - buf;
|
||||
total_len += buf_len;
|
||||
|
||||
head = os_zalloc(total_len);
|
||||
if (!head)
|
||||
return NULL;
|
||||
|
||||
head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
||||
WLAN_FC_STYPE_ACTION);
|
||||
os_memset(head->da, 0xff, ETH_ALEN);
|
||||
os_memcpy(head->sa, hapd->own_addr, ETH_ALEN);
|
||||
os_memcpy(head->bssid, hapd->own_addr, ETH_ALEN);
|
||||
|
||||
head->u.action.category = WLAN_ACTION_PUBLIC;
|
||||
head->u.action.u.public_action.action = WLAN_PA_FILS_DISCOVERY;
|
||||
|
||||
pos = &head->u.action.u.public_action.variable[0];
|
||||
|
||||
/* FILS Discovery Information field */
|
||||
|
||||
/* FILS Discovery Frame Control */
|
||||
WPA_PUT_LE16(pos, ctl);
|
||||
pos += 2;
|
||||
|
||||
/* Hardware or low-level driver will fill in the Timestamp value */
|
||||
pos += 8;
|
||||
|
||||
/* Beacon Interval */
|
||||
WPA_PUT_LE16(pos, hapd->iconf->beacon_int);
|
||||
pos += 2;
|
||||
|
||||
/* Short SSID */
|
||||
WPA_PUT_LE32(pos, hapd->conf->ssid.short_ssid);
|
||||
pos += sizeof(hapd->conf->ssid.short_ssid);
|
||||
|
||||
/* Store position of FILS discovery information element Length field */
|
||||
length_pos = pos++;
|
||||
|
||||
/* FD Capability */
|
||||
WPA_PUT_LE16(pos, hostapd_fils_discovery_cap(hapd));
|
||||
pos += 2;
|
||||
|
||||
/* Operating Class - not present */
|
||||
|
||||
/* Primary Channel - not present */
|
||||
|
||||
/* AP Configuration Sequence Number - not present */
|
||||
|
||||
/* Access Network Options - not present */
|
||||
|
||||
/* FD RSN Information */
|
||||
if (ctl & FD_FRAME_CTL_RSN_INFO_PRESENT) {
|
||||
os_memcpy(pos, fd_rsn_info, sizeof(fd_rsn_info));
|
||||
pos += sizeof(fd_rsn_info);
|
||||
}
|
||||
|
||||
/* Channel Center Frequency Segment 1 - not present */
|
||||
|
||||
/* Mobility Domain */
|
||||
if (ctl & FD_FRAME_CTL_MD_PRESENT) {
|
||||
os_memcpy(pos, &mobility_domain[2], 3);
|
||||
pos += 3;
|
||||
}
|
||||
|
||||
/* Fill in the Length field value */
|
||||
*length_pos = pos - (length_pos + 1);
|
||||
|
||||
/* FILS Indication element */
|
||||
if (buf_len) {
|
||||
os_memcpy(pos, buf, buf_len);
|
||||
pos += buf_len;
|
||||
}
|
||||
|
||||
*len = pos - (u8 *) head;
|
||||
wpa_hexdump(MSG_DEBUG, "FILS Discovery frame template",
|
||||
head, pos - (u8 *) head);
|
||||
return (u8 *) head;
|
||||
}
|
||||
|
||||
|
||||
/* Configure FILS Discovery frame transmission parameters */
|
||||
static u8 * hostapd_fils_discovery(struct hostapd_data *hapd,
|
||||
struct wpa_driver_ap_params *params)
|
||||
{
|
||||
params->fd_max_int = hapd->conf->fils_discovery_max_int;
|
||||
if (is_6ghz_op_class(hapd->iconf->op_class) &&
|
||||
params->fd_max_int > FD_MAX_INTERVAL_6GHZ)
|
||||
params->fd_max_int = FD_MAX_INTERVAL_6GHZ;
|
||||
|
||||
params->fd_min_int = hapd->conf->fils_discovery_min_int;
|
||||
if (params->fd_min_int > params->fd_max_int)
|
||||
params->fd_min_int = params->fd_max_int;
|
||||
|
||||
if (params->fd_max_int)
|
||||
return hostapd_gen_fils_discovery(hapd,
|
||||
¶ms->fd_frame_tmpl_len);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_FILS */
|
||||
|
||||
|
||||
int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
||||
struct wpa_driver_ap_params *params)
|
||||
{
|
||||
|
@ -1478,6 +1715,10 @@ void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params)
|
|||
params->head = NULL;
|
||||
os_free(params->proberesp);
|
||||
params->proberesp = NULL;
|
||||
#ifdef CONFIG_FILS
|
||||
os_free(params->fd_frame_tmpl);
|
||||
params->fd_frame_tmpl = NULL;
|
||||
#endif /* CONFIG_FILS */
|
||||
}
|
||||
|
||||
|
||||
|
@ -1534,6 +1775,10 @@ int ieee802_11_set_beacon(struct hostapd_data *hapd)
|
|||
params.sae_pwe = hapd->conf->sae_pwe;
|
||||
#endif /* CONFIG_SAE */
|
||||
|
||||
#ifdef CONFIG_FILS
|
||||
params.fd_frame_tmpl = hostapd_fils_discovery(hapd, ¶ms);
|
||||
#endif /* CONFIG_FILS */
|
||||
|
||||
if (cmode &&
|
||||
hostapd_set_freq_params(&freq, iconf->hw_mode, iface->freq,
|
||||
iconf->channel, iconf->enable_edmg,
|
||||
|
|
|
@ -537,6 +537,8 @@ u8 * wpa_auth_write_assoc_resp_owe(struct wpa_state_machine *sm,
|
|||
u8 * wpa_auth_write_assoc_resp_fils(struct wpa_state_machine *sm,
|
||||
u8 *pos, size_t max_len,
|
||||
const u8 *req_ies, size_t req_ies_len);
|
||||
bool wpa_auth_write_fd_rsn_info(struct wpa_authenticator *wpa_auth,
|
||||
u8 *fd_rsn_info);
|
||||
void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg);
|
||||
void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z);
|
||||
void wpa_auth_set_transition_disable(struct wpa_authenticator *wpa_auth,
|
||||
|
|
|
@ -1125,6 +1125,7 @@ u8 * wpa_auth_write_assoc_resp_owe(struct wpa_state_machine *sm,
|
|||
|
||||
|
||||
#ifdef CONFIG_FILS
|
||||
|
||||
u8 * wpa_auth_write_assoc_resp_fils(struct wpa_state_machine *sm,
|
||||
u8 *pos, size_t max_len,
|
||||
const u8 *req_ies, size_t req_ies_len)
|
||||
|
@ -1141,4 +1142,91 @@ u8 * wpa_auth_write_assoc_resp_fils(struct wpa_state_machine *sm,
|
|||
return pos;
|
||||
return pos + res;
|
||||
}
|
||||
|
||||
|
||||
bool wpa_auth_write_fd_rsn_info(struct wpa_authenticator *wpa_auth,
|
||||
u8 *fd_rsn_info)
|
||||
{
|
||||
struct wpa_auth_config *conf;
|
||||
u32 selectors = 0;
|
||||
u8 *pos = fd_rsn_info;
|
||||
int i, res;
|
||||
u32 cipher, suite, selector, mask;
|
||||
u8 tmp[10 * RSN_SELECTOR_LEN];
|
||||
|
||||
if (!wpa_auth)
|
||||
return false;
|
||||
conf = &wpa_auth->conf;
|
||||
|
||||
if (!(conf->wpa & WPA_PROTO_RSN))
|
||||
return false;
|
||||
|
||||
/* RSN Capability (B0..B15) */
|
||||
WPA_PUT_LE16(pos, wpa_own_rsn_capab(conf));
|
||||
pos += 2;
|
||||
|
||||
/* Group Data Cipher Suite Selector (B16..B21) */
|
||||
suite = wpa_cipher_to_suite(WPA_PROTO_RSN, conf->wpa_group);
|
||||
if (suite == RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED)
|
||||
cipher = 63; /* No cipher suite selected */
|
||||
if ((suite >> 8) == 0x000fac && ((suite & 0xff) <= 13))
|
||||
cipher = suite & 0xff;
|
||||
else
|
||||
cipher = 62; /* vendor specific */
|
||||
selectors |= cipher;
|
||||
|
||||
/* Group Management Cipher Suite Selector (B22..B27) */
|
||||
cipher = 63; /* Default to no cipher suite selected */
|
||||
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
|
||||
switch (conf->group_mgmt_cipher) {
|
||||
case WPA_CIPHER_AES_128_CMAC:
|
||||
cipher = RSN_CIPHER_SUITE_AES_128_CMAC & 0xff;
|
||||
break;
|
||||
case WPA_CIPHER_BIP_GMAC_128:
|
||||
cipher = RSN_CIPHER_SUITE_BIP_GMAC_128 & 0xff;
|
||||
break;
|
||||
case WPA_CIPHER_BIP_GMAC_256:
|
||||
cipher = RSN_CIPHER_SUITE_BIP_GMAC_256 & 0xff;
|
||||
break;
|
||||
case WPA_CIPHER_BIP_CMAC_256:
|
||||
cipher = RSN_CIPHER_SUITE_BIP_CMAC_256 & 0xff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
selectors |= cipher << 6;
|
||||
|
||||
/* Pairwise Cipher Suite Selector (B28..B33) */
|
||||
cipher = 63; /* Default to no cipher suite selected */
|
||||
res = rsn_cipher_put_suites(tmp, conf->rsn_pairwise);
|
||||
if (res == 1 && tmp[0] == 0x00 && tmp[1] == 0x0f && tmp[2] == 0xac &&
|
||||
tmp[3] <= 13)
|
||||
cipher = tmp[3];
|
||||
selectors |= cipher << 12;
|
||||
|
||||
/* AKM Suite Selector (B34..B39) */
|
||||
selector = 0; /* default to AKM from RSNE in Beacon/Probe Response */
|
||||
mask = WPA_KEY_MGMT_FILS_SHA256 | WPA_KEY_MGMT_FILS_SHA384 |
|
||||
WPA_KEY_MGMT_FT_FILS_SHA384;
|
||||
if ((conf->wpa_key_mgmt & mask) && (conf->wpa_key_mgmt & ~mask) == 0) {
|
||||
suite = conf->wpa_key_mgmt & mask;
|
||||
if (suite == WPA_KEY_MGMT_FILS_SHA256)
|
||||
selector = 1; /* 00-0f-ac:14 */
|
||||
else if (suite == WPA_KEY_MGMT_FILS_SHA384)
|
||||
selector = 2; /* 00-0f-ac:15 */
|
||||
else if (suite == (WPA_KEY_MGMT_FILS_SHA256 |
|
||||
WPA_KEY_MGMT_FILS_SHA384))
|
||||
selector = 3; /* 00-0f-ac:14 or 00-0f-ac:15 */
|
||||
else if (suite == WPA_KEY_MGMT_FT_FILS_SHA384)
|
||||
selector = 4; /* 00-0f-ac:17 */
|
||||
}
|
||||
selectors |= selector << 18;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
*pos++ = selectors & 0xff;
|
||||
selectors >>= 8;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_FILS */
|
||||
|
|
|
@ -1541,6 +1541,26 @@ struct wpa_driver_ap_params {
|
|||
* 2 = both hunting-and-pecking loop and hash-to-element enabled
|
||||
*/
|
||||
int sae_pwe;
|
||||
|
||||
/**
|
||||
* FILS Discovery frame minimum interval in TUs
|
||||
*/
|
||||
u32 fd_min_int;
|
||||
|
||||
/**
|
||||
* FILS Discovery frame maximum interval in TUs (0 = FD frame disabled)
|
||||
*/
|
||||
u32 fd_max_int;
|
||||
|
||||
/**
|
||||
* FILS Discovery frame template data
|
||||
*/
|
||||
u8 *fd_frame_tmpl;
|
||||
|
||||
/**
|
||||
* FILS Discovery frame template length
|
||||
*/
|
||||
size_t fd_frame_tmpl_len;
|
||||
};
|
||||
|
||||
struct wpa_driver_mesh_bss_params {
|
||||
|
|
Loading…
Reference in a new issue