DPP3: Add PKEX initiator retries and fallback from v2 to v1 for hostapd
This extends hostapd with the design used in wpa_supplicant for PKEX initiator retries and automatic version fallback from v2 to v1 (the latter is enabled only with CONFIG_DPP3=y). Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
parent
3f67ab5871
commit
9d3f347a2b
1 changed files with 171 additions and 17 deletions
|
@ -216,6 +216,163 @@ static void hostapd_dpp_auth_resp_retry(struct hostapd_data *hapd)
|
|||
}
|
||||
|
||||
|
||||
static int hostapd_dpp_allow_ir(struct hostapd_data *hapd, unsigned int freq)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (!hapd->iface->hw_features)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < hapd->iface->num_hw_features; i++) {
|
||||
struct hostapd_hw_modes *mode = &hapd->iface->hw_features[i];
|
||||
|
||||
for (j = 0; j < mode->num_channels; j++) {
|
||||
struct hostapd_channel_data *chan = &mode->channels[j];
|
||||
|
||||
if (chan->freq != (int) freq)
|
||||
continue;
|
||||
|
||||
if (chan->flag & (HOSTAPD_CHAN_DISABLED |
|
||||
HOSTAPD_CHAN_NO_IR |
|
||||
HOSTAPD_CHAN_RADAR))
|
||||
continue;
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list",
|
||||
freq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_dpp_pkex_next_channel(struct hostapd_data *hapd,
|
||||
struct dpp_pkex *pkex)
|
||||
{
|
||||
if (pkex->freq == 2437)
|
||||
pkex->freq = 5745;
|
||||
else if (pkex->freq == 5745)
|
||||
pkex->freq = 5220;
|
||||
else if (pkex->freq == 5220)
|
||||
pkex->freq = 60480;
|
||||
else
|
||||
return -1; /* no more channels to try */
|
||||
|
||||
if (hostapd_dpp_allow_ir(hapd, pkex->freq) == 1) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz",
|
||||
pkex->freq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Could not use this channel - try the next one */
|
||||
return hostapd_dpp_pkex_next_channel(hapd, pkex);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_dpp_pkex_init(struct hostapd_data *hapd, bool v2)
|
||||
{
|
||||
struct dpp_pkex *pkex;
|
||||
struct wpabuf *msg;
|
||||
unsigned int wait_time;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DPP: Initiating PKEXv%d", v2 ? 2 : 1);
|
||||
dpp_pkex_free(hapd->dpp_pkex);
|
||||
hapd->dpp_pkex = dpp_pkex_init(hapd->msg_ctx, hapd->dpp_pkex_bi,
|
||||
hapd->own_addr,
|
||||
hapd->dpp_pkex_identifier,
|
||||
hapd->dpp_pkex_code, v2);
|
||||
pkex = hapd->dpp_pkex;
|
||||
if (!pkex)
|
||||
return -1;
|
||||
|
||||
msg = hapd->dpp_pkex->exchange_req;
|
||||
wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
|
||||
pkex->freq = 2437;
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
|
||||
" freq=%u type=%d", MAC2STR(broadcast), pkex->freq,
|
||||
v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
|
||||
DPP_PA_PKEX_V1_EXCHANGE_REQ);
|
||||
hostapd_drv_send_action(hapd, pkex->freq, 0, broadcast,
|
||||
wpabuf_head(msg), wpabuf_len(msg));
|
||||
pkex->exch_req_wait_time = wait_time;
|
||||
pkex->exch_req_tries = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = eloop_ctx;
|
||||
struct dpp_pkex *pkex = hapd->dpp_pkex;
|
||||
|
||||
if (!pkex || !pkex->exchange_req)
|
||||
return;
|
||||
if (pkex->exch_req_tries >= 5) {
|
||||
if (hostapd_dpp_pkex_next_channel(hapd, pkex) < 0) {
|
||||
#ifdef CONFIG_DPP3
|
||||
if (pkex->v2) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Fall back to PKEXv1");
|
||||
hostapd_dpp_pkex_init(hapd, false);
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_DPP3 */
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
|
||||
"No response from PKEX peer");
|
||||
dpp_pkex_free(pkex);
|
||||
hapd->dpp_pkex = NULL;
|
||||
return;
|
||||
}
|
||||
pkex->exch_req_tries = 0;
|
||||
}
|
||||
|
||||
pkex->exch_req_tries++;
|
||||
wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
|
||||
pkex->exch_req_tries);
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
|
||||
" freq=%u type=%d",
|
||||
MAC2STR(broadcast), pkex->freq,
|
||||
pkex->v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
|
||||
DPP_PA_PKEX_V1_EXCHANGE_REQ);
|
||||
hostapd_drv_send_action(hapd, pkex->freq, pkex->exch_req_wait_time,
|
||||
broadcast,
|
||||
wpabuf_head(pkex->exchange_req),
|
||||
wpabuf_len(pkex->exchange_req));
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_dpp_pkex_tx_status(struct hostapd_data *hapd, const u8 *dst,
|
||||
const u8 *data, size_t data_len, int ok)
|
||||
{
|
||||
struct dpp_pkex *pkex = hapd->dpp_pkex;
|
||||
|
||||
if (pkex->failed) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Terminate PKEX exchange due to an earlier error");
|
||||
if (pkex->t > pkex->own_bi->pkex_t)
|
||||
pkex->own_bi->pkex_t = pkex->t;
|
||||
dpp_pkex_free(pkex);
|
||||
hapd->dpp_pkex = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (pkex->exch_req_wait_time && pkex->exchange_req) {
|
||||
/* Wait for PKEX Exchange Response frame and retry request if
|
||||
* no response is seen. */
|
||||
eloop_cancel_timeout(hostapd_dpp_pkex_retry_timeout, hapd,
|
||||
NULL);
|
||||
eloop_register_timeout(pkex->exch_req_wait_time / 1000,
|
||||
(pkex->exch_req_wait_time % 1000) * 1000,
|
||||
hostapd_dpp_pkex_retry_timeout, hapd,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void hostapd_dpp_tx_status(struct hostapd_data *hapd, const u8 *dst,
|
||||
const u8 *data, size_t data_len, int ok)
|
||||
{
|
||||
|
@ -227,6 +384,11 @@ void hostapd_dpp_tx_status(struct hostapd_data *hapd, const u8 *dst,
|
|||
" result=%s", MAC2STR(dst), ok ? "SUCCESS" : "FAILED");
|
||||
|
||||
if (!hapd->dpp_auth) {
|
||||
if (hapd->dpp_pkex) {
|
||||
hostapd_dpp_pkex_tx_status(hapd, dst, data, data_len,
|
||||
ok);
|
||||
return;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Ignore TX status since there is no ongoing authentication exchange");
|
||||
return;
|
||||
|
@ -1783,6 +1945,9 @@ hostapd_dpp_rx_pkex_exchange_resp(struct hostapd_data *hapd, const u8 *src,
|
|||
return;
|
||||
}
|
||||
|
||||
eloop_cancel_timeout(hostapd_dpp_pkex_retry_timeout, hapd, NULL);
|
||||
hapd->dpp_pkex->exch_req_wait_time = 0;
|
||||
|
||||
msg = dpp_pkex_rx_exchange_resp(hapd->dpp_pkex, src, buf, len);
|
||||
if (!msg) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
|
||||
|
@ -2172,26 +2337,14 @@ int hostapd_dpp_pkex_add(struct hostapd_data *hapd, const char *cmd)
|
|||
return -1;
|
||||
|
||||
if (os_strstr(cmd, " init=1") || os_strstr(cmd, " init=2")) {
|
||||
struct wpabuf *msg;
|
||||
#ifdef CONFIG_DPP3
|
||||
bool v2 = true;
|
||||
#else /* CONFIG_DPP3 */
|
||||
bool v2 = os_strstr(cmd, " init=2") != NULL;
|
||||
#endif /* CONFIG_DPP3 */
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
|
||||
dpp_pkex_free(hapd->dpp_pkex);
|
||||
hapd->dpp_pkex = dpp_pkex_init(hapd->msg_ctx, own_bi,
|
||||
hapd->own_addr,
|
||||
hapd->dpp_pkex_identifier,
|
||||
hapd->dpp_pkex_code, v2);
|
||||
if (!hapd->dpp_pkex)
|
||||
if (hostapd_dpp_pkex_init(hapd, v2) < 0)
|
||||
return -1;
|
||||
|
||||
msg = hapd->dpp_pkex->exchange_req;
|
||||
/* TODO: Which channel to use? */
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
|
||||
" freq=%u type=%d", MAC2STR(broadcast), 2437,
|
||||
v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
|
||||
DPP_PA_PKEX_V1_EXCHANGE_REQ);
|
||||
hostapd_drv_send_action(hapd, 2437, 0, broadcast,
|
||||
wpabuf_head(msg), wpabuf_len(msg));
|
||||
}
|
||||
|
||||
/* TODO: Support multiple PKEX info entries */
|
||||
|
@ -2319,6 +2472,7 @@ void hostapd_dpp_deinit(struct hostapd_data *hapd)
|
|||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
if (!hapd->dpp_init_done)
|
||||
return;
|
||||
eloop_cancel_timeout(hostapd_dpp_pkex_retry_timeout, hapd, NULL);
|
||||
eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
|
||||
eloop_cancel_timeout(hostapd_dpp_auth_conf_wait_timeout, hapd, NULL);
|
||||
eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
|
||||
|
|
Loading…
Add table
Reference in a new issue