]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Interworking: Keep up to two pending GAS_REQUEST responses
authorJouni Malinen <j@w1.fi>
Mon, 6 Jan 2014 05:53:37 +0000 (07:53 +0200)
committerJouni Malinen <j@w1.fi>
Tue, 7 Jan 2014 08:45:12 +0000 (10:45 +0200)
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>

wpa_supplicant/ctrl_iface.c
wpa_supplicant/interworking.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index 155207a4e35b84180a28ac4865d835605ef80b52..32941aeddb63c5778213661ac1fde9070c95ded0 100644 (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,
-                               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 */
 
index 5e7fe5b27b38c23cb5dfeaddc591b8db0d2aa4fb..da8971d9bffd08b6dbdf7abfeada37f44b402ad6 100644 (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;
 }
index b722b1319c83b150098f23b6c8d60e1c2fd6197f..187e5d9bce4ec6553053a4b6ac28acb46ac80bec 100644 (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;
index 61d155af1804603c37534565179363118fec74bc..17e1ca04c5864bd740011331f5410c91aa27ba68 100644 (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;