diff options
Diffstat (limited to 'src/p2p/p2p_sd.c')
-rw-r--r-- | src/p2p/p2p_sd.c | 74 |
1 files changed, 47 insertions, 27 deletions
diff --git a/src/p2p/p2p_sd.c b/src/p2p/p2p_sd.c index 1a2af04b8004..a8bc5ba7f344 100644 --- a/src/p2p/p2p_sd.c +++ b/src/p2p/p2p_sd.c @@ -28,11 +28,11 @@ static int wfd_wsd_supported(struct wpabuf *wfd) pos = wpabuf_head(wfd); end = pos + wpabuf_len(wfd); - while (pos + 3 <= end) { + while (end - pos >= 3) { subelem = *pos++; len = WPA_GET_BE16(pos); pos += 2; - if (pos + len > end) + if (len > end - pos) break; if (subelem == WFD_SUBELEM_DEVICE_INFO && len >= 6) { @@ -288,6 +288,14 @@ int p2p_start_sd(struct p2p_data *p2p, struct p2p_device *dev) query = p2p_pending_sd_req(p2p, dev); if (query == NULL) return -1; + if (p2p->state == P2P_SEARCH && + os_memcmp(p2p->sd_query_no_ack, dev->info.p2p_device_addr, + ETH_ALEN) == 0) { + p2p_dbg(p2p, "Do not start Service Discovery with " MACSTR + " due to it being the first no-ACK peer in this search iteration", + MAC2STR(dev->info.p2p_device_addr)); + return -2; + } p2p_dbg(p2p, "Start Service Discovery with " MACSTR, MAC2STR(dev->info.p2p_device_addr)); @@ -355,11 +363,11 @@ void p2p_rx_gas_initial_req(struct p2p_data *p2p, const u8 *sa, pos++; slen = *pos++; - next = pos + slen; - if (next > end || slen < 2) { + if (slen > end - pos || slen < 2) { p2p_dbg(p2p, "Invalid IE in GAS Initial Request"); return; } + next = pos + slen; pos++; /* skip QueryRespLenLimit and PAME-BI */ if (*pos != ACCESS_NETWORK_QUERY_PROTOCOL) { @@ -370,16 +378,16 @@ void p2p_rx_gas_initial_req(struct p2p_data *p2p, const u8 *sa, pos = next; /* Query Request */ - if (pos + 2 > end) + if (end - pos < 2) return; slen = WPA_GET_LE16(pos); pos += 2; - if (pos + slen > end) + if (slen > end - pos) return; end = pos + slen; /* ANQP Query Request */ - if (pos + 4 > end) + if (end - pos < 4) return; if (WPA_GET_LE16(pos) != ANQP_VENDOR_SPECIFIC) { p2p_dbg(p2p, "Unsupported ANQP Info ID %u", WPA_GET_LE16(pos)); @@ -389,7 +397,7 @@ void p2p_rx_gas_initial_req(struct p2p_data *p2p, const u8 *sa, slen = WPA_GET_LE16(pos); pos += 2; - if (pos + slen > end || slen < 3 + 1) { + if (slen > end - pos || slen < 3 + 1) { p2p_dbg(p2p, "Invalid ANQP Query Request length"); return; } @@ -401,7 +409,7 @@ void p2p_rx_gas_initial_req(struct p2p_data *p2p, const u8 *sa, } pos += 4; - if (pos + 2 > end) + if (end - pos < 2) return; update_indic = WPA_GET_LE16(pos); p2p_dbg(p2p, "Service Update Indicator: %u", update_indic); @@ -417,9 +425,16 @@ void p2p_sd_response(struct p2p_data *p2p, int freq, const u8 *dst, u8 dialog_token, const struct wpabuf *resp_tlvs) { struct wpabuf *resp; + size_t max_len; + + /* + * In the 60 GHz, we have a smaller maximum frame length for management + * frames. + */ + max_len = (freq > 56160) ? 928 : 1400; /* TODO: fix the length limit to match with the maximum frame length */ - if (wpabuf_len(resp_tlvs) > 1400) { + if (wpabuf_len(resp_tlvs) > max_len) { p2p_dbg(p2p, "SD response long enough to require fragmentation"); if (p2p->sd_resp) { /* @@ -512,11 +527,11 @@ void p2p_rx_gas_initial_resp(struct p2p_data *p2p, const u8 *sa, pos++; slen = *pos++; - next = pos + slen; - if (next > end || slen < 2) { + if (slen > end - pos || slen < 2) { p2p_dbg(p2p, "Invalid IE in GAS Initial Response"); return; } + next = pos + slen; pos++; /* skip QueryRespLenLimit and PAME-BI */ if (*pos != ACCESS_NETWORK_QUERY_PROTOCOL) { @@ -527,14 +542,14 @@ void p2p_rx_gas_initial_resp(struct p2p_data *p2p, const u8 *sa, pos = next; /* Query Response */ - if (pos + 2 > end) { + if (end - pos < 2) { p2p_dbg(p2p, "Too short Query Response"); return; } slen = WPA_GET_LE16(pos); pos += 2; p2p_dbg(p2p, "Query Response Length: %d", slen); - if (pos + slen > end) { + if (slen > end - pos) { p2p_dbg(p2p, "Not enough Query Response data"); return; } @@ -552,7 +567,7 @@ void p2p_rx_gas_initial_resp(struct p2p_data *p2p, const u8 *sa, } /* ANQP Query Response */ - if (pos + 4 > end) + if (end - pos < 4) return; if (WPA_GET_LE16(pos) != ANQP_VENDOR_SPECIFIC) { p2p_dbg(p2p, "Unsupported ANQP Info ID %u", WPA_GET_LE16(pos)); @@ -562,7 +577,7 @@ void p2p_rx_gas_initial_resp(struct p2p_data *p2p, const u8 *sa, slen = WPA_GET_LE16(pos); pos += 2; - if (pos + slen > end || slen < 3 + 1) { + if (slen > end - pos || slen < 3 + 1) { p2p_dbg(p2p, "Invalid ANQP Query Response length"); return; } @@ -574,7 +589,7 @@ void p2p_rx_gas_initial_resp(struct p2p_data *p2p, const u8 *sa, } pos += 4; - if (pos + 2 > end) + if (end - pos < 2) return; update_indic = WPA_GET_LE16(pos); p2p_dbg(p2p, "Service Update Indicator: %u", update_indic); @@ -606,7 +621,7 @@ void p2p_rx_gas_comeback_req(struct p2p_data *p2p, const u8 *sa, { struct wpabuf *resp; u8 dialog_token; - size_t frag_len; + size_t frag_len, max_len; int more = 0; wpa_hexdump(MSG_DEBUG, "P2P: RX GAS Comeback Request", data, len); @@ -630,9 +645,14 @@ void p2p_rx_gas_comeback_req(struct p2p_data *p2p, const u8 *sa, return; } + /* + * In the 60 GHz, we have a smaller maximum frame length for management + * frames. + */ + max_len = (rx_freq > 56160) ? 928 : 1400; frag_len = wpabuf_len(p2p->sd_resp) - p2p->sd_resp_pos; - if (frag_len > 1400) { - frag_len = 1400; + if (frag_len > max_len) { + frag_len = max_len; more = 1; } resp = p2p_build_gas_comeback_resp(dialog_token, WLAN_STATUS_SUCCESS, @@ -727,11 +747,11 @@ void p2p_rx_gas_comeback_resp(struct p2p_data *p2p, const u8 *sa, pos++; slen = *pos++; - next = pos + slen; - if (next > end || slen < 2) { + if (slen > end - pos || slen < 2) { p2p_dbg(p2p, "Invalid IE in GAS Comeback Response"); return; } + next = pos + slen; pos++; /* skip QueryRespLenLimit and PAME-BI */ if (*pos != ACCESS_NETWORK_QUERY_PROTOCOL) { @@ -742,14 +762,14 @@ void p2p_rx_gas_comeback_resp(struct p2p_data *p2p, const u8 *sa, pos = next; /* Query Response */ - if (pos + 2 > end) { + if (end - pos < 2) { p2p_dbg(p2p, "Too short Query Response"); return; } slen = WPA_GET_LE16(pos); pos += 2; p2p_dbg(p2p, "Query Response Length: %d", slen); - if (pos + slen > end) { + if (slen > end - pos) { p2p_dbg(p2p, "Not enough Query Response data"); return; } @@ -768,7 +788,7 @@ void p2p_rx_gas_comeback_resp(struct p2p_data *p2p, const u8 *sa, } /* ANQP Query Response */ - if (pos + 4 > end) + if (end - pos < 4) return; if (WPA_GET_LE16(pos) != ANQP_VENDOR_SPECIFIC) { p2p_dbg(p2p, "Unsupported ANQP Info ID %u", WPA_GET_LE16(pos)); @@ -783,7 +803,7 @@ void p2p_rx_gas_comeback_resp(struct p2p_data *p2p, const u8 *sa, p2p_dbg(p2p, "Invalid ANQP Query Response length"); return; } - if (pos + 4 > end) + if (end - pos < 4) return; if (WPA_GET_BE32(pos) != P2P_IE_VENDOR_TYPE) { @@ -793,7 +813,7 @@ void p2p_rx_gas_comeback_resp(struct p2p_data *p2p, const u8 *sa, } pos += 4; - if (pos + 2 > end) + if (end - pos < 2) return; p2p->sd_rx_update_indic = WPA_GET_LE16(pos); p2p_dbg(p2p, "Service Update Indicator: %u", p2p->sd_rx_update_indic); |