Interworking: Keep up to two pending GAS_REQUEST responses

Previously, only the last response data was kept in memory. This
increases that to hold up to two last responses to allow some more
parallel operations to be requested. In addition, the response data is
now freed as soon as the external program has fetched it.

Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2014-01-06 07:53:37 +02:00
parent 090b8e3d14
commit b6a9590b34
4 changed files with 45 additions and 15 deletions

View file

@ -4849,9 +4849,8 @@ static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf,
int used;
char *pos;
size_t resp_len, start, requested_len;
if (!wpa_s->last_gas_resp)
return -1;
struct wpabuf *resp;
int ret;
used = hwaddr_aton2(cmd, addr);
if (used < 0)
@ -4862,11 +4861,18 @@ static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf,
pos++;
dialog_token = atoi(pos);
if (os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) != 0 ||
dialog_token != wpa_s->last_gas_dialog_token)
if (wpa_s->last_gas_resp &&
os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) == 0 &&
dialog_token == wpa_s->last_gas_dialog_token)
resp = wpa_s->last_gas_resp;
else if (wpa_s->prev_gas_resp &&
os_memcmp(addr, wpa_s->prev_gas_addr, ETH_ALEN) == 0 &&
dialog_token == wpa_s->prev_gas_dialog_token)
resp = wpa_s->prev_gas_resp;
else
return -1;
resp_len = wpabuf_len(wpa_s->last_gas_resp);
resp_len = wpabuf_len(resp);
start = 0;
requested_len = resp_len;
@ -4887,9 +4893,24 @@ static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf,
if (requested_len * 2 + 1 > buflen)
return os_snprintf(buf, buflen, "FAIL-Too long response");
return wpa_snprintf_hex(buf, buflen,
wpabuf_head_u8(wpa_s->last_gas_resp) + start,
ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(resp) + start,
requested_len);
if (start + requested_len == resp_len) {
/*
* Free memory by dropping the response after it has been
* fetched.
*/
if (resp == wpa_s->prev_gas_resp) {
wpabuf_free(wpa_s->prev_gas_resp);
wpa_s->prev_gas_resp = NULL;
} else {
wpabuf_free(wpa_s->last_gas_resp);
wpa_s->last_gas_resp = NULL;
}
}
return ret;
}
#endif /* CONFIG_INTERWORKING */

View file

@ -1,6 +1,7 @@
/*
* Interworking (IEEE 802.11u)
* Copyright (c) 2011-2013, Qualcomm Atheros, Inc.
* Copyright (c) 2011-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -2231,6 +2232,7 @@ static void gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
const struct wpabuf *resp, u16 status_code)
{
struct wpa_supplicant *wpa_s = ctx;
struct wpabuf *n;
wpa_msg(wpa_s, MSG_INFO, GAS_RESPONSE_INFO "addr=" MACSTR
" dialog_token=%d status_code=%d resp_len=%d",
@ -2239,10 +2241,14 @@ static void gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
if (!resp)
return;
wpabuf_free(wpa_s->last_gas_resp);
wpa_s->last_gas_resp = wpabuf_dup(resp);
if (wpa_s->last_gas_resp == NULL)
n = wpabuf_dup(resp);
if (n == NULL)
return;
wpabuf_free(wpa_s->prev_gas_resp);
wpa_s->prev_gas_resp = wpa_s->last_gas_resp;
os_memcpy(wpa_s->prev_gas_addr, wpa_s->last_gas_addr, ETH_ALEN);
wpa_s->prev_gas_dialog_token = wpa_s->last_gas_dialog_token;
wpa_s->last_gas_resp = n;
os_memcpy(wpa_s->last_gas_addr, addr, ETH_ALEN);
wpa_s->last_gas_dialog_token = dialog_token;
}

View file

@ -477,6 +477,9 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
wpa_s->ext_pw = NULL;
wpabuf_free(wpa_s->last_gas_resp);
wpa_s->last_gas_resp = NULL;
wpabuf_free(wpa_s->prev_gas_resp);
wpa_s->prev_gas_resp = NULL;
os_free(wpa_s->last_scan_res);
wpa_s->last_scan_res = NULL;

View file

@ -770,9 +770,9 @@ struct wpa_supplicant {
struct ext_password_data *ext_pw;
struct wpabuf *last_gas_resp;
u8 last_gas_addr[ETH_ALEN];
u8 last_gas_dialog_token;
struct wpabuf *last_gas_resp, *prev_gas_resp;
u8 last_gas_addr[ETH_ALEN], prev_gas_addr[ETH_ALEN];
u8 last_gas_dialog_token, prev_gas_dialog_token;
unsigned int no_keep_alive:1;