aboutsummaryrefslogtreecommitdiffstats
path: root/wpa_supplicant/dpp_supplicant.c
diff options
context:
space:
mode:
authorJouni Malinen <jouni@qca.qualcomm.com>2017-11-22 13:54:35 (GMT)
committerJouni Malinen <j@w1.fi>2017-11-22 13:54:35 (GMT)
commit00d2d13db2abb75582ed5184e68b0e9572980c64 (patch)
tree4b64b0fdae6d9e39454c5ea4e367de2ffb5f7fbb /wpa_supplicant/dpp_supplicant.c
parentcb6b22325fe41d4963f7d5c6a864f043fe28db4d (diff)
downloadhostap-00d2d13db2abb75582ed5184e68b0e9572980c64.zip
hostap-00d2d13db2abb75582ed5184e68b0e9572980c64.tar.gz
hostap-00d2d13db2abb75582ed5184e68b0e9572980c64.tar.bz2
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>
Diffstat (limited to 'wpa_supplicant/dpp_supplicant.c')
-rw-r--r--wpa_supplicant/dpp_supplicant.c82
1 files changed, 70 insertions, 12 deletions
diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c
index 41fbab8..7a7a821 100644
--- a/wpa_supplicant/dpp_supplicant.c
+++ b/wpa_supplicant/dpp_supplicant.c
@@ -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);