DPP: Retry PKEX Exchange Request frame up to five times
Retransmit the PKEX Exchange Request frame if no response from a peer is received. This makes the exchange more robust since this frame is sent to a broadcast address and has no link layer retries. Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
cb6b22325f
commit
00d2d13db2
2 changed files with 73 additions and 12 deletions
|
@ -131,6 +131,9 @@ struct dpp_pkex {
|
|||
struct wpabuf *exchange_req;
|
||||
struct wpabuf *exchange_resp;
|
||||
unsigned int t; /* number of failures on code use */
|
||||
unsigned int exch_req_wait_time;
|
||||
unsigned int exch_req_tries;
|
||||
unsigned int freq;
|
||||
};
|
||||
|
||||
struct dpp_configuration {
|
||||
|
|
|
@ -37,6 +37,12 @@ static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
|
|||
enum offchannel_send_action_result result);
|
||||
static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx);
|
||||
static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s);
|
||||
static void
|
||||
wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
|
||||
unsigned int freq, const u8 *dst,
|
||||
const u8 *src, const u8 *bssid,
|
||||
const u8 *data, size_t data_len,
|
||||
enum offchannel_send_action_result result);
|
||||
|
||||
static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
|
@ -1554,6 +1560,35 @@ fail:
|
|||
}
|
||||
|
||||
|
||||
static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = eloop_ctx;
|
||||
struct dpp_pkex *pkex = wpa_s->dpp_pkex;
|
||||
|
||||
if (!pkex || !pkex->exchange_req)
|
||||
return;
|
||||
if (pkex->exch_req_tries >= 5) {
|
||||
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
|
||||
"No response from PKEX peer");
|
||||
dpp_pkex_free(pkex);
|
||||
wpa_s->dpp_pkex = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
pkex->exch_req_tries++;
|
||||
wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
|
||||
pkex->exch_req_tries);
|
||||
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
|
||||
MAC2STR(broadcast), pkex->freq, DPP_PA_PKEX_EXCHANGE_REQ);
|
||||
offchannel_send_action(wpa_s, pkex->freq, broadcast,
|
||||
wpa_s->own_addr, broadcast,
|
||||
wpabuf_head(pkex->exchange_req),
|
||||
wpabuf_len(pkex->exchange_req),
|
||||
pkex->exch_req_wait_time,
|
||||
wpas_dpp_tx_pkex_status, 0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
|
||||
unsigned int freq, const u8 *dst,
|
||||
|
@ -1562,6 +1597,7 @@ wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
|
|||
enum offchannel_send_action_result result)
|
||||
{
|
||||
const char *res_txt;
|
||||
struct dpp_pkex *pkex = wpa_s->dpp_pkex;
|
||||
|
||||
res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
|
||||
(result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
|
||||
|
@ -1571,21 +1607,31 @@ wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
|
|||
freq, MAC2STR(dst), res_txt);
|
||||
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
|
||||
" freq=%u result=%s", MAC2STR(dst), freq, res_txt);
|
||||
/* TODO: Time out wait for response more quickly in error cases? */
|
||||
|
||||
if (!wpa_s->dpp_pkex) {
|
||||
if (!pkex) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Ignore TX status since there is no ongoing PKEX exchange");
|
||||
return;
|
||||
}
|
||||
|
||||
if (wpa_s->dpp_pkex->failed) {
|
||||
if (pkex->failed) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Terminate PKEX exchange due to an earlier error");
|
||||
if (wpa_s->dpp_pkex->t > wpa_s->dpp_pkex->own_bi->pkex_t)
|
||||
wpa_s->dpp_pkex->own_bi->pkex_t = wpa_s->dpp_pkex->t;
|
||||
dpp_pkex_free(wpa_s->dpp_pkex);
|
||||
if (pkex->t > pkex->own_bi->pkex_t)
|
||||
pkex->own_bi->pkex_t = pkex->t;
|
||||
dpp_pkex_free(pkex);
|
||||
wpa_s->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(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
|
||||
eloop_register_timeout(pkex->exch_req_wait_time / 1000,
|
||||
(pkex->exch_req_wait_time % 1000) * 1000,
|
||||
wpas_dpp_pkex_retry_timeout, wpa_s,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1659,6 +1705,9 @@ wpas_dpp_rx_pkex_exchange_resp(struct wpa_supplicant *wpa_s, const u8 *src,
|
|||
return;
|
||||
}
|
||||
|
||||
eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
|
||||
wpa_s->dpp_pkex->exch_req_wait_time = 0;
|
||||
|
||||
os_memcpy(wpa_s->dpp_pkex->peer_mac, src, ETH_ALEN);
|
||||
msg = dpp_pkex_rx_exchange_resp(wpa_s->dpp_pkex, buf, len);
|
||||
if (!msg) {
|
||||
|
@ -2226,6 +2275,7 @@ int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
|
|||
return -1;
|
||||
|
||||
if (os_strstr(cmd, " init=1")) {
|
||||
struct dpp_pkex *pkex;
|
||||
struct wpabuf *msg;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
|
||||
|
@ -2233,21 +2283,28 @@ int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
|
|||
wpa_s->dpp_pkex = dpp_pkex_init(wpa_s, own_bi, wpa_s->own_addr,
|
||||
wpa_s->dpp_pkex_identifier,
|
||||
wpa_s->dpp_pkex_code);
|
||||
if (!wpa_s->dpp_pkex)
|
||||
pkex = wpa_s->dpp_pkex;
|
||||
if (!pkex)
|
||||
return -1;
|
||||
|
||||
msg = wpa_s->dpp_pkex->exchange_req;
|
||||
msg = pkex->exchange_req;
|
||||
wait_time = wpa_s->max_remain_on_chan;
|
||||
if (wait_time > 2000)
|
||||
wait_time = 2000;
|
||||
/* TODO: Which channel to use? */
|
||||
/* TODO: Support for 5 GHz channels */
|
||||
pkex->freq = 2437;
|
||||
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
|
||||
" freq=%u type=%d",
|
||||
MAC2STR(broadcast), 2437, DPP_PA_PKEX_EXCHANGE_REQ);
|
||||
offchannel_send_action(wpa_s, 2437, broadcast, wpa_s->own_addr,
|
||||
broadcast,
|
||||
MAC2STR(broadcast), pkex->freq,
|
||||
DPP_PA_PKEX_EXCHANGE_REQ);
|
||||
offchannel_send_action(wpa_s, pkex->freq, broadcast,
|
||||
wpa_s->own_addr, broadcast,
|
||||
wpabuf_head(msg), wpabuf_len(msg),
|
||||
wait_time, wpas_dpp_tx_pkex_status, 0);
|
||||
if (wait_time == 0)
|
||||
wait_time = 2000;
|
||||
pkex->exch_req_wait_time = wait_time;
|
||||
pkex->exch_req_tries = 1;
|
||||
}
|
||||
|
||||
/* TODO: Support multiple PKEX info entries */
|
||||
|
@ -2330,6 +2387,7 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
|
|||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
if (!wpa_s->dpp_init_done)
|
||||
return;
|
||||
eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
|
||||
eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
|
||||
eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
|
||||
eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
|
||||
|
|
Loading…
Reference in a new issue