p2p.c revision 8da800a193fb6f8832218715f82a7b4e2d2ad338
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Wi-Fi Direct - P2P module
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2009-2010, Atheros Communications
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_common.h"
15c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#include "common/wpa_ctrl.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps/wps_i.h"
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p_i.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_state_timeout(void *eloop_ctx, void *timeout_ctx);
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev);
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_req(struct p2p_data *p2p, const u8 *da,
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const u8 *sa, const u8 *data, size_t len,
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     int rx_freq);
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_resp(struct p2p_data *p2p, const u8 *da,
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *sa, const u8 *data,
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      size_t len);
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_ext_listen_timeout(void *eloop_ctx, void *timeout_ctx);
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_scan_timeout(void *eloop_ctx, void *timeout_ctx);
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_scan recovery timeout
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Many drivers are using 30 second timeout on scan results. Allow a bit larger
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * timeout for this to avoid hitting P2P timeout unnecessarily.
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define P2P_SCAN_TIMEOUT 35
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * P2P_PEER_EXPIRATION_AGE - Number of seconds after which inactive peer
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * entries will be removed
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
452fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt#ifdef ANDROID_P2P
462fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt#define P2P_PEER_EXPIRATION_AGE 30
472fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt#else
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define P2P_PEER_EXPIRATION_AGE 300
492fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt#endif
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define P2P_PEER_EXPIRATION_INTERVAL (P2P_PEER_EXPIRATION_AGE / 2)
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
532fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt#ifdef ANDROID_P2P
542fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidtint p2p_connection_in_progress(struct p2p_data *p2p)
552fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt{
562fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt	int ret = 0;
572fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt
582fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt	switch (p2p->state) {
592fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		case P2P_CONNECT:
602fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		case P2P_CONNECT_LISTEN:
612fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		case P2P_GO_NEG:
622fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		case P2P_WAIT_PEER_CONNECT:
6398f9e76624da6bb96edc1982c423e4a119c5170aDmitry Shmidt		case P2P_WAIT_PEER_IDLE:
642fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		case P2P_PROVISIONING:
652fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		case P2P_INVITE:
662fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		case P2P_INVITE_LISTEN:
672fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt			ret = 1;
682fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt			break;
692fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt
702fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		default:
7198f9e76624da6bb96edc1982c423e4a119c5170aDmitry Shmidt			wpa_printf(MSG_DEBUG, "p2p_connection_in_progress state %d", p2p->state);
722fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt			ret = 0;
732fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt	}
742fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt
752fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt	return ret;
762fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt}
772fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt#endif
782fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_expire_peers(struct p2p_data *p2p)
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev, *n;
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct os_time now;
83c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	size_t i;
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&now);
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each_safe(dev, n, &p2p->devices, struct p2p_device, list) {
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->last_seen.sec + P2P_PEER_EXPIRATION_AGE >= now.sec)
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
89c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
90c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (p2p->cfg->go_connected &&
91c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		    p2p->cfg->go_connected(p2p->cfg->cb_ctx,
92c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt					   dev->info.p2p_device_addr)) {
93c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			/*
94c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 * We are connected as a client to a group in which the
95c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 * peer is the GO, so do not expire the peer entry.
96c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 */
97c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			os_get_time(&dev->last_seen);
98c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			continue;
99c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		}
100c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
101c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		for (i = 0; i < p2p->num_groups; i++) {
102c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			if (p2p_group_is_client_connected(
103c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				    p2p->groups[i], dev->info.p2p_device_addr))
104c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				break;
105c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		}
106c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (i < p2p->num_groups) {
107c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			/*
108c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 * The peer is connected as a client in a group where
109c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 * we are the GO, so do not expire the peer entry.
110c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 */
111c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			os_get_time(&dev->last_seen);
112c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			continue;
113c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		}
114c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1152fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt#ifdef ANDROID_P2P
1162fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		/* If Connection is in progress, don't expire the peer
1172fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		*/
1182fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		if (p2p_connection_in_progress(p2p))
1192fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt			continue;
1202fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt#endif
1212fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt
12204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Expiring old peer "
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"entry " MACSTR, MAC2STR(dev->info.p2p_device_addr));
124f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#ifdef ANDROID_P2P
125f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		/* SD_FAIR_POLICY: Update the current sd_dev_list pointer to next device */
126f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		if(&dev->list == p2p->sd_dev_list)
127f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff			p2p->sd_dev_list = dev->list.next;
128f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#endif
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dl_list_del(&dev->list);
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_device_free(p2p, dev);
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_expiration_timeout(void *eloop_ctx, void *timeout_ctx)
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_expire_peers(p2p);
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(P2P_PEER_EXPIRATION_INTERVAL, 0,
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p_expiration_timeout, p2p, NULL);
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * p2p_state_txt(int state)
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (state) {
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_IDLE:
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "IDLE";
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SEARCH:
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "SEARCH";
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT:
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "CONNECT";
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT_LISTEN:
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "CONNECT_LISTEN";
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG:
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "GO_NEG";
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_LISTEN_ONLY:
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "LISTEN_ONLY";
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_CONNECT:
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "WAIT_PEER_CONNECT";
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_IDLE:
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "WAIT_PEER_IDLE";
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SD_DURING_FIND:
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "SD_DURING_FIND";
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROVISIONING:
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "PROVISIONING";
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PD_DURING_FIND:
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "PD_DURING_FIND";
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE:
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "INVITE";
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE_LISTEN:
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "INVITE_LISTEN";
1731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case P2P_SEARCH_WHEN_READY:
1741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return "SEARCH_WHEN_READY";
17561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	case P2P_CONTINUE_SEARCH_WHEN_READY:
17661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return "CONTINUE_SEARCH_WHEN_READY";
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "?";
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtu16 p2p_get_provisioning_info(struct p2p_data *p2p, const u8 *addr)
1841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
1851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_device *dev = NULL;
1861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (!addr || !p2p)
1881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
1891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	dev = p2p_get_device(p2p, addr);
1911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (dev)
1921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return dev->wps_prov_info;
1931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	else
1941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
1951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
1961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
19804949598a23f501be6eec21697465fd46a28840aDmitry Shmidtvoid p2p_clear_provisioning_info(struct p2p_data *p2p, const u8 *addr)
1991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
2001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_device *dev = NULL;
2011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (!addr || !p2p)
2031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
2041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	dev = p2p_get_device(p2p, addr);
2061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (dev)
2071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->wps_prov_info = 0;
2081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
2091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_state(struct p2p_data *p2p, int new_state)
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: State %s -> %s",
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state), p2p_state_txt(new_state));
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->state = new_state;
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_timeout(struct p2p_data *p2p, unsigned int sec, unsigned int usec)
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Set timeout (state=%s): %u.%06u sec",
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state), sec, usec);
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_state_timeout, p2p, NULL);
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(sec, usec, p2p_state_timeout, p2p, NULL);
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_clear_timeout(struct p2p_data *p2p)
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Clear timeout (state=%s)",
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state));
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_state_timeout, p2p, NULL);
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_go_neg_failed(struct p2p_data *p2p, struct p2p_device *peer,
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       int status)
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_go_neg_results res;
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_IDLE);
2438c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	if (p2p->go_neg_peer) {
2448c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		p2p->go_neg_peer->flags &= ~P2P_DEV_PEER_WAITING_RESPONSE;
2451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p->go_neg_peer->wps_method = WPS_NOT_READY;
2468c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	}
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer = NULL;
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&res, 0, sizeof(res));
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.status = status;
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (peer) {
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(res.peer_device_addr, peer->info.p2p_device_addr,
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(res.peer_interface_addr, peer->intended_addr,
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->go_neg_completed(p2p->cfg->cb_ctx, &res);
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
261d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic void p2p_listen_in_find(struct p2p_data *p2p, int dev_disc)
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int r, tu;
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *ies;
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Starting short listen state (state=%s)",
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state));
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	freq = p2p_channel_to_freq(p2p->cfg->country, p2p->cfg->reg_class,
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   p2p->cfg->channel);
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq < 0) {
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Unknown regulatory class/channel");
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_random((u8 *) &r, sizeof(r));
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tu = (r % ((p2p->max_disc_int - p2p->min_disc_int) + 1) +
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	      p2p->min_disc_int) * 100;
282d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (p2p->max_disc_tu >= 0 && tu > (unsigned int) p2p->max_disc_tu)
283d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		tu = p2p->max_disc_tu;
284d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (!dev_disc && tu < 100)
285d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		tu = 100; /* Need to wait in non-device discovery use cases */
286d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (p2p->cfg->max_listen && 1024 * tu / 1000 > p2p->cfg->max_listen)
287d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		tu = p2p->cfg->max_listen * 1000 / 1024;
288d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
289d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (tu == 0) {
290d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Skip listen state "
291d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			"since duration was 0 TU");
292d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		p2p_set_timeout(p2p, 0, 0);
293d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return;
294d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_freq = freq;
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_sec = 0;
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_usec = 1024 * tu;
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ies = p2p_build_probe_resp_ies(p2p);
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ies == NULL)
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->start_listen(p2p->cfg->cb_ctx, freq, 1024 * tu / 1000,
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    ies) < 0) {
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to start listen mode");
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_freq = 0;
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(ies);
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_listen(struct p2p_data *p2p, unsigned int timeout)
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *ies;
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Going to listen(only) state");
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	freq = p2p_channel_to_freq(p2p->cfg->country, p2p->cfg->reg_class,
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   p2p->cfg->channel);
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq < 0) {
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Unknown regulatory class/channel");
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_freq = freq;
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_sec = timeout / 1000;
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_usec = (timeout % 1000) * 1000;
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
33504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (p2p->start_after_scan == P2P_AFTER_SCAN_CONNECT) {
3361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
3371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				"P2P: p2p_scan running - connect is already "
3381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				"pending - skip listen");
3391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return 0;
3401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: p2p_scan running - delay start of listen state");
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->start_after_scan = P2P_AFTER_SCAN_LISTEN;
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ies = p2p_build_probe_resp_ies(p2p);
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ies == NULL)
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->start_listen(p2p->cfg->cb_ctx, freq, timeout, ies) < 0) {
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to start listen mode");
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_freq = 0;
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(ies);
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(ies);
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_LISTEN_ONLY);
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_device_clear_reported(struct p2p_data *p2p)
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list)
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~P2P_DEV_REPORTED;
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_get_device - Fetch a peer entry
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: P2P Device Address of the peer
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the device entry or %NULL if not found
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_device * p2p_get_device(struct p2p_data *p2p, const u8 *addr)
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(dev->info.p2p_device_addr, addr, ETH_ALEN) == 0)
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return dev;
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_get_device_interface - Fetch a peer entry based on P2P Interface Address
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: P2P Interface Address of the peer
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the device entry or %NULL if not found
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_device * p2p_get_device_interface(struct p2p_data *p2p,
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     const u8 *addr)
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(dev->interface_addr, addr, ETH_ALEN) == 0)
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return dev;
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_create_device - Create a peer entry
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: P2P Device Address of the peer
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the device entry or %NULL on failure
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * If there is already an entry for the peer, it will be returned instead of
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * creating a new one.
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct p2p_device * p2p_create_device(struct p2p_data *p2p,
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     const u8 *addr)
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev, *oldest = NULL;
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t count = 0;
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev)
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return dev;
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		count++;
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (oldest == NULL ||
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_time_before(&dev->last_seen, &oldest->last_seen))
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			oldest = dev;
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (count + 1 > p2p->cfg->max_peers && oldest) {
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Remove oldest peer entry to make room for a new "
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"peer");
438f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#ifdef ANDROID_P2P
439f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		/* SD_FAIR_POLICY: Update the current sd_dev_list pointer to next device */
440f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		if(&oldest->list == p2p->sd_dev_list)
441f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff			p2p->sd_dev_list = oldest->list.next;
442f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#endif
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dl_list_del(&oldest->list);
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_device_free(p2p, oldest);
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = os_zalloc(sizeof(*dev));
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_add(&p2p->devices, &dev->list);
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.p2p_device_addr, addr, ETH_ALEN);
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return dev;
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_copy_client_info(struct p2p_device *dev,
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 struct p2p_client_info *cli)
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.device_name, cli->dev_name, cli->dev_name_len);
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.device_name[cli->dev_name_len] = '\0';
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.dev_capab = cli->dev_capab;
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.config_methods = cli->config_methods;
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.pri_dev_type, cli->pri_dev_type, 8);
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.wps_sec_dev_type_list_len = 8 * cli->num_sec_dev_types;
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.wps_sec_dev_type_list, cli->sec_dev_types,
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  dev->info.wps_sec_dev_type_list_len);
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_add_group_clients(struct p2p_data *p2p, const u8 *go_dev_addr,
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const u8 *go_interface_addr, int freq,
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const u8 *gi, size_t gi_len)
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_info info;
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t c;
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gi == NULL)
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_group_info_parse(gi, gi_len, &info) < 0)
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Clear old data for this group; if the devices are still in the
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * group, the information will be restored in the loop following this.
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
4901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (os_memcmp(dev->member_in_go_iface, go_interface_addr,
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      ETH_ALEN) == 0) {
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(dev->member_in_go_iface, 0, ETH_ALEN);
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(dev->member_in_go_dev, 0, ETH_ALEN);
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (c = 0; c < info.num_clients; c++) {
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct p2p_client_info *cli = &info.client[c];
4991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (os_memcmp(cli->p2p_device_addr, p2p->cfg->dev_addr,
5001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      ETH_ALEN) == 0)
5011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			continue; /* ignore our own entry */
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, cli->p2p_device_addr);
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev) {
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev->flags & (P2P_DEV_GROUP_CLIENT_ONLY |
50504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					  P2P_DEV_PROBE_REQ_ONLY)) {
50604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				/*
50704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 * Update information since we have not
50804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 * received this directly from the client.
50904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 */
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p_copy_client_info(dev, cli);
51104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			} else {
51204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				/*
51304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 * Need to update P2P Client Discoverability
51404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 * flag since it is valid only in P2P Group
51504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 * Info attribute.
51604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 */
51704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				dev->info.dev_capab &=
51804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
51904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				dev->info.dev_capab |=
52004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					cli->dev_capab &
52104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
52204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			}
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev->flags & P2P_DEV_PROBE_REQ_ONLY) {
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev->flags &= ~P2P_DEV_PROBE_REQ_ONLY;
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev = p2p_create_device(p2p, cli->p2p_device_addr);
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev == NULL)
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				continue;
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->flags |= P2P_DEV_GROUP_CLIENT_ONLY;
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_copy_client_info(dev, cli);
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->oper_freq = freq;
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->cfg->dev_found(p2p->cfg->cb_ctx,
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    dev->info.p2p_device_addr,
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    &dev->info, 1);
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->interface_addr, cli->p2p_interface_addr,
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_get_time(&dev->last_seen);
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->member_in_go_dev, go_dev_addr, ETH_ALEN);
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->member_in_go_iface, go_interface_addr,
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_copy_wps_info(struct p2p_device *dev, int probe_req,
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      const struct p2p_message *msg)
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.device_name, msg->device_name,
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  sizeof(dev->info.device_name));
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->manufacturer &&
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->manufacturer_len < sizeof(dev->info.manufacturer)) {
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.manufacturer, 0,
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.manufacturer));
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.manufacturer, msg->manufacturer,
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->manufacturer_len);
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->model_name &&
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->model_name_len < sizeof(dev->info.model_name)) {
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.model_name, 0,
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.model_name));
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.model_name, msg->model_name,
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->model_name_len);
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->model_number &&
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->model_number_len < sizeof(dev->info.model_number)) {
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.model_number, 0,
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.model_number));
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.model_number, msg->model_number,
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->model_number_len);
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->serial_number &&
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->serial_number_len < sizeof(dev->info.serial_number)) {
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.serial_number, 0,
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.serial_number));
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.serial_number, msg->serial_number,
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->serial_number_len);
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->pri_dev_type)
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.pri_dev_type, msg->pri_dev_type,
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.pri_dev_type));
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (msg->wps_pri_dev_type)
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.pri_dev_type, msg->wps_pri_dev_type,
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.pri_dev_type));
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->wps_sec_dev_type_list) {
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.wps_sec_dev_type_list,
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->wps_sec_dev_type_list,
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->wps_sec_dev_type_list_len);
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_sec_dev_type_list_len =
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg->wps_sec_dev_type_list_len;
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->capability) {
60504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/*
60604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * P2P Client Discoverability bit is reserved in all frames
60704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * that use this function, so do not change its value here.
60804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 */
60904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->info.dev_capab &= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
61004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->info.dev_capab |= msg->capability[0] &
61104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.group_capab = msg->capability[1];
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->ext_listen_timing) {
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->ext_listen_period = WPA_GET_LE16(msg->ext_listen_timing);
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->ext_listen_interval =
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			WPA_GET_LE16(msg->ext_listen_timing + 2);
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
62004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!probe_req) {
622f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		u16 new_config_methods;
623f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		new_config_methods = msg->config_methods ?
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg->config_methods : msg->wps_config_methods;
625f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		if (new_config_methods &&
626f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		    dev->info.config_methods != new_config_methods) {
627f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Update peer " MACSTR
628f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt				   " config_methods 0x%x -> 0x%x",
629f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt				   MAC2STR(dev->info.p2p_device_addr),
630f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt				   dev->info.config_methods,
631f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt				   new_config_methods);
632f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			dev->info.config_methods = new_config_methods;
633f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		}
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
63904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * p2p_add_device - Add peer entries based on scan results or P2P frames
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: Source address of Beacon or Probe Response frame (may be either
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *	P2P Device Address or P2P Interface Address)
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @level: Signal level (signal strength of the received frame from the peer)
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @freq: Frequency on which the Beacon or Probe Response frame was received
645f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * @rx_time: Time when the result was received
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ies: IEs from the Beacon or Probe Response frame
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ies_len: Length of ies buffer in octets
64804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * @scan_res: Whether this was based on scan results
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * If the scan result is for a GO, the clients in the group will also be added
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to the peer table. This function can also be used with some other frames
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * like Provision Discovery Request that contains P2P Capability and P2P Device
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Info attributes.
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
656a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtint p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq,
657f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		   struct os_time *rx_time, int level, const u8 *ies,
658a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		   size_t ies_len, int scan_res)
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *p2p_dev_addr;
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
664f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	struct os_time time_now;
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ies, ies_len, &msg)) {
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to parse P2P IE for a device entry");
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.p2p_device_addr)
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_addr = msg.p2p_device_addr;
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (msg.device_id)
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_addr = msg.device_id;
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Ignore scan data without P2P Device Info or "
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P Device Id");
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!is_zero_ether_addr(p2p->peer_filter) &&
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(p2p_dev_addr, p2p->peer_filter, ETH_ALEN) != 0) {
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Do not add peer "
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"filter for " MACSTR " due to peer filter",
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(p2p_dev_addr));
691a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p_parse_free(&msg);
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_create_device(p2p, p2p_dev_addr);
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
700a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
701f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	if (rx_time == NULL) {
702f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		os_get_time(&time_now);
703f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		rx_time = &time_now;
704f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	}
705a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
706a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	/*
707a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	 * Update the device entry only if the new peer
708a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	 * entry is newer than the one previously stored.
709a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	 */
710f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	if (dev->last_seen.sec > 0 &&
711f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	    os_time_before(rx_time, &dev->last_seen)) {
712f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Do not update peer "
713f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			"entry based on old frame (rx_time=%u.%06u "
714f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			"last_seen=%u.%06u)",
715f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			(unsigned int) rx_time->sec,
716f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			(unsigned int) rx_time->usec,
717f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			(unsigned int) dev->last_seen.sec,
718f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			(unsigned int) dev->last_seen.usec);
719a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p_parse_free(&msg);
720a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
721a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
722a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
723f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	os_memcpy(&dev->last_seen, rx_time, sizeof(struct os_time));
724a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~(P2P_DEV_PROBE_REQ_ONLY | P2P_DEV_GROUP_CLIENT_ONLY);
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(addr, p2p_dev_addr, ETH_ALEN) != 0)
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->interface_addr, addr, ETH_ALEN);
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.ssid &&
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (msg.ssid[1] != P2P_WILDCARD_SSID_LEN ||
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     os_memcmp(msg.ssid + 2, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN)
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     != 0)) {
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->oper_ssid, msg.ssid + 2, msg.ssid[1]);
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->oper_ssid_len = msg.ssid[1];
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq >= 2412 && freq <= 2484 && msg.ds_params &&
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    *msg.ds_params >= 1 && *msg.ds_params <= 14) {
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int ds_freq;
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*msg.ds_params == 14)
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ds_freq = 2484;
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ds_freq = 2407 + *msg.ds_params * 5;
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freq != ds_freq) {
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Update Listen frequency based on DS "
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Parameter Set IE: %d -> %d MHz",
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				freq, ds_freq);
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq = ds_freq;
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
75304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (dev->listen_freq && dev->listen_freq != freq && scan_res) {
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Update Listen frequency based on scan "
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"results (" MACSTR " %d -> %d MHz (DS param %d)",
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr), dev->listen_freq,
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq, msg.ds_params ? *msg.ds_params : -1);
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
76004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (scan_res) {
76104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->listen_freq = freq;
76204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (msg.group_info)
76304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			dev->oper_freq = freq;
76404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
76575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	dev->info.level = level;
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_copy_wps_info(dev, 0, &msg);
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(dev->info.wps_vendor_ext[i]);
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_vendor_ext[i] = NULL;
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (msg.wps_vendor_ext[i] == NULL)
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_vendor_ext[i] = wpabuf_alloc_copy(
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg.wps_vendor_ext[i], msg.wps_vendor_ext_len[i]);
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->info.wps_vendor_ext[i] == NULL)
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
78361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (msg.wfd_subelems) {
78461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_free(dev->info.wfd_subelems);
78561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
78661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
78761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
78804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (scan_res) {
78904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p_add_group_clients(p2p, p2p_dev_addr, addr, freq,
79004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				      msg.group_info, msg.group_info_len);
79104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_pending_sd_req(p2p, dev))
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags |= P2P_DEV_SD_SCHEDULE;
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_REPORTED)
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
802f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		"P2P: Peer found with Listen frequency %d MHz "
803f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		"(rx_time=%u.%06u)", freq, (unsigned int) rx_time->sec,
804f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		(unsigned int) rx_time->usec);
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_USER_REJECTED) {
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Do not report rejected device");
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
811f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	if (dev->info.config_methods == 0 &&
812f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	    (freq == 2412 || freq == 2437 || freq == 2462)) {
813f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		/*
814f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * If we have only seen a Beacon frame from a GO, we do not yet
815f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * know what WPS config methods it supports. Since some
816f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * applications use config_methods value from P2P-DEVICE-FOUND
817f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * events, postpone reporting this peer until we've fully
818f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * discovered its capabilities.
819f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 *
820f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * At least for now, do this only if the peer was detected on
821f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * one of the social channels since that peer can be easily be
822f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * found again and there are no limitations of having to use
823f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * passive scan on this channels, so this can be done through
824f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * Probe Response frame that includes the config_methods
825f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * information.
826f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 */
827f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
828f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			"P2P: Do not report peer " MACSTR " with unknown "
829f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			"config methods", MAC2STR(addr));
830f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		return 0;
831f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	}
832f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->dev_found(p2p->cfg->cb_ctx, addr, &dev->info,
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    !(dev->flags & P2P_DEV_REPORTED_ONCE));
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev)
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
845497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt	if (p2p->go_neg_peer == dev) {
8461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/*
8471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * If GO Negotiation is in progress, report that it has failed.
8481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
849497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt		p2p_go_neg_failed(p2p, dev, -1);
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->go_neg_peer = NULL;
851497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt	}
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->invite_peer == dev)
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->invite_peer = NULL;
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->sd_peer == dev)
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->sd_peer = NULL;
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->pending_client_disc_go == dev)
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_client_disc_go = NULL;
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
859c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	/* dev_lost() device, but only if it was previously dev_found() */
860c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	if (dev->flags & P2P_DEV_REPORTED_ONCE)
861c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		p2p->cfg->dev_lost(p2p->cfg->cb_ctx,
862c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt				   dev->info.p2p_device_addr);
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(dev->info.wps_vendor_ext[i]);
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_vendor_ext[i] = NULL;
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
86961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(dev->info.wfd_subelems);
87061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(dev);
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_get_next_prog_freq(struct p2p_data *p2p)
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_channels *c;
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_reg_class *cla;
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t cl, ch;
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int found = 0;
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 reg_class;
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 channel;
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	c = &p2p->cfg->channels;
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (cl = 0; cl < c->reg_classes; cl++) {
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cla = &c->reg_class[cl];
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (cla->reg_class != p2p->last_prog_scan_class)
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (ch = 0; ch < cla->channels; ch++) {
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (cla->channel[ch] == p2p->last_prog_scan_chan) {
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				found = 1;
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (found)
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!found) {
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Start from beginning */
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reg_class = c->reg_class[0].reg_class;
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		channel = c->reg_class[0].channel[0];
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Pick the next channel */
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ch++;
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ch == cla->channels) {
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			cl++;
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (cl == c->reg_classes)
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				cl = 0;
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ch = 0;
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reg_class = c->reg_class[cl].reg_class;
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		channel = c->reg_class[cl].channel[ch];
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	freq = p2p_channel_to_freq(p2p->cfg->country, reg_class, channel);
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Next progressive search "
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"channel: reg_class %u channel %u -> %d MHz",
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reg_class, channel, freq);
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->last_prog_scan_class = reg_class;
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->last_prog_scan_chan = channel;
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq == 2412 || freq == 2437 || freq == 2462)
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* No need to add social channels */
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return freq;
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_search(struct p2p_data *p2p)
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq = 0;
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum p2p_scan_type type;
93404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	u16 pw_id = DEV_PW_DEFAULT;
93561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	int res;
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->drv_in_listen) {
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Driver is still "
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"in Listen state - wait for it to end before "
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"continuing");
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
94504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p->find_type == P2P_FIND_PROGRESSIVE &&
94604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    (freq = p2p_get_next_prog_freq(p2p)) > 0) {
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type = P2P_SCAN_SOCIAL_PLUS_ONE;
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting search "
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"(+ freq %u)", freq);
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type = P2P_SCAN_SOCIAL;
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting search");
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
95561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, type, freq,
95661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				 p2p->num_req_dev_types, p2p->req_dev_types,
95761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				 p2p->find_dev_id, pw_id);
95861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (res < 0) {
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Scan request failed");
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
96261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else if (res == 1) {
96361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Could not start "
96461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			"p2p_scan at this point - will try again after "
96561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			"previous scan completes");
96661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_set_state(p2p, P2P_CONTINUE_SEARCH_WHEN_READY);
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Running p2p_scan");
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->p2p_scan_running = 1;
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(P2P_SCAN_TIMEOUT, 0, p2p_scan_timeout,
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p, NULL);
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_find_timeout(void *eloop_ctx, void *timeout_ctx)
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Find timeout -> stop");
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_stop_find(p2p);
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_run_after_scan(struct p2p_data *p2p)
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum p2p_after_scan op;
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->after_scan_tx) {
9918da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt		p2p->after_scan_tx_in_progress = 1;
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send pending "
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Action frame at p2p_scan completion");
9941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p->cfg->send_action(p2p->cfg->cb_ctx,
9951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->freq,
9961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->dst,
9971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->src,
9981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->bssid,
9991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      (u8 *) (p2p->after_scan_tx + 1),
10001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->len,
10011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->wait_time);
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p2p->after_scan_tx);
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = NULL;
1004f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#ifdef ANDROID_P2P
1005f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		/* For SD frames, there is a scenario, where we can receive a SD request frame during p2p_scan.
1006f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * At that moment, we will send the SD response from this context. After sending the SD response,
1007f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * we need to continue p2p_find. But if we return 1 from here, p2p_find is going to be stopped.
1008f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 */
1009f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		return 0;
1010f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#else
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
1012f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#endif
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	op = p2p->start_after_scan;
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (op) {
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_AFTER_SCAN_NOTHING:
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_AFTER_SCAN_LISTEN:
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Start previously "
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"requested Listen state");
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_listen(p2p, p2p->pending_listen_sec * 1000 +
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   p2p->pending_listen_usec / 1000);
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_AFTER_SCAN_CONNECT:
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Start previously "
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"requested connect with " MACSTR,
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(p2p->after_scan_peer));
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, p2p->after_scan_peer);
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev == NULL) {
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer not "
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"known anymore");
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, dev);
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_scan_timeout(void *eloop_ctx, void *timeout_ctx)
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int running;
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan timeout "
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"(running=%d)", p2p->p2p_scan_running);
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	running = p2p->p2p_scan_running;
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Make sure we recover from missed scan results callback */
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->p2p_scan_running = 0;
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (running)
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_run_after_scan(p2p);
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_free_req_dev_types(struct p2p_data *p2p)
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->num_req_dev_types = 0;
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->req_dev_types);
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->req_dev_types = NULL;
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_find(struct p2p_data *p2p, unsigned int timeout,
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     enum p2p_discovery_type type,
1069c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	     unsigned int num_req_dev_types, const u8 *req_dev_types,
107061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	     const u8 *dev_id, unsigned int search_delay)
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting find (type=%d)",
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type);
1076f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	os_get_time(&p2p->find_start);
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan is "
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"already running");
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_req_dev_types(p2p);
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req_dev_types && num_req_dev_types) {
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->req_dev_types = os_malloc(num_req_dev_types *
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       WPS_DEV_TYPE_LEN);
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->req_dev_types == NULL)
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->req_dev_types, req_dev_types,
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  num_req_dev_types * WPS_DEV_TYPE_LEN);
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->num_req_dev_types = num_req_dev_types;
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1093c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (dev_id) {
1094c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		os_memcpy(p2p->find_dev_id_buf, dev_id, ETH_ALEN);
1095c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		p2p->find_dev_id = p2p->find_dev_id_buf;
1096c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	} else
1097c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		p2p->find_dev_id = NULL;
1098c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->find_type = type;
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_device_clear_reported(p2p);
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_SEARCH);
110561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->search_delay = search_delay;
110661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->in_search_delay = 0;
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
11081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p->last_p2p_find_timeout = timeout;
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (timeout)
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(timeout, 0, p2p_find_timeout,
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p, NULL);
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (type) {
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_FIND_START_WITH_FULL:
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_FIND_PROGRESSIVE:
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_FULL, 0,
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 p2p->num_req_dev_types,
111704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 p2p->req_dev_types, dev_id,
111804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 DEV_PW_DEFAULT);
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_FIND_ONLY_SOCIAL:
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_SOCIAL, 0,
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 p2p->num_req_dev_types,
112304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 p2p->req_dev_types, dev_id,
112404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 DEV_PW_DEFAULT);
11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res == 0) {
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Running p2p_scan");
11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->p2p_scan_running = 1;
11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(P2P_SCAN_TIMEOUT, 0, p2p_scan_timeout,
11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p, NULL);
11361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	} else if (res == 1) {
11371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Could not start "
11381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			"p2p_scan at this point - will try again after "
11391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			"previous scan completes");
11401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		res = 0;
11411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_set_state(p2p, P2P_SEARCH_WHEN_READY);
11421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Failed to start "
11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"p2p_scan");
11461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
11471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11532fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt#ifdef ANDROID_P2P
11542fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidtint p2p_search_pending(struct p2p_data *p2p)
11552fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt{
11562fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt	if(p2p == NULL)
11572fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		return 0;
11582fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt
11592fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt	if(p2p->state == P2P_SEARCH_WHEN_READY)
11602fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		return 1;
11612fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt
11622fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt	return 0;
11632fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt}
11642fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt#endif
11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_other_scan_completed(struct p2p_data *p2p)
11671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
116861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->state == P2P_CONTINUE_SEARCH_WHEN_READY) {
116961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_set_state(p2p, P2P_SEARCH);
117061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_search(p2p);
117161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return 1;
117261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
11731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p->state != P2P_SEARCH_WHEN_READY)
11741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
11751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting pending P2P find "
11761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		"now that previous scan was completed");
11771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p_find(p2p, p2p->last_p2p_find_timeout, p2p->find_type,
1178c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		     p2p->num_req_dev_types, p2p->req_dev_types,
1179f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		     p2p->find_dev_id, p2p->search_delay) < 0) {
1180f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, P2P_EVENT_FIND_STOPPED);
11811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
1182f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	}
11831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return 1;
11841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
11851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_stop_find_for_freq(struct p2p_data *p2p, int freq)
11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Stopping find");
11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
1192a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (p2p->state == P2P_SEARCH ||
1193a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	    p2p->state == P2P_CONTINUE_SEARCH_WHEN_READY ||
1194a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	    p2p->state == P2P_SEARCH_WHEN_READY)
1195c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, P2P_EVENT_FIND_STOPPED);
11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_IDLE);
11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_req_dev_types(p2p);
11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
11998c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	if (p2p->go_neg_peer)
12008c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		p2p->go_neg_peer->flags &= ~P2P_DEV_PEER_WAITING_RESPONSE;
12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer = NULL;
12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->sd_peer = NULL;
12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->invite_peer = NULL;
120404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_stop_listen_for_freq(p2p, freq);
120504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
120604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
120704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
120804949598a23f501be6eec21697465fd46a28840aDmitry Shmidtvoid p2p_stop_listen_for_freq(struct p2p_data *p2p, int freq)
120904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq > 0 && p2p->drv_in_listen == freq && p2p->in_listen) {
12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Skip stop_listen "
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"since we are on correct channel for response");
12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
121504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p->in_listen) {
121604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->in_listen = 0;
121704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p_clear_timeout(p2p);
121804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
12191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p->drv_in_listen) {
12201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/*
12211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * The driver may not deliver callback to p2p_listen_end()
12221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * when the operation gets canceled, so clear the internal
12231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * variable that is tracking driver state.
12241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
12251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Clear "
12261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			"drv_in_listen (%d)", p2p->drv_in_listen);
12271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p->drv_in_listen = 0;
12281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_stop_find(struct p2p_data *p2p)
12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_stop_find_for_freq(p2p, 0);
12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1239a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtstatic int p2p_prepare_channel_pref(struct p2p_data *p2p,
1240a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt				    unsigned int force_freq,
1241a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt				    unsigned int pref_freq)
12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1243a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	u8 op_class, op_channel;
1244a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	unsigned int freq = force_freq ? force_freq : pref_freq;
12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1246a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (p2p_freq_to_channel(p2p->cfg->country, freq,
1247a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt				&op_class, &op_channel) < 0) {
1248a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
1249a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			"P2P: Unsupported frequency %u MHz", freq);
1250a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
1251a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
1252a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1253a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (!p2p_channels_includes(&p2p->cfg->channels, op_class, op_channel)) {
1254a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
1255a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			"P2P: Frequency %u MHz (oper_class %u channel %u) not "
1256a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			"allowed for P2P", freq, op_class, op_channel);
1257a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
1258a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
1259a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1260a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	p2p->op_reg_class = op_class;
1261a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	p2p->op_channel = op_channel;
12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1263a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (force_freq) {
1264a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->channels.reg_classes = 1;
1265a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->channels.reg_class[0].channels = 1;
1266a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->channels.reg_class[0].reg_class = p2p->op_reg_class;
1267a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->channels.reg_class[0].channel[0] = p2p->op_channel;
1268a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	} else {
12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(&p2p->channels, &p2p->cfg->channels,
12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(struct p2p_channels));
12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1272a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1273a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	return 0;
1274a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt}
1275a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1276a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1277a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtstatic void p2p_prepare_channel_best(struct p2p_data *p2p)
1278a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{
1279a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	u8 op_class, op_channel;
1280a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1281a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (!p2p->cfg->cfg_op_channel && p2p->best_freq_overall > 0 &&
1282a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	    p2p_supported_freq(p2p, p2p->best_freq_overall) &&
1283a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	    p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_overall,
1284a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt				&op_class, &op_channel) == 0) {
1285a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Select best "
1286a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			"overall channel as operating channel preference");
1287a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_reg_class = op_class;
1288a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_channel = op_channel;
1289a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	} else if (!p2p->cfg->cfg_op_channel && p2p->best_freq_5 > 0 &&
1290a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		   p2p_supported_freq(p2p, p2p->best_freq_5) &&
1291a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		   p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_5,
1292a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt				       &op_class, &op_channel) == 0) {
1293a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Select best 5 GHz "
1294a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			"channel as operating channel preference");
1295a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_reg_class = op_class;
1296a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_channel = op_channel;
1297a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	} else if (!p2p->cfg->cfg_op_channel && p2p->best_freq_24 > 0 &&
1298a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		   p2p_supported_freq(p2p, p2p->best_freq_24) &&
1299a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		   p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_24,
1300a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt				       &op_class, &op_channel) == 0) {
1301a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Select best 2.4 "
1302a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			"GHz channel as operating channel preference");
1303a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_reg_class = op_class;
1304a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_channel = op_channel;
1305a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	} else {
1306a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_reg_class = p2p->cfg->op_reg_class;
1307a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_channel = p2p->cfg->op_channel;
1308a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
1309a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1310a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	os_memcpy(&p2p->channels, &p2p->cfg->channels,
1311a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		  sizeof(struct p2p_channels));
1312a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt}
1313a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1314a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1315a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt/**
1316a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * p2p_prepare_channel - Select operating channel for GO Negotiation
1317a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @p2p: P2P module context from p2p_init()
1318a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @dev: Selected peer device
1319a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @force_freq: Forced frequency in MHz or 0 if not forced
1320a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @pref_freq: Preferred frequency in MHz or 0 if no preference
1321a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Returns: 0 on success, -1 on failure (channel not supported for P2P)
1322a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *
1323a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * This function is used to do initial operating channel selection for GO
1324a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Negotiation prior to having received peer information. The selected channel
1325a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * may be further optimized in p2p_reselect_channel() once the peer information
1326a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * is available.
1327a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt */
13287a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidtint p2p_prepare_channel(struct p2p_data *p2p, struct p2p_device *dev,
13297a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt			unsigned int force_freq, unsigned int pref_freq)
1330a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{
1331a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (force_freq || pref_freq) {
1332a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		if (p2p_prepare_channel_pref(p2p, force_freq, pref_freq) < 0)
1333a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			return -1;
1334a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	} else {
1335a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p_prepare_channel_best(p2p);
1336a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Own preference for operation channel: "
13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"Operating Class %u Channel %u%s",
13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->op_reg_class, p2p->op_channel,
13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		force_freq ? " (forced)" : "");
13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1343a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (force_freq)
1344a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		dev->flags |= P2P_DEV_FORCE_FREQ;
1345a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	else
1346a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		dev->flags &= ~P2P_DEV_FORCE_FREQ;
1347a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void p2p_set_dev_persistent(struct p2p_device *dev,
13531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   int persistent_group)
13541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
13551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	switch (persistent_group) {
13561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case 0:
13571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags &= ~(P2P_DEV_PREFER_PERSISTENT_GROUP |
13581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				P2P_DEV_PREFER_PERSISTENT_RECONN);
13591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
13601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case 1:
13611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP;
13621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags &= ~P2P_DEV_PREFER_PERSISTENT_RECONN;
13631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
13641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case 2:
13651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP |
13661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			P2P_DEV_PREFER_PERSISTENT_RECONN;
13671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
13681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
13691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
13701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
13711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		enum p2p_wps_method wps_method,
13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int go_intent, const u8 *own_interface_addr,
137504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		unsigned int force_freq, int persistent_group,
137604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		const u8 *force_ssid, size_t force_ssid_len,
1377d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		int pd_before_go_neg, unsigned int pref_freq)
13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Request to start group negotiation - peer=" MACSTR
13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  GO Intent=%d  Intended Interface Address=" MACSTR
1384d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		" wps_method=%d persistent_group=%d pd_before_go_neg=%d",
13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
1386d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wps_method, persistent_group, pd_before_go_neg);
13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Cannot connect to unknown P2P Device " MACSTR,
13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(peer_addr));
13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1396a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (p2p_prepare_channel(p2p, dev, force_freq, pref_freq) < 0)
1397a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
1398a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!(dev->info.dev_capab &
14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Cannot connect to P2P Device " MACSTR
14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				" that is in a group and is not discoverable",
14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(peer_addr));
14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->oper_freq <= 0) {
14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Cannot connect to P2P Device " MACSTR
14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				" with incomplete information",
14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(peer_addr));
14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * First, try to connect directly. If the peer does not
14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * acknowledge frames, assume it is sleeping and use device
14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * discoverability via the GO at that point.
14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
142304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p->ssid_set = 0;
142404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (force_ssid) {
142504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "P2P: Forced SSID",
142604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  force_ssid, force_ssid_len);
142704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(p2p->ssid, force_ssid, force_ssid_len);
142804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->ssid_len = force_ssid_len;
142904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->ssid_set = 1;
143004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
143104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_NOT_YET_READY;
14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_USER_REJECTED;
14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE;
14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM;
143604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (pd_before_go_neg)
143704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->flags |= P2P_DEV_PD_BEFORE_GO_NEG;
1438a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	else {
143904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->flags &= ~P2P_DEV_PD_BEFORE_GO_NEG;
1440a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		/*
14419cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt		 * Assign dialog token and tie breaker here to use the same
14429cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt		 * values in each retry within the same GO Negotiation exchange.
1443a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		 */
1444a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		dev->dialog_token++;
1445a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		if (dev->dialog_token == 0)
1446a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			dev->dialog_token = 1;
14479cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt		dev->tie_breaker = p2p->next_tie_breaker;
14489cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt		p2p->next_tie_breaker = !p2p->next_tie_breaker;
1449a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->connect_reqs = 0;
14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_neg_req_sent = 0;
14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_state = UNKNOWN_GO;
14531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_set_dev_persistent(dev, persistent_group);
14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_intent = go_intent;
14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state != P2P_IDLE)
14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_stop_find(p2p);
14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->after_scan_tx) {
14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * We need to drop the pending frame to avoid issues with the
14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * new GO Negotiation, e.g., when the pending frame was from a
14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * previous attempt at starting a GO Negotiation.
14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Dropped "
14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"previous pending Action frame TX that was waiting "
14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"for p2p_scan completion");
14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p2p->after_scan_tx);
14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = NULL;
14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wps_method = wps_method;
14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->status = P2P_SC_SUCCESS;
14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: p2p_scan running - delay connect send");
14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->start_after_scan = P2P_AFTER_SCAN_CONNECT;
14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_peer, peer_addr, ETH_ALEN);
14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_connect_send(p2p, dev);
14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  enum p2p_wps_method wps_method,
14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  int go_intent, const u8 *own_interface_addr,
149204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		  unsigned int force_freq, int persistent_group,
1493d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		  const u8 *force_ssid, size_t force_ssid_len,
1494d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		  unsigned int pref_freq)
14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Request to authorize group negotiation - peer=" MACSTR
15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  GO Intent=%d  Intended Interface Address=" MACSTR
15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" wps_method=%d  persistent_group=%d",
15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wps_method, persistent_group);
15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Cannot authorize unknown P2P Device " MACSTR,
15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(peer_addr));
15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1513a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (p2p_prepare_channel(p2p, dev, force_freq, pref_freq) < 0)
1514a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
1515a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
151604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p->ssid_set = 0;
151704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (force_ssid) {
151804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "P2P: Forced SSID",
151904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  force_ssid, force_ssid_len);
152004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(p2p->ssid, force_ssid, force_ssid_len);
152104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->ssid_len = force_ssid_len;
152204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->ssid_set = 1;
152304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
152404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_NOT_YET_READY;
15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_USER_REJECTED;
15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_neg_req_sent = 0;
15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_state = UNKNOWN_GO;
15291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_set_dev_persistent(dev, persistent_group);
15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_intent = go_intent;
15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wps_method = wps_method;
15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->status = P2P_SC_SUCCESS;
15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_add_dev_info(struct p2p_data *p2p, const u8 *addr,
15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      struct p2p_device *dev, struct p2p_message *msg)
15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&dev->last_seen);
15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_copy_wps_info(dev, 0, msg);
15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->listen_channel) {
15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int freq;
15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		freq = p2p_channel_to_freq((char *) msg->listen_channel,
15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   msg->listen_channel[3],
15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   msg->listen_channel[4]);
15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freq < 0) {
15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Unknown peer Listen channel: "
15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"country=%c%c(0x%02x) reg_class=%u channel=%u",
15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[0],
15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[1],
15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[2],
15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[3],
15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[4]);
15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Update "
15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"peer " MACSTR " Listen channel: %u -> %u MHz",
15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(dev->info.p2p_device_addr),
15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev->listen_freq, freq);
15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->listen_freq = freq;
15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
157061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (msg->wfd_subelems) {
157161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_free(dev->info.wfd_subelems);
157261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		dev->info.wfd_subelems = wpabuf_dup(msg->wfd_subelems);
157361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
157461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_PROBE_REQ_ONLY) {
15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~P2P_DEV_PROBE_REQ_ONLY;
15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Completed device entry based on data from "
15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"GO Negotiation Request");
15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Created device entry based on GO Neg Req: "
15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MACSTR " dev_capab=0x%x group_capab=0x%x name='%s' "
15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"listen_freq=%d",
15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr),
15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->info.dev_capab, dev->info.group_capab,
15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->info.device_name, dev->listen_freq);
15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_GROUP_CLIENT_ONLY;
15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_USER_REJECTED) {
15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Do not report rejected device");
15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->dev_found(p2p->cfg->cb_ctx, addr, &dev->info,
15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    !(dev->flags & P2P_DEV_REPORTED_ONCE));
16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_build_ssid(struct p2p_data *p2p, u8 *ssid, size_t *ssid_len)
16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_random((char *) &ssid[P2P_WILDCARD_SSID_LEN], 2);
16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&ssid[P2P_WILDCARD_SSID_LEN + 2],
16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  p2p->cfg->ssid_postfix, p2p->cfg->ssid_postfix_len);
16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*ssid_len = P2P_WILDCARD_SSID_LEN + 2 + p2p->cfg->ssid_postfix_len;
16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_go_params(struct p2p_data *p2p, struct p2p_go_neg_results *params)
16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_build_ssid(p2p, params->ssid, &params->ssid_len);
16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_random(params->passphrase, 8);
16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_go_complete(struct p2p_data *p2p, struct p2p_device *peer)
16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_go_neg_results res;
16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int go = peer->go_state == LOCAL_GO;
16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_channels intersection;
16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freqs;
16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i, j;
16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: GO Negotiation with " MACSTR " completed (%s will be "
16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"GO)", MAC2STR(peer->info.p2p_device_addr),
16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		go ? "local end" : "peer");
16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&res, 0, sizeof(res));
16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.role_go = go;
16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(res.peer_device_addr, peer->info.p2p_device_addr, ETH_ALEN);
16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(res.peer_interface_addr, peer->intended_addr, ETH_ALEN);
16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.wps_method = peer->wps_method;
16401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) {
16411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN)
16421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			res.persistent_group = 2;
16431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		else
16441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			res.persistent_group = 1;
16451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (go) {
16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Setup AP mode for WPS provisioning */
16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res.freq = p2p_channel_to_freq(p2p->cfg->country,
16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       p2p->op_reg_class,
16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       p2p->op_channel);
16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(res.ssid, p2p->ssid, p2p->ssid_len);
16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res.ssid_len = p2p->ssid_len;
16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_random(res.passphrase, 8);
16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res.freq = peer->oper_freq;
16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->ssid_len) {
16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(res.ssid, p2p->ssid, p2p->ssid_len);
16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res.ssid_len = p2p->ssid_len;
16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_channels_intersect(&p2p->channels, &peer->channels,
16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       &intersection);
16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	freqs = 0;
16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < intersection.reg_classes; i++) {
16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct p2p_reg_class *c = &intersection.reg_class[i];
16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freqs + 1 == P2P_MAX_CHANNELS)
16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < c->channels; j++) {
16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			int freq;
16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (freqs + 1 == P2P_MAX_CHANNELS)
16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq = p2p_channel_to_freq(peer->country, c->reg_class,
16758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   c->channel[j]);
16768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (freq < 0)
16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				continue;
16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res.freq_list[freqs++] = freq;
16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.peer_config_timeout = go ? peer->client_timeout : peer->go_timeout;
16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
16851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p->ssid_set = 0;
16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer->go_neg_req_sent = 0;
16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer->wps_method = WPS_NOT_READY;
16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_PROVISIONING);
16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->go_neg_completed(p2p->cfg->cb_ctx, &res);
16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_rx_p2p_action(struct p2p_data *p2p, const u8 *sa,
16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      const u8 *data, size_t len, int rx_freq)
16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: RX P2P Public Action from " MACSTR, MAC2STR(sa));
16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "P2P: P2P Public Action contents", data, len);
17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1)
17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data[0]) {
17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG_REQ:
17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_neg_req(p2p, sa, data + 1, len - 1, rx_freq);
17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG_RESP:
17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_neg_resp(p2p, sa, data + 1, len - 1, rx_freq);
17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG_CONF:
17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_neg_conf(p2p, sa, data + 1, len - 1);
17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITATION_REQ:
17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_invitation_req(p2p, sa, data + 1, len - 1,
17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   rx_freq);
17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITATION_RESP:
17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_invitation_resp(p2p, sa, data + 1, len - 1);
17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROV_DISC_REQ:
17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_prov_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROV_DISC_RESP:
17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_prov_disc_resp(p2p, sa, data + 1, len - 1);
17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_DEV_DISC_REQ:
17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_dev_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_DEV_DISC_RESP:
17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_dev_disc_resp(p2p, sa, data + 1, len - 1);
17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Unsupported P2P Public Action frame type %d",
17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data[0]);
17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void p2p_rx_action_public(struct p2p_data *p2p, const u8 *da,
17431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				 const u8 *sa, const u8 *bssid, const u8 *data,
17441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				 size_t len, int freq)
17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1)
17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data[0]) {
17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_VENDOR_SPECIFIC:
17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data++;
17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len--;
17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 3)
17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (WPA_GET_BE24(data) != OUI_WFA)
17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data += 3;
17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len -= 3;
17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 1)
17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*data != P2P_OUI_TYPE)
17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_p2p_action(p2p, sa, data + 1, len - 1, freq);
17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_INITIAL_REQ:
17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_initial_req(p2p, sa, data + 1, len - 1, freq);
17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_INITIAL_RESP:
17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_initial_resp(p2p, sa, data + 1, len - 1, freq);
17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_COMEBACK_REQ:
17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_comeback_req(p2p, sa, data + 1, len - 1, freq);
17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_COMEBACK_RESP:
17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_comeback_resp(p2p, sa, data + 1, len - 1, freq);
17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_rx_action(struct p2p_data *p2p, const u8 *da, const u8 *sa,
17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *bssid, u8 category,
17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *data, size_t len, int freq)
17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (category == WLAN_ACTION_PUBLIC) {
17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_action_public(p2p, da, sa, bssid, data, len, freq);
17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (category != WLAN_ACTION_VENDOR_SPECIFIC)
17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 4)
17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (WPA_GET_BE24(data) != OUI_WFA)
18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data += 3;
18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len -= 3;
18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*data != P2P_OUI_TYPE)
18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data++;
18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len--;
18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P action frame */
18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: RX P2P Action from " MACSTR, MAC2STR(sa));
18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "P2P: P2P Action contents", data, len);
18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1)
18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data[0]) {
18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_NOA:
18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Received P2P Action - Notice of Absence");
18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO */
18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PRESENCE_REQ:
18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_presence_req(p2p, da, sa, data + 1, len - 1, freq);
18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PRESENCE_RESP:
18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_presence_resp(p2p, da, sa, data + 1, len - 1);
18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_DISC_REQ:
18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_disc_req(p2p, da, sa, data + 1, len - 1, freq);
18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Received P2P Action - unknown type %u", data[0]);
18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_start(void *eloop_ctx, void *timeout_ctx)
18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == NULL)
18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer->status = P2P_SC_SUCCESS;
18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_connect_send(p2p, p2p->go_neg_peer);
18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_invite_start(void *eloop_ctx, void *timeout_ctx)
18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->invite_peer == NULL)
18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_invite_send(p2p, p2p->invite_peer, p2p->invite_go_dev_addr);
18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_add_dev_from_probe_req(struct p2p_data *p2p, const u8 *addr,
18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const u8 *ie, size_t ie_len)
18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
18658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg) < 0 || msg.p2p_attributes == NULL)
18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* not a P2P probe */
18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.ssid == NULL || msg.ssid[1] != P2P_WILDCARD_SSID_LEN ||
18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(msg.ssid + 2, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN)
18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    != 0) {
18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* The Probe Request is not part of P2P Device Discovery. It is
18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * not known whether the source address of the frame is the P2P
18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Device Address or P2P Interface Address. Do not add a new
18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * peer entry based on this frames.
18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev) {
18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->country[0] == 0 && msg.listen_channel)
18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(dev->country, msg.listen_channel, 3);
18891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		os_get_time(&dev->last_seen);
18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* already known */
18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_create_device(p2p, addr);
18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&dev->last_seen);
19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_PROBE_REQ_ONLY;
19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.listen_channel) {
19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->country, msg.listen_channel, 3);
19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->listen_freq = p2p_channel_to_freq(dev->country,
19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       msg.listen_channel[3],
19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       msg.listen_channel[4]);
19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_copy_wps_info(dev, 1, &msg);
19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
191261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (msg.wfd_subelems) {
191361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_free(dev->info.wfd_subelems);
191461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
191561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
191661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Created device entry based on Probe Req: " MACSTR
19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" dev_capab=0x%x group_capab=0x%x name='%s' listen_freq=%d",
19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(dev->info.p2p_device_addr), dev->info.dev_capab,
19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.group_capab, dev->info.device_name,
19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->listen_freq);
19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_device * p2p_add_dev_from_go_neg_req(struct p2p_data *p2p,
19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						const u8 *addr,
19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						struct p2p_message *msg)
19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev) {
19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_get_time(&dev->last_seen);
19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return dev; /* already known */
19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_create_device(p2p, addr);
19418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_add_dev_info(p2p, addr, dev, msg);
19458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return dev;
19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int dev_type_match(const u8 *dev_type, const u8 *req_dev_type)
19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(dev_type, req_dev_type, WPS_DEV_TYPE_LEN) == 0)
19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(dev_type, req_dev_type, 2) == 0 &&
19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    WPA_GET_BE32(&req_dev_type[2]) == 0 &&
19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    WPA_GET_BE16(&req_dev_type[6]) == 0)
19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Category match with wildcard OUI/sub-category */
19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint dev_type_list_match(const u8 *dev_type, const u8 *req_dev_type[],
19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			size_t num_req_dev_type)
19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_req_dev_type; i++) {
19678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev_type_match(dev_type, req_dev_type[i]))
19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 1;
19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_match_dev_type - Match local device type with requested type
19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wps: WPS TLVs from Probe Request frame (concatenated WPS IEs)
19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 on match, 0 on mismatch
19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function can be used to match the Requested Device Type attribute in
19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPS IE with the local device types for deciding whether to reply to a Probe
19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Request frame.
19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
19848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_match_dev_type(struct p2p_data *p2p, struct wpabuf *wps)
19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wps_parse_attr attr;
19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wps_parse_msg(wps, &attr))
19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* assume no Requested Device Type attributes */
19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (attr.num_req_dev_type == 0)
19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* no Requested Device Type attributes -> match */
19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev_type_list_match(p2p->cfg->pri_dev_type, attr.req_dev_type,
19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				attr.num_req_dev_type))
19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Own Primary Device Type matches */
19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < p2p->cfg->num_sec_dev_types; i++)
20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev_type_list_match(p2p->cfg->sec_dev_type[i],
20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					attr.req_dev_type,
20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					attr.num_req_dev_type))
20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Own Secondary Device Type matches */
20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* No matching device type found */
20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * p2p_build_probe_resp_ies(struct p2p_data *p2p)
20118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
201404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	int pw_id = -1;
201561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t extra = 0;
201661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
201761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
201861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_probe_resp)
201961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		extra = wpabuf_len(p2p->wfd_ie_probe_resp);
202061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
202261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	buf = wpabuf_alloc(1000 + extra);
20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
202604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p->go_neg_peer) {
202704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/* Advertise immediate availability of WPS credential */
202804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		pw_id = p2p_wps_method_pw_id(p2p->go_neg_peer->wps_method);
202904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
203004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
203104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_build_wps_ie(p2p, buf, pw_id, 1);
20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
203361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
203461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_probe_resp)
203561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(buf, p2p->wfd_ie_probe_resp);
203661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
203761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P IE */
20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(buf);
204004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_buf_add_capability(buf, p2p->dev_capab &
204104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			       ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 0);
20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval)
20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_ext_listen_timing(buf, p2p->ext_listen_period,
20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      p2p->ext_listen_interval);
20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_device_info(buf, p2p, NULL);
20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(buf, len);
20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int is_11b(u8 rate)
20531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
20541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
20551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
20561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int supp_rates_11b_only(struct ieee802_11_elems *elems)
20591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
20601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int num_11b = 0, num_others = 0;
20611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int i;
20621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (elems->supp_rates == NULL && elems->ext_supp_rates == NULL)
20641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
20651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (i = 0; elems->supp_rates && i < elems->supp_rates_len; i++) {
20671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (is_11b(elems->supp_rates[i]))
20681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			num_11b++;
20691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		else
20701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			num_others++;
20711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
20721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (i = 0; elems->ext_supp_rates && i < elems->ext_supp_rates_len;
20741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	     i++) {
20751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (is_11b(elems->ext_supp_rates[i]))
20761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			num_11b++;
20771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		else
20781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			num_others++;
20791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
20801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return num_11b > 0 && num_others == 0;
20821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
20831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
208504949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic enum p2p_probe_req_status
208604949598a23f501be6eec21697465fd46a28840aDmitry Shmidtp2p_reply_probe(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
208704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		const u8 *bssid, const u8 *ie, size_t ie_len)
20888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ieee802_11_elems elems;
20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ieee80211_mgmt *resp;
20921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_message msg;
20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *ies;
20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p->in_listen || !p2p->drv_in_listen) {
20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* not in Listen state - ignore Probe Request */
209704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_LISTEN;
20988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ieee802_11_parse_elems((u8 *) ie, ie_len, &elems, 0) ==
21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ParseFailed) {
21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Ignore invalid Probe Request frames */
210304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_MALFORMED;
21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (elems.p2p == NULL) {
21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* not a P2P probe - ignore it */
210804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_P2P;
21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (dst && !is_broadcast_ether_addr(dst) &&
21121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    os_memcmp(dst, p2p->cfg->dev_addr, ETH_ALEN) != 0) {
21131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Not sent to the broadcast address or our P2P Device Address
21141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
211504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
21161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
21171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
21181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (bssid && !is_broadcast_ether_addr(bssid)) {
21191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Not sent to the Wildcard BSSID */
212004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
21211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
21221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (elems.ssid == NULL || elems.ssid_len != P2P_WILDCARD_SSID_LEN ||
21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(elems.ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) !=
21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0) {
21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* not using P2P Wildcard SSID - ignore */
212704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (supp_rates_11b_only(&elems)) {
21311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Indicates support for 11b rates only */
213204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_P2P;
21331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
21341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
21351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
21361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg) < 0) {
21371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Could not parse P2P attributes */
213804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_P2P;
21391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
21401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
21411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (msg.device_id &&
214204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    os_memcmp(msg.device_id, p2p->cfg->dev_addr, ETH_ALEN) != 0) {
21431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Device ID did not match */
21441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_parse_free(&msg);
214504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
21461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
21471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Check Requested Device Type match */
21491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (msg.wps_attributes &&
21501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    !p2p_match_dev_type(p2p, msg.wps_attributes)) {
21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* No match with Requested Device Type */
21521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_parse_free(&msg);
215304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_parse_free(&msg);
21568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
215704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (!p2p->cfg->send_probe_resp) {
215804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/* Response generated elsewhere */
215904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
216004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Reply to P2P Probe Request in Listen state");
21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * We do not really have a specific BSS that this frame is advertising,
21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * so build a frame that has some information in valid format. This is
21688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * really only used for discovery purposes, not to learn exact BSS
21698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * parameters.
21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
21718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ies = p2p_build_probe_resp_ies(p2p);
21728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ies == NULL)
217304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
21748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = wpabuf_alloc(200 + wpabuf_len(ies));
21768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL) {
21778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(ies);
217804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
21798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = NULL;
21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = wpabuf_put(buf, resp->u.probe_resp.variable - (u8 *) resp);
21838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   (WLAN_FC_STYPE_PROBE_RESP << 4));
21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(resp->da, addr, ETH_ALEN);
21878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(resp->sa, p2p->cfg->dev_addr, ETH_ALEN);
21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(resp->bssid, p2p->cfg->dev_addr, ETH_ALEN);
21898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->u.probe_resp.beacon_int = host_to_le16(100);
21908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* hardware or low-level driver will setup seq_ctrl and timestamp */
21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->u.probe_resp.capab_info =
21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		host_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE |
21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     WLAN_CAPABILITY_PRIVACY |
21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     WLAN_CAPABILITY_SHORT_SLOT_TIME);
21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_SSID);
21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, P2P_WILDCARD_SSID_LEN);
21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(buf, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
21998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_SUPP_RATES);
22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 8);
22028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, (60 / 5) | 0x80);
22038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 90 / 5);
22048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, (120 / 5) | 0x80);
22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 180 / 5);
22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, (240 / 5) | 0x80);
22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 360 / 5);
22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 480 / 5);
22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 540 / 5);
22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_DS_PARAMS);
22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 1);
22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, p2p->cfg->channel);
22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_buf(buf, ies);
22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(ies);
22178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_probe_resp(p2p->cfg->cb_ctx, buf);
22198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(buf);
222104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
222204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return P2P_PREQ_NOT_PROCESSED;
22238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
222604949598a23f501be6eec21697465fd46a28840aDmitry Shmidtenum p2p_probe_req_status
222704949598a23f501be6eec21697465fd46a28840aDmitry Shmidtp2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
222804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 const u8 *bssid, const u8 *ie, size_t ie_len)
22298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
223004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	enum p2p_probe_req_status res;
223104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
22328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_add_dev_from_probe_req(p2p, addr, ie, ie_len);
22338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
223404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	res = p2p_reply_probe(p2p, addr, dst, bssid, ie, ie_len);
22358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((p2p->state == P2P_CONNECT || p2p->state == P2P_CONNECT_LISTEN) &&
22378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    p2p->go_neg_peer &&
22388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(addr, p2p->go_neg_peer->info.p2p_device_addr, ETH_ALEN)
22399cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt	    == 0 &&
22409cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt	    !(p2p->go_neg_peer->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM)) {
22418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Received a Probe Request from GO Negotiation peer */
22428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
22438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Found GO Negotiation peer - try to start GO "
22448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"negotiation from timeout");
22459cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt		eloop_cancel_timeout(p2p_go_neg_start, p2p, NULL);
22468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(0, 0, p2p_go_neg_start, p2p, NULL);
224704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_PROCESSED;
22488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((p2p->state == P2P_INVITE || p2p->state == P2P_INVITE_LISTEN) &&
22518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    p2p->invite_peer &&
22528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(addr, p2p->invite_peer->info.p2p_device_addr, ETH_ALEN)
22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    == 0) {
22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Received a Probe Request from Invite peer */
22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
22568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Found Invite peer - try to start Invite from "
22578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"timeout");
22588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(0, 0, p2p_invite_start, p2p, NULL);
225904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_PROCESSED;
22608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
226204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return res;
22638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_assoc_req_ie_wlan_ap(struct p2p_data *p2p, const u8 *bssid,
22678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    u8 *buf, size_t len, struct wpabuf *p2p_ie)
22688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *tmp;
22708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *lpos;
22718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t tmplen;
22728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
22738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 group_capab;
22748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_ie == NULL)
22768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* WLAN AP is not a P2P manager */
22778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
22798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (Re)Association Request - P2P IE
22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Capability attribute (shall be present)
22818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Interface attribute (present if concurrent device and
22828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *	P2P Management is enabled)
22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
22848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp = wpabuf_alloc(200);
22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp == NULL)
22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	lpos = p2p_buf_add_ie_hdr(tmp);
22898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group_capab = 0;
22908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->num_groups > 0) {
22918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group_capab |= P2P_GROUP_CAPAB_GROUP_OWNER;
22928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) &&
22938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED) &&
22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    p2p->cross_connect)
22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
22968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_capability(tmp, p2p->dev_capab, group_capab);
22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) &&
22998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED))
23008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_p2p_interface(tmp, p2p);
23018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(tmp, lpos);
23028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmplen = wpabuf_len(tmp);
23048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmplen > len)
23058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = -1;
23068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
23078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(buf, wpabuf_head(tmp), tmplen);
23088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = tmplen;
23098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(tmp);
23118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
23138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_assoc_req_ie(struct p2p_data *p2p, const u8 *bssid, u8 *buf,
23178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     size_t len, int p2p_group, struct wpabuf *p2p_ie)
23188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *tmp;
23208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *lpos;
23218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *peer;
23228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t tmplen;
23238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
232461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t extra = 0;
23258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p_group)
23278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return p2p_assoc_req_ie_wlan_ap(p2p, bssid, buf, len, p2p_ie);
23288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
232961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
233061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_assoc_req)
233161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		extra = wpabuf_len(p2p->wfd_ie_assoc_req);
233261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
233361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
23348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
23358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (Re)Association Request - P2P IE
23368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Capability attribute (shall be present)
23378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Extended Listen Timing (may be present)
23388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Device Info attribute (shall be present)
23398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
234061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	tmp = wpabuf_alloc(200 + extra);
23418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp == NULL)
23428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
23438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
234461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
234561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_assoc_req)
234661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(tmp, p2p->wfd_ie_assoc_req);
234761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
234861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
23498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer = bssid ? p2p_get_device(p2p, bssid) : NULL;
23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	lpos = p2p_buf_add_ie_hdr(tmp);
23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_capability(tmp, p2p->dev_capab, 0);
23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval)
23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_ext_listen_timing(tmp, p2p->ext_listen_period,
23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      p2p->ext_listen_interval);
23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_device_info(tmp, p2p, peer);
23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(tmp, lpos);
23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmplen = wpabuf_len(tmp);
23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmplen > len)
23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = -1;
23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(buf, wpabuf_head(tmp), tmplen);
23648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = tmplen;
23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(tmp);
23678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_scan_result_text(const u8 *ies, size_t ies_len, char *buf, char *end)
23738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *p2p_ie;
23758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len, P2P_IE_VENDOR_TYPE);
23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_ie == NULL)
23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
23808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = p2p_attr_text(p2p_ie, buf, end);
23828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(p2p_ie);
23838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
238704949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint p2p_parse_dev_addr_in_p2p_ie(struct wpabuf *p2p_ie, u8 *dev_addr)
2388c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{
2389c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	struct p2p_message msg;
2390c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
2391c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
239204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p_parse_p2p_ie(p2p_ie, &msg))
2393c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return -1;
2394c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
239504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (msg.p2p_device_addr) {
239604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(dev_addr, msg.p2p_device_addr, ETH_ALEN);
239704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 0;
239804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	} else if (msg.device_id) {
239904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(dev_addr, msg.device_id, ETH_ALEN);
240004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 0;
2401c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
240204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return -1;
240304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
2404c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
240504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
240604949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint p2p_parse_dev_addr(const u8 *ies, size_t ies_len, u8 *dev_addr)
240704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
240804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct wpabuf *p2p_ie;
240904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	int ret;
241004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
241104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
241204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					     P2P_IE_VENDOR_TYPE);
241304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p_ie == NULL)
241404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return -1;
241504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	ret = p2p_parse_dev_addr_in_p2p_ie(p2p_ie, dev_addr);
2416c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	wpabuf_free(p2p_ie);
241704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return ret;
2418c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt}
2419c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
2420c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
24218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_clear_go_neg(struct p2p_data *p2p)
24228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer = NULL;
24248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
24258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_IDLE);
24268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_wps_success_cb(struct p2p_data *p2p, const u8 *mac_addr)
24308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == NULL) {
24328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
24338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No pending Group Formation - "
24348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"ignore WPS registration success notification");
24358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* No pending Group Formation */
24368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(mac_addr, p2p->go_neg_peer->intended_addr, ETH_ALEN) !=
24398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0) {
24408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
24418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Ignore WPS registration success notification "
24428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"for " MACSTR " (GO Negotiation peer " MACSTR ")",
24438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(mac_addr),
24448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(p2p->go_neg_peer->intended_addr));
24458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* Ignore unexpected peer address */
24468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
24498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Group Formation completed successfully with " MACSTR,
24508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(mac_addr));
24518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_go_neg(p2p);
24538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_group_formation_failed(struct p2p_data *p2p)
24578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == NULL) {
24598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
24608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No pending Group Formation - "
24618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"ignore group formation failure notification");
24628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* No pending Group Formation */
24638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
24668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Group Formation failed with " MACSTR,
24678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(p2p->go_neg_peer->intended_addr));
24688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_go_neg(p2p);
24708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_data * p2p_init(const struct p2p_config *cfg)
24748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p;
24768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->max_peers < 1)
24788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
24798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p = os_zalloc(sizeof(*p2p) + sizeof(*cfg));
24818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p == NULL)
24828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
24838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg = (struct p2p_config *) (p2p + 1);
24848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg, cfg, sizeof(*cfg));
24858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->dev_name)
24868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->dev_name = os_strdup(cfg->dev_name);
24878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->manufacturer)
24888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->manufacturer = os_strdup(cfg->manufacturer);
24898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->model_name)
24908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_name = os_strdup(cfg->model_name);
24918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->model_number)
24928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_number = os_strdup(cfg->model_number);
24938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->serial_number)
24948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->serial_number = os_strdup(cfg->serial_number);
249504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (cfg->pref_chan) {
249604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->cfg->pref_chan = os_malloc(cfg->num_pref_chan *
249704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt						sizeof(struct p2p_channel));
249804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (p2p->cfg->pref_chan) {
249904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			os_memcpy(p2p->cfg->pref_chan, cfg->pref_chan,
250004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  cfg->num_pref_chan *
250104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  sizeof(struct p2p_channel));
250204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		} else
250304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			p2p->cfg->num_pref_chan = 0;
250404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
250504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
2506f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#ifdef ANDROID_P2P
2507f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	/* 100ms listen time is too less to receive the response frames in some scenarios
2508f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	 * increasing min listen time to 200ms.
2509f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	 */
2510f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	p2p->min_disc_int = 2;
2511f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	/* SD_FAIR_POLICY: Initializing the SD current serviced pointer to NULL */
2512f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	p2p->sd_dev_list = NULL;
2513f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#else
25148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->min_disc_int = 1;
2515f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#endif
25168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->max_disc_int = 3;
2517d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p->max_disc_tu = -1;
25188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_random(&p2p->next_tie_breaker, 1);
25208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->next_tie_breaker &= 0x01;
25218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->sd_request)
25228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_SERVICE_DISCOVERY;
25238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->dev_capab |= P2P_DEV_CAPAB_INVITATION_PROCEDURE;
25248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->concurrent_operations)
25258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_CONCURRENT_OPER;
25268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->dev_capab |= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
25278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_init(&p2p->devices);
25298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(P2P_PEER_EXPIRATION_INTERVAL, 0,
25318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p_expiration_timeout, p2p, NULL);
25328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
253361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->go_timeout = 100;
253461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->client_timeout = 20;
253561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
25368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p;
25378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_deinit(struct p2p_data *p2p)
25418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
254261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
254361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_beacon);
254461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_probe_req);
254561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_probe_resp);
254661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_assoc_req);
254761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_invitation);
254861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_prov_disc_req);
254961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_prov_disc_resp);
255061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_go_neg);
255161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_dev_info);
255261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_assoc_bssid);
255361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_coupled_sink_info);
255461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
255561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
25568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_expiration_timeout, p2p, NULL);
25578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_ext_listen_timeout, p2p, NULL);
25588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
25599cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt	eloop_cancel_timeout(p2p_go_neg_start, p2p, NULL);
25608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_flush(p2p);
25618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_req_dev_types(p2p);
25628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->dev_name);
25638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->manufacturer);
25648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_name);
25658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_number);
25668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->serial_number);
256704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	os_free(p2p->cfg->pref_chan);
25688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->groups);
25698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(p2p->sd_resp);
25708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->after_scan_tx);
25718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_remove_wps_vendor_extensions(p2p);
25728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p);
25738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_flush(struct p2p_data *p2p)
25778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev, *prev;
257904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_stop_find(p2p);
25808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each_safe(dev, prev, &p2p->devices, struct p2p_device,
25818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      list) {
25828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dl_list_del(&dev->list);
25838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_device_free(p2p, dev);
25848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2585f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#ifdef ANDROID_P2P
2586f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	/* SD_FAIR_POLICY: Initializing the SD current serviced pointer to NULL */
2587f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	p2p->sd_dev_list = NULL;
2588f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#endif
25898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_sd_queries(p2p);
25908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->after_scan_tx);
25918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->after_scan_tx = NULL;
25928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_unauthorize(struct p2p_data *p2p, const u8 *addr)
25968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
25988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
26008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
26018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
26028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Unauthorizing " MACSTR,
26048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(addr));
26058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == dev)
26078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->go_neg_peer = NULL;
26088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wps_method = WPS_NOT_READY;
26108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE;
26118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM;
26128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Check if after_scan_tx is for this peer. If so free it */
26148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->after_scan_tx &&
26158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(addr, p2p->after_scan_tx->dst, ETH_ALEN) == 0) {
26168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p2p->after_scan_tx);
26178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = NULL;
26188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_dev_name(struct p2p_data *p2p, const char *dev_name)
26258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->dev_name);
26278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev_name) {
26288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->dev_name = os_strdup(dev_name);
26298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->dev_name == NULL)
26308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
26318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
26328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->dev_name = NULL;
26338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_manufacturer(struct p2p_data *p2p, const char *manufacturer)
26388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->manufacturer);
26408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->manufacturer = NULL;
26418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (manufacturer) {
26428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->manufacturer = os_strdup(manufacturer);
26438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->manufacturer == NULL)
26448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
26458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_model_name(struct p2p_data *p2p, const char *model_name)
26528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_name);
26548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->model_name = NULL;
26558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (model_name) {
26568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_name = os_strdup(model_name);
26578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->model_name == NULL)
26588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
26598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_model_number(struct p2p_data *p2p, const char *model_number)
26668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_number);
26688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->model_number = NULL;
26698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (model_number) {
26708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_number = os_strdup(model_number);
26718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->model_number == NULL)
26728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
26738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_serial_number(struct p2p_data *p2p, const char *serial_number)
26808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->serial_number);
26828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->serial_number = NULL;
26838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (serial_number) {
26848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->serial_number = os_strdup(serial_number);
26858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->serial_number == NULL)
26868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
26878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_config_methods(struct p2p_data *p2p, u16 config_methods)
26948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->config_methods = config_methods;
26968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_uuid(struct p2p_data *p2p, const u8 *uuid)
27008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->uuid, uuid, 16);
27028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_pri_dev_type(struct p2p_data *p2p, const u8 *pri_dev_type)
27068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->pri_dev_type, pri_dev_type, 8);
27088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
27098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_sec_dev_types(struct p2p_data *p2p, const u8 dev_types[][8],
27138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  size_t num_dev_types)
27148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (num_dev_types > P2P_SEC_DEVICE_TYPES)
27168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num_dev_types = P2P_SEC_DEVICE_TYPES;
27178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->num_sec_dev_types = num_dev_types;
27188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->sec_dev_type, dev_types, num_dev_types * 8);
27198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
27208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_remove_wps_vendor_extensions(struct p2p_data *p2p)
27248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
27268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
27288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(p2p->wps_vendor_ext[i]);
27298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->wps_vendor_ext[i] = NULL;
27308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_add_wps_vendor_extension(struct p2p_data *p2p,
27358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const struct wpabuf *vendor_ext)
27368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
27388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (vendor_ext == NULL)
27408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
27418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
27438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->wps_vendor_ext[i] == NULL)
27448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
27458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (i >= P2P_MAX_WPS_VENDOR_EXT)
27478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
27488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->wps_vendor_ext[i] = wpabuf_dup(vendor_ext);
27508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->wps_vendor_ext[i] == NULL)
27518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
27528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
27548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_country(struct p2p_data *p2p, const char *country)
27588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->country, country, 3);
27608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
27618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_continue_find(struct p2p_data *p2p)
27658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
2767f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#ifdef ANDROID_P2P
2768f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	int skip=1;
2769f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#endif
27708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_SEARCH);
27718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
2772f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#ifdef ANDROID_P2P
2773f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		/* SD_FAIR_POLICY: We need to give chance to all devices in the device list
2774f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * There may be a scenario, where a particular peer device have
2775f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * not registered any query response. When we send a SD request to such device,
2776f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * no response will be received. And if we continue to get probe responses from that device,
2777f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * and if that device happens to be on top in our device list,
2778f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * we will always continue to send SD requests always to that peer only.
2779f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * We will not be able to send SD requests to other devices in that case.
2780f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * This implementation keeps track of last serviced peer device.
2781f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * And then takes the next one from the device list, in the next iteration.
2782f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 */
2783f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		if (p2p->sd_dev_list && p2p->sd_dev_list != &p2p->devices) {
2784f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff			if(skip) {
2785f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff				if ((&dev->list == p2p->sd_dev_list) ) {
2786f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff					skip = 0;
2787f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff					if (dev->list.next == &p2p->devices)
2788f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff						p2p->sd_dev_list = NULL;
2789f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff				}
2790f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff				continue;
2791f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff			}
2792f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		}
2793f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		p2p->sd_dev_list = &dev->list;
2794f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		wpa_printf(MSG_DEBUG, "P2P: ### Servicing %p dev->flags 0x%x SD schedule %s devaddr " MACSTR,
2795f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff			p2p->sd_dev_list, dev->flags, dev->flags & P2P_DEV_SD_SCHEDULE ? "TRUE": "FALSE",
2796f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff			MAC2STR(dev->info.p2p_device_addr));
2797f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#endif
27988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->flags & P2P_DEV_SD_SCHEDULE) {
27998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (p2p_start_sd(p2p, dev) == 0)
28008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
28018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
28028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
28038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (dev->req_config_methods &&
28048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   !(dev->flags & P2P_DEV_PD_FOR_JOIN)) {
28058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send "
28061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				"pending Provision Discovery Request to "
28078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MACSTR " (config methods 0x%x)",
28088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(dev->info.p2p_device_addr),
28098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev->req_config_methods);
28101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (p2p_send_prov_disc_req(p2p, dev, 0, 0) == 0)
28118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
28128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
28138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2815d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p_listen_in_find(p2p, 1);
28168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_sd_cb(struct p2p_data *p2p, int success)
28208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
28228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Service Discovery Query TX callback: success=%d",
28238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
28248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
28258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!success) {
28278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->sd_peer) {
28288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE;
28298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->sd_peer = NULL;
28308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
28318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
28328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
28338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->sd_peer == NULL) {
28368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
28378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No SD peer entry known");
28388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
28398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
28408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Wait for response from the peer */
28438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_SD_DURING_FIND);
28448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_timeout(p2p, 0, 200000);
28458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
284775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
284875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen/**
284975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen * p2p_retry_pd - Retry any pending provision disc requests in IDLE state
285075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen * @p2p: P2P module context from p2p_init()
285175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen */
28521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void p2p_retry_pd(struct p2p_data *p2p)
285375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
285475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	struct p2p_device *dev;
285575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
285675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p->state != P2P_IDLE)
285775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
285875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
285975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
286075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * Retry the prov disc req attempt only for the peer that the user had
2861d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	 * requested.
286275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
286375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
286475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
286575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (os_memcmp(p2p->pending_pd_devaddr,
286675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			      dev->info.p2p_device_addr, ETH_ALEN) != 0)
286775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			continue;
286875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (!dev->req_config_methods)
286975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			continue;
287075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
287175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send "
28721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			"pending Provision Discovery Request to "
287375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			MACSTR " (config methods 0x%x)",
287475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			MAC2STR(dev->info.p2p_device_addr),
287575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			dev->req_config_methods);
2876d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		p2p_send_prov_disc_req(p2p, dev,
2877d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				       dev->flags & P2P_DEV_PD_FOR_JOIN, 0);
287875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
287975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	}
288075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
288175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
288275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
28838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_prov_disc_cb(struct p2p_data *p2p, int success)
28848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
28868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Provision Discovery Request TX callback: success=%d",
28878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
288875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
288975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
289075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * Postpone resetting the pending action state till after we actually
289175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * time out. This allows us to take some action like notifying any
289275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * interested parties about no response to the request.
289375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 *
289475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * When the timer (below) goes off we check in IDLE, SEARCH, or
289575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * LISTEN_ONLY state, which are the only allowed states to issue a PD
289675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * requests in, if this was still pending and then raise notification.
289775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
28988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!success) {
290075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pending_action_state = P2P_NO_PENDING_ACTION;
290175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
290261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->user_initiated_pd &&
290361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		    (p2p->state == P2P_SEARCH || p2p->state == P2P_LISTEN_ONLY))
290461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		{
290561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			/* Retry request from timeout to avoid busy loops */
290661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p->pending_action_state = P2P_PENDING_PD;
290761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p_set_timeout(p2p, 0, 50000);
290861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		} else if (p2p->state != P2P_IDLE)
29098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_continue_find(p2p);
291075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		else if (p2p->user_initiated_pd) {
291175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p->pending_action_state = P2P_PENDING_PD;
29121a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#ifdef ANDROID_P2P
29131a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff			p2p_set_timeout(p2p, 0, 350000);
29141a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#else
291575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_set_timeout(p2p, 0, 300000);
29161a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#endif
291775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		}
29188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
29198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
292175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
292275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * This postponing, of resetting pending_action_state, needs to be
292375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * done only for user initiated PD requests and not internal ones.
292475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
292575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p->user_initiated_pd)
292675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pending_action_state = P2P_PENDING_PD;
292775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	else
292875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pending_action_state = P2P_NO_PENDING_ACTION;
292975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
29308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Wait for response from the peer */
29318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_SEARCH)
29328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_PD_DURING_FIND);
29331a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#ifdef ANDROID_P2P
29341a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff	p2p_set_timeout(p2p, 0, 350000);
29351a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#else
29368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_timeout(p2p, 0, 200000);
29371a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#endif
29388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_scan_res_handler(struct p2p_data *p2p, const u8 *bssid, int freq,
2942f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			 struct os_time *rx_time, int level, const u8 *ies,
2943a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			 size_t ies_len)
29448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2945f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	if (os_time_before(rx_time, &p2p->find_start)) {
2946f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		/*
2947f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * The driver may have cached (e.g., in cfg80211 BSS table) the
2948f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * scan results for relatively long time. To avoid reporting
2949f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * stale information, update P2P peers only based on results
2950f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * that have based on frames received after the last p2p_find
2951f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * operation was started.
2952f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 */
2953f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Ignore old scan "
2954f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			"result for " MACSTR " (rx_time=%u.%06u)",
2955f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			MAC2STR(bssid), (unsigned int) rx_time->sec,
2956f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			(unsigned int) rx_time->usec);
2957f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		return 0;
2958f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	}
2959f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
2960f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	p2p_add_device(p2p, bssid, freq, rx_time, level, ies, ies_len, 1);
29618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
29638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_scan_res_handled(struct p2p_data *p2p)
29678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p->p2p_scan_running) {
29698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan was not "
29708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"running, but scan results received");
29718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->p2p_scan_running = 0;
29738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
29748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_run_after_scan(p2p))
29768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
29778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_SEARCH)
29788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
29798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2982c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtvoid p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id)
29838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
298461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 *len;
298561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
298661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
298761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_probe_req)
298861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(ies, p2p->wfd_ie_probe_req);
298961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
299061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
299161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	len = p2p_buf_add_ie_hdr(ies);
299204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_buf_add_capability(ies, p2p->dev_capab &
299304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			       ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 0);
2994c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (dev_id)
2995c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		p2p_buf_add_device_id(ies, dev_id);
29968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->reg_class && p2p->cfg->channel)
29978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_listen_channel(ies, p2p->cfg->country,
29988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   p2p->cfg->reg_class,
29998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   p2p->cfg->channel);
30008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval)
30018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_ext_listen_timing(ies, p2p->ext_listen_period,
30028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      p2p->ext_listen_interval);
30038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: p2p_buf_add_operating_channel() if GO */
30048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(ies, len);
30058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtsize_t p2p_scan_ie_buf_len(struct p2p_data *p2p)
30091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
301061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t len = 100;
301161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
301261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
301361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p && p2p->wfd_ie_probe_req)
301461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		len += wpabuf_len(p2p->wfd_ie_probe_req);
301561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
301661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
301761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return len;
30181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
30191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
30201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
30218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_ie_text(struct wpabuf *p2p_ie, char *buf, char *end)
30228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_attr_text(p2p_ie, buf, end);
30248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_req_cb(struct p2p_data *p2p, int success)
30288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p->go_neg_peer;
30308c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	int timeout;
30318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
30338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: GO Negotiation Request TX callback: success=%d",
30348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
30358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
30378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
30388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No pending GO Negotiation");
30398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
30408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (success) {
30438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->flags & P2P_DEV_USER_REJECTED) {
30448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_set_state(p2p, P2P_IDLE);
30458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
30468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
304704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	} else if (dev->go_neg_req_sent) {
304804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/* Cancel the increment from p2p_connect_send() on failure */
304998f9e76624da6bb96edc1982c423e4a119c5170aDmitry Shmidt		dev->go_neg_req_sent--;
305098f9e76624da6bb96edc1982c423e4a119c5170aDmitry Shmidt	}
30518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!success &&
30538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (dev->info.dev_capab & P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY) &&
30548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !is_zero_ether_addr(dev->member_in_go_dev)) {
30558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
30568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Peer " MACSTR " did not acknowledge request - "
30578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"try to use device discoverability through its GO",
30588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr));
30598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
30608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_send_dev_disc_req(p2p, dev);
30618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
30628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
30658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Use P2P find, if needed, to find the other device from its listen
30668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * channel.
30678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
30688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_CONNECT);
30698c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	timeout = success ? 500000 : 100000;
30708c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	if (!success && p2p->go_neg_peer &&
30718c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	    (p2p->go_neg_peer->flags & P2P_DEV_PEER_WAITING_RESPONSE)) {
30728c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		unsigned int r;
30738c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		/*
30748c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		 * Peer is expected to wait our response and we will skip the
30758c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		 * listen phase. Add some randomness to the wait time here to
30768c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		 * make it less likely to hit cases where we could end up in
30778c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		 * sync with peer not listening.
30788c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		 */
30798c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		os_get_random((u8 *) &r, sizeof(r));
30808c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		timeout += r % 100000;
30818c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	}
30828c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	p2p_set_timeout(p2p, 0, timeout);
30838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_resp_cb(struct p2p_data *p2p, int success)
30878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
30898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: GO Negotiation Response TX callback: success=%d",
30908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
30918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p->go_neg_peer && p2p->state == P2P_PROVISIONING) {
30928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
30938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Ignore TX callback event - GO Negotiation is "
30948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"not running anymore");
30958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
30968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_CONNECT);
30988c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	p2p_set_timeout(p2p, 0, 500000);
30998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_resp_failure_cb(struct p2p_data *p2p, int success)
31038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
31058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: GO Negotiation Response (failure) TX callback: "
31068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"success=%d", success);
31078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer && p2p->go_neg_peer->status != P2P_SC_SUCCESS) {
31088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_failed(p2p, p2p->go_neg_peer,
31098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  p2p->go_neg_peer->status);
31108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_conf_cb(struct p2p_data *p2p,
31158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       enum p2p_send_action_result result)
31168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
31188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
31208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: GO Negotiation Confirm TX callback: result=%d",
31218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		result);
31228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
31238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (result == P2P_SEND_ACTION_FAILED) {
31248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
31258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
31268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (result == P2P_SEND_ACTION_NO_ACK) {
31288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
31298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * It looks like the TX status for GO Negotiation Confirm is
31308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * often showing failure even when the peer has actually
31318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * received the frame. Since the peer may change channels
31328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * immediately after having received the frame, we may not see
31338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * an Ack for retries, so just dropping a single frame may
31348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * trigger this. To allow the group formation to succeed if the
31358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * peer did indeed receive the frame, continue regardless of
31368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * the TX status.
31378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
31388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
31398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Assume GO Negotiation Confirm TX was actually "
31408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"received by the peer even though Ack was not "
31418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"reported");
31428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p->go_neg_peer;
31458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
31468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
31478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_go_complete(p2p, dev);
31498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_send_action_cb(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
31538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const u8 *src, const u8 *bssid,
31548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			enum p2p_send_action_result result)
31558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum p2p_pending_action_state state;
31578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int success;
31588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
31608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Action frame TX callback (state=%d freq=%u dst=" MACSTR
31618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" src=" MACSTR " bssid=" MACSTR " result=%d",
31628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_action_state, freq, MAC2STR(dst), MAC2STR(src),
31638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(bssid), result);
31648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	success = result == P2P_SEND_ACTION_SUCCESS;
31658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	state = p2p->pending_action_state;
31668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
31678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (state) {
31688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_NO_PENDING_ACTION:
31698da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt		if (p2p->after_scan_tx_in_progress) {
31708da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt			p2p->after_scan_tx_in_progress = 0;
31718da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt			if (p2p->start_after_scan != P2P_AFTER_SCAN_NOTHING &&
31728da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt			    p2p_run_after_scan(p2p))
31738da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt				break;
31748da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt			if (p2p->state == P2P_SEARCH) {
31758da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt				wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
31768da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt					"P2P: Continue find after "
31778da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt					"after_scan_tx completion");
31788da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt				p2p_continue_find(p2p);
31798da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt			}
31808da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt		}
31818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
31828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_REQUEST:
31838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_req_cb(p2p, success);
31848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
31858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_RESPONSE:
31868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_resp_cb(p2p, success);
31878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
31888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_RESPONSE_FAILURE:
31898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_resp_failure_cb(p2p, success);
31908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
31918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_CONFIRM:
31928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_conf_cb(p2p, result);
31938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
31948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_SD:
31958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_sd_cb(p2p, success);
31968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
31978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_PD:
31988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_prov_disc_cb(p2p, success);
31998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
32008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_INVITATION_REQUEST:
32018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_invitation_req_cb(p2p, success);
32028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
32038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_INVITATION_RESPONSE:
32048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_invitation_resp_cb(p2p, success);
32058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
32068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_DEV_DISC_REQUEST:
32078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_disc_req_cb(p2p, success);
32088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
32098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_DEV_DISC_RESPONSE:
32108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_disc_resp_cb(p2p, success);
32118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
32128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_DISC_REQ:
32138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_disc_req_cb(p2p, success);
32148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
32158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32168da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt
32178da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt	p2p->after_scan_tx_in_progress = 0;
32188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_listen_cb(struct p2p_data *p2p, unsigned int freq,
32228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   unsigned int duration)
32238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
32248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq == p2p->pending_client_disc_freq) {
32258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
32268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Client discoverability remain-awake completed");
32278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_client_disc_freq = 0;
32288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
32298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq != p2p->pending_listen_freq) {
32328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
32338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Unexpected listen callback for freq=%u "
32348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"duration=%u (pending_listen_freq=%u)",
32358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq, duration, p2p->pending_listen_freq);
32368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
32378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
32408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Starting Listen timeout(%u,%u) on freq=%u based on "
32418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"callback",
32428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_sec, p2p->pending_listen_usec,
32438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_freq);
32448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->in_listen = 1;
32458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->drv_in_listen = freq;
32468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->pending_listen_sec || p2p->pending_listen_usec) {
32478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
32488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Add 20 msec extra wait to avoid race condition with driver
32498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * remain-on-channel end event, i.e., give driver more time to
32508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * complete the operation before our timeout expires.
32518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
32528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_timeout(p2p, p2p->pending_listen_sec,
32538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p->pending_listen_usec + 20000);
32548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_freq = 0;
32578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_listen_end(struct p2p_data *p2p, unsigned int freq)
32618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
32628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Driver ended Listen "
32638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"state (freq=%u)", freq);
32648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->drv_in_listen = 0;
32658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->in_listen)
32668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* Internal timeout will trigger the next step */
32678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_CONNECT_LISTEN && p2p->go_neg_peer) {
32698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->go_neg_peer->connect_reqs >= 120) {
32708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
32718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Timeout on sending GO Negotiation "
32728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Request without getting response");
32738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
32748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 0;
32758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
32768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_CONNECT);
32788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, p2p->go_neg_peer);
32798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
32808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (p2p->state == P2P_SEARCH) {
3281c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (p2p->p2p_scan_running) {
3282c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 /*
3283c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * Search is already in progress. This can happen if
3284c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * an Action frame RX is reported immediately after
3285c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * the end of a remain-on-channel operation and the
3286c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * response frame to that is sent using an offchannel
3287c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * operation while in p2p_find. Avoid an attempt to
3288c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * restart a scan here.
3289c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  */
3290c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan "
3291c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				"already in progress - do not try to start a "
3292c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				"new one");
3293c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			return 1;
3294c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		}
329504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (p2p->pending_listen_freq) {
329604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			/*
329704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 * Better wait a bit if the driver is unable to start
329804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 * offchannel operation for some reason. p2p_search()
329904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 * will be started from internal timeout.
330004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 */
330104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Listen "
330204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				"operation did not seem to start - delay "
330304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				"search phase to avoid busy loop");
330404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			p2p_set_timeout(p2p, 0, 100000);
330504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			return 1;
330604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
330761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->search_delay) {
330861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Delay "
330961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				"search operation by %u ms",
331061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				p2p->search_delay);
331161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p_set_timeout(p2p, p2p->search_delay / 1000,
331261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					(p2p->search_delay % 1000) * 1000);
331361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return 1;
331461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
33158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_search(p2p);
33168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
33178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
33208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_connect(struct p2p_data *p2p)
33248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
332604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p->go_neg_peer &&
332704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    (p2p->go_neg_peer->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM)) {
332804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Wait for GO "
332904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			"Negotiation Confirm timed out - assume GO "
333004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			"Negotiation failed");
333104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
333204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return;
333304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
33348c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	if (p2p->go_neg_peer &&
33358c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	    (p2p->go_neg_peer->flags & P2P_DEV_PEER_WAITING_RESPONSE) &&
33368c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	    p2p->go_neg_peer->connect_reqs < 120) {
33378c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer expected to "
33388c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt			"wait our response - skip listen");
33398c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		p2p_connect_send(p2p, p2p->go_neg_peer);
33408c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		return;
33418c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	}
33428c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt
33438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_CONNECT_LISTEN);
3344d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p_listen_in_find(p2p, 0);
33458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_connect_listen(struct p2p_data *p2p)
33498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer) {
33518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->drv_in_listen) {
33528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Driver is "
33538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"still in Listen state; wait for it to "
33548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"complete");
33558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
33568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
33578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->go_neg_peer->connect_reqs >= 120) {
33598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
33608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Timeout on sending GO Negotiation "
33618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Request without getting response");
33628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
33638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
33648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
33658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_CONNECT);
33678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, p2p->go_neg_peer);
33688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
33698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
33708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_wait_peer_connect(struct p2p_data *p2p)
33748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
33768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * TODO: could remain constantly in Listen state for some time if there
33778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * are no other concurrent uses for the radio. For now, go to listen
33788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * state once per second to give other uses a chance to use the radio.
33798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
33808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_WAIT_PEER_IDLE);
33811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_set_timeout(p2p, 0, 500000);
33828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_wait_peer_idle(struct p2p_data *p2p)
33868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p->go_neg_peer;
33888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
33908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
33918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Unknown GO Neg peer - stop GO Neg wait");
33928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
33938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wait_count++;
33968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->wait_count >= 120) {
33978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
33988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Timeout on waiting peer to become ready for GO "
33998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Negotiation");
34008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_failed(p2p, dev, -1);
34018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
34028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
34058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Go to Listen state while waiting for the peer to become "
34068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"ready for GO Negotiation");
34078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_WAIT_PEER_CONNECT);
3408d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p_listen_in_find(p2p, 0);
34098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_sd_during_find(struct p2p_data *p2p)
34138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
34158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Service Discovery Query timeout");
34168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->sd_peer) {
34178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
34188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE;
34198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->sd_peer = NULL;
34208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_continue_find(p2p);
34228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_prov_disc_during_find(struct p2p_data *p2p)
34268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
34288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Provision Discovery Request timeout");
34298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
34308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_continue_find(p2p);
34318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
343475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic void p2p_timeout_prov_disc_req(struct p2p_data *p2p)
343575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
343675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
343775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
343875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
343975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * For user initiated PD requests that we have not gotten any responses
344075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * for while in IDLE state, we retry them a couple of times before
344175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * giving up.
344275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
344375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (!p2p->user_initiated_pd)
344475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
344575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
344675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
344775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		"P2P: User initiated Provision Discovery Request timeout");
344875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
344975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p->pd_retries) {
345075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pd_retries--;
345175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p_retry_pd(p2p);
345275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	} else {
3453d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		struct p2p_device *dev;
3454d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		int for_join = 0;
3455d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
3456d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
3457d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			if (os_memcmp(p2p->pending_pd_devaddr,
3458d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				      dev->info.p2p_device_addr, ETH_ALEN) != 0)
3459d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				continue;
3460d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			if (dev->req_config_methods &&
3461d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			    (dev->flags & P2P_DEV_PD_FOR_JOIN))
3462d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				for_join = 1;
3463d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		}
3464d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
346575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->cfg->prov_disc_fail)
346675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx,
346775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen						 p2p->pending_pd_devaddr,
3468d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt						 for_join ?
3469d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt						 P2P_PROV_DISC_TIMEOUT_JOIN :
347075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen						 P2P_PROV_DISC_TIMEOUT);
347175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p_reset_pending_pd(p2p);
347275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	}
347375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
347475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
347575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
34768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_invite(struct p2p_data *p2p)
34778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
34798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_INVITE_LISTEN);
34808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->inv_role == P2P_INVITE_ROLE_ACTIVE_GO) {
34818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
34828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Better remain on operating channel instead of listen channel
34838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * when running a group.
34848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
34858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Inviting in "
34868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"active GO role - wait on operating channel");
34878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_timeout(p2p, 0, 100000);
34888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
34898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3490d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p_listen_in_find(p2p, 0);
34918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_invite_listen(struct p2p_data *p2p)
34958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->invite_peer && p2p->invite_peer->invitation_reqs < 100) {
34978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_INVITE);
34988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_invite_send(p2p, p2p->invite_peer,
34998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p->invite_go_dev_addr);
35008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
35018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->invite_peer) {
35028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
35038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Invitation Request retry limit reached");
35048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (p2p->cfg->invitation_result)
35058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p->cfg->invitation_result(
3506700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt					p2p->cfg->cb_ctx, -1, NULL, NULL,
3507700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt					p2p->invite_peer->info.p2p_device_addr);
35088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
35098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
35108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
35118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
35128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_state_timeout(void *eloop_ctx, void *timeout_ctx)
35158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
35168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
35178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Timeout (state=%s)",
35198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state));
35208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->in_listen = 0;
35228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (p2p->state) {
35248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_IDLE:
352575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/* Check if we timed out waiting for PD req */
352675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->pending_action_state == P2P_PENDING_PD)
352775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_timeout_prov_disc_req(p2p);
35288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SEARCH:
353075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/* Check if we timed out waiting for PD req */
353175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->pending_action_state == P2P_PENDING_PD)
353275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_timeout_prov_disc_req(p2p);
353361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->search_delay && !p2p->in_search_delay) {
353461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Delay "
353561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				"search operation by %u ms",
353661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				p2p->search_delay);
353761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p->in_search_delay = 1;
353861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p_set_timeout(p2p, p2p->search_delay / 1000,
353961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					(p2p->search_delay % 1000) * 1000);
354061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			break;
354161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
354261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->in_search_delay = 0;
35438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_search(p2p);
35448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT:
35468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_connect(p2p);
35478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT_LISTEN:
35498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_connect_listen(p2p);
35508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG:
35528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_LISTEN_ONLY:
355475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/* Check if we timed out waiting for PD req */
355575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->pending_action_state == P2P_PENDING_PD)
355675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_timeout_prov_disc_req(p2p);
355775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
35588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->ext_listen_only) {
35598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
35608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Extended Listen Timing - Listen State "
35618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"completed");
35628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->ext_listen_only = 0;
35638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_set_state(p2p, P2P_IDLE);
35648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
35658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_CONNECT:
35678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_wait_peer_connect(p2p);
35688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_IDLE:
35708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_wait_peer_idle(p2p);
35718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SD_DURING_FIND:
35738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_sd_during_find(p2p);
35748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROVISIONING:
35768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PD_DURING_FIND:
35788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_prov_disc_during_find(p2p);
35798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE:
35818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_invite(p2p);
35828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE_LISTEN:
35848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_invite_listen(p2p);
35858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case P2P_SEARCH_WHEN_READY:
35871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
358861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	case P2P_CONTINUE_SEARCH_WHEN_READY:
358961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		break;
35908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
35918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
35928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_reject(struct p2p_data *p2p, const u8 *peer_addr)
35958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
35968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
35978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
35998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Local request to reject "
36008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"connection attempts by peer " MACSTR, MAC2STR(peer_addr));
36018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
36028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR
36038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			" unknown", MAC2STR(peer_addr));
36048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
36058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
36068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->status = P2P_SC_FAIL_REJECTED_BY_USER;
36078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_USER_REJECTED;
36088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
36098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
36108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtconst char * p2p_wps_method_text(enum p2p_wps_method method)
36138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
36148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (method) {
36158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_NOT_READY:
36168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "not-ready";
36178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_PIN_DISPLAY:
36188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "Display";
36198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_PIN_KEYPAD:
36208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "Keypad";
36218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_PBC:
36228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "PBC";
36238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
36248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return "??";
36268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
36278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * p2p_go_state_text(enum p2p_go_state go_state)
36308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
36318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (go_state) {
36328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case UNKNOWN_GO:
36338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "unknown";
36348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case LOCAL_GO:
36358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "local";
36368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case  REMOTE_GO:
36378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "remote";
36388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
36398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return "??";
36418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
36428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtconst struct p2p_peer_info * p2p_get_peer_info(struct p2p_data *p2p,
36451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					       const u8 *addr, int next)
36468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
36478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
36488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr)
36508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, addr);
36518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
36528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = dl_list_first(&p2p->devices, struct p2p_device, list);
36538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev && next) {
36558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = dl_list_first(&dev->list, struct p2p_device, list);
36568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (&dev->list == &p2p->devices)
36578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev = NULL;
36588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
36598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
36611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return NULL;
36621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
36631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return &dev->info;
36641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
36651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
36661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
36671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_get_peer_info_txt(const struct p2p_peer_info *info,
36681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			  char *buf, size_t buflen)
36691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
36701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_device *dev;
36711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int res;
36721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	char *pos, *end;
36731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct os_time now;
36741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
36751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (info == NULL)
36768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
36778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	dev = (struct p2p_device *) (((u8 *) info) -
36791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				     offsetof(struct p2p_device, info));
36801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
36818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf;
36828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = buf + buflen;
36838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&now);
36858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = os_snprintf(pos, end - pos,
36868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "age=%d\n"
36878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "listen_freq=%d\n"
36888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "wps_method=%s\n"
36898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "interface_addr=" MACSTR "\n"
36908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "member_in_go_dev=" MACSTR "\n"
36918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "member_in_go_iface=" MACSTR "\n"
36928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "go_neg_req_sent=%d\n"
36938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "go_state=%s\n"
36948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dialog_token=%u\n"
36958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "intended_addr=" MACSTR "\n"
36968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "country=%c%c\n"
36978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "oper_freq=%d\n"
36988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "req_config_methods=0x%x\n"
36998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "flags=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n"
37008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "status=%d\n"
37018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "wait_count=%u\n"
37028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "invitation_reqs=%u\n",
37038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  (int) (now.sec - dev->last_seen.sec),
37048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->listen_freq,
37058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  p2p_wps_method_text(dev->wps_method),
37068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->interface_addr),
37078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->member_in_go_dev),
37088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->member_in_go_iface),
37098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->go_neg_req_sent,
37108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  p2p_go_state_text(dev->go_state),
37118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->dialog_token,
37128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->intended_addr),
37138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->country[0] ? dev->country[0] : '_',
37148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->country[1] ? dev->country[1] : '_',
37158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->oper_freq,
37168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->req_config_methods,
37178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PROBE_REQ_ONLY ?
37188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PROBE_REQ_ONLY]" : "",
37198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_REPORTED ? "[REPORTED]" : "",
37208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_NOT_YET_READY ?
37218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[NOT_YET_READY]" : "",
37228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_SD_INFO ? "[SD_INFO]" : "",
37238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_SD_SCHEDULE ? "[SD_SCHEDULE]" :
37248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "",
37258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PD_PEER_DISPLAY ?
37268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PD_PEER_DISPLAY]" : "",
37278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PD_PEER_KEYPAD ?
37288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PD_PEER_KEYPAD]" : "",
37298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_USER_REJECTED ?
37308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[USER_REJECTED]" : "",
37318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PEER_WAITING_RESPONSE ?
37328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PEER_WAITING_RESPONSE]" : "",
37338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PREFER_PERSISTENT_GROUP ?
37348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PREFER_PERSISTENT_GROUP]" : "",
37358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_WAIT_GO_NEG_RESPONSE ?
37368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[WAIT_GO_NEG_RESPONSE]" : "",
37378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM ?
37388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[WAIT_GO_NEG_CONFIRM]" : "",
37398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_GROUP_CLIENT_ONLY ?
37408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[GROUP_CLIENT_ONLY]" : "",
37418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_FORCE_FREQ ?
37428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[FORCE_FREQ]" : "",
37438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PD_FOR_JOIN ?
37448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PD_FOR_JOIN]" : "",
37458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->status,
37468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->wait_count,
37478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->invitation_reqs);
37488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0 || res >= end - pos)
37498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return pos - buf;
37508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += res;
37518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->ext_listen_period) {
37538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = os_snprintf(pos, end - pos,
37548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "ext_listen_period=%u\n"
37558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "ext_listen_interval=%u\n",
37568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  dev->ext_listen_period,
37578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  dev->ext_listen_interval);
37588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res < 0 || res >= end - pos)
37598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos - buf;
37608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += res;
37618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->oper_ssid_len) {
37648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = os_snprintf(pos, end - pos,
37658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "oper_ssid=%s\n",
37668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  wpa_ssid_txt(dev->oper_ssid,
37678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       dev->oper_ssid_len));
37688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res < 0 || res >= end - pos)
37698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos - buf;
37708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += res;
37718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
377361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
377461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (dev->info.wfd_subelems) {
377561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		res = os_snprintf(pos, end - pos, "wfd_subelems=");
377661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (res < 0 || res >= end - pos)
377761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return pos - buf;
377861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += res;
377961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
378061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += wpa_snprintf_hex(pos, end - pos,
378161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					wpabuf_head(dev->info.wfd_subelems),
378261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					wpabuf_len(dev->info.wfd_subelems));
378361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
378461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		res = os_snprintf(pos, end - pos, "\n");
378561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (res < 0 || res >= end - pos)
378661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return pos - buf;
378761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += res;
378861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
378961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
379061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
37918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return pos - buf;
37928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
37938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_peer_known(struct p2p_data *p2p, const u8 *addr)
37961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
37971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return p2p_get_device(p2p, addr) != NULL;
37981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
37991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
38001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
38018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_client_discoverability(struct p2p_data *p2p, int enabled)
38028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
38038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (enabled) {
38048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Client "
38058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"discoverability enabled");
38068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
38078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
38088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Client "
38098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"discoverability disabled");
38108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab &= ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
38118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
38138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_presence_req(u32 duration1, u32 interval1,
38168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      u32 duration2, u32 interval2)
38178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
38188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
38198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_noa_desc desc1, desc2, *ptr1 = NULL, *ptr2 = NULL;
38208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
38218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req = wpabuf_alloc(100);
38238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL)
38248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
38258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (duration1 || interval1) {
38278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(&desc1, 0, sizeof(desc1));
38288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc1.count_type = 1;
38298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc1.duration = duration1;
38308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc1.interval = interval1;
38318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ptr1 = &desc1;
38328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (duration2 || interval2) {
38348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(&desc2, 0, sizeof(desc2));
38358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc2.count_type = 2;
38368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc2.duration = duration2;
38378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc2.interval = interval2;
38388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ptr2 = &desc2;
38398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
38408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_action_hdr(req, P2P_PRESENCE_REQ, 1);
38438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(req);
38448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_noa(req, 0, 0, 0, ptr1, ptr2);
38458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(req, len);
38468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return req;
38488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
38498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_presence_req(struct p2p_data *p2p, const u8 *go_interface_addr,
38528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     const u8 *own_interface_addr, unsigned int freq,
38538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     u32 duration1, u32 interval1, u32 duration2,
38548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     u32 interval2)
38558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
38568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
38578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send Presence Request to "
38598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"GO " MACSTR " (own interface " MACSTR ") freq=%u dur1=%u "
38608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"int1=%u dur2=%u int2=%u",
38618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(go_interface_addr), MAC2STR(own_interface_addr),
38628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		freq, duration1, interval1, duration2, interval2);
38638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req = p2p_build_presence_req(duration1, interval1, duration2,
38658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     interval2);
38668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL)
38678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
38688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
38708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_send_action(p2p, freq, go_interface_addr, own_interface_addr,
38718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    go_interface_addr,
38728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpabuf_head(req), wpabuf_len(req), 200) < 0) {
38738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
38748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to send Action frame");
38758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(req);
38778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
38798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
38808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_presence_resp(u8 status, const u8 *noa,
38838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       size_t noa_len, u8 dialog_token)
38848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
38858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
38868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
38878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = wpabuf_alloc(100 + noa_len);
38898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
38908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
38918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_action_hdr(resp, P2P_PRESENCE_RESP, dialog_token);
38938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(resp);
38948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_status(resp, status);
38958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (noa) {
38968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(resp, P2P_ATTR_NOTICE_OF_ABSENCE);
38978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_le16(resp, noa_len);
38988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_data(resp, noa, noa_len);
38998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
39008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_noa(resp, 0, 0, 0, NULL, NULL);
39018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(resp, len);
39028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return resp;
39048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_req(struct p2p_data *p2p, const u8 *da,
39088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const u8 *sa, const u8 *data, size_t len,
39098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     int rx_freq)
39108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
39118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
39128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 status;
39138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
39148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t g;
39158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group *group = NULL;
39168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int parsed = 0;
39178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 noa[50];
39188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int noa_len;
39198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
39218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Received P2P Action - P2P Presence Request");
39228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (g = 0; g < p2p->num_groups; g++) {
39248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(da, p2p_group_get_interface_addr(p2p->groups[g]),
39258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      ETH_ALEN) == 0) {
39268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group = p2p->groups[g];
39278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
39288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
39298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group == NULL) {
39318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
39328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Ignore P2P Presence Request for unknown group "
39338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MACSTR, MAC2STR(da));
39348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
39358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse(data, len, &msg) < 0) {
39388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
39398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to parse P2P Presence Request");
39408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		status = P2P_SC_FAIL_INVALID_PARAMS;
39418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
39428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	parsed = 1;
39448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.noa == NULL) {
39468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
39478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No NoA attribute in P2P Presence Request");
39488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		status = P2P_SC_FAIL_INVALID_PARAMS;
39498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
39508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	status = p2p_group_presence_req(group, sa, msg.noa, msg.noa_len);
39538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail:
39558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->get_noa)
39568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		noa_len = p2p->cfg->get_noa(p2p->cfg->cb_ctx, da, noa,
39578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    sizeof(noa));
39588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
39598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		noa_len = -1;
39608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = p2p_build_presence_resp(status, noa_len > 0 ? noa : NULL,
39618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       noa_len > 0 ? noa_len : 0,
39628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       msg.dialog_token);
39638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (parsed)
39648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
39658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
39668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
39678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
39698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_send_action(p2p, rx_freq, sa, da, da,
39708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
39718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
39728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to send Action frame");
39738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(resp);
39758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_resp(struct p2p_data *p2p, const u8 *da,
39798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *sa, const u8 *data, size_t len)
39808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
39818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
39828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
39848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Received P2P Action - P2P Presence Response");
39858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse(data, len, &msg) < 0) {
39878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
39888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to parse P2P Presence Response");
39898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
39908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.status == NULL || msg.noa == NULL) {
39938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
39948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No Status or NoA attribute in P2P Presence "
39958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Response");
39968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
39978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
39988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*msg.status) {
40018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
40028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: P2P Presence Request was rejected: status %u",
40038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*msg.status);
40048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
40058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
40068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
40078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
40098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: P2P Presence Request was accepted");
40108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "P2P: P2P Presence Response - NoA",
40118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    msg.noa, msg.noa_len);
40128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: process NoA */
40138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
40148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
40158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_ext_listen_timeout(void *eloop_ctx, void *timeout_ctx)
40188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
40198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
40208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval) {
40228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Schedule next extended listen timeout */
40238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(p2p->ext_listen_interval_sec,
40248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p->ext_listen_interval_usec,
40258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p_ext_listen_timeout, p2p, NULL);
40268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
40278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_LISTEN_ONLY && p2p->ext_listen_only) {
40298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
40308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * This should not really happen, but it looks like the Listen
40318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * command may fail is something else (e.g., a scan) was
40328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * running at an inconvenient time. As a workaround, allow new
40338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Extended Listen operation to be started.
40348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
40358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Previous "
40368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Extended Listen operation had not been completed - "
40378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"try again");
40388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_only = 0;
40398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
40408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
40418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state != P2P_IDLE) {
40438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Skip Extended "
40448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Listen timeout in active state (%s)",
40458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_state_txt(p2p->state));
40468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
40478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
40488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Extended Listen timeout");
40508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_only = 1;
40518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_listen(p2p, p2p->ext_listen_period) < 0) {
40528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Failed to start "
40538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Listen state for Extended Listen Timing");
40548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_only = 0;
40558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
40568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
40578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_ext_listen(struct p2p_data *p2p, unsigned int period,
40608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   unsigned int interval)
40618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
40628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (period > 65535 || interval > 65535 || period > interval ||
40638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (period == 0 && interval > 0) || (period > 0 && interval == 0)) {
40648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
40658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Invalid Extended Listen Timing request: "
40668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"period=%u interval=%u", period, interval);
40678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
40688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
40698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_ext_listen_timeout, p2p, NULL);
40718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (interval == 0) {
40738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
40748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Disabling Extended Listen Timing");
40758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_period = 0;
40768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_interval = 0;
40778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
40788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
40798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
40818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Enabling Extended Listen Timing: period %u msec, "
40828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"interval %u msec", period, interval);
40838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_period = period;
40848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_interval = interval;
40858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_interval_sec = interval / 1000;
40868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_interval_usec = (interval % 1000) * 1000;
40878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(p2p->ext_listen_interval_sec,
40898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p->ext_listen_interval_usec,
40908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p_ext_listen_timeout, p2p, NULL);
40918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
40938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
40948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_deauth_notif(struct p2p_data *p2p, const u8 *bssid, u16 reason_code,
40978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      const u8 *ie, size_t ie_len)
40988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
40998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
41008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bssid == NULL || ie == NULL)
41028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
41038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
41058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg))
41068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
41078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.minor_reason_code == NULL)
41088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
41098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_INFO,
41118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Deauthentication notification BSSID " MACSTR
41128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" reason_code=%u minor_reason_code=%u",
41138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(bssid), reason_code, *msg.minor_reason_code);
41148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
41168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_disassoc_notif(struct p2p_data *p2p, const u8 *bssid, u16 reason_code,
41208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const u8 *ie, size_t ie_len)
41218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
41228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
41238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bssid == NULL || ie == NULL)
41258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
41268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
41288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg))
41298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
41308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.minor_reason_code == NULL)
41318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
41328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_INFO,
41348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Disassociation notification BSSID " MACSTR
41358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" reason_code=%u minor_reason_code=%u",
41368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(bssid), reason_code, *msg.minor_reason_code);
41378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
41398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_managed_oper(struct p2p_data *p2p, int enabled)
41438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
41448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (enabled) {
41458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Managed P2P "
41468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Device operations enabled");
41478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_INFRA_MANAGED;
41488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
41498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Managed P2P "
41508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Device operations disabled");
41518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab &= ~P2P_DEV_CAPAB_INFRA_MANAGED;
41528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
41538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel)
41578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
41588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_channel_to_freq(p2p->cfg->country, reg_class, channel) < 0)
41598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
41608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Set Listen channel: "
41628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"reg_class %u channel %u", reg_class, channel);
41638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->reg_class = reg_class;
41648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->channel = channel;
41658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
41678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_ssid_postfix(struct p2p_data *p2p, const u8 *postfix, size_t len)
41718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
41728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "P2P: New SSID postfix", postfix, len);
41738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (postfix == NULL) {
41748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->ssid_postfix_len = 0;
41758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
41768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
41778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > sizeof(p2p->cfg->ssid_postfix))
41788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
41798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->ssid_postfix, postfix, len);
41808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->ssid_postfix_len = len;
41818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
41828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
418575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenint p2p_set_oper_channel(struct p2p_data *p2p, u8 op_reg_class, u8 op_channel,
418675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			 int cfg_op_channel)
418775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
418875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p_channel_to_freq(p2p->cfg->country, op_reg_class, op_channel)
418975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	    < 0)
419075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return -1;
419175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
419275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, "P2P: Set Operating channel: "
419375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		"reg_class %u channel %u", op_reg_class, op_channel);
419475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->cfg->op_reg_class = op_reg_class;
419575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->cfg->op_channel = op_channel;
419675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->cfg->cfg_op_channel = cfg_op_channel;
419775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	return 0;
419875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
419975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
420075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
420104949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint p2p_set_pref_chan(struct p2p_data *p2p, unsigned int num_pref_chan,
420204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		      const struct p2p_channel *pref_chan)
420304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
420404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct p2p_channel *n;
420504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
420604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (pref_chan) {
420704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		n = os_malloc(num_pref_chan * sizeof(struct p2p_channel));
420804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (n == NULL)
420904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			return -1;
421004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(n, pref_chan,
421104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			  num_pref_chan * sizeof(struct p2p_channel));
421204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	} else
421304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		n = NULL;
421404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
421504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	os_free(p2p->cfg->pref_chan);
421604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p->cfg->pref_chan = n;
421704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p->cfg->num_pref_chan = num_pref_chan;
421804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
421904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return 0;
422004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
422104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
422204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
42238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_interface_addr(struct p2p_data *p2p, const u8 *dev_addr,
42248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   u8 *iface_addr)
42258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
42268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p_get_device(p2p, dev_addr);
42278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL || is_zero_ether_addr(dev->interface_addr))
42288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
42298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(iface_addr, dev->interface_addr, ETH_ALEN);
42308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
42318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
42328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_dev_addr(struct p2p_data *p2p, const u8 *iface_addr,
42358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   u8 *dev_addr)
42368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
42378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p_get_device_interface(p2p, iface_addr);
42388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
42398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
42408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev_addr, dev->info.p2p_device_addr, ETH_ALEN);
42418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
42428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
42438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_peer_filter(struct p2p_data *p2p, const u8 *addr)
42468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
42478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->peer_filter, addr, ETH_ALEN);
42488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (is_zero_ether_addr(p2p->peer_filter))
42498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Disable peer "
42508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"filter");
42518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
42528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Enable peer "
42538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"filter for " MACSTR, MAC2STR(p2p->peer_filter));
42548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
42558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_cross_connect(struct p2p_data *p2p, int enabled)
42588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
42598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Cross connection %s",
42608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		enabled ? "enabled" : "disabled");
42618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cross_connect == enabled)
42628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
42638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cross_connect = enabled;
42648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: may need to tear down any action group where we are GO(?) */
42658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
42668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_oper_freq(struct p2p_data *p2p, const u8 *iface_addr)
42698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
42708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p_get_device_interface(p2p, iface_addr);
42718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
42728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
42738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->oper_freq <= 0)
42748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
42758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return dev->oper_freq;
42768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
42778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_intra_bss_dist(struct p2p_data *p2p, int enabled)
42808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
42818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Intra BSS distribution %s",
42828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		enabled ? "enabled" : "disabled");
42838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->p2p_intra_bss = enabled;
42848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
42858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_update_channel_list(struct p2p_data *p2p, struct p2p_channels *chan)
42888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
42898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Update channel list");
42908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&p2p->cfg->channels, chan, sizeof(struct p2p_channels));
42918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
42928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_send_action(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
42958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    const u8 *src, const u8 *bssid, const u8 *buf,
42968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    size_t len, unsigned int wait_time)
42978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
42988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
42998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Delay Action "
43008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"frame TX until p2p_scan completes");
43018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->after_scan_tx) {
43028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Dropped "
43038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"previous pending Action frame TX");
43048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(p2p->after_scan_tx);
43058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
43068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = os_malloc(sizeof(*p2p->after_scan_tx) +
43078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       len);
43088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->after_scan_tx == NULL)
43098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
43108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx->freq = freq;
43118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx->dst, dst, ETH_ALEN);
43128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx->src, src, ETH_ALEN);
43138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx->bssid, bssid, ETH_ALEN);
43148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx->len = len;
43158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx->wait_time = wait_time;
43168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx + 1, buf, len);
43178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
43188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
43198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, dst, src, bssid,
43218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     buf, len, wait_time);
43228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
43238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_best_channels(struct p2p_data *p2p, int freq_24, int freq_5,
43268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   int freq_overall)
43278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
43288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Best channel: 2.4 GHz: %d,"
43298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  5 GHz: %d,  overall: %d", freq_24, freq_5, freq_overall);
43308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->best_freq_24 = freq_24;
43318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->best_freq_5 = freq_5;
43328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->best_freq_overall = freq_overall;
43338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
43348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4336700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidtvoid p2p_set_own_freq_preference(struct p2p_data *p2p, int freq)
4337700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt{
4338700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Own frequency preference: "
4339700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt		"%d MHz", freq);
4340700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	p2p->own_freq_preference = freq;
4341700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt}
4342700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt
4343700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt
43448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * p2p_get_go_neg_peer(struct p2p_data *p2p)
43458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
43468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p == NULL || p2p->go_neg_peer == NULL)
43478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
43488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p->go_neg_peer->info.p2p_device_addr;
43498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
43508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst struct p2p_peer_info *
43538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtp2p_get_peer_found(struct p2p_data *p2p, const u8 *addr, int next)
43548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
43558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
43568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr) {
43588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, addr);
43598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!dev)
43608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
43618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!next) {
43638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev->flags & P2P_DEV_PROBE_REQ_ONLY)
43648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return NULL;
43658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return &dev->info;
43678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
43688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			do {
43698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev = dl_list_first(&dev->list,
43708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    struct p2p_device,
43718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    list);
43728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				if (&dev->list == &p2p->devices)
43738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					return NULL;
43748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} while (dev->flags & P2P_DEV_PROBE_REQ_ONLY);
43758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
43768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
43778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = dl_list_first(&p2p->devices, struct p2p_device, list);
43788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!dev)
43798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
43808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (dev->flags & P2P_DEV_PROBE_REQ_ONLY) {
43818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev = dl_list_first(&dev->list,
43828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    struct p2p_device,
43838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    list);
43848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (&dev->list == &p2p->devices)
43858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return NULL;
43868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
43878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
43888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return &dev->info;
43908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
43911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
43921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef ANDROID_P2P
43931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_search_in_progress(struct p2p_data *p2p)
43941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
43951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p == NULL)
43961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
43971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
43981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return p2p->state == P2P_SEARCH;
43991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
44001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif
44011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
44021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_in_progress(struct p2p_data *p2p)
44031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
44041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p == NULL)
44051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
440661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->state == P2P_SEARCH || p2p->state == P2P_SEARCH_WHEN_READY ||
440761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	    p2p->state == P2P_CONTINUE_SEARCH_WHEN_READY)
440861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return 2;
44091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return p2p->state != P2P_IDLE && p2p->state != P2P_PROVISIONING;
44101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
441161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
441261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
441361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid p2p_set_config_timeout(struct p2p_data *p2p, u8 go_timeout,
441461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			    u8 client_timeout)
441561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
441661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p) {
441761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->go_timeout = go_timeout;
441861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->client_timeout = client_timeout;
441961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
442061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
442161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
442261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
442361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid p2p_increase_search_delay(struct p2p_data *p2p, unsigned int delay)
442461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
442561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p && p2p->search_delay < delay)
442661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->search_delay = delay;
442761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
442861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
442961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
443061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
443161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
443261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void p2p_update_wfd_ie_groups(struct p2p_data *p2p)
443361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
443461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t g;
443561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct p2p_group *group;
443661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
443761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	for (g = 0; g < p2p->num_groups; g++) {
443861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		group = p2p->groups[g];
443961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_group_update_ies(group);
444061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
444161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
444261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
444361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
444461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_beacon(struct p2p_data *p2p, struct wpabuf *ie)
444561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
444661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_beacon);
444761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_beacon = ie;
444861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_update_wfd_ie_groups(p2p);
444961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
445061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
445161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
445261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
445361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_probe_req(struct p2p_data *p2p, struct wpabuf *ie)
445461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
445561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_probe_req);
445661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_probe_req = ie;
445761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
445861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
445961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
446061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
446161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_probe_resp(struct p2p_data *p2p, struct wpabuf *ie)
446261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
446361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_probe_resp);
446461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_probe_resp = ie;
446561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_update_wfd_ie_groups(p2p);
446661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
446761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
446861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
446961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
447061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_assoc_req(struct p2p_data *p2p, struct wpabuf *ie)
447161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
447261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_assoc_req);
447361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_assoc_req = ie;
447461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
447561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
447661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
447761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
447861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_invitation(struct p2p_data *p2p, struct wpabuf *ie)
447961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
448061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_invitation);
448161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_invitation = ie;
448261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
448361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
448461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
448561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
448661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_prov_disc_req(struct p2p_data *p2p, struct wpabuf *ie)
448761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
448861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_prov_disc_req);
448961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_prov_disc_req = ie;
449061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
449161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
449261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
449361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
449461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_prov_disc_resp(struct p2p_data *p2p, struct wpabuf *ie)
449561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
449661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_prov_disc_resp);
449761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_prov_disc_resp = ie;
449861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
449961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
450061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
450161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
450261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_go_neg(struct p2p_data *p2p, struct wpabuf *ie)
450361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
450461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_go_neg);
450561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_go_neg = ie;
450661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
450761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
450861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
450961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
451061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_dev_info(struct p2p_data *p2p, const struct wpabuf *elem)
451161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
451261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_dev_info);
451361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (elem) {
451461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_dev_info = wpabuf_dup(elem);
451561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->wfd_dev_info == NULL)
451661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
451761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else
451861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_dev_info = NULL;
451961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
452061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
452161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
452261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
452361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
452461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_assoc_bssid(struct p2p_data *p2p, const struct wpabuf *elem)
452561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
452661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_assoc_bssid);
452761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (elem) {
452861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_assoc_bssid = wpabuf_dup(elem);
452961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->wfd_assoc_bssid == NULL)
453061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
453161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else
453261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_assoc_bssid = NULL;
453361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
453461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
453561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
453661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
453761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
453861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_coupled_sink_info(struct p2p_data *p2p,
453961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				  const struct wpabuf *elem)
454061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
454161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_coupled_sink_info);
454261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (elem) {
454361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_coupled_sink_info = wpabuf_dup(elem);
454461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->wfd_coupled_sink_info == NULL)
454561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
454661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else
454761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_coupled_sink_info = NULL;
454861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
454961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
455061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
455161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
455261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
4553d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
4554d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
4555d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtint p2p_set_disc_int(struct p2p_data *p2p, int min_disc_int, int max_disc_int,
4556d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		     int max_disc_tu)
4557d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt{
4558d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (min_disc_int > max_disc_int || min_disc_int < 0 || max_disc_int < 0)
4559d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return -1;
4560d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
4561d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p->min_disc_int = min_disc_int;
4562d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p->max_disc_int = max_disc_int;
4563d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p->max_disc_tu = max_disc_tu;
4564d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Set discoverable interval: "
4565d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		"min=%d max=%d max_tu=%d", min_disc_int, max_disc_int,
4566d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		max_disc_tu);
4567d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
4568d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	return 0;
4569d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt}
4570