From b6a9590b34af0766029085de9b51563dced383a8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 6 Jan 2014 07:53:37 +0200 Subject: [PATCH] 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 --- wpa_supplicant/ctrl_iface.c | 39 ++++++++++++++++++++++++------- wpa_supplicant/interworking.c | 12 +++++++--- wpa_supplicant/wpa_supplicant.c | 3 +++ wpa_supplicant/wpa_supplicant_i.h | 6 ++--- 4 files changed, 45 insertions(+), 15 deletions(-) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 155207a4e..32941aedd 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -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, - requested_len); + 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 */ diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c index 5e7fe5b27..da8971d9b 100644 --- a/wpa_supplicant/interworking.c +++ b/wpa_supplicant/interworking.c @@ -1,6 +1,7 @@ /* * Interworking (IEEE 802.11u) * Copyright (c) 2011-2013, Qualcomm Atheros, Inc. + * Copyright (c) 2011-2014, Jouni Malinen * * 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; } diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index b722b1319..187e5d9bc 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -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; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 61d155af1..17e1ca04c 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -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;