|
@@ -2234,6 +2234,58 @@ struct wpabuf * p2p_build_probe_resp_ies(struct p2p_data *p2p,
|
|
|
return buf;
|
|
|
}
|
|
|
|
|
|
+static int p2p_build_probe_resp_buf(struct p2p_data *p2p, struct wpabuf *buf,
|
|
|
+ struct wpabuf *ies,
|
|
|
+ const u8 *addr, int rx_freq)
|
|
|
+{
|
|
|
+ struct ieee80211_mgmt *resp;
|
|
|
+ u8 channel, op_class;
|
|
|
+
|
|
|
+ resp = wpabuf_put(buf, offsetof(struct ieee80211_mgmt,
|
|
|
+ u.probe_resp.variable));
|
|
|
+
|
|
|
+ resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
|
|
|
+ (WLAN_FC_STYPE_PROBE_RESP << 4));
|
|
|
+ os_memcpy(resp->da, addr, ETH_ALEN);
|
|
|
+ os_memcpy(resp->sa, p2p->cfg->dev_addr, ETH_ALEN);
|
|
|
+ os_memcpy(resp->bssid, p2p->cfg->dev_addr, ETH_ALEN);
|
|
|
+ resp->u.probe_resp.beacon_int = host_to_le16(100);
|
|
|
+ /* hardware or low-level driver will setup seq_ctrl and timestamp */
|
|
|
+ resp->u.probe_resp.capab_info =
|
|
|
+ host_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE |
|
|
|
+ WLAN_CAPABILITY_PRIVACY |
|
|
|
+ WLAN_CAPABILITY_SHORT_SLOT_TIME);
|
|
|
+
|
|
|
+ wpabuf_put_u8(buf, WLAN_EID_SSID);
|
|
|
+ wpabuf_put_u8(buf, P2P_WILDCARD_SSID_LEN);
|
|
|
+ wpabuf_put_data(buf, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
|
|
|
+
|
|
|
+ wpabuf_put_u8(buf, WLAN_EID_SUPP_RATES);
|
|
|
+ wpabuf_put_u8(buf, 8);
|
|
|
+ wpabuf_put_u8(buf, (60 / 5) | 0x80);
|
|
|
+ wpabuf_put_u8(buf, 90 / 5);
|
|
|
+ wpabuf_put_u8(buf, (120 / 5) | 0x80);
|
|
|
+ wpabuf_put_u8(buf, 180 / 5);
|
|
|
+ wpabuf_put_u8(buf, (240 / 5) | 0x80);
|
|
|
+ wpabuf_put_u8(buf, 360 / 5);
|
|
|
+ wpabuf_put_u8(buf, 480 / 5);
|
|
|
+ wpabuf_put_u8(buf, 540 / 5);
|
|
|
+
|
|
|
+ if (!rx_freq) {
|
|
|
+ channel = p2p->cfg->channel;
|
|
|
+ } else if (p2p_freq_to_channel(rx_freq, &op_class, &channel)) {
|
|
|
+ p2p_err(p2p, "Failed to convert freq to channel");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ wpabuf_put_u8(buf, WLAN_EID_DS_PARAMS);
|
|
|
+ wpabuf_put_u8(buf, 1);
|
|
|
+ wpabuf_put_u8(buf, channel);
|
|
|
+
|
|
|
+ wpabuf_put_buf(buf, ies);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
|
|
|
static int p2p_service_find_asp(struct p2p_data *p2p, const u8 *hash)
|
|
|
{
|
|
@@ -2267,10 +2319,8 @@ p2p_reply_probe(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
|
|
|
{
|
|
|
struct ieee802_11_elems elems;
|
|
|
struct wpabuf *buf;
|
|
|
- struct ieee80211_mgmt *resp;
|
|
|
struct p2p_message msg;
|
|
|
struct wpabuf *ies;
|
|
|
- u8 channel, op_class;
|
|
|
|
|
|
if (ieee802_11_parse_elems((u8 *) ie, ie_len, &elems, 0) ==
|
|
|
ParseFailed) {
|
|
@@ -2414,49 +2464,12 @@ p2p_reply_probe(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
|
|
|
return P2P_PREQ_NOT_PROCESSED;
|
|
|
}
|
|
|
|
|
|
- resp = wpabuf_put(buf, offsetof(struct ieee80211_mgmt,
|
|
|
- u.probe_resp.variable));
|
|
|
-
|
|
|
- resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
|
|
|
- (WLAN_FC_STYPE_PROBE_RESP << 4));
|
|
|
- os_memcpy(resp->da, addr, ETH_ALEN);
|
|
|
- os_memcpy(resp->sa, p2p->cfg->dev_addr, ETH_ALEN);
|
|
|
- os_memcpy(resp->bssid, p2p->cfg->dev_addr, ETH_ALEN);
|
|
|
- resp->u.probe_resp.beacon_int = host_to_le16(100);
|
|
|
- /* hardware or low-level driver will setup seq_ctrl and timestamp */
|
|
|
- resp->u.probe_resp.capab_info =
|
|
|
- host_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE |
|
|
|
- WLAN_CAPABILITY_PRIVACY |
|
|
|
- WLAN_CAPABILITY_SHORT_SLOT_TIME);
|
|
|
-
|
|
|
- wpabuf_put_u8(buf, WLAN_EID_SSID);
|
|
|
- wpabuf_put_u8(buf, P2P_WILDCARD_SSID_LEN);
|
|
|
- wpabuf_put_data(buf, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
|
|
|
-
|
|
|
- wpabuf_put_u8(buf, WLAN_EID_SUPP_RATES);
|
|
|
- wpabuf_put_u8(buf, 8);
|
|
|
- wpabuf_put_u8(buf, (60 / 5) | 0x80);
|
|
|
- wpabuf_put_u8(buf, 90 / 5);
|
|
|
- wpabuf_put_u8(buf, (120 / 5) | 0x80);
|
|
|
- wpabuf_put_u8(buf, 180 / 5);
|
|
|
- wpabuf_put_u8(buf, (240 / 5) | 0x80);
|
|
|
- wpabuf_put_u8(buf, 360 / 5);
|
|
|
- wpabuf_put_u8(buf, 480 / 5);
|
|
|
- wpabuf_put_u8(buf, 540 / 5);
|
|
|
-
|
|
|
- if (!rx_freq) {
|
|
|
- channel = p2p->cfg->channel;
|
|
|
- } else if (p2p_freq_to_channel(rx_freq, &op_class, &channel)) {
|
|
|
+ if (p2p_build_probe_resp_buf(p2p, buf, ies, addr, rx_freq)) {
|
|
|
wpabuf_free(ies);
|
|
|
wpabuf_free(buf);
|
|
|
return P2P_PREQ_NOT_PROCESSED;
|
|
|
}
|
|
|
|
|
|
- wpabuf_put_u8(buf, WLAN_EID_DS_PARAMS);
|
|
|
- wpabuf_put_u8(buf, 1);
|
|
|
- wpabuf_put_u8(buf, channel);
|
|
|
-
|
|
|
- wpabuf_put_buf(buf, ies);
|
|
|
wpabuf_free(ies);
|
|
|
|
|
|
p2p->cfg->send_probe_resp(p2p->cfg->cb_ctx, buf, rx_freq);
|
|
@@ -2470,12 +2483,18 @@ p2p_reply_probe(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
|
|
|
enum p2p_probe_req_status
|
|
|
p2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
|
|
|
const u8 *bssid, const u8 *ie, size_t ie_len,
|
|
|
- unsigned int rx_freq)
|
|
|
+ unsigned int rx_freq, int p2p_lo_started)
|
|
|
{
|
|
|
enum p2p_probe_req_status res;
|
|
|
|
|
|
p2p_add_dev_from_probe_req(p2p, addr, ie, ie_len);
|
|
|
|
|
|
+ if (p2p_lo_started) {
|
|
|
+ p2p_dbg(p2p,
|
|
|
+ "Probe Response is offloaded, do not reply Probe Request");
|
|
|
+ return P2P_PREQ_PROCESSED;
|
|
|
+ }
|
|
|
+
|
|
|
res = p2p_reply_probe(p2p, addr, dst, bssid, ie, ie_len, rx_freq);
|
|
|
if (res != P2P_PREQ_PROCESSED && res != P2P_PREQ_NOT_PROCESSED)
|
|
|
return res;
|
|
@@ -5490,3 +5509,34 @@ void p2p_set_own_pref_freq_list(struct p2p_data *p2p,
|
|
|
i, p2p->pref_freq_list[i]);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+struct wpabuf * p2p_build_probe_resp_template(struct p2p_data *p2p,
|
|
|
+ unsigned int freq)
|
|
|
+{
|
|
|
+ struct wpabuf *ies, *buf;
|
|
|
+ u8 addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ies = p2p_build_probe_resp_ies(p2p, NULL, 0);
|
|
|
+ if (!ies) {
|
|
|
+ wpa_printf(MSG_ERROR,
|
|
|
+ "CTRL: Failed to build Probe Response IEs");
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ buf = wpabuf_alloc(200 + wpabuf_len(ies));
|
|
|
+ if (!buf) {
|
|
|
+ wpabuf_free(ies);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = p2p_build_probe_resp_buf(p2p, buf, ies, addr, freq);
|
|
|
+ wpabuf_free(ies);
|
|
|
+ if (ret) {
|
|
|
+ wpabuf_free(buf);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ return buf;
|
|
|
+}
|