Cumulative patch from commit 2c0efd9e49b15da163cee659409eee85390620c3
2c0efd9 P2P: Fix stopping on search after SD callback
db3168d OpenSSL: Use SSL_cache_hit() when available
68ae477 OpenSSL: Use library wrapper functions to access cert store
abe96d0 P2P: Clean up Listen channel optimization debug prints
d2ca6ba Fix hostapd obss_interval documentation
d027c7b Fix 20/40 MHz co-ex report processing with obss_interval=0
93eca61 P2PS: Do not remove pending interface on p2p_stop_find
ae2dd83 P2PS: Allow PD retry in SEARCH and LISTEN_ONLY also
87d5ef5 P2PS: Add commands to control interface redir list
0cf12b3 P2PS: Send P2P_FIND_STOPPED event during P2P SD also
306aaf4 P2PS: Start WPS registrar upon GO formation
9e96e46 P2PS: PD Response processing
ab8ee77 P2PS: Provision Discovery fail event
1300cc8 P2PS: PD Request processing and PD Response building
5fefce2 P2PS: Callback to send P2PS provisioning events
9a58e52 P2PS: Callback to create pending group after sending PD Response
895d94d P2PS: Callback to remove stale persistent groups
f309c18 P2PS: ASP provisioning commands to control interface
6d90851 P2PS: Process P2PS provisioning commands
369678a P2PS: Add P2PS attributes into PD Request if requested
59fec34 P2PS: Allow p2p_build_ssid() to use pre-set SSID
d4b43b5 P2PS: Add support to send ASP-RESP events
6df08d0 P2PS: Logic to parse GAS requests for ASP services
5a4102c P2PS: Add support to send ASP service requests
095b3c4 P2PS: Add Application Service Info to device found events
4660e73 P2PS: Add Advertised Service Info into Probe Response frames
9e7321e P2PS: Parse Probe Request frames for matching ASP hashes
ae9d45f P2PS: Extend add/del services logic to support ASP
ea8e033 P2P: Allow p2p_get_group_num_members() to be called with NULL
4f88fc0 P2PS: WPS changes needed for P2PS default PIN
1a94b0a P2PS: Add service hash to Probe Request frames
5177509 P2PS: Add option to specify seek strings into P2P_FIND
5f18501 P2PS: Helper functions to build new P2P attributes
60d1148 P2PS: Add parsing of new P2P attributes
b9348be P2PS: Add new P2P identifier assignments from P2P spec v1.5
c3d6c71 Add helper functions for escaping and unescaping UTF-8
66eaf8a Fix driver-offloaded offchannel TX done processing
c5e154c P2P: Add P2P state into p2p_send_action_cb() debug entry
f2dc06e P2P: Ignore remain-on-channel callback event if not waiting for one
6a6569b HS 2.0R2: Add password to DB in case of machine managed subscription
f0d0a5d Improve BSS selection with default noise floor values
7f7bfba Add an option allow canned EAP-Success for wired IEEE 802.1X
49fcc32 EAP-MSCHAPv2 peer: Add option to disable password retry query
66bc683 hostapd: Simplify vlan_add_dynamic error paths
99805a0 Interworking: Convert wpa_printf() to wpa_msg()
b42f539 Add a variable to handle extra CFLAGS values
e6dd819 Work around Linux packet socket regression
7650f9e Fix resource leaks on rsn_preauth_init() error paths
a565e03 dhcp_snoop: Make IPv4 addresses human readable in debug log
2dd4f3a Fix STA re-bind to another VLAN on reauthentication
4437f8f Free old eap_user_file data on configuration change
1180dd6 WPA auth: Disconnect STA if MSK cannot be fetched
40aaa64 WPA auth: Clear temporary MSK storage from stack explicitly
01b481a Convert couple of remaining printf to wpa_printf in ap_list
bfaefd5 EAP-PEAP server: Fix Phase 2 TLV length in error case
745d936 mesh: Create new station entry on popen frames
41bff86 mesh: Always free the station if peering failed
871ff0b mesh: Sync plink state with kernel
ba42261 Simplify eapol_sm_notify_pmkid_attempt()
993a865 Add eap_session_id to wpa_supplicant STATUS output
f19c907 OpenSSL: Implement aes_wrap() and aes_unwrap()
fee31f7 OpenSSL: Remove support for versions older than 0.9.8
8bf3030 OpenSSL: Use a common helper function for HMAC
983c6a6 OpenSSL: Replace internal HMAC-MD5 implementation
Change-Id: I5743003f14efae324537f7dc2c5e6ada892a33a7
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index f3e31a8..602aa36 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -13,6 +13,8 @@
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "common/wpa_ctrl.h"
+#include "crypto/sha256.h"
+#include "crypto/crypto.h"
#include "wps/wps_i.h"
#include "p2p_i.h"
#include "p2p.h"
@@ -151,6 +153,19 @@
}
+struct p2ps_advertisement * p2p_get_p2ps_adv_list(struct p2p_data *p2p)
+{
+ return p2p ? p2p->p2ps_adv_list : NULL;
+}
+
+
+void p2p_set_intended_addr(struct p2p_data *p2p, const u8 *intended_addr)
+{
+ if (p2p && intended_addr)
+ os_memcpy(p2p->intended_addr, intended_addr, ETH_ALEN);
+}
+
+
u16 p2p_get_provisioning_info(struct p2p_data *p2p, const u8 *addr)
{
struct p2p_device *dev = NULL;
@@ -770,6 +785,12 @@
dev->oper_ssid_len = msg.ssid[1];
}
+ if (msg.adv_service_instance && msg.adv_service_instance_len) {
+ wpabuf_free(dev->info.p2ps_instance);
+ dev->info.p2ps_instance = wpabuf_alloc_copy(
+ msg.adv_service_instance, msg.adv_service_instance_len);
+ }
+
if (freq >= 2412 && freq <= 2484 && msg.ds_params &&
*msg.ds_params >= 1 && *msg.ds_params <= 14) {
int ds_freq;
@@ -829,7 +850,9 @@
p2p_update_peer_vendor_elems(dev, ies, ies_len);
- if (dev->flags & P2P_DEV_REPORTED && !wfd_changed)
+ if (dev->flags & P2P_DEV_REPORTED && !wfd_changed &&
+ (!msg.adv_service_instance ||
+ (dev->flags & P2P_DEV_P2PS_REPORTED)))
return 0;
p2p_dbg(p2p, "Peer found with Listen frequency %d MHz (rx_time=%u.%06u)",
@@ -865,6 +888,9 @@
!(dev->flags & P2P_DEV_REPORTED_ONCE));
dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
+ if (msg.adv_service_instance)
+ dev->flags |= P2P_DEV_P2PS_REPORTED;
+
return 0;
}
@@ -899,6 +925,7 @@
wpabuf_free(dev->info.wfd_subelems);
wpabuf_free(dev->info.vendor_elems);
wpabuf_free(dev->go_neg_conf);
+ wpabuf_free(dev->info.p2ps_instance);
os_free(dev);
}
@@ -1083,10 +1110,44 @@
}
+static int p2ps_gen_hash(struct p2p_data *p2p, const char *str, u8 *hash)
+{
+ u8 buf[SHA256_MAC_LEN];
+ char str_buf[256];
+ const u8 *adv_array;
+ size_t i, adv_len;
+
+ if (!str || !hash)
+ return 0;
+
+ if (!str[0]) {
+ os_memcpy(hash, p2p->wild_card_hash, P2PS_HASH_LEN);
+ return 1;
+ }
+
+ adv_array = (u8 *) str_buf;
+ adv_len = os_strlen(str);
+
+ for (i = 0; str[i] && i < adv_len; i++) {
+ if (str[i] >= 'A' && str[i] <= 'Z')
+ str_buf[i] = str[i] - 'A' + 'a';
+ else
+ str_buf[i] = str[i];
+ }
+
+ if (sha256_vector(1, &adv_array, &adv_len, buf))
+ return 0;
+
+ os_memcpy(hash, buf, P2PS_HASH_LEN);
+ return 1;
+}
+
+
int p2p_find(struct p2p_data *p2p, unsigned int timeout,
enum p2p_discovery_type type,
unsigned int num_req_dev_types, const u8 *req_dev_types,
- const u8 *dev_id, unsigned int search_delay)
+ const u8 *dev_id, unsigned int search_delay,
+ u8 seek_count, const char **seek)
{
int res;
@@ -1113,6 +1174,47 @@
} else
p2p->find_dev_id = NULL;
+ if (seek_count == 0 || !seek) {
+ /* Not an ASP search */
+ p2p->p2ps_seek = 0;
+ } else if (seek_count == 1 && seek && (!seek[0] || !seek[0][0])) {
+ /*
+ * An empty seek string means no hash values, but still an ASP
+ * search.
+ */
+ p2p->p2ps_seek_count = 0;
+ p2p->p2ps_seek = 1;
+ } else if (seek && seek_count <= P2P_MAX_QUERY_HASH) {
+ u8 buf[P2PS_HASH_LEN];
+ int i;
+
+ p2p->p2ps_seek_count = seek_count;
+ for (i = 0; i < seek_count; i++) {
+ if (!p2ps_gen_hash(p2p, seek[i], buf))
+ continue;
+
+ /* If asking for wildcard, don't do others */
+ if (os_memcmp(buf, p2p->wild_card_hash,
+ P2PS_HASH_LEN) == 0) {
+ p2p->p2ps_seek_count = 0;
+ break;
+ }
+
+ os_memcpy(&p2p->query_hash[i * P2PS_HASH_LEN], buf,
+ P2PS_HASH_LEN);
+ }
+ p2p->p2ps_seek = 1;
+ } else {
+ p2p->p2ps_seek_count = 0;
+ p2p->p2ps_seek = 1;
+ }
+
+ /* Special case to perform wildcard search */
+ if (p2p->p2ps_seek_count == 0 && p2p->p2ps_seek) {
+ p2p->p2ps_seek_count = 1;
+ os_memcpy(&p2p->query_hash, p2p->wild_card_hash, P2PS_HASH_LEN);
+ }
+
p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
p2p_clear_timeout(p2p);
p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
@@ -1163,8 +1265,11 @@
p2p_dbg(p2p, "Stopping find");
eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
p2p_clear_timeout(p2p);
- if (p2p->state == P2P_SEARCH)
+ if (p2p->state == P2P_SEARCH || p2p->state == P2P_SD_DURING_FIND)
p2p->cfg->find_stopped(p2p->cfg->cb_ctx);
+
+ p2p->p2ps_seek_count = 0;
+
p2p_set_state(p2p, P2P_IDLE);
p2p_free_req_dev_types(p2p);
p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
@@ -1637,7 +1742,14 @@
int p2p_go_params(struct p2p_data *p2p, struct p2p_go_neg_results *params)
{
- p2p_build_ssid(p2p, params->ssid, ¶ms->ssid_len);
+ if (p2p->ssid_set) {
+ os_memcpy(params->ssid, p2p->ssid, p2p->ssid_len);
+ params->ssid_len = p2p->ssid_len;
+ } else {
+ p2p_build_ssid(p2p, params->ssid, ¶ms->ssid_len);
+ }
+ p2p->ssid_set = 0;
+
p2p_random(params->passphrase, p2p->cfg->passphrase_len);
return 0;
}
@@ -2036,6 +2148,9 @@
if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_PROBE_RESP_P2P])
extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_PROBE_RESP_P2P]);
+ if (p2p->query_count)
+ extra += MAX_SVC_ADV_IE_LEN;
+
buf = wpabuf_alloc(1000 + extra);
if (buf == NULL)
return NULL;
@@ -2070,10 +2185,38 @@
p2p_buf_add_device_info(buf, p2p, NULL);
p2p_buf_update_ie_hdr(buf, len);
+ if (p2p->query_count) {
+ p2p_buf_add_service_instance(buf, p2p, p2p->query_count,
+ p2p->query_hash,
+ p2p->p2ps_adv_list);
+ }
+
return buf;
}
+static int p2p_service_find_asp(struct p2p_data *p2p, const u8 *hash)
+{
+ struct p2ps_advertisement *adv_data;
+
+ p2p_dbg(p2p, "ASP find - ASP list: %p", p2p->p2ps_adv_list);
+
+ /* Wildcard always matches if we have actual services */
+ if (os_memcmp(hash, p2p->wild_card_hash, P2PS_HASH_LEN) == 0)
+ return p2p->p2ps_adv_list != NULL;
+
+ adv_data = p2p->p2ps_adv_list;
+ while (adv_data) {
+ p2p_dbg(p2p, "ASP hash: %x =? %x", hash[0], adv_data->hash[0]);
+ if (os_memcmp(hash, adv_data->hash, P2PS_HASH_LEN) == 0)
+ return 1;
+ adv_data = adv_data->next;
+ }
+
+ return 0;
+}
+
+
static enum p2p_probe_req_status
p2p_reply_probe(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
const u8 *bssid, const u8 *ie, size_t ie_len)
@@ -2084,13 +2227,6 @@
struct p2p_message msg;
struct wpabuf *ies;
- if (!p2p->in_listen || !p2p->drv_in_listen) {
- /* not in Listen state - ignore Probe Request */
- p2p_dbg(p2p, "Not in Listen state (in_listen=%d drv_in_listen=%d) - ignore Probe Request",
- p2p->in_listen, p2p->drv_in_listen);
- return P2P_PREQ_NOT_LISTEN;
- }
-
if (ieee802_11_parse_elems((u8 *) ie, ie_len, &elems, 0) ==
ParseFailed) {
/* Ignore invalid Probe Request frames */
@@ -2141,6 +2277,64 @@
return P2P_PREQ_NOT_P2P;
}
+ p2p->p2ps_svc_found = 0;
+
+ if (msg.service_hash && msg.service_hash_count) {
+ const u8 *hash = msg.service_hash;
+ u8 *dest = p2p->query_hash;
+ u8 i;
+
+ p2p->query_count = 0;
+ for (i = 0; i < msg.service_hash_count; i++) {
+ if (p2p_service_find_asp(p2p, hash)) {
+ p2p->p2ps_svc_found = 1;
+
+ if (!os_memcmp(hash, p2p->wild_card_hash,
+ P2PS_HASH_LEN)) {
+ /* We found match(es) but wildcard
+ * will return all */
+ p2p->query_count = 1;
+ os_memcpy(p2p->query_hash, hash,
+ P2PS_HASH_LEN);
+ break;
+ }
+
+ /* Save each matching hash */
+ if (p2p->query_count < P2P_MAX_QUERY_HASH) {
+ os_memcpy(dest, hash, P2PS_HASH_LEN);
+ dest += P2PS_HASH_LEN;
+ p2p->query_count++;
+ } else {
+ /* We found match(es) but too many to
+ * return all */
+ p2p->query_count = 0;
+ break;
+ }
+ }
+ hash += P2PS_HASH_LEN;
+ }
+
+ p2p_dbg(p2p, "ASP adv found: %d", p2p->p2ps_svc_found);
+
+ /* Probed hash unknown */
+ if (!p2p->p2ps_svc_found) {
+ p2p_parse_free(&msg);
+ return P2P_PREQ_NOT_PROCESSED;
+ }
+ } else {
+ /* This is not a P2PS Probe Request */
+ p2p->query_count = 0;
+ p2p_dbg(p2p, "No P2PS Hash in Probe Request");
+
+ if (!p2p->in_listen || !p2p->drv_in_listen) {
+ /* not in Listen state - ignore Probe Request */
+ p2p_dbg(p2p, "Not in Listen state (in_listen=%d drv_in_listen=%d) - ignore Probe Request",
+ p2p->in_listen, p2p->drv_in_listen);
+ p2p_parse_free(&msg);
+ return P2P_PREQ_NOT_LISTEN;
+ }
+ }
+
if (msg.device_id &&
os_memcmp(msg.device_id, p2p->cfg->dev_addr, ETH_ALEN) != 0) {
/* Device ID did not match */
@@ -2238,6 +2432,7 @@
p2p_add_dev_from_probe_req(p2p, addr, ie, ie_len);
res = p2p_reply_probe(p2p, addr, dst, bssid, ie, ie_len);
+ p2p->query_count = 0;
if ((p2p->state == P2P_CONNECT || p2p->state == P2P_CONNECT_LISTEN) &&
p2p->go_neg_peer &&
@@ -2395,6 +2590,132 @@
}
+struct p2ps_advertisement *
+p2p_service_p2ps_id(struct p2p_data *p2p, u32 adv_id)
+{
+ struct p2ps_advertisement *adv_data;
+
+ if (!p2p)
+ return NULL;
+
+ adv_data = p2p->p2ps_adv_list;
+ while (adv_data) {
+ if (adv_data->id == adv_id)
+ return adv_data;
+ adv_data = adv_data->next;
+ }
+
+ return NULL;
+}
+
+
+int p2p_service_del_asp(struct p2p_data *p2p, u32 adv_id)
+{
+ struct p2ps_advertisement *adv_data;
+ struct p2ps_advertisement **prior;
+
+ if (!p2p)
+ return -1;
+
+ adv_data = p2p->p2ps_adv_list;
+ prior = &p2p->p2ps_adv_list;
+ while (adv_data) {
+ if (adv_data->id == adv_id) {
+ p2p_dbg(p2p, "Delete ASP adv_id=0x%x", adv_id);
+ *prior = adv_data->next;
+ os_free(adv_data);
+ return 0;
+ }
+ prior = &adv_data->next;
+ adv_data = adv_data->next;
+ }
+
+ return -1;
+}
+
+
+int p2p_service_add_asp(struct p2p_data *p2p, int auto_accept, u32 adv_id,
+ const char *adv_str, u8 svc_state, u16 config_methods,
+ const char *svc_info)
+{
+ struct p2ps_advertisement *adv_data, *tmp, **prev;
+ u8 buf[P2PS_HASH_LEN];
+ size_t adv_data_len, adv_len, info_len = 0;
+
+ if (!p2p || !adv_str || !adv_str[0])
+ return -1;
+
+ if (!(config_methods & p2p->cfg->config_methods)) {
+ p2p_dbg(p2p, "Config methods not supported svc: 0x%x dev: 0x%x",
+ config_methods, p2p->cfg->config_methods);
+ return -1;
+ }
+
+ if (!p2ps_gen_hash(p2p, adv_str, buf))
+ return -1;
+
+ if (svc_info)
+ info_len = os_strlen(svc_info);
+ adv_len = os_strlen(adv_str);
+ adv_data_len = sizeof(struct p2ps_advertisement) + adv_len + 1 +
+ info_len + 1;
+
+ adv_data = os_zalloc(adv_data_len);
+ if (!adv_data)
+ return -1;
+
+ os_memcpy(adv_data->hash, buf, P2PS_HASH_LEN);
+ adv_data->id = adv_id;
+ adv_data->state = svc_state;
+ adv_data->config_methods = config_methods & p2p->cfg->config_methods;
+ adv_data->auto_accept = (u8) auto_accept;
+ os_memcpy(adv_data->svc_name, adv_str, adv_len);
+
+ if (svc_info && info_len) {
+ adv_data->svc_info = &adv_data->svc_name[adv_len + 1];
+ os_memcpy(adv_data->svc_info, svc_info, info_len);
+ }
+
+ /*
+ * Group Advertisements by service string. They do not need to be
+ * sorted, but groups allow easier Probe Response instance grouping
+ */
+ tmp = p2p->p2ps_adv_list;
+ prev = &p2p->p2ps_adv_list;
+ while (tmp) {
+ if (tmp->id == adv_data->id) {
+ if (os_strcmp(tmp->svc_name, adv_data->svc_name) != 0) {
+ os_free(adv_data);
+ return -1;
+ }
+ adv_data->next = tmp->next;
+ *prev = adv_data;
+ os_free(tmp);
+ goto inserted;
+ } else {
+ if (os_strcmp(tmp->svc_name, adv_data->svc_name) == 0) {
+ adv_data->next = tmp->next;
+ tmp->next = adv_data;
+ goto inserted;
+ }
+ }
+ prev = &tmp->next;
+ tmp = tmp->next;
+ }
+
+ /* No svc_name match found */
+ adv_data->next = p2p->p2ps_adv_list;
+ p2p->p2ps_adv_list = adv_data;
+
+inserted:
+ p2p_dbg(p2p,
+ "Added ASP advertisement adv_id=0x%x config_methods=0x%x svc_state=0x%x adv_str='%s'",
+ adv_id, adv_data->config_methods, svc_state, adv_str);
+
+ return 0;
+}
+
+
int p2p_parse_dev_addr_in_p2p_ie(struct wpabuf *p2p_ie, u8 *dev_addr)
{
struct p2p_message msg;
@@ -2508,6 +2829,8 @@
p2p->cfg->num_pref_chan = 0;
}
+ p2ps_gen_hash(p2p, P2PS_WILD_HASH_STR, p2p->wild_card_hash);
+
p2p->min_disc_int = 1;
p2p->max_disc_int = 3;
p2p->max_disc_tu = -1;
@@ -2541,6 +2864,8 @@
void p2p_deinit(struct p2p_data *p2p)
{
+ struct p2ps_advertisement *adv, *prev;
+
#ifdef CONFIG_WIFI_DISPLAY
wpabuf_free(p2p->wfd_ie_beacon);
wpabuf_free(p2p->wfd_ie_probe_req);
@@ -2569,10 +2894,19 @@
os_free(p2p->cfg->serial_number);
os_free(p2p->cfg->pref_chan);
os_free(p2p->groups);
+ os_free(p2p->p2ps_prov);
wpabuf_free(p2p->sd_resp);
os_free(p2p->after_scan_tx);
p2p_remove_wps_vendor_extensions(p2p);
os_free(p2p->no_go_freq.range);
+
+ adv = p2p->p2ps_adv_list;
+ while (adv) {
+ prev = adv;
+ adv = adv->next;
+ os_free(prev);
+ }
+
os_free(p2p);
}
@@ -2837,13 +3171,15 @@
if (p2p->sd_peer)
p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
p2p->sd_peer = NULL;
- p2p_continue_find(p2p);
+ if (p2p->state != P2P_IDLE)
+ p2p_continue_find(p2p);
return;
}
if (p2p->sd_peer == NULL) {
p2p_dbg(p2p, "No SD peer entry known");
- p2p_continue_find(p2p);
+ if (p2p->state != P2P_IDLE)
+ p2p_continue_find(p2p);
return;
}
@@ -2874,9 +3210,6 @@
{
struct p2p_device *dev;
- if (p2p->state != P2P_IDLE)
- return;
-
/*
* Retry the prov disc req attempt only for the peer that the user had
* requested.
@@ -2950,6 +3283,51 @@
}
+static int p2p_check_after_scan_tx_continuation(struct p2p_data *p2p)
+{
+ if (p2p->after_scan_tx_in_progress) {
+ p2p->after_scan_tx_in_progress = 0;
+ if (p2p->start_after_scan != P2P_AFTER_SCAN_NOTHING &&
+ p2p_run_after_scan(p2p))
+ return 1;
+ if (p2p->state == P2P_SEARCH) {
+ p2p_dbg(p2p, "Continue find after after_scan_tx completion");
+ p2p_continue_find(p2p);
+ }
+ }
+
+ return 0;
+}
+
+
+static void p2p_prov_disc_resp_cb(struct p2p_data *p2p, int success)
+{
+ p2p_dbg(p2p, "Provision Discovery Response TX callback: success=%d",
+ success);
+
+ if (p2p->send_action_in_progress) {
+ p2p->send_action_in_progress = 0;
+ p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
+ }
+
+ p2p->pending_action_state = P2P_NO_PENDING_ACTION;
+
+ if (!success)
+ goto continue_search;
+
+ if (!p2p->cfg->prov_disc_resp_cb ||
+ p2p->cfg->prov_disc_resp_cb(p2p->cfg->cb_ctx) < 1)
+ goto continue_search;
+
+ p2p_dbg(p2p,
+ "Post-Provision Discovery operations started - do not try to continue other P2P operations");
+ return;
+
+continue_search:
+ p2p_check_after_scan_tx_continuation(p2p);
+}
+
+
int p2p_scan_res_handler(struct p2p_data *p2p, const u8 *bssid, int freq,
struct os_reltime *rx_time, int level, const u8 *ies,
size_t ies_len)
@@ -2992,6 +3370,7 @@
void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id)
{
+ u8 dev_capab;
u8 *len;
#ifdef CONFIG_WIFI_DISPLAY
@@ -3004,8 +3383,15 @@
p2p->vendor_elem[VENDOR_ELEM_PROBE_REQ_P2P]);
len = p2p_buf_add_ie_hdr(ies);
- p2p_buf_add_capability(ies, p2p->dev_capab &
- ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 0);
+
+ dev_capab = p2p->dev_capab & ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
+
+ /* P2PS requires Probe Request frames to include SD bit */
+ if (p2p->p2ps_seek && p2p->p2ps_seek_count)
+ dev_capab |= P2P_DEV_CAPAB_SERVICE_DISCOVERY;
+
+ p2p_buf_add_capability(ies, dev_capab, 0);
+
if (dev_id)
p2p_buf_add_device_id(ies, dev_id);
if (p2p->cfg->reg_class && p2p->cfg->channel)
@@ -3015,6 +3401,10 @@
if (p2p->ext_listen_interval)
p2p_buf_add_ext_listen_timing(ies, p2p->ext_listen_period,
p2p->ext_listen_interval);
+
+ if (p2p->p2ps_seek && p2p->p2ps_seek_count)
+ p2p_buf_add_service_hash(ies, p2p);
+
/* TODO: p2p_buf_add_operating_channel() if GO */
p2p_buf_update_ie_hdr(ies, len);
}
@@ -3209,9 +3599,9 @@
int success;
p2p_dbg(p2p, "Action frame TX callback (state=%d freq=%u dst=" MACSTR
- " src=" MACSTR " bssid=" MACSTR " result=%d",
+ " src=" MACSTR " bssid=" MACSTR " result=%d p2p_state=%s)",
p2p->pending_action_state, freq, MAC2STR(dst), MAC2STR(src),
- MAC2STR(bssid), result);
+ MAC2STR(bssid), result, p2p_state_txt(p2p->state));
success = result == P2P_SEND_ACTION_SUCCESS;
state = p2p->pending_action_state;
p2p->pending_action_state = P2P_NO_PENDING_ACTION;
@@ -3221,16 +3611,7 @@
p2p->send_action_in_progress = 0;
p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
}
- if (p2p->after_scan_tx_in_progress) {
- p2p->after_scan_tx_in_progress = 0;
- if (p2p->start_after_scan != P2P_AFTER_SCAN_NOTHING &&
- p2p_run_after_scan(p2p))
- break;
- if (p2p->state == P2P_SEARCH) {
- p2p_dbg(p2p, "Continue find after after_scan_tx completion");
- p2p_continue_find(p2p);
- }
- }
+ p2p_check_after_scan_tx_continuation(p2p);
break;
case P2P_PENDING_GO_NEG_REQUEST:
p2p_go_neg_req_cb(p2p, success);
@@ -3250,6 +3631,9 @@
case P2P_PENDING_PD:
p2p_prov_disc_cb(p2p, success);
break;
+ case P2P_PENDING_PD_RESPONSE:
+ p2p_prov_disc_resp_cb(p2p, success);
+ break;
case P2P_PENDING_INVITATION_REQUEST:
p2p_invitation_req_cb(p2p, success);
break;
@@ -3456,6 +3840,9 @@
static void p2p_timeout_prov_disc_req(struct p2p_data *p2p)
{
+ u32 adv_id = 0;
+ u8 *adv_mac = NULL;
+
p2p->pending_action_state = P2P_NO_PENDING_ACTION;
/*
@@ -3484,12 +3871,18 @@
for_join = 1;
}
+ if (p2p->p2ps_prov) {
+ adv_id = p2p->p2ps_prov->adv_id;
+ adv_mac = p2p->p2ps_prov->adv_mac;
+ }
+
if (p2p->cfg->prov_disc_fail)
p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx,
p2p->pending_pd_devaddr,
for_join ?
P2P_PROV_DISC_TIMEOUT_JOIN :
- P2P_PROV_DISC_TIMEOUT);
+ P2P_PROV_DISC_TIMEOUT,
+ adv_id, adv_mac, NULL);
p2p_reset_pending_pd(p2p);
}
}
@@ -3638,6 +4031,8 @@
return "PBC";
case WPS_NFC:
return "NFC";
+ case WPS_P2PS:
+ return "P2PS";
}
return "??";
@@ -3714,7 +4109,7 @@
"country=%c%c\n"
"oper_freq=%d\n"
"req_config_methods=0x%x\n"
- "flags=%s%s%s%s%s%s%s%s%s%s%s%s%s\n"
+ "flags=%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n"
"status=%d\n"
"invitation_reqs=%u\n",
(int) (now.sec - dev->last_seen.sec),
@@ -3740,6 +4135,8 @@
"[PD_PEER_DISPLAY]" : "",
dev->flags & P2P_DEV_PD_PEER_KEYPAD ?
"[PD_PEER_KEYPAD]" : "",
+ dev->flags & P2P_DEV_PD_PEER_P2PS ?
+ "[PD_PEER_P2PS]" : "",
dev->flags & P2P_DEV_USER_REJECTED ?
"[USER_REJECTED]" : "",
dev->flags & P2P_DEV_PEER_WAITING_RESPONSE ?
@@ -4171,15 +4568,18 @@
if (p2p_channel_to_freq(reg_class, channel) < 0)
return -1;
- p2p_dbg(p2p, "Set Listen channel: reg_class %u channel %u",
- reg_class, channel);
-
/*
* Listen channel was set in configuration or set by control interface;
* cannot override it.
*/
- if (p2p->cfg->channel_forced && forced == 0)
+ if (p2p->cfg->channel_forced && forced == 0) {
+ p2p_dbg(p2p,
+ "Listen channel was previously configured - do not override based on optimization");
return -1;
+ }
+
+ p2p_dbg(p2p, "Set Listen channel: reg_class %u channel %u",
+ reg_class, channel);
if (p2p->state == P2P_IDLE) {
p2p->cfg->reg_class = reg_class;