diff options
Diffstat (limited to 'wpa_supplicant/gas_query.c')
-rw-r--r-- | wpa_supplicant/gas_query.c | 56 |
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; } |