DPP2: Accept Config Result before GAS response TX status
The TX event for the next frame in the sequence might be received before the TX status for the final GAS response frame is processed. This used to result in the Config Result getting discarded and the negotiation not completing successfully on the Configurator side. Accept the Config Result message as an indication of the final GAS response frame having went through fine even if the TX status has not yet been processed to avoid this issue from a potential race condition on kernel events. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
6518c72b02
commit
976c3c161f
4 changed files with 36 additions and 4 deletions
|
@ -348,6 +348,7 @@ struct dpp_authentication {
|
|||
struct wpabuf *cacert;
|
||||
struct wpabuf *certbag;
|
||||
void *cert_resp_ctx;
|
||||
void *gas_server_ctx;
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
char *config_obj_override;
|
||||
char *discovery_override;
|
||||
|
|
|
@ -489,6 +489,21 @@ int gas_server_set_resp(struct gas_server *gas, void *resp_ctx,
|
|||
}
|
||||
|
||||
|
||||
bool gas_server_response_sent(struct gas_server *gas, void *resp_ctx)
|
||||
{
|
||||
struct gas_server_response *tmp;
|
||||
|
||||
dl_list_for_each(tmp, &gas->responses, struct gas_server_response,
|
||||
list) {
|
||||
if (tmp == resp_ctx)
|
||||
return tmp->resp &&
|
||||
tmp->offset == wpabuf_len(tmp->resp);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
struct gas_server * gas_server_init(void *ctx,
|
||||
void (*tx)(void *ctx, int freq,
|
||||
const u8 *da,
|
||||
|
|
|
@ -36,6 +36,7 @@ void gas_server_tx_status(struct gas_server *gas, const u8 *dst, const u8 *data,
|
|||
size_t data_len, int ack);
|
||||
int gas_server_set_resp(struct gas_server *gas, void *resp_ctx,
|
||||
struct wpabuf *resp);
|
||||
bool gas_server_response_sent(struct gas_server *gas, void *resp_ctx);
|
||||
|
||||
#else /* CONFIG_GAS_SERVER */
|
||||
|
||||
|
|
|
@ -1918,9 +1918,22 @@ static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src,
|
|||
MAC2STR(src));
|
||||
|
||||
if (!auth || !auth->waiting_conf_result) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: No DPP Configuration waiting for result - drop");
|
||||
return;
|
||||
if (auth &&
|
||||
os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) == 0 &&
|
||||
gas_server_response_sent(wpa_s->gas_server,
|
||||
auth->gas_server_ctx)) {
|
||||
/* This could happen if the TX status event gets delayed
|
||||
* long enough for the Enrollee to have time to send
|
||||
* the next frame before the TX status gets processed
|
||||
* locally. */
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: GAS response was sent but TX status not yet received - assume it was ACKed since the Enrollee sent the next frame in the sequence");
|
||||
auth->waiting_conf_result = 1;
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: No DPP Configuration waiting for result - drop");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
|
||||
|
@ -2969,6 +2982,7 @@ wpas_dpp_gas_req_handler(void *ctx, void *resp_ctx, const u8 *sa,
|
|||
if (!resp)
|
||||
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
|
||||
auth->conf_resp = resp;
|
||||
auth->gas_server_ctx = resp_ctx;
|
||||
return resp;
|
||||
}
|
||||
|
||||
|
@ -3006,7 +3020,8 @@ wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
|
|||
eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
|
||||
#ifdef CONFIG_DPP2
|
||||
if (ok && auth->peer_version >= 2 &&
|
||||
auth->conf_resp_status == DPP_STATUS_OK) {
|
||||
auth->conf_resp_status == DPP_STATUS_OK &&
|
||||
!auth->waiting_conf_result) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
|
||||
auth->waiting_conf_result = 1;
|
||||
auth->conf_resp = NULL;
|
||||
|
|
Loading…
Reference in a new issue