aboutsummaryrefslogtreecommitdiff
path: root/wpa_supplicant/gas_query.c
diff options
context:
space:
mode:
Diffstat (limited to 'wpa_supplicant/gas_query.c')
-rw-r--r--wpa_supplicant/gas_query.c56
1 files changed, 36 insertions, 20 deletions
diff --git a/wpa_supplicant/gas_query.c b/wpa_supplicant/gas_query.c
index a6172d69233b..7d2993179660 100644
--- a/wpa_supplicant/gas_query.c
+++ b/wpa_supplicant/gas_query.c
@@ -30,6 +30,8 @@
#define GAS_QUERY_WAIT_TIME_INITIAL 1000
#define GAS_QUERY_WAIT_TIME_COMEBACK 150
+#define GAS_QUERY_MAX_COMEBACK_DELAY 60000
+
/**
* struct gas_query_pending - Pending GAS query
*/
@@ -197,10 +199,16 @@ static struct gas_query_pending *
gas_query_get_pending(struct gas_query *gas, const u8 *addr, u8 dialog_token)
{
struct gas_query_pending *q;
+ struct wpa_supplicant *wpa_s = gas->wpa_s;
+
dl_list_for_each(q, &gas->pending, struct gas_query_pending, list) {
- if (os_memcmp(q->addr, addr, ETH_ALEN) == 0 &&
+ if (ether_addr_equal(q->addr, addr) &&
q->dialog_token == dialog_token)
return q;
+ if (wpa_s->valid_links &&
+ ether_addr_equal(wpa_s->ap_mld_addr, addr) &&
+ wpas_ap_link_address(wpa_s, q->addr))
+ return q;
}
return NULL;
}
@@ -241,7 +249,7 @@ static void gas_query_tx_status(struct wpa_supplicant *wpa_s,
wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
" result=%d query=%p dialog_token=%u dur=%d ms",
freq, MAC2STR(dst), result, query, query->dialog_token, dur);
- if (os_memcmp(dst, query->addr, ETH_ALEN) != 0) {
+ if (!ether_addr_equal(dst, query->addr)) {
wpa_printf(MSG_DEBUG, "GAS: TX status for unexpected destination");
return;
}
@@ -298,7 +306,7 @@ static int gas_query_tx(struct gas_query *gas, struct gas_query_pending *query,
(!gas->wpa_s->conf->gas_address3 ||
(gas->wpa_s->current_ssid &&
gas->wpa_s->wpa_state >= WPA_ASSOCIATED &&
- os_memcmp(query->addr, gas->wpa_s->bssid, ETH_ALEN) == 0)))
+ ether_addr_equal(query->addr, gas->wpa_s->bssid))))
bssid = query->addr;
else
bssid = wildcard_bssid;
@@ -402,14 +410,14 @@ static void gas_query_tx_comeback_req_delay(struct gas_query *gas,
static void gas_query_rx_initial(struct gas_query *gas,
struct gas_query_pending *query,
- const u8 *adv_proto, const u8 *resp,
- size_t len, u16 comeback_delay)
+ const u8 *adv_proto, size_t adv_proto_len,
+ const u8 *resp, size_t len, u16 comeback_delay)
{
wpa_printf(MSG_DEBUG, "GAS: Received initial response from "
MACSTR " (dialog_token=%u comeback_delay=%u)",
MAC2STR(query->addr), query->dialog_token, comeback_delay);
- query->adv_proto = wpabuf_alloc_copy(adv_proto, 2 + adv_proto[1]);
+ query->adv_proto = wpabuf_alloc_copy(adv_proto, adv_proto_len);
if (query->adv_proto == NULL) {
gas_query_done(gas, query, GAS_QUERY_INTERNAL_ERROR);
return;
@@ -434,9 +442,9 @@ static void gas_query_rx_initial(struct gas_query *gas,
static void gas_query_rx_comeback(struct gas_query *gas,
struct gas_query_pending *query,
- const u8 *adv_proto, const u8 *resp,
- size_t len, u8 frag_id, u8 more_frags,
- u16 comeback_delay)
+ const u8 *adv_proto, size_t adv_proto_len,
+ const u8 *resp, size_t len, u8 frag_id,
+ u8 more_frags, u16 comeback_delay)
{
wpa_printf(MSG_DEBUG, "GAS: Received comeback response from "
MACSTR " (dialog_token=%u frag_id=%u more_frags=%u "
@@ -445,7 +453,7 @@ static void gas_query_rx_comeback(struct gas_query *gas,
more_frags, comeback_delay);
eloop_cancel_timeout(gas_query_rx_comeback_timeout, gas, query);
- if ((size_t) 2 + adv_proto[1] != wpabuf_len(query->adv_proto) ||
+ if (adv_proto_len != wpabuf_len(query->adv_proto) ||
os_memcmp(adv_proto, wpabuf_head(query->adv_proto),
wpabuf_len(query->adv_proto)) != 0) {
wpa_printf(MSG_DEBUG, "GAS: Advertisement Protocol changed "
@@ -514,6 +522,7 @@ int gas_query_rx(struct gas_query *gas, const u8 *da, const u8 *sa,
u8 action, dialog_token, frag_id = 0, more_frags = 0;
u16 comeback_delay, resp_len;
const u8 *pos, *adv_proto;
+ size_t adv_proto_len;
int prot, pmf;
unsigned int left;
@@ -589,25 +598,31 @@ int gas_query_rx(struct gas_query *gas, const u8 *da, const u8 *sa,
if (pos + 2 > data + len)
return 0;
comeback_delay = WPA_GET_LE16(pos);
+ if (comeback_delay > GAS_QUERY_MAX_COMEBACK_DELAY)
+ comeback_delay = GAS_QUERY_MAX_COMEBACK_DELAY;
pos += 2;
/* Advertisement Protocol element */
- if (pos + 2 > data + len || pos + 2 + pos[1] > data + len) {
+ adv_proto = pos;
+ left = data + len - adv_proto;
+ if (left < 2 || adv_proto[1] > left - 2) {
wpa_printf(MSG_DEBUG, "GAS: No room for Advertisement "
"Protocol element in the response from " MACSTR,
MAC2STR(sa));
return 0;
}
- if (*pos != WLAN_EID_ADV_PROTO) {
+ if (*adv_proto != WLAN_EID_ADV_PROTO) {
wpa_printf(MSG_DEBUG, "GAS: Unexpected Advertisement "
"Protocol element ID %u in response from " MACSTR,
- *pos, MAC2STR(sa));
+ *adv_proto, MAC2STR(sa));
return 0;
}
+ adv_proto_len = 2 + adv_proto[1];
+ if (adv_proto_len > (size_t) (data + len - pos))
+ return 0; /* unreachable due to an earlier check */
- adv_proto = pos;
- pos += 2 + pos[1];
+ pos += adv_proto_len;
/* Query Response Length */
if (pos + 2 > data + len) {
@@ -631,11 +646,12 @@ int gas_query_rx(struct gas_query *gas, const u8 *da, const u8 *sa,
}
if (action == WLAN_PA_GAS_COMEBACK_RESP)
- gas_query_rx_comeback(gas, query, adv_proto, pos, resp_len,
- frag_id, more_frags, comeback_delay);
+ gas_query_rx_comeback(gas, query, adv_proto, adv_proto_len,
+ pos, resp_len, frag_id, more_frags,
+ comeback_delay);
else
- gas_query_rx_initial(gas, query, adv_proto, pos, resp_len,
- comeback_delay);
+ gas_query_rx_initial(gas, query, adv_proto, adv_proto_len,
+ pos, resp_len, comeback_delay);
return 0;
}
@@ -658,7 +674,7 @@ static int gas_query_dialog_token_available(struct gas_query *gas,
{
struct gas_query_pending *q;
dl_list_for_each(q, &gas->pending, struct gas_query_pending, list) {
- if (os_memcmp(dst, q->addr, ETH_ALEN) == 0 &&
+ if (ether_addr_equal(dst, q->addr) &&
dialog_token == q->dialog_token)
return 0;
}