GAS: Delay GAS query Tx while another query is in progress
It would be possible to issue another GAS query when a previous one is still in progress and this could result in conflicting offchannel operations. Prevent that by delaying GAS query initiation until the previous operation has been completed. Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
7255983b59
commit
24c694b465
3 changed files with 47 additions and 15 deletions
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Generic advertisement service (GAS) query
|
* Generic advertisement service (GAS) query
|
||||||
* Copyright (c) 2009, Atheros Communications
|
* Copyright (c) 2009, Atheros Communications
|
||||||
* Copyright (c) 2011, Qualcomm Atheros
|
* Copyright (c) 2011-2013, Qualcomm Atheros, Inc.
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
|
@ -21,6 +21,8 @@
|
||||||
|
|
||||||
/** GAS query timeout in seconds */
|
/** GAS query timeout in seconds */
|
||||||
#define GAS_QUERY_TIMEOUT_PERIOD 2
|
#define GAS_QUERY_TIMEOUT_PERIOD 2
|
||||||
|
/** Retry period for GAS query requests in milliseconds */
|
||||||
|
#define GAS_SERVICE_RETRY_PERIOD_MS 500
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,6 +37,7 @@ struct gas_query_pending {
|
||||||
unsigned int offchannel_tx_started:1;
|
unsigned int offchannel_tx_started:1;
|
||||||
int freq;
|
int freq;
|
||||||
u16 status_code;
|
u16 status_code;
|
||||||
|
struct wpabuf *req;
|
||||||
struct wpabuf *adv_proto;
|
struct wpabuf *adv_proto;
|
||||||
struct wpabuf *resp;
|
struct wpabuf *resp;
|
||||||
void (*cb)(void *ctx, const u8 *dst, u8 dialog_token,
|
void (*cb)(void *ctx, const u8 *dst, u8 dialog_token,
|
||||||
|
@ -50,11 +53,13 @@ struct gas_query_pending {
|
||||||
struct gas_query {
|
struct gas_query {
|
||||||
struct wpa_supplicant *wpa_s;
|
struct wpa_supplicant *wpa_s;
|
||||||
struct dl_list pending; /* struct gas_query_pending */
|
struct dl_list pending; /* struct gas_query_pending */
|
||||||
|
struct gas_query_pending *current;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void gas_query_tx_comeback_timeout(void *eloop_data, void *user_ctx);
|
static void gas_query_tx_comeback_timeout(void *eloop_data, void *user_ctx);
|
||||||
static void gas_query_timeout(void *eloop_data, void *user_ctx);
|
static void gas_query_timeout(void *eloop_data, void *user_ctx);
|
||||||
|
static void gas_service_timeout(void *eloop_data, void *user_ctx);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -81,13 +86,17 @@ static void gas_query_done(struct gas_query *gas,
|
||||||
struct gas_query_pending *query,
|
struct gas_query_pending *query,
|
||||||
enum gas_query_result result)
|
enum gas_query_result result)
|
||||||
{
|
{
|
||||||
|
if (gas->current == query)
|
||||||
|
gas->current = NULL;
|
||||||
if (query->offchannel_tx_started)
|
if (query->offchannel_tx_started)
|
||||||
offchannel_send_action_done(gas->wpa_s);
|
offchannel_send_action_done(gas->wpa_s);
|
||||||
eloop_cancel_timeout(gas_query_tx_comeback_timeout, gas, query);
|
eloop_cancel_timeout(gas_query_tx_comeback_timeout, gas, query);
|
||||||
eloop_cancel_timeout(gas_query_timeout, gas, query);
|
eloop_cancel_timeout(gas_query_timeout, gas, query);
|
||||||
|
eloop_cancel_timeout(gas_service_timeout, gas, query);
|
||||||
dl_list_del(&query->list);
|
dl_list_del(&query->list);
|
||||||
query->cb(query->ctx, query->addr, query->dialog_token, result,
|
query->cb(query->ctx, query->addr, query->dialog_token, result,
|
||||||
query->adv_proto, query->resp, query->status_code);
|
query->adv_proto, query->resp, query->status_code);
|
||||||
|
wpabuf_free(query->req);
|
||||||
wpabuf_free(query->adv_proto);
|
wpabuf_free(query->adv_proto);
|
||||||
wpabuf_free(query->resp);
|
wpabuf_free(query->resp);
|
||||||
os_free(query);
|
os_free(query);
|
||||||
|
@ -466,6 +475,35 @@ static void gas_query_timeout(void *eloop_data, void *user_ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void gas_service_timeout(void *eloop_data, void *user_ctx)
|
||||||
|
{
|
||||||
|
struct gas_query *gas = eloop_data;
|
||||||
|
struct gas_query_pending *query = user_ctx;
|
||||||
|
|
||||||
|
if (gas->current) {
|
||||||
|
wpa_printf(MSG_DEBUG, "GAS: Delaying GAS query Tx while another operation is in progress");
|
||||||
|
eloop_register_timeout(
|
||||||
|
GAS_SERVICE_RETRY_PERIOD_MS / 1000,
|
||||||
|
(GAS_SERVICE_RETRY_PERIOD_MS % 1000) * 1000,
|
||||||
|
gas_service_timeout, gas, query);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gas_query_tx(gas, query, query->req) < 0) {
|
||||||
|
wpa_printf(MSG_DEBUG, "GAS: Failed to send Action frame to "
|
||||||
|
MACSTR, MAC2STR(query->addr));
|
||||||
|
dl_list_del(&query->list);
|
||||||
|
wpabuf_free(query->req);
|
||||||
|
os_free(query);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gas->current = query;
|
||||||
|
|
||||||
|
eloop_register_timeout(GAS_QUERY_TIMEOUT_PERIOD, 0,
|
||||||
|
gas_query_timeout, gas, query);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int gas_query_dialog_token_available(struct gas_query *gas,
|
static int gas_query_dialog_token_available(struct gas_query *gas,
|
||||||
const u8 *dst, u8 dialog_token)
|
const u8 *dst, u8 dialog_token)
|
||||||
{
|
{
|
||||||
|
@ -485,7 +523,8 @@ static int gas_query_dialog_token_available(struct gas_query *gas,
|
||||||
* @gas: GAS query data from gas_query_init()
|
* @gas: GAS query data from gas_query_init()
|
||||||
* @dst: Destination MAC address for the query
|
* @dst: Destination MAC address for the query
|
||||||
* @freq: Frequency (in MHz) for the channel on which to send the query
|
* @freq: Frequency (in MHz) for the channel on which to send the query
|
||||||
* @req: GAS query payload
|
* @req: GAS query payload (to be freed by gas_query module in case of success
|
||||||
|
* return)
|
||||||
* @cb: Callback function for reporting GAS query result and response
|
* @cb: Callback function for reporting GAS query result and response
|
||||||
* @ctx: Context pointer to use with the @cb call
|
* @ctx: Context pointer to use with the @cb call
|
||||||
* Returns: dialog token (>= 0) on success or -1 on failure
|
* Returns: dialog token (>= 0) on success or -1 on failure
|
||||||
|
@ -524,22 +563,15 @@ int gas_query_req(struct gas_query *gas, const u8 *dst, int freq,
|
||||||
query->freq = freq;
|
query->freq = freq;
|
||||||
query->cb = cb;
|
query->cb = cb;
|
||||||
query->ctx = ctx;
|
query->ctx = ctx;
|
||||||
|
query->req = req;
|
||||||
dl_list_add(&gas->pending, &query->list);
|
dl_list_add(&gas->pending, &query->list);
|
||||||
|
|
||||||
*(wpabuf_mhead_u8(req) + 2) = dialog_token;
|
*(wpabuf_mhead_u8(req) + 2) = dialog_token;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "GAS: Starting request for " MACSTR
|
wpa_printf(MSG_DEBUG, "GAS: Starting request for " MACSTR
|
||||||
" dialog_token %u", MAC2STR(dst), dialog_token);
|
" dialog_token %u", MAC2STR(dst), dialog_token);
|
||||||
if (gas_query_tx(gas, query, req) < 0) {
|
|
||||||
wpa_printf(MSG_DEBUG, "GAS: Failed to send Action frame to "
|
|
||||||
MACSTR, MAC2STR(query->addr));
|
|
||||||
dl_list_del(&query->list);
|
|
||||||
os_free(query);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
eloop_register_timeout(GAS_QUERY_TIMEOUT_PERIOD, 0, gas_query_timeout,
|
eloop_register_timeout(0, 0, gas_service_timeout, gas, query);
|
||||||
gas, query);
|
|
||||||
|
|
||||||
return dialog_token;
|
return dialog_token;
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,12 +125,12 @@ int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes,
|
||||||
res = gas_query_req(wpa_s->gas, dst, freq, buf, anqp_resp_cb, wpa_s);
|
res = gas_query_req(wpa_s->gas, dst, freq, buf, anqp_resp_cb, wpa_s);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request");
|
wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request");
|
||||||
|
wpabuf_free(buf);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
} else
|
} else
|
||||||
wpa_printf(MSG_DEBUG, "ANQP: Query started with dialog token "
|
wpa_printf(MSG_DEBUG, "ANQP: Query started with dialog token "
|
||||||
"%u", res);
|
"%u", res);
|
||||||
|
|
||||||
wpabuf_free(buf);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -244,6 +244,7 @@ static int interworking_anqp_send_req(struct wpa_supplicant *wpa_s,
|
||||||
interworking_anqp_resp_cb, wpa_s);
|
interworking_anqp_resp_cb, wpa_s);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request");
|
wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request");
|
||||||
|
wpabuf_free(buf);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
eloop_register_timeout(0, 0, interworking_continue_anqp, wpa_s,
|
eloop_register_timeout(0, 0, interworking_continue_anqp, wpa_s,
|
||||||
NULL);
|
NULL);
|
||||||
|
@ -251,7 +252,6 @@ static int interworking_anqp_send_req(struct wpa_supplicant *wpa_s,
|
||||||
wpa_printf(MSG_DEBUG, "ANQP: Query started with dialog token "
|
wpa_printf(MSG_DEBUG, "ANQP: Query started with dialog token "
|
||||||
"%u", res);
|
"%u", res);
|
||||||
|
|
||||||
wpabuf_free(buf);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1877,12 +1877,12 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
|
||||||
res = gas_query_req(wpa_s->gas, dst, freq, buf, anqp_resp_cb, wpa_s);
|
res = gas_query_req(wpa_s->gas, dst, freq, buf, anqp_resp_cb, wpa_s);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request");
|
wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request");
|
||||||
|
wpabuf_free(buf);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
} else
|
} else
|
||||||
wpa_printf(MSG_DEBUG, "ANQP: Query started with dialog token "
|
wpa_printf(MSG_DEBUG, "ANQP: Query started with dialog token "
|
||||||
"%u", res);
|
"%u", res);
|
||||||
|
|
||||||
wpabuf_free(buf);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2177,11 +2177,11 @@ int gas_send_request(struct wpa_supplicant *wpa_s, const u8 *dst,
|
||||||
res = gas_query_req(wpa_s->gas, dst, freq, buf, gas_resp_cb, wpa_s);
|
res = gas_query_req(wpa_s->gas, dst, freq, buf, gas_resp_cb, wpa_s);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
wpa_printf(MSG_DEBUG, "GAS: Failed to send Query Request");
|
wpa_printf(MSG_DEBUG, "GAS: Failed to send Query Request");
|
||||||
|
wpabuf_free(buf);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
} else
|
} else
|
||||||
wpa_printf(MSG_DEBUG, "GAS: Query started with dialog token "
|
wpa_printf(MSG_DEBUG, "GAS: Query started with dialog token "
|
||||||
"%u", res);
|
"%u", res);
|
||||||
|
|
||||||
wpabuf_free(buf);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue