Updated to hostap_2_6
[mech_eap.git] / libeap / src / p2p / p2p_sd.c
index 1a2af04..a8bc5ba 100644 (file)
@@ -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);