p2p.c revision 8c65289885e84727226d81b3d32856f79c31ee5f
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) {
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO: schedule p2p_run_after_scan to be called from TX
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * status callback(?) */
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send pending "
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Action frame at p2p_scan completion");
9951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p->cfg->send_action(p2p->cfg->cb_ctx,
9961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->freq,
9971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->dst,
9981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->src,
9991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->bssid,
10001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      (u8 *) (p2p->after_scan_tx + 1),
10011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->len,
10021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->wait_time);
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p2p->after_scan_tx);
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = NULL;
1005f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#ifdef ANDROID_P2P
1006f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		/* For SD frames, there is a scenario, where we can receive a SD request frame during p2p_scan.
1007f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * At that moment, we will send the SD response from this context. After sending the SD response,
1008f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * we need to continue p2p_find. But if we return 1 from here, p2p_find is going to be stopped.
1009f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 */
1010f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		return 0;
1011f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#else
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
1013f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#endif
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	op = p2p->start_after_scan;
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (op) {
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_AFTER_SCAN_NOTHING:
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_AFTER_SCAN_LISTEN:
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Start previously "
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"requested Listen state");
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_listen(p2p, p2p->pending_listen_sec * 1000 +
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   p2p->pending_listen_usec / 1000);
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_AFTER_SCAN_CONNECT:
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Start previously "
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"requested connect with " MACSTR,
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(p2p->after_scan_peer));
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, p2p->after_scan_peer);
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev == NULL) {
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer not "
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"known anymore");
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, dev);
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_scan_timeout(void *eloop_ctx, void *timeout_ctx)
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int running;
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan timeout "
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"(running=%d)", p2p->p2p_scan_running);
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	running = p2p->p2p_scan_running;
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Make sure we recover from missed scan results callback */
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->p2p_scan_running = 0;
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (running)
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_run_after_scan(p2p);
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_free_req_dev_types(struct p2p_data *p2p)
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->num_req_dev_types = 0;
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->req_dev_types);
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->req_dev_types = NULL;
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_find(struct p2p_data *p2p, unsigned int timeout,
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     enum p2p_discovery_type type,
1070c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	     unsigned int num_req_dev_types, const u8 *req_dev_types,
107161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	     const u8 *dev_id, unsigned int search_delay)
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting find (type=%d)",
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type);
1077f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	os_get_time(&p2p->find_start);
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan is "
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"already running");
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_req_dev_types(p2p);
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req_dev_types && num_req_dev_types) {
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->req_dev_types = os_malloc(num_req_dev_types *
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       WPS_DEV_TYPE_LEN);
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->req_dev_types == NULL)
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->req_dev_types, req_dev_types,
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  num_req_dev_types * WPS_DEV_TYPE_LEN);
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->num_req_dev_types = num_req_dev_types;
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1094c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (dev_id) {
1095c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		os_memcpy(p2p->find_dev_id_buf, dev_id, ETH_ALEN);
1096c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		p2p->find_dev_id = p2p->find_dev_id_buf;
1097c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	} else
1098c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		p2p->find_dev_id = NULL;
1099c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->find_type = type;
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_device_clear_reported(p2p);
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_SEARCH);
110661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->search_delay = search_delay;
110761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->in_search_delay = 0;
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
11091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p->last_p2p_find_timeout = timeout;
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (timeout)
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(timeout, 0, p2p_find_timeout,
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p, NULL);
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (type) {
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_FIND_START_WITH_FULL:
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_FIND_PROGRESSIVE:
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_FULL, 0,
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 p2p->num_req_dev_types,
111804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 p2p->req_dev_types, dev_id,
111904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 DEV_PW_DEFAULT);
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_FIND_ONLY_SOCIAL:
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_SOCIAL, 0,
11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 p2p->num_req_dev_types,
112404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 p2p->req_dev_types, dev_id,
112504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 DEV_PW_DEFAULT);
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res == 0) {
11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Running p2p_scan");
11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->p2p_scan_running = 1;
11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(P2P_SCAN_TIMEOUT, 0, p2p_scan_timeout,
11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p, NULL);
11371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	} else if (res == 1) {
11381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Could not start "
11391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			"p2p_scan at this point - will try again after "
11401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			"previous scan completes");
11411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		res = 0;
11421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_set_state(p2p, P2P_SEARCH_WHEN_READY);
11431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Failed to start "
11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"p2p_scan");
11471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
11481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11542fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt#ifdef ANDROID_P2P
11552fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidtint p2p_search_pending(struct p2p_data *p2p)
11562fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt{
11572fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt	if(p2p == NULL)
11582fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		return 0;
11592fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt
11602fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt	if(p2p->state == P2P_SEARCH_WHEN_READY)
11612fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		return 1;
11622fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt
11632fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt	return 0;
11642fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt}
11652fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt#endif
11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_other_scan_completed(struct p2p_data *p2p)
11681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
116961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->state == P2P_CONTINUE_SEARCH_WHEN_READY) {
117061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_set_state(p2p, P2P_SEARCH);
117161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_search(p2p);
117261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return 1;
117361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
11741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p->state != P2P_SEARCH_WHEN_READY)
11751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
11761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting pending P2P find "
11771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		"now that previous scan was completed");
11781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p_find(p2p, p2p->last_p2p_find_timeout, p2p->find_type,
1179c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		     p2p->num_req_dev_types, p2p->req_dev_types,
1180f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		     p2p->find_dev_id, p2p->search_delay) < 0) {
1181f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, P2P_EVENT_FIND_STOPPED);
11821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
1183f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	}
11841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return 1;
11851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
11861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_stop_find_for_freq(struct p2p_data *p2p, int freq)
11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Stopping find");
11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
1193a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (p2p->state == P2P_SEARCH ||
1194a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	    p2p->state == P2P_CONTINUE_SEARCH_WHEN_READY ||
1195a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	    p2p->state == P2P_SEARCH_WHEN_READY)
1196c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, P2P_EVENT_FIND_STOPPED);
11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_IDLE);
11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_req_dev_types(p2p);
11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
12008c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	if (p2p->go_neg_peer)
12018c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		p2p->go_neg_peer->flags &= ~P2P_DEV_PEER_WAITING_RESPONSE;
12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer = NULL;
12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->sd_peer = NULL;
12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->invite_peer = NULL;
120504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_stop_listen_for_freq(p2p, freq);
120604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
120704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
120804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
120904949598a23f501be6eec21697465fd46a28840aDmitry Shmidtvoid p2p_stop_listen_for_freq(struct p2p_data *p2p, int freq)
121004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq > 0 && p2p->drv_in_listen == freq && p2p->in_listen) {
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Skip stop_listen "
12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"since we are on correct channel for response");
12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
121604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p->in_listen) {
121704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->in_listen = 0;
121804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p_clear_timeout(p2p);
121904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
12201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p->drv_in_listen) {
12211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/*
12221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * The driver may not deliver callback to p2p_listen_end()
12231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * when the operation gets canceled, so clear the internal
12241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * variable that is tracking driver state.
12251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
12261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Clear "
12271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			"drv_in_listen (%d)", p2p->drv_in_listen);
12281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p->drv_in_listen = 0;
12291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_stop_find(struct p2p_data *p2p)
12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_stop_find_for_freq(p2p, 0);
12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1240a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtstatic int p2p_prepare_channel_pref(struct p2p_data *p2p,
1241a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt				    unsigned int force_freq,
1242a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt				    unsigned int pref_freq)
12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1244a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	u8 op_class, op_channel;
1245a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	unsigned int freq = force_freq ? force_freq : pref_freq;
12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1247a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (p2p_freq_to_channel(p2p->cfg->country, freq,
1248a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt				&op_class, &op_channel) < 0) {
1249a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
1250a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			"P2P: Unsupported frequency %u MHz", freq);
1251a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
1252a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
1253a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1254a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (!p2p_channels_includes(&p2p->cfg->channels, op_class, op_channel)) {
1255a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
1256a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			"P2P: Frequency %u MHz (oper_class %u channel %u) not "
1257a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			"allowed for P2P", freq, op_class, op_channel);
1258a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
1259a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
1260a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1261a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	p2p->op_reg_class = op_class;
1262a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	p2p->op_channel = op_channel;
12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1264a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (force_freq) {
1265a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->channels.reg_classes = 1;
1266a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->channels.reg_class[0].channels = 1;
1267a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->channels.reg_class[0].reg_class = p2p->op_reg_class;
1268a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->channels.reg_class[0].channel[0] = p2p->op_channel;
1269a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	} else {
12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(&p2p->channels, &p2p->cfg->channels,
12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(struct p2p_channels));
12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1273a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1274a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	return 0;
1275a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt}
1276a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1277a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1278a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtstatic void p2p_prepare_channel_best(struct p2p_data *p2p)
1279a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{
1280a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	u8 op_class, op_channel;
1281a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1282a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (!p2p->cfg->cfg_op_channel && p2p->best_freq_overall > 0 &&
1283a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	    p2p_supported_freq(p2p, p2p->best_freq_overall) &&
1284a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	    p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_overall,
1285a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt				&op_class, &op_channel) == 0) {
1286a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Select best "
1287a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			"overall channel as operating channel preference");
1288a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_reg_class = op_class;
1289a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_channel = op_channel;
1290a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	} else if (!p2p->cfg->cfg_op_channel && p2p->best_freq_5 > 0 &&
1291a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		   p2p_supported_freq(p2p, p2p->best_freq_5) &&
1292a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		   p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_5,
1293a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt				       &op_class, &op_channel) == 0) {
1294a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Select best 5 GHz "
1295a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			"channel as operating channel preference");
1296a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_reg_class = op_class;
1297a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_channel = op_channel;
1298a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	} else if (!p2p->cfg->cfg_op_channel && p2p->best_freq_24 > 0 &&
1299a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		   p2p_supported_freq(p2p, p2p->best_freq_24) &&
1300a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		   p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_24,
1301a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt				       &op_class, &op_channel) == 0) {
1302a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Select best 2.4 "
1303a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			"GHz channel as operating channel preference");
1304a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_reg_class = op_class;
1305a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_channel = op_channel;
1306a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	} else {
1307a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_reg_class = p2p->cfg->op_reg_class;
1308a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_channel = p2p->cfg->op_channel;
1309a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
1310a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1311a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	os_memcpy(&p2p->channels, &p2p->cfg->channels,
1312a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		  sizeof(struct p2p_channels));
1313a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt}
1314a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1315a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1316a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt/**
1317a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * p2p_prepare_channel - Select operating channel for GO Negotiation
1318a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @p2p: P2P module context from p2p_init()
1319a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @dev: Selected peer device
1320a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @force_freq: Forced frequency in MHz or 0 if not forced
1321a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @pref_freq: Preferred frequency in MHz or 0 if no preference
1322a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Returns: 0 on success, -1 on failure (channel not supported for P2P)
1323a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *
1324a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * This function is used to do initial operating channel selection for GO
1325a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Negotiation prior to having received peer information. The selected channel
1326a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * may be further optimized in p2p_reselect_channel() once the peer information
1327a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * is available.
1328a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt */
1329a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtstatic int p2p_prepare_channel(struct p2p_data *p2p, struct p2p_device *dev,
1330a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			       unsigned int force_freq, unsigned int pref_freq)
1331a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{
1332a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (force_freq || pref_freq) {
1333a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		if (p2p_prepare_channel_pref(p2p, force_freq, pref_freq) < 0)
1334a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			return -1;
1335a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	} else {
1336a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p_prepare_channel_best(p2p);
1337a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Own preference for operation channel: "
13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"Operating Class %u Channel %u%s",
13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->op_reg_class, p2p->op_channel,
13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		force_freq ? " (forced)" : "");
13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1344a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (force_freq)
1345a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		dev->flags |= P2P_DEV_FORCE_FREQ;
1346a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	else
1347a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		dev->flags &= ~P2P_DEV_FORCE_FREQ;
1348a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void p2p_set_dev_persistent(struct p2p_device *dev,
13541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   int persistent_group)
13551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
13561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	switch (persistent_group) {
13571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case 0:
13581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags &= ~(P2P_DEV_PREFER_PERSISTENT_GROUP |
13591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				P2P_DEV_PREFER_PERSISTENT_RECONN);
13601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
13611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case 1:
13621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP;
13631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags &= ~P2P_DEV_PREFER_PERSISTENT_RECONN;
13641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
13651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case 2:
13661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP |
13671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			P2P_DEV_PREFER_PERSISTENT_RECONN;
13681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
13691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
13701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
13711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
13721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		enum p2p_wps_method wps_method,
13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int go_intent, const u8 *own_interface_addr,
137604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		unsigned int force_freq, int persistent_group,
137704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		const u8 *force_ssid, size_t force_ssid_len,
1378d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		int pd_before_go_neg, unsigned int pref_freq)
13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Request to start group negotiation - peer=" MACSTR
13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  GO Intent=%d  Intended Interface Address=" MACSTR
1385d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		" wps_method=%d persistent_group=%d pd_before_go_neg=%d",
13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
1387d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wps_method, persistent_group, pd_before_go_neg);
13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Cannot connect to unknown P2P Device " MACSTR,
13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(peer_addr));
13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1397a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (p2p_prepare_channel(p2p, dev, force_freq, pref_freq) < 0)
1398a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
1399a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!(dev->info.dev_capab &
14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Cannot connect to P2P Device " MACSTR
14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				" that is in a group and is not discoverable",
14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(peer_addr));
14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->oper_freq <= 0) {
14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Cannot connect to P2P Device " MACSTR
14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				" with incomplete information",
14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(peer_addr));
14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * First, try to connect directly. If the peer does not
14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * acknowledge frames, assume it is sleeping and use device
14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * discoverability via the GO at that point.
14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
142404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p->ssid_set = 0;
142504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (force_ssid) {
142604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "P2P: Forced SSID",
142704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  force_ssid, force_ssid_len);
142804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(p2p->ssid, force_ssid, force_ssid_len);
142904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->ssid_len = force_ssid_len;
143004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->ssid_set = 1;
143104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
143204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_NOT_YET_READY;
14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_USER_REJECTED;
14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE;
14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM;
143704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (pd_before_go_neg)
143804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->flags |= P2P_DEV_PD_BEFORE_GO_NEG;
1439a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	else {
144004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->flags &= ~P2P_DEV_PD_BEFORE_GO_NEG;
1441a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		/*
14429cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt		 * Assign dialog token and tie breaker here to use the same
14439cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt		 * values in each retry within the same GO Negotiation exchange.
1444a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		 */
1445a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		dev->dialog_token++;
1446a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		if (dev->dialog_token == 0)
1447a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			dev->dialog_token = 1;
14489cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt		dev->tie_breaker = p2p->next_tie_breaker;
14499cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt		p2p->next_tie_breaker = !p2p->next_tie_breaker;
1450a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->connect_reqs = 0;
14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_neg_req_sent = 0;
14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_state = UNKNOWN_GO;
14541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_set_dev_persistent(dev, persistent_group);
14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_intent = go_intent;
14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state != P2P_IDLE)
14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_stop_find(p2p);
14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->after_scan_tx) {
14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * We need to drop the pending frame to avoid issues with the
14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * new GO Negotiation, e.g., when the pending frame was from a
14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * previous attempt at starting a GO Negotiation.
14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Dropped "
14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"previous pending Action frame TX that was waiting "
14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"for p2p_scan completion");
14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p2p->after_scan_tx);
14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = NULL;
14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wps_method = wps_method;
14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->status = P2P_SC_SUCCESS;
14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: p2p_scan running - delay connect send");
14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->start_after_scan = P2P_AFTER_SCAN_CONNECT;
14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_peer, peer_addr, ETH_ALEN);
14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_connect_send(p2p, dev);
14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  enum p2p_wps_method wps_method,
14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  int go_intent, const u8 *own_interface_addr,
149304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		  unsigned int force_freq, int persistent_group,
1494d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		  const u8 *force_ssid, size_t force_ssid_len,
1495d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		  unsigned int pref_freq)
14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Request to authorize group negotiation - peer=" MACSTR
15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  GO Intent=%d  Intended Interface Address=" MACSTR
15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" wps_method=%d  persistent_group=%d",
15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wps_method, persistent_group);
15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Cannot authorize unknown P2P Device " MACSTR,
15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(peer_addr));
15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1514a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (p2p_prepare_channel(p2p, dev, force_freq, pref_freq) < 0)
1515a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
1516a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
151704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p->ssid_set = 0;
151804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (force_ssid) {
151904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "P2P: Forced SSID",
152004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  force_ssid, force_ssid_len);
152104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(p2p->ssid, force_ssid, force_ssid_len);
152204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->ssid_len = force_ssid_len;
152304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->ssid_set = 1;
152404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
152504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_NOT_YET_READY;
15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_USER_REJECTED;
15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_neg_req_sent = 0;
15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_state = UNKNOWN_GO;
15301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_set_dev_persistent(dev, persistent_group);
15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_intent = go_intent;
15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wps_method = wps_method;
15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->status = P2P_SC_SUCCESS;
15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_add_dev_info(struct p2p_data *p2p, const u8 *addr,
15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      struct p2p_device *dev, struct p2p_message *msg)
15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&dev->last_seen);
15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_copy_wps_info(dev, 0, msg);
15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->listen_channel) {
15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int freq;
15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		freq = p2p_channel_to_freq((char *) msg->listen_channel,
15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   msg->listen_channel[3],
15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   msg->listen_channel[4]);
15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freq < 0) {
15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Unknown peer Listen channel: "
15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"country=%c%c(0x%02x) reg_class=%u channel=%u",
15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[0],
15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[1],
15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[2],
15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[3],
15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[4]);
15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Update "
15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"peer " MACSTR " Listen channel: %u -> %u MHz",
15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(dev->info.p2p_device_addr),
15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev->listen_freq, freq);
15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->listen_freq = freq;
15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
157161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (msg->wfd_subelems) {
157261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_free(dev->info.wfd_subelems);
157361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		dev->info.wfd_subelems = wpabuf_dup(msg->wfd_subelems);
157461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
157561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_PROBE_REQ_ONLY) {
15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~P2P_DEV_PROBE_REQ_ONLY;
15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Completed device entry based on data from "
15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"GO Negotiation Request");
15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Created device entry based on GO Neg Req: "
15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MACSTR " dev_capab=0x%x group_capab=0x%x name='%s' "
15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"listen_freq=%d",
15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr),
15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->info.dev_capab, dev->info.group_capab,
15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->info.device_name, dev->listen_freq);
15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_GROUP_CLIENT_ONLY;
15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_USER_REJECTED) {
15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Do not report rejected device");
15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->dev_found(p2p->cfg->cb_ctx, addr, &dev->info,
16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    !(dev->flags & P2P_DEV_REPORTED_ONCE));
16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_build_ssid(struct p2p_data *p2p, u8 *ssid, size_t *ssid_len)
16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_random((char *) &ssid[P2P_WILDCARD_SSID_LEN], 2);
16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&ssid[P2P_WILDCARD_SSID_LEN + 2],
16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  p2p->cfg->ssid_postfix, p2p->cfg->ssid_postfix_len);
16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*ssid_len = P2P_WILDCARD_SSID_LEN + 2 + p2p->cfg->ssid_postfix_len;
16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_go_params(struct p2p_data *p2p, struct p2p_go_neg_results *params)
16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_build_ssid(p2p, params->ssid, &params->ssid_len);
16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_random(params->passphrase, 8);
16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_go_complete(struct p2p_data *p2p, struct p2p_device *peer)
16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_go_neg_results res;
16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int go = peer->go_state == LOCAL_GO;
16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_channels intersection;
16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freqs;
16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i, j;
16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: GO Negotiation with " MACSTR " completed (%s will be "
16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"GO)", MAC2STR(peer->info.p2p_device_addr),
16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		go ? "local end" : "peer");
16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&res, 0, sizeof(res));
16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.role_go = go;
16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(res.peer_device_addr, peer->info.p2p_device_addr, ETH_ALEN);
16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(res.peer_interface_addr, peer->intended_addr, ETH_ALEN);
16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.wps_method = peer->wps_method;
16411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) {
16421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN)
16431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			res.persistent_group = 2;
16441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		else
16451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			res.persistent_group = 1;
16461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (go) {
16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Setup AP mode for WPS provisioning */
16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res.freq = p2p_channel_to_freq(p2p->cfg->country,
16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       p2p->op_reg_class,
16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       p2p->op_channel);
16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(res.ssid, p2p->ssid, p2p->ssid_len);
16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res.ssid_len = p2p->ssid_len;
16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_random(res.passphrase, 8);
16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res.freq = peer->oper_freq;
16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->ssid_len) {
16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(res.ssid, p2p->ssid, p2p->ssid_len);
16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res.ssid_len = p2p->ssid_len;
16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_channels_intersect(&p2p->channels, &peer->channels,
16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       &intersection);
16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	freqs = 0;
16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < intersection.reg_classes; i++) {
16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct p2p_reg_class *c = &intersection.reg_class[i];
16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freqs + 1 == P2P_MAX_CHANNELS)
16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < c->channels; j++) {
16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			int freq;
16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (freqs + 1 == P2P_MAX_CHANNELS)
16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
16758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq = p2p_channel_to_freq(peer->country, c->reg_class,
16768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   c->channel[j]);
16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (freq < 0)
16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				continue;
16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res.freq_list[freqs++] = freq;
16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.peer_config_timeout = go ? peer->client_timeout : peer->go_timeout;
16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
16861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p->ssid_set = 0;
16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer->go_neg_req_sent = 0;
16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer->wps_method = WPS_NOT_READY;
16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_PROVISIONING);
16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->go_neg_completed(p2p->cfg->cb_ctx, &res);
16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_rx_p2p_action(struct p2p_data *p2p, const u8 *sa,
16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      const u8 *data, size_t len, int rx_freq)
16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: RX P2P Public Action from " MACSTR, MAC2STR(sa));
17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "P2P: P2P Public Action contents", data, len);
17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1)
17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data[0]) {
17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG_REQ:
17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_neg_req(p2p, sa, data + 1, len - 1, rx_freq);
17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG_RESP:
17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_neg_resp(p2p, sa, data + 1, len - 1, rx_freq);
17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG_CONF:
17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_neg_conf(p2p, sa, data + 1, len - 1);
17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITATION_REQ:
17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_invitation_req(p2p, sa, data + 1, len - 1,
17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   rx_freq);
17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITATION_RESP:
17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_invitation_resp(p2p, sa, data + 1, len - 1);
17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROV_DISC_REQ:
17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_prov_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROV_DISC_RESP:
17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_prov_disc_resp(p2p, sa, data + 1, len - 1);
17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_DEV_DISC_REQ:
17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_dev_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_DEV_DISC_RESP:
17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_dev_disc_resp(p2p, sa, data + 1, len - 1);
17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Unsupported P2P Public Action frame type %d",
17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data[0]);
17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void p2p_rx_action_public(struct p2p_data *p2p, const u8 *da,
17441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				 const u8 *sa, const u8 *bssid, const u8 *data,
17451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				 size_t len, int freq)
17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1)
17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data[0]) {
17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_VENDOR_SPECIFIC:
17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data++;
17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len--;
17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 3)
17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (WPA_GET_BE24(data) != OUI_WFA)
17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data += 3;
17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len -= 3;
17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 1)
17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*data != P2P_OUI_TYPE)
17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_p2p_action(p2p, sa, data + 1, len - 1, freq);
17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_INITIAL_REQ:
17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_initial_req(p2p, sa, data + 1, len - 1, freq);
17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_INITIAL_RESP:
17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_initial_resp(p2p, sa, data + 1, len - 1, freq);
17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_COMEBACK_REQ:
17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_comeback_req(p2p, sa, data + 1, len - 1, freq);
17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_COMEBACK_RESP:
17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_comeback_resp(p2p, sa, data + 1, len - 1, freq);
17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_rx_action(struct p2p_data *p2p, const u8 *da, const u8 *sa,
17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *bssid, u8 category,
17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *data, size_t len, int freq)
17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (category == WLAN_ACTION_PUBLIC) {
17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_action_public(p2p, da, sa, bssid, data, len, freq);
17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (category != WLAN_ACTION_VENDOR_SPECIFIC)
17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 4)
17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (WPA_GET_BE24(data) != OUI_WFA)
18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data += 3;
18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len -= 3;
18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*data != P2P_OUI_TYPE)
18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data++;
18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len--;
18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P action frame */
18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: RX P2P Action from " MACSTR, MAC2STR(sa));
18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "P2P: P2P Action contents", data, len);
18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1)
18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data[0]) {
18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_NOA:
18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Received P2P Action - Notice of Absence");
18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO */
18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PRESENCE_REQ:
18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_presence_req(p2p, da, sa, data + 1, len - 1, freq);
18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PRESENCE_RESP:
18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_presence_resp(p2p, da, sa, data + 1, len - 1);
18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_DISC_REQ:
18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_disc_req(p2p, da, sa, data + 1, len - 1, freq);
18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Received P2P Action - unknown type %u", data[0]);
18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_start(void *eloop_ctx, void *timeout_ctx)
18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == NULL)
18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer->status = P2P_SC_SUCCESS;
18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_connect_send(p2p, p2p->go_neg_peer);
18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_invite_start(void *eloop_ctx, void *timeout_ctx)
18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->invite_peer == NULL)
18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_invite_send(p2p, p2p->invite_peer, p2p->invite_go_dev_addr);
18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_add_dev_from_probe_req(struct p2p_data *p2p, const u8 *addr,
18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const u8 *ie, size_t ie_len)
18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
18658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg) < 0 || msg.p2p_attributes == NULL)
18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* not a P2P probe */
18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.ssid == NULL || msg.ssid[1] != P2P_WILDCARD_SSID_LEN ||
18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(msg.ssid + 2, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN)
18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    != 0) {
18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* The Probe Request is not part of P2P Device Discovery. It is
18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * not known whether the source address of the frame is the P2P
18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Device Address or P2P Interface Address. Do not add a new
18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * peer entry based on this frames.
18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev) {
18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->country[0] == 0 && msg.listen_channel)
18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(dev->country, msg.listen_channel, 3);
18901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		os_get_time(&dev->last_seen);
18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* already known */
18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_create_device(p2p, addr);
18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&dev->last_seen);
19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_PROBE_REQ_ONLY;
19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.listen_channel) {
19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->country, msg.listen_channel, 3);
19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->listen_freq = p2p_channel_to_freq(dev->country,
19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       msg.listen_channel[3],
19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       msg.listen_channel[4]);
19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_copy_wps_info(dev, 1, &msg);
19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
191361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (msg.wfd_subelems) {
191461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_free(dev->info.wfd_subelems);
191561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
191661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
191761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Created device entry based on Probe Req: " MACSTR
19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" dev_capab=0x%x group_capab=0x%x name='%s' listen_freq=%d",
19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(dev->info.p2p_device_addr), dev->info.dev_capab,
19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.group_capab, dev->info.device_name,
19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->listen_freq);
19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_device * p2p_add_dev_from_go_neg_req(struct p2p_data *p2p,
19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						const u8 *addr,
19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						struct p2p_message *msg)
19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev) {
19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_get_time(&dev->last_seen);
19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return dev; /* already known */
19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_create_device(p2p, addr);
19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
19448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_add_dev_info(p2p, addr, dev, msg);
19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return dev;
19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int dev_type_match(const u8 *dev_type, const u8 *req_dev_type)
19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(dev_type, req_dev_type, WPS_DEV_TYPE_LEN) == 0)
19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(dev_type, req_dev_type, 2) == 0 &&
19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    WPA_GET_BE32(&req_dev_type[2]) == 0 &&
19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    WPA_GET_BE16(&req_dev_type[6]) == 0)
19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Category match with wildcard OUI/sub-category */
19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint dev_type_list_match(const u8 *dev_type, const u8 *req_dev_type[],
19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			size_t num_req_dev_type)
19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
19678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_req_dev_type; i++) {
19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev_type_match(dev_type, req_dev_type[i]))
19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 1;
19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_match_dev_type - Match local device type with requested type
19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wps: WPS TLVs from Probe Request frame (concatenated WPS IEs)
19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 on match, 0 on mismatch
19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function can be used to match the Requested Device Type attribute in
19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPS IE with the local device types for deciding whether to reply to a Probe
19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Request frame.
19848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_match_dev_type(struct p2p_data *p2p, struct wpabuf *wps)
19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wps_parse_attr attr;
19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wps_parse_msg(wps, &attr))
19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* assume no Requested Device Type attributes */
19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (attr.num_req_dev_type == 0)
19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* no Requested Device Type attributes -> match */
19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev_type_list_match(p2p->cfg->pri_dev_type, attr.req_dev_type,
19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				attr.num_req_dev_type))
19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Own Primary Device Type matches */
19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < p2p->cfg->num_sec_dev_types; i++)
20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev_type_list_match(p2p->cfg->sec_dev_type[i],
20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					attr.req_dev_type,
20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					attr.num_req_dev_type))
20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Own Secondary Device Type matches */
20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* No matching device type found */
20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * p2p_build_probe_resp_ies(struct p2p_data *p2p)
20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
201504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	int pw_id = -1;
201661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t extra = 0;
201761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
201861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
201961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_probe_resp)
202061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		extra = wpabuf_len(p2p->wfd_ie_probe_resp);
202161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
202361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	buf = wpabuf_alloc(1000 + extra);
20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
202704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p->go_neg_peer) {
202804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/* Advertise immediate availability of WPS credential */
202904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		pw_id = p2p_wps_method_pw_id(p2p->go_neg_peer->wps_method);
203004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
203104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
203204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_build_wps_ie(p2p, buf, pw_id, 1);
20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
203461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
203561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_probe_resp)
203661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(buf, p2p->wfd_ie_probe_resp);
203761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
203861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P IE */
20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(buf);
204104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_buf_add_capability(buf, p2p->dev_capab &
204204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			       ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 0);
20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval)
20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_ext_listen_timing(buf, p2p->ext_listen_period,
20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      p2p->ext_listen_interval);
20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_device_info(buf, p2p, NULL);
20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(buf, len);
20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int is_11b(u8 rate)
20541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
20551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
20561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
20571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int supp_rates_11b_only(struct ieee802_11_elems *elems)
20601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
20611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int num_11b = 0, num_others = 0;
20621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int i;
20631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (elems->supp_rates == NULL && elems->ext_supp_rates == NULL)
20651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
20661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (i = 0; elems->supp_rates && i < elems->supp_rates_len; i++) {
20681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (is_11b(elems->supp_rates[i]))
20691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			num_11b++;
20701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		else
20711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			num_others++;
20721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
20731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (i = 0; elems->ext_supp_rates && i < elems->ext_supp_rates_len;
20751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	     i++) {
20761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (is_11b(elems->ext_supp_rates[i]))
20771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			num_11b++;
20781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		else
20791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			num_others++;
20801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
20811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return num_11b > 0 && num_others == 0;
20831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
20841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
208604949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic enum p2p_probe_req_status
208704949598a23f501be6eec21697465fd46a28840aDmitry Shmidtp2p_reply_probe(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
208804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		const u8 *bssid, const u8 *ie, size_t ie_len)
20898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ieee802_11_elems elems;
20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
20928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ieee80211_mgmt *resp;
20931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_message msg;
20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *ies;
20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p->in_listen || !p2p->drv_in_listen) {
20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* not in Listen state - ignore Probe Request */
209804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_LISTEN;
20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ieee802_11_parse_elems((u8 *) ie, ie_len, &elems, 0) ==
21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ParseFailed) {
21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Ignore invalid Probe Request frames */
210404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_MALFORMED;
21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (elems.p2p == NULL) {
21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* not a P2P probe - ignore it */
210904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_P2P;
21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (dst && !is_broadcast_ether_addr(dst) &&
21131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    os_memcmp(dst, p2p->cfg->dev_addr, ETH_ALEN) != 0) {
21141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Not sent to the broadcast address or our P2P Device Address
21151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
211604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
21171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
21181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
21191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (bssid && !is_broadcast_ether_addr(bssid)) {
21201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Not sent to the Wildcard BSSID */
212104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
21221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
21231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (elems.ssid == NULL || elems.ssid_len != P2P_WILDCARD_SSID_LEN ||
21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(elems.ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) !=
21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0) {
21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* not using P2P Wildcard SSID - ignore */
212804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (supp_rates_11b_only(&elems)) {
21321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Indicates support for 11b rates only */
213304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_P2P;
21341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
21351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
21361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
21371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg) < 0) {
21381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Could not parse P2P attributes */
213904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_P2P;
21401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
21411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
21421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (msg.device_id &&
214304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    os_memcmp(msg.device_id, p2p->cfg->dev_addr, ETH_ALEN) != 0) {
21441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Device ID did not match */
21451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_parse_free(&msg);
214604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
21471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
21481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Check Requested Device Type match */
21501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (msg.wps_attributes &&
21511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    !p2p_match_dev_type(p2p, msg.wps_attributes)) {
21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* No match with Requested Device Type */
21531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_parse_free(&msg);
215404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
21558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_parse_free(&msg);
21578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
215804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (!p2p->cfg->send_probe_resp) {
215904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/* Response generated elsewhere */
216004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
216104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Reply to P2P Probe Request in Listen state");
21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * We do not really have a specific BSS that this frame is advertising,
21688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * so build a frame that has some information in valid format. This is
21698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * really only used for discovery purposes, not to learn exact BSS
21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * parameters.
21718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
21728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ies = p2p_build_probe_resp_ies(p2p);
21738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ies == NULL)
217404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
21758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = wpabuf_alloc(200 + wpabuf_len(ies));
21778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL) {
21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(ies);
217904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
21808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = NULL;
21838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = wpabuf_put(buf, resp->u.probe_resp.variable - (u8 *) resp);
21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   (WLAN_FC_STYPE_PROBE_RESP << 4));
21878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(resp->da, addr, ETH_ALEN);
21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(resp->sa, p2p->cfg->dev_addr, ETH_ALEN);
21898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(resp->bssid, p2p->cfg->dev_addr, ETH_ALEN);
21908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->u.probe_resp.beacon_int = host_to_le16(100);
21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* hardware or low-level driver will setup seq_ctrl and timestamp */
21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->u.probe_resp.capab_info =
21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		host_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE |
21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     WLAN_CAPABILITY_PRIVACY |
21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     WLAN_CAPABILITY_SHORT_SLOT_TIME);
21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_SSID);
21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, P2P_WILDCARD_SSID_LEN);
21998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(buf, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_SUPP_RATES);
22028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 8);
22038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, (60 / 5) | 0x80);
22048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 90 / 5);
22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, (120 / 5) | 0x80);
22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 180 / 5);
22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, (240 / 5) | 0x80);
22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 360 / 5);
22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 480 / 5);
22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 540 / 5);
22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_DS_PARAMS);
22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 1);
22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, p2p->cfg->channel);
22158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_buf(buf, ies);
22178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(ies);
22188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_probe_resp(p2p->cfg->cb_ctx, buf);
22208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(buf);
222204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
222304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return P2P_PREQ_NOT_PROCESSED;
22248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
222704949598a23f501be6eec21697465fd46a28840aDmitry Shmidtenum p2p_probe_req_status
222804949598a23f501be6eec21697465fd46a28840aDmitry Shmidtp2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
222904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 const u8 *bssid, const u8 *ie, size_t ie_len)
22308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
223104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	enum p2p_probe_req_status res;
223204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
22338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_add_dev_from_probe_req(p2p, addr, ie, ie_len);
22348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
223504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	res = p2p_reply_probe(p2p, addr, dst, bssid, ie, ie_len);
22368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((p2p->state == P2P_CONNECT || p2p->state == P2P_CONNECT_LISTEN) &&
22388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    p2p->go_neg_peer &&
22398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(addr, p2p->go_neg_peer->info.p2p_device_addr, ETH_ALEN)
22409cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt	    == 0 &&
22419cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt	    !(p2p->go_neg_peer->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM)) {
22428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Received a Probe Request from GO Negotiation peer */
22438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
22448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Found GO Negotiation peer - try to start GO "
22458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"negotiation from timeout");
22469cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt		eloop_cancel_timeout(p2p_go_neg_start, p2p, NULL);
22478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(0, 0, p2p_go_neg_start, p2p, NULL);
224804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_PROCESSED;
22498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((p2p->state == P2P_INVITE || p2p->state == P2P_INVITE_LISTEN) &&
22528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    p2p->invite_peer &&
22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(addr, p2p->invite_peer->info.p2p_device_addr, ETH_ALEN)
22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    == 0) {
22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Received a Probe Request from Invite peer */
22568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
22578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Found Invite peer - try to start Invite from "
22588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"timeout");
22598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(0, 0, p2p_invite_start, p2p, NULL);
226004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_PROCESSED;
22618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
226304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return res;
22648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_assoc_req_ie_wlan_ap(struct p2p_data *p2p, const u8 *bssid,
22688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    u8 *buf, size_t len, struct wpabuf *p2p_ie)
22698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *tmp;
22718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *lpos;
22728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t tmplen;
22738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
22748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 group_capab;
22758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_ie == NULL)
22778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* WLAN AP is not a P2P manager */
22788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (Re)Association Request - P2P IE
22818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Capability attribute (shall be present)
22828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Interface attribute (present if concurrent device and
22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *	P2P Management is enabled)
22848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp = wpabuf_alloc(200);
22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp == NULL)
22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
22888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	lpos = p2p_buf_add_ie_hdr(tmp);
22908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group_capab = 0;
22918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->num_groups > 0) {
22928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group_capab |= P2P_GROUP_CAPAB_GROUP_OWNER;
22938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) &&
22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED) &&
22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    p2p->cross_connect)
22968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_capability(tmp, p2p->dev_capab, group_capab);
22998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) &&
23008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED))
23018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_p2p_interface(tmp, p2p);
23028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(tmp, lpos);
23038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmplen = wpabuf_len(tmp);
23058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmplen > len)
23068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = -1;
23078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
23088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(buf, wpabuf_head(tmp), tmplen);
23098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = tmplen;
23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(tmp);
23128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
23148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_assoc_req_ie(struct p2p_data *p2p, const u8 *bssid, u8 *buf,
23188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     size_t len, int p2p_group, struct wpabuf *p2p_ie)
23198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *tmp;
23218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *lpos;
23228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *peer;
23238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t tmplen;
23248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
232561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t extra = 0;
23268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p_group)
23288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return p2p_assoc_req_ie_wlan_ap(p2p, bssid, buf, len, p2p_ie);
23298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
233061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
233161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_assoc_req)
233261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		extra = wpabuf_len(p2p->wfd_ie_assoc_req);
233361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
233461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
23358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
23368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (Re)Association Request - P2P IE
23378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Capability attribute (shall be present)
23388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Extended Listen Timing (may be present)
23398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Device Info attribute (shall be present)
23408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
234161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	tmp = wpabuf_alloc(200 + extra);
23428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp == NULL)
23438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
23448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
234561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
234661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_assoc_req)
234761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(tmp, p2p->wfd_ie_assoc_req);
234861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
234961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer = bssid ? p2p_get_device(p2p, bssid) : NULL;
23518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	lpos = p2p_buf_add_ie_hdr(tmp);
23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_capability(tmp, p2p->dev_capab, 0);
23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval)
23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_ext_listen_timing(tmp, p2p->ext_listen_period,
23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      p2p->ext_listen_interval);
23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_device_info(tmp, p2p, peer);
23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(tmp, lpos);
23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmplen = wpabuf_len(tmp);
23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmplen > len)
23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = -1;
23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
23648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(buf, wpabuf_head(tmp), tmplen);
23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = tmplen;
23668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(tmp);
23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
23708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_scan_result_text(const u8 *ies, size_t ies_len, char *buf, char *end)
23748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *p2p_ie;
23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len, P2P_IE_VENDOR_TYPE);
23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_ie == NULL)
23808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = p2p_attr_text(p2p_ie, buf, end);
23838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(p2p_ie);
23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
23858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
238804949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint p2p_parse_dev_addr_in_p2p_ie(struct wpabuf *p2p_ie, u8 *dev_addr)
2389c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{
2390c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	struct p2p_message msg;
2391c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
2392c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
239304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p_parse_p2p_ie(p2p_ie, &msg))
2394c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return -1;
2395c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
239604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (msg.p2p_device_addr) {
239704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(dev_addr, msg.p2p_device_addr, ETH_ALEN);
239804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 0;
239904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	} else if (msg.device_id) {
240004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(dev_addr, msg.device_id, ETH_ALEN);
240104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 0;
2402c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
240304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return -1;
240404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
2405c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
240604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
240704949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint p2p_parse_dev_addr(const u8 *ies, size_t ies_len, u8 *dev_addr)
240804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
240904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct wpabuf *p2p_ie;
241004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	int ret;
241104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
241204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
241304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					     P2P_IE_VENDOR_TYPE);
241404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p_ie == NULL)
241504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return -1;
241604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	ret = p2p_parse_dev_addr_in_p2p_ie(p2p_ie, dev_addr);
2417c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	wpabuf_free(p2p_ie);
241804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return ret;
2419c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt}
2420c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
2421c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
24228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_clear_go_neg(struct p2p_data *p2p)
24238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer = NULL;
24258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
24268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_IDLE);
24278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_wps_success_cb(struct p2p_data *p2p, const u8 *mac_addr)
24318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == NULL) {
24338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
24348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No pending Group Formation - "
24358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"ignore WPS registration success notification");
24368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* No pending Group Formation */
24378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(mac_addr, p2p->go_neg_peer->intended_addr, ETH_ALEN) !=
24408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0) {
24418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
24428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Ignore WPS registration success notification "
24438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"for " MACSTR " (GO Negotiation peer " MACSTR ")",
24448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(mac_addr),
24458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(p2p->go_neg_peer->intended_addr));
24468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* Ignore unexpected peer address */
24478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
24508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Group Formation completed successfully with " MACSTR,
24518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(mac_addr));
24528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_go_neg(p2p);
24548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_group_formation_failed(struct p2p_data *p2p)
24588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == NULL) {
24608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
24618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No pending Group Formation - "
24628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"ignore group formation failure notification");
24638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* No pending Group Formation */
24648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
24678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Group Formation failed with " MACSTR,
24688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(p2p->go_neg_peer->intended_addr));
24698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_go_neg(p2p);
24718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_data * p2p_init(const struct p2p_config *cfg)
24758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p;
24778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->max_peers < 1)
24798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
24808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p = os_zalloc(sizeof(*p2p) + sizeof(*cfg));
24828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p == NULL)
24838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
24848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg = (struct p2p_config *) (p2p + 1);
24858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg, cfg, sizeof(*cfg));
24868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->dev_name)
24878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->dev_name = os_strdup(cfg->dev_name);
24888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->manufacturer)
24898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->manufacturer = os_strdup(cfg->manufacturer);
24908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->model_name)
24918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_name = os_strdup(cfg->model_name);
24928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->model_number)
24938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_number = os_strdup(cfg->model_number);
24948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->serial_number)
24958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->serial_number = os_strdup(cfg->serial_number);
249604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (cfg->pref_chan) {
249704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->cfg->pref_chan = os_malloc(cfg->num_pref_chan *
249804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt						sizeof(struct p2p_channel));
249904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (p2p->cfg->pref_chan) {
250004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			os_memcpy(p2p->cfg->pref_chan, cfg->pref_chan,
250104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  cfg->num_pref_chan *
250204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  sizeof(struct p2p_channel));
250304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		} else
250404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			p2p->cfg->num_pref_chan = 0;
250504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
250604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
2507f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#ifdef ANDROID_P2P
2508f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	/* 100ms listen time is too less to receive the response frames in some scenarios
2509f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	 * increasing min listen time to 200ms.
2510f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	 */
2511f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	p2p->min_disc_int = 2;
2512f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	/* SD_FAIR_POLICY: Initializing the SD current serviced pointer to NULL */
2513f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	p2p->sd_dev_list = NULL;
2514f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#else
25158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->min_disc_int = 1;
2516f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#endif
25178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->max_disc_int = 3;
2518d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p->max_disc_tu = -1;
25198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_random(&p2p->next_tie_breaker, 1);
25218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->next_tie_breaker &= 0x01;
25228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->sd_request)
25238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_SERVICE_DISCOVERY;
25248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->dev_capab |= P2P_DEV_CAPAB_INVITATION_PROCEDURE;
25258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->concurrent_operations)
25268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_CONCURRENT_OPER;
25278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->dev_capab |= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
25288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_init(&p2p->devices);
25308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(P2P_PEER_EXPIRATION_INTERVAL, 0,
25328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p_expiration_timeout, p2p, NULL);
25338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
253461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->go_timeout = 100;
253561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->client_timeout = 20;
253661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
25378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p;
25388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_deinit(struct p2p_data *p2p)
25428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
254361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
254461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_beacon);
254561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_probe_req);
254661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_probe_resp);
254761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_assoc_req);
254861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_invitation);
254961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_prov_disc_req);
255061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_prov_disc_resp);
255161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_go_neg);
255261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_dev_info);
255361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_assoc_bssid);
255461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_coupled_sink_info);
255561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
255661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
25578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_expiration_timeout, p2p, NULL);
25588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_ext_listen_timeout, p2p, NULL);
25598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
25609cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt	eloop_cancel_timeout(p2p_go_neg_start, p2p, NULL);
25618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_flush(p2p);
25628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_req_dev_types(p2p);
25638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->dev_name);
25648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->manufacturer);
25658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_name);
25668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_number);
25678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->serial_number);
256804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	os_free(p2p->cfg->pref_chan);
25698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->groups);
25708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(p2p->sd_resp);
25718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->after_scan_tx);
25728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_remove_wps_vendor_extensions(p2p);
25738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p);
25748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_flush(struct p2p_data *p2p)
25788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev, *prev;
258004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_stop_find(p2p);
25818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each_safe(dev, prev, &p2p->devices, struct p2p_device,
25828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      list) {
25838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dl_list_del(&dev->list);
25848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_device_free(p2p, dev);
25858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2586f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#ifdef ANDROID_P2P
2587f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	/* SD_FAIR_POLICY: Initializing the SD current serviced pointer to NULL */
2588f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	p2p->sd_dev_list = NULL;
2589f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#endif
25908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_sd_queries(p2p);
25918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->after_scan_tx);
25928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->after_scan_tx = NULL;
25938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_unauthorize(struct p2p_data *p2p, const u8 *addr)
25978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
25998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
26018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
26028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
26038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Unauthorizing " MACSTR,
26058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(addr));
26068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == dev)
26088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->go_neg_peer = NULL;
26098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wps_method = WPS_NOT_READY;
26118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE;
26128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM;
26138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Check if after_scan_tx is for this peer. If so free it */
26158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->after_scan_tx &&
26168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(addr, p2p->after_scan_tx->dst, ETH_ALEN) == 0) {
26178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p2p->after_scan_tx);
26188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = NULL;
26198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_dev_name(struct p2p_data *p2p, const char *dev_name)
26268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->dev_name);
26288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev_name) {
26298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->dev_name = os_strdup(dev_name);
26308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->dev_name == NULL)
26318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
26328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
26338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->dev_name = NULL;
26348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_manufacturer(struct p2p_data *p2p, const char *manufacturer)
26398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->manufacturer);
26418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->manufacturer = NULL;
26428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (manufacturer) {
26438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->manufacturer = os_strdup(manufacturer);
26448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->manufacturer == NULL)
26458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
26468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_model_name(struct p2p_data *p2p, const char *model_name)
26538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_name);
26558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->model_name = NULL;
26568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (model_name) {
26578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_name = os_strdup(model_name);
26588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->model_name == NULL)
26598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
26608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_model_number(struct p2p_data *p2p, const char *model_number)
26678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_number);
26698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->model_number = NULL;
26708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (model_number) {
26718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_number = os_strdup(model_number);
26728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->model_number == NULL)
26738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
26748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_serial_number(struct p2p_data *p2p, const char *serial_number)
26818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->serial_number);
26838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->serial_number = NULL;
26848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (serial_number) {
26858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->serial_number = os_strdup(serial_number);
26868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->serial_number == NULL)
26878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
26888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_config_methods(struct p2p_data *p2p, u16 config_methods)
26958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->config_methods = config_methods;
26978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_uuid(struct p2p_data *p2p, const u8 *uuid)
27018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->uuid, uuid, 16);
27038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_pri_dev_type(struct p2p_data *p2p, const u8 *pri_dev_type)
27078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->pri_dev_type, pri_dev_type, 8);
27098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
27108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_sec_dev_types(struct p2p_data *p2p, const u8 dev_types[][8],
27148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  size_t num_dev_types)
27158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (num_dev_types > P2P_SEC_DEVICE_TYPES)
27178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num_dev_types = P2P_SEC_DEVICE_TYPES;
27188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->num_sec_dev_types = num_dev_types;
27198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->sec_dev_type, dev_types, num_dev_types * 8);
27208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
27218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_remove_wps_vendor_extensions(struct p2p_data *p2p)
27258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
27278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
27298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(p2p->wps_vendor_ext[i]);
27308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->wps_vendor_ext[i] = NULL;
27318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_add_wps_vendor_extension(struct p2p_data *p2p,
27368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const struct wpabuf *vendor_ext)
27378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
27398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (vendor_ext == NULL)
27418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
27428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
27448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->wps_vendor_ext[i] == NULL)
27458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
27468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (i >= P2P_MAX_WPS_VENDOR_EXT)
27488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
27498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->wps_vendor_ext[i] = wpabuf_dup(vendor_ext);
27518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->wps_vendor_ext[i] == NULL)
27528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
27538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
27558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_country(struct p2p_data *p2p, const char *country)
27598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->country, country, 3);
27618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
27628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_continue_find(struct p2p_data *p2p)
27668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
2768f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#ifdef ANDROID_P2P
2769f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	int skip=1;
2770f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#endif
27718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_SEARCH);
27728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
2773f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#ifdef ANDROID_P2P
2774f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		/* SD_FAIR_POLICY: We need to give chance to all devices in the device list
2775f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * There may be a scenario, where a particular peer device have
2776f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * not registered any query response. When we send a SD request to such device,
2777f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * no response will be received. And if we continue to get probe responses from that device,
2778f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * and if that device happens to be on top in our device list,
2779f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * we will always continue to send SD requests always to that peer only.
2780f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * We will not be able to send SD requests to other devices in that case.
2781f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * This implementation keeps track of last serviced peer device.
2782f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * And then takes the next one from the device list, in the next iteration.
2783f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 */
2784f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		if (p2p->sd_dev_list && p2p->sd_dev_list != &p2p->devices) {
2785f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff			if(skip) {
2786f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff				if ((&dev->list == p2p->sd_dev_list) ) {
2787f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff					skip = 0;
2788f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff					if (dev->list.next == &p2p->devices)
2789f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff						p2p->sd_dev_list = NULL;
2790f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff				}
2791f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff				continue;
2792f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff			}
2793f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		}
2794f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		p2p->sd_dev_list = &dev->list;
2795f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		wpa_printf(MSG_DEBUG, "P2P: ### Servicing %p dev->flags 0x%x SD schedule %s devaddr " MACSTR,
2796f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff			p2p->sd_dev_list, dev->flags, dev->flags & P2P_DEV_SD_SCHEDULE ? "TRUE": "FALSE",
2797f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff			MAC2STR(dev->info.p2p_device_addr));
2798f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#endif
27998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->flags & P2P_DEV_SD_SCHEDULE) {
28008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (p2p_start_sd(p2p, dev) == 0)
28018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
28028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
28038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
28048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (dev->req_config_methods &&
28058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   !(dev->flags & P2P_DEV_PD_FOR_JOIN)) {
28068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send "
28071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				"pending Provision Discovery Request to "
28088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MACSTR " (config methods 0x%x)",
28098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(dev->info.p2p_device_addr),
28108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev->req_config_methods);
28111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (p2p_send_prov_disc_req(p2p, dev, 0, 0) == 0)
28128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
28138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
28148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2816d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p_listen_in_find(p2p, 1);
28178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_sd_cb(struct p2p_data *p2p, int success)
28218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
28238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Service Discovery Query TX callback: success=%d",
28248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
28258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
28268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!success) {
28288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->sd_peer) {
28298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE;
28308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->sd_peer = NULL;
28318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
28328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
28338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
28348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->sd_peer == NULL) {
28378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
28388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No SD peer entry known");
28398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
28408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
28418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Wait for response from the peer */
28448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_SD_DURING_FIND);
28458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_timeout(p2p, 0, 200000);
28468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
284875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
284975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen/**
285075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen * p2p_retry_pd - Retry any pending provision disc requests in IDLE state
285175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen * @p2p: P2P module context from p2p_init()
285275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen */
28531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void p2p_retry_pd(struct p2p_data *p2p)
285475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
285575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	struct p2p_device *dev;
285675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
285775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p->state != P2P_IDLE)
285875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
285975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
286075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
286175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * Retry the prov disc req attempt only for the peer that the user had
2862d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	 * requested.
286375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
286475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
286575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
286675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (os_memcmp(p2p->pending_pd_devaddr,
286775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			      dev->info.p2p_device_addr, ETH_ALEN) != 0)
286875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			continue;
286975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (!dev->req_config_methods)
287075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			continue;
287175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
287275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send "
28731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			"pending Provision Discovery Request to "
287475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			MACSTR " (config methods 0x%x)",
287575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			MAC2STR(dev->info.p2p_device_addr),
287675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			dev->req_config_methods);
2877d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		p2p_send_prov_disc_req(p2p, dev,
2878d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				       dev->flags & P2P_DEV_PD_FOR_JOIN, 0);
287975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
288075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	}
288175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
288275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
288375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
28848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_prov_disc_cb(struct p2p_data *p2p, int success)
28858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
28878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Provision Discovery Request TX callback: success=%d",
28888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
288975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
289075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
289175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * Postpone resetting the pending action state till after we actually
289275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * time out. This allows us to take some action like notifying any
289375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * interested parties about no response to the request.
289475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 *
289575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * When the timer (below) goes off we check in IDLE, SEARCH, or
289675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * LISTEN_ONLY state, which are the only allowed states to issue a PD
289775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * requests in, if this was still pending and then raise notification.
289875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
28998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!success) {
290175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pending_action_state = P2P_NO_PENDING_ACTION;
290275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
290361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->user_initiated_pd &&
290461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		    (p2p->state == P2P_SEARCH || p2p->state == P2P_LISTEN_ONLY))
290561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		{
290661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			/* Retry request from timeout to avoid busy loops */
290761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p->pending_action_state = P2P_PENDING_PD;
290861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p_set_timeout(p2p, 0, 50000);
290961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		} else if (p2p->state != P2P_IDLE)
29108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_continue_find(p2p);
291175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		else if (p2p->user_initiated_pd) {
291275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p->pending_action_state = P2P_PENDING_PD;
29131a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#ifdef ANDROID_P2P
29141a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff			p2p_set_timeout(p2p, 0, 350000);
29151a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#else
291675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_set_timeout(p2p, 0, 300000);
29171a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#endif
291875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		}
29198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
29208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
292275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
292375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * This postponing, of resetting pending_action_state, needs to be
292475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * done only for user initiated PD requests and not internal ones.
292575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
292675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p->user_initiated_pd)
292775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pending_action_state = P2P_PENDING_PD;
292875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	else
292975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pending_action_state = P2P_NO_PENDING_ACTION;
293075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
29318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Wait for response from the peer */
29328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_SEARCH)
29338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_PD_DURING_FIND);
29341a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#ifdef ANDROID_P2P
29351a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff	p2p_set_timeout(p2p, 0, 350000);
29361a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#else
29378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_timeout(p2p, 0, 200000);
29381a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#endif
29398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_scan_res_handler(struct p2p_data *p2p, const u8 *bssid, int freq,
2943f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			 struct os_time *rx_time, int level, const u8 *ies,
2944a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			 size_t ies_len)
29458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2946f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	if (os_time_before(rx_time, &p2p->find_start)) {
2947f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		/*
2948f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * The driver may have cached (e.g., in cfg80211 BSS table) the
2949f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * scan results for relatively long time. To avoid reporting
2950f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * stale information, update P2P peers only based on results
2951f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * that have based on frames received after the last p2p_find
2952f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * operation was started.
2953f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 */
2954f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Ignore old scan "
2955f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			"result for " MACSTR " (rx_time=%u.%06u)",
2956f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			MAC2STR(bssid), (unsigned int) rx_time->sec,
2957f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			(unsigned int) rx_time->usec);
2958f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		return 0;
2959f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	}
2960f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
2961f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	p2p_add_device(p2p, bssid, freq, rx_time, level, ies, ies_len, 1);
29628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
29648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_scan_res_handled(struct p2p_data *p2p)
29688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p->p2p_scan_running) {
29708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan was not "
29718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"running, but scan results received");
29728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->p2p_scan_running = 0;
29748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
29758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_run_after_scan(p2p))
29778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
29788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_SEARCH)
29798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
29808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2983c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtvoid p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id)
29848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
298561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 *len;
298661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
298761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
298861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_probe_req)
298961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(ies, p2p->wfd_ie_probe_req);
299061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
299161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
299261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	len = p2p_buf_add_ie_hdr(ies);
299304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_buf_add_capability(ies, p2p->dev_capab &
299404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			       ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 0);
2995c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (dev_id)
2996c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		p2p_buf_add_device_id(ies, dev_id);
29978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->reg_class && p2p->cfg->channel)
29988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_listen_channel(ies, p2p->cfg->country,
29998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   p2p->cfg->reg_class,
30008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   p2p->cfg->channel);
30018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval)
30028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_ext_listen_timing(ies, p2p->ext_listen_period,
30038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      p2p->ext_listen_interval);
30048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: p2p_buf_add_operating_channel() if GO */
30058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(ies, len);
30068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtsize_t p2p_scan_ie_buf_len(struct p2p_data *p2p)
30101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
301161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t len = 100;
301261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
301361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
301461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p && p2p->wfd_ie_probe_req)
301561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		len += wpabuf_len(p2p->wfd_ie_probe_req);
301661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
301761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
301861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return len;
30191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
30201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
30211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
30228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_ie_text(struct wpabuf *p2p_ie, char *buf, char *end)
30238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_attr_text(p2p_ie, buf, end);
30258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_req_cb(struct p2p_data *p2p, int success)
30298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p->go_neg_peer;
30318c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	int timeout;
30328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
30348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: GO Negotiation Request TX callback: success=%d",
30358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
30368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
30388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
30398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No pending GO Negotiation");
30408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
30418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (success) {
30448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->flags & P2P_DEV_USER_REJECTED) {
30458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_set_state(p2p, P2P_IDLE);
30468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
30478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
304804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	} else if (dev->go_neg_req_sent) {
304904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/* Cancel the increment from p2p_connect_send() on failure */
305098f9e76624da6bb96edc1982c423e4a119c5170aDmitry Shmidt		dev->go_neg_req_sent--;
305198f9e76624da6bb96edc1982c423e4a119c5170aDmitry Shmidt	}
30528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!success &&
30548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (dev->info.dev_capab & P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY) &&
30558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !is_zero_ether_addr(dev->member_in_go_dev)) {
30568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
30578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Peer " MACSTR " did not acknowledge request - "
30588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"try to use device discoverability through its GO",
30598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr));
30608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
30618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_send_dev_disc_req(p2p, dev);
30628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
30638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
30668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Use P2P find, if needed, to find the other device from its listen
30678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * channel.
30688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
30698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_CONNECT);
30708c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	timeout = success ? 500000 : 100000;
30718c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	if (!success && p2p->go_neg_peer &&
30728c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	    (p2p->go_neg_peer->flags & P2P_DEV_PEER_WAITING_RESPONSE)) {
30738c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		unsigned int r;
30748c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		/*
30758c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		 * Peer is expected to wait our response and we will skip the
30768c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		 * listen phase. Add some randomness to the wait time here to
30778c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		 * make it less likely to hit cases where we could end up in
30788c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		 * sync with peer not listening.
30798c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		 */
30808c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		os_get_random((u8 *) &r, sizeof(r));
30818c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		timeout += r % 100000;
30828c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	}
30838c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	p2p_set_timeout(p2p, 0, timeout);
30848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_resp_cb(struct p2p_data *p2p, int success)
30888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
30908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: GO Negotiation Response TX callback: success=%d",
30918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
30928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p->go_neg_peer && p2p->state == P2P_PROVISIONING) {
30938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
30948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Ignore TX callback event - GO Negotiation is "
30958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"not running anymore");
30968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
30978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_CONNECT);
30998c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	p2p_set_timeout(p2p, 0, 500000);
31008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_resp_failure_cb(struct p2p_data *p2p, int success)
31048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
31068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: GO Negotiation Response (failure) TX callback: "
31078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"success=%d", success);
31088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer && p2p->go_neg_peer->status != P2P_SC_SUCCESS) {
31098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_failed(p2p, p2p->go_neg_peer,
31108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  p2p->go_neg_peer->status);
31118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_conf_cb(struct p2p_data *p2p,
31168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       enum p2p_send_action_result result)
31178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
31198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
31218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: GO Negotiation Confirm TX callback: result=%d",
31228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		result);
31238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
31248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (result == P2P_SEND_ACTION_FAILED) {
31258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
31268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
31278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (result == P2P_SEND_ACTION_NO_ACK) {
31298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
31308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * It looks like the TX status for GO Negotiation Confirm is
31318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * often showing failure even when the peer has actually
31328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * received the frame. Since the peer may change channels
31338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * immediately after having received the frame, we may not see
31348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * an Ack for retries, so just dropping a single frame may
31358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * trigger this. To allow the group formation to succeed if the
31368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * peer did indeed receive the frame, continue regardless of
31378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * the TX status.
31388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
31398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
31408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Assume GO Negotiation Confirm TX was actually "
31418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"received by the peer even though Ack was not "
31428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"reported");
31438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p->go_neg_peer;
31468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
31478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
31488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_go_complete(p2p, dev);
31508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_send_action_cb(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
31548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const u8 *src, const u8 *bssid,
31558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			enum p2p_send_action_result result)
31568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum p2p_pending_action_state state;
31588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int success;
31598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
31618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Action frame TX callback (state=%d freq=%u dst=" MACSTR
31628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" src=" MACSTR " bssid=" MACSTR " result=%d",
31638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_action_state, freq, MAC2STR(dst), MAC2STR(src),
31648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(bssid), result);
31658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	success = result == P2P_SEND_ACTION_SUCCESS;
31668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	state = p2p->pending_action_state;
31678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
31688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (state) {
31698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_NO_PENDING_ACTION:
31708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
31718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_REQUEST:
31728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_req_cb(p2p, success);
31738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
31748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_RESPONSE:
31758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_resp_cb(p2p, success);
31768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
31778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_RESPONSE_FAILURE:
31788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_resp_failure_cb(p2p, success);
31798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
31808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_CONFIRM:
31818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_conf_cb(p2p, result);
31828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
31838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_SD:
31848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_sd_cb(p2p, success);
31858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
31868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_PD:
31878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_prov_disc_cb(p2p, success);
31888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
31898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_INVITATION_REQUEST:
31908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_invitation_req_cb(p2p, success);
31918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
31928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_INVITATION_RESPONSE:
31938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_invitation_resp_cb(p2p, success);
31948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
31958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_DEV_DISC_REQUEST:
31968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_disc_req_cb(p2p, success);
31978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
31988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_DEV_DISC_RESPONSE:
31998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_disc_resp_cb(p2p, success);
32008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
32018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_DISC_REQ:
32028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_disc_req_cb(p2p, success);
32038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
32048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_listen_cb(struct p2p_data *p2p, unsigned int freq,
32098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   unsigned int duration)
32108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
32118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq == p2p->pending_client_disc_freq) {
32128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
32138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Client discoverability remain-awake completed");
32148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_client_disc_freq = 0;
32158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
32168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq != p2p->pending_listen_freq) {
32198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
32208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Unexpected listen callback for freq=%u "
32218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"duration=%u (pending_listen_freq=%u)",
32228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq, duration, p2p->pending_listen_freq);
32238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
32248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
32278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Starting Listen timeout(%u,%u) on freq=%u based on "
32288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"callback",
32298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_sec, p2p->pending_listen_usec,
32308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_freq);
32318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->in_listen = 1;
32328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->drv_in_listen = freq;
32338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->pending_listen_sec || p2p->pending_listen_usec) {
32348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
32358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Add 20 msec extra wait to avoid race condition with driver
32368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * remain-on-channel end event, i.e., give driver more time to
32378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * complete the operation before our timeout expires.
32388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
32398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_timeout(p2p, p2p->pending_listen_sec,
32408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p->pending_listen_usec + 20000);
32418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_freq = 0;
32448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_listen_end(struct p2p_data *p2p, unsigned int freq)
32488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
32498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Driver ended Listen "
32508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"state (freq=%u)", freq);
32518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->drv_in_listen = 0;
32528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->in_listen)
32538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* Internal timeout will trigger the next step */
32548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_CONNECT_LISTEN && p2p->go_neg_peer) {
32568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->go_neg_peer->connect_reqs >= 120) {
32578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
32588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Timeout on sending GO Negotiation "
32598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Request without getting response");
32608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
32618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 0;
32628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
32638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_CONNECT);
32658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, p2p->go_neg_peer);
32668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
32678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (p2p->state == P2P_SEARCH) {
3268c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (p2p->p2p_scan_running) {
3269c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 /*
3270c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * Search is already in progress. This can happen if
3271c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * an Action frame RX is reported immediately after
3272c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * the end of a remain-on-channel operation and the
3273c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * response frame to that is sent using an offchannel
3274c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * operation while in p2p_find. Avoid an attempt to
3275c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * restart a scan here.
3276c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  */
3277c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan "
3278c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				"already in progress - do not try to start a "
3279c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				"new one");
3280c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			return 1;
3281c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		}
328204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (p2p->pending_listen_freq) {
328304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			/*
328404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 * Better wait a bit if the driver is unable to start
328504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 * offchannel operation for some reason. p2p_search()
328604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 * will be started from internal timeout.
328704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 */
328804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Listen "
328904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				"operation did not seem to start - delay "
329004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				"search phase to avoid busy loop");
329104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			p2p_set_timeout(p2p, 0, 100000);
329204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			return 1;
329304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
329461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->search_delay) {
329561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Delay "
329661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				"search operation by %u ms",
329761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				p2p->search_delay);
329861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p_set_timeout(p2p, p2p->search_delay / 1000,
329961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					(p2p->search_delay % 1000) * 1000);
330061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return 1;
330161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
33028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_search(p2p);
33038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
33048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
33078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_connect(struct p2p_data *p2p)
33118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
331304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p->go_neg_peer &&
331404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    (p2p->go_neg_peer->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM)) {
331504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Wait for GO "
331604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			"Negotiation Confirm timed out - assume GO "
331704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			"Negotiation failed");
331804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
331904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return;
332004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
33218c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	if (p2p->go_neg_peer &&
33228c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	    (p2p->go_neg_peer->flags & P2P_DEV_PEER_WAITING_RESPONSE) &&
33238c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	    p2p->go_neg_peer->connect_reqs < 120) {
33248c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer expected to "
33258c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt			"wait our response - skip listen");
33268c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		p2p_connect_send(p2p, p2p->go_neg_peer);
33278c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		return;
33288c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	}
33298c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt
33308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_CONNECT_LISTEN);
3331d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p_listen_in_find(p2p, 0);
33328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_connect_listen(struct p2p_data *p2p)
33368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer) {
33388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->drv_in_listen) {
33398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Driver is "
33408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"still in Listen state; wait for it to "
33418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"complete");
33428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
33438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
33448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->go_neg_peer->connect_reqs >= 120) {
33468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
33478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Timeout on sending GO Negotiation "
33488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Request without getting response");
33498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
33508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
33518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
33528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_CONNECT);
33548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, p2p->go_neg_peer);
33558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
33568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
33578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_wait_peer_connect(struct p2p_data *p2p)
33618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
33638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * TODO: could remain constantly in Listen state for some time if there
33648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * are no other concurrent uses for the radio. For now, go to listen
33658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * state once per second to give other uses a chance to use the radio.
33668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
33678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_WAIT_PEER_IDLE);
33681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_set_timeout(p2p, 0, 500000);
33698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_wait_peer_idle(struct p2p_data *p2p)
33738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p->go_neg_peer;
33758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
33778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
33788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Unknown GO Neg peer - stop GO Neg wait");
33798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
33808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wait_count++;
33838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->wait_count >= 120) {
33848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
33858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Timeout on waiting peer to become ready for GO "
33868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Negotiation");
33878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_failed(p2p, dev, -1);
33888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
33898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
33928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Go to Listen state while waiting for the peer to become "
33938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"ready for GO Negotiation");
33948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_WAIT_PEER_CONNECT);
3395d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p_listen_in_find(p2p, 0);
33968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_sd_during_find(struct p2p_data *p2p)
34008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
34028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Service Discovery Query timeout");
34038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->sd_peer) {
34048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
34058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE;
34068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->sd_peer = NULL;
34078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_continue_find(p2p);
34098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_prov_disc_during_find(struct p2p_data *p2p)
34138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
34158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Provision Discovery Request timeout");
34168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
34178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_continue_find(p2p);
34188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
342175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic void p2p_timeout_prov_disc_req(struct p2p_data *p2p)
342275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
342375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
342475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
342575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
342675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * For user initiated PD requests that we have not gotten any responses
342775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * for while in IDLE state, we retry them a couple of times before
342875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * giving up.
342975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
343075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (!p2p->user_initiated_pd)
343175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
343275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
343375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
343475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		"P2P: User initiated Provision Discovery Request timeout");
343575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
343675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p->pd_retries) {
343775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pd_retries--;
343875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p_retry_pd(p2p);
343975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	} else {
3440d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		struct p2p_device *dev;
3441d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		int for_join = 0;
3442d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
3443d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
3444d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			if (os_memcmp(p2p->pending_pd_devaddr,
3445d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				      dev->info.p2p_device_addr, ETH_ALEN) != 0)
3446d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				continue;
3447d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			if (dev->req_config_methods &&
3448d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			    (dev->flags & P2P_DEV_PD_FOR_JOIN))
3449d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				for_join = 1;
3450d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		}
3451d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
345275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->cfg->prov_disc_fail)
345375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx,
345475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen						 p2p->pending_pd_devaddr,
3455d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt						 for_join ?
3456d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt						 P2P_PROV_DISC_TIMEOUT_JOIN :
345775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen						 P2P_PROV_DISC_TIMEOUT);
345875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p_reset_pending_pd(p2p);
345975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	}
346075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
346175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
346275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
34638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_invite(struct p2p_data *p2p)
34648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
34668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_INVITE_LISTEN);
34678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->inv_role == P2P_INVITE_ROLE_ACTIVE_GO) {
34688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
34698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Better remain on operating channel instead of listen channel
34708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * when running a group.
34718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
34728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Inviting in "
34738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"active GO role - wait on operating channel");
34748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_timeout(p2p, 0, 100000);
34758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
34768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3477d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p_listen_in_find(p2p, 0);
34788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_invite_listen(struct p2p_data *p2p)
34828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->invite_peer && p2p->invite_peer->invitation_reqs < 100) {
34848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_INVITE);
34858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_invite_send(p2p, p2p->invite_peer,
34868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p->invite_go_dev_addr);
34878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
34888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->invite_peer) {
34898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
34908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Invitation Request retry limit reached");
34918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (p2p->cfg->invitation_result)
34928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p->cfg->invitation_result(
34938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					p2p->cfg->cb_ctx, -1, NULL);
34948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
34958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
34968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_state_timeout(void *eloop_ctx, void *timeout_ctx)
35018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
35028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
35038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Timeout (state=%s)",
35058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state));
35068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->in_listen = 0;
35088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (p2p->state) {
35108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_IDLE:
351175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/* Check if we timed out waiting for PD req */
351275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->pending_action_state == P2P_PENDING_PD)
351375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_timeout_prov_disc_req(p2p);
35148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SEARCH:
351675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/* Check if we timed out waiting for PD req */
351775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->pending_action_state == P2P_PENDING_PD)
351875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_timeout_prov_disc_req(p2p);
351961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->search_delay && !p2p->in_search_delay) {
352061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Delay "
352161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				"search operation by %u ms",
352261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				p2p->search_delay);
352361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p->in_search_delay = 1;
352461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p_set_timeout(p2p, p2p->search_delay / 1000,
352561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					(p2p->search_delay % 1000) * 1000);
352661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			break;
352761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
352861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->in_search_delay = 0;
35298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_search(p2p);
35308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT:
35328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_connect(p2p);
35338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT_LISTEN:
35358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_connect_listen(p2p);
35368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG:
35388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_LISTEN_ONLY:
354075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/* Check if we timed out waiting for PD req */
354175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->pending_action_state == P2P_PENDING_PD)
354275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_timeout_prov_disc_req(p2p);
354375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
35448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->ext_listen_only) {
35458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
35468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Extended Listen Timing - Listen State "
35478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"completed");
35488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->ext_listen_only = 0;
35498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_set_state(p2p, P2P_IDLE);
35508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
35518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_CONNECT:
35538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_wait_peer_connect(p2p);
35548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_IDLE:
35568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_wait_peer_idle(p2p);
35578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SD_DURING_FIND:
35598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_sd_during_find(p2p);
35608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROVISIONING:
35628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PD_DURING_FIND:
35648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_prov_disc_during_find(p2p);
35658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE:
35678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_invite(p2p);
35688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE_LISTEN:
35708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_invite_listen(p2p);
35718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
35721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case P2P_SEARCH_WHEN_READY:
35731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
357461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	case P2P_CONTINUE_SEARCH_WHEN_READY:
357561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		break;
35768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
35778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
35788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_reject(struct p2p_data *p2p, const u8 *peer_addr)
35818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
35828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
35838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
35858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Local request to reject "
35868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"connection attempts by peer " MACSTR, MAC2STR(peer_addr));
35878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
35888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR
35898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			" unknown", MAC2STR(peer_addr));
35908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
35918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
35928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->status = P2P_SC_FAIL_REJECTED_BY_USER;
35938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_USER_REJECTED;
35948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
35958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
35968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtconst char * p2p_wps_method_text(enum p2p_wps_method method)
35998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
36008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (method) {
36018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_NOT_READY:
36028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "not-ready";
36038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_PIN_DISPLAY:
36048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "Display";
36058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_PIN_KEYPAD:
36068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "Keypad";
36078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_PBC:
36088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "PBC";
36098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
36108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return "??";
36128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
36138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * p2p_go_state_text(enum p2p_go_state go_state)
36168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
36178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (go_state) {
36188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case UNKNOWN_GO:
36198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "unknown";
36208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case LOCAL_GO:
36218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "local";
36228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case  REMOTE_GO:
36238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "remote";
36248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
36258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return "??";
36278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
36288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtconst struct p2p_peer_info * p2p_get_peer_info(struct p2p_data *p2p,
36311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					       const u8 *addr, int next)
36328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
36338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
36348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr)
36368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, addr);
36378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
36388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = dl_list_first(&p2p->devices, struct p2p_device, list);
36398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev && next) {
36418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = dl_list_first(&dev->list, struct p2p_device, list);
36428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (&dev->list == &p2p->devices)
36438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev = NULL;
36448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
36458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
36471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return NULL;
36481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
36491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return &dev->info;
36501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
36511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
36521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
36531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_get_peer_info_txt(const struct p2p_peer_info *info,
36541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			  char *buf, size_t buflen)
36551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
36561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_device *dev;
36571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int res;
36581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	char *pos, *end;
36591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct os_time now;
36601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
36611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (info == NULL)
36628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
36638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	dev = (struct p2p_device *) (((u8 *) info) -
36651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				     offsetof(struct p2p_device, info));
36661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
36678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf;
36688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = buf + buflen;
36698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&now);
36718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = os_snprintf(pos, end - pos,
36728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "age=%d\n"
36738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "listen_freq=%d\n"
36748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "wps_method=%s\n"
36758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "interface_addr=" MACSTR "\n"
36768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "member_in_go_dev=" MACSTR "\n"
36778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "member_in_go_iface=" MACSTR "\n"
36788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "go_neg_req_sent=%d\n"
36798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "go_state=%s\n"
36808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dialog_token=%u\n"
36818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "intended_addr=" MACSTR "\n"
36828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "country=%c%c\n"
36838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "oper_freq=%d\n"
36848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "req_config_methods=0x%x\n"
36858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "flags=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n"
36868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "status=%d\n"
36878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "wait_count=%u\n"
36888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "invitation_reqs=%u\n",
36898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  (int) (now.sec - dev->last_seen.sec),
36908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->listen_freq,
36918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  p2p_wps_method_text(dev->wps_method),
36928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->interface_addr),
36938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->member_in_go_dev),
36948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->member_in_go_iface),
36958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->go_neg_req_sent,
36968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  p2p_go_state_text(dev->go_state),
36978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->dialog_token,
36988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->intended_addr),
36998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->country[0] ? dev->country[0] : '_',
37008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->country[1] ? dev->country[1] : '_',
37018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->oper_freq,
37028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->req_config_methods,
37038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PROBE_REQ_ONLY ?
37048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PROBE_REQ_ONLY]" : "",
37058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_REPORTED ? "[REPORTED]" : "",
37068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_NOT_YET_READY ?
37078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[NOT_YET_READY]" : "",
37088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_SD_INFO ? "[SD_INFO]" : "",
37098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_SD_SCHEDULE ? "[SD_SCHEDULE]" :
37108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "",
37118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PD_PEER_DISPLAY ?
37128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PD_PEER_DISPLAY]" : "",
37138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PD_PEER_KEYPAD ?
37148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PD_PEER_KEYPAD]" : "",
37158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_USER_REJECTED ?
37168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[USER_REJECTED]" : "",
37178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PEER_WAITING_RESPONSE ?
37188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PEER_WAITING_RESPONSE]" : "",
37198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PREFER_PERSISTENT_GROUP ?
37208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PREFER_PERSISTENT_GROUP]" : "",
37218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_WAIT_GO_NEG_RESPONSE ?
37228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[WAIT_GO_NEG_RESPONSE]" : "",
37238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM ?
37248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[WAIT_GO_NEG_CONFIRM]" : "",
37258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_GROUP_CLIENT_ONLY ?
37268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[GROUP_CLIENT_ONLY]" : "",
37278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_FORCE_FREQ ?
37288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[FORCE_FREQ]" : "",
37298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PD_FOR_JOIN ?
37308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PD_FOR_JOIN]" : "",
37318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->status,
37328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->wait_count,
37338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->invitation_reqs);
37348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0 || res >= end - pos)
37358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return pos - buf;
37368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += res;
37378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->ext_listen_period) {
37398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = os_snprintf(pos, end - pos,
37408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "ext_listen_period=%u\n"
37418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "ext_listen_interval=%u\n",
37428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  dev->ext_listen_period,
37438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  dev->ext_listen_interval);
37448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res < 0 || res >= end - pos)
37458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos - buf;
37468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += res;
37478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->oper_ssid_len) {
37508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = os_snprintf(pos, end - pos,
37518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "oper_ssid=%s\n",
37528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  wpa_ssid_txt(dev->oper_ssid,
37538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       dev->oper_ssid_len));
37548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res < 0 || res >= end - pos)
37558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos - buf;
37568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += res;
37578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
375961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
376061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (dev->info.wfd_subelems) {
376161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		res = os_snprintf(pos, end - pos, "wfd_subelems=");
376261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (res < 0 || res >= end - pos)
376361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return pos - buf;
376461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += res;
376561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
376661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += wpa_snprintf_hex(pos, end - pos,
376761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					wpabuf_head(dev->info.wfd_subelems),
376861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					wpabuf_len(dev->info.wfd_subelems));
376961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
377061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		res = os_snprintf(pos, end - pos, "\n");
377161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (res < 0 || res >= end - pos)
377261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return pos - buf;
377361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += res;
377461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
377561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
377661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
37778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return pos - buf;
37788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
37798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_peer_known(struct p2p_data *p2p, const u8 *addr)
37821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
37831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return p2p_get_device(p2p, addr) != NULL;
37841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
37851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
37861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
37878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_client_discoverability(struct p2p_data *p2p, int enabled)
37888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
37898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (enabled) {
37908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Client "
37918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"discoverability enabled");
37928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
37938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
37948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Client "
37958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"discoverability disabled");
37968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab &= ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
37978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
37998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_presence_req(u32 duration1, u32 interval1,
38028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      u32 duration2, u32 interval2)
38038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
38048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
38058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_noa_desc desc1, desc2, *ptr1 = NULL, *ptr2 = NULL;
38068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
38078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req = wpabuf_alloc(100);
38098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL)
38108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
38118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (duration1 || interval1) {
38138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(&desc1, 0, sizeof(desc1));
38148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc1.count_type = 1;
38158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc1.duration = duration1;
38168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc1.interval = interval1;
38178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ptr1 = &desc1;
38188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (duration2 || interval2) {
38208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(&desc2, 0, sizeof(desc2));
38218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc2.count_type = 2;
38228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc2.duration = duration2;
38238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc2.interval = interval2;
38248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ptr2 = &desc2;
38258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
38268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_action_hdr(req, P2P_PRESENCE_REQ, 1);
38298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(req);
38308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_noa(req, 0, 0, 0, ptr1, ptr2);
38318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(req, len);
38328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return req;
38348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
38358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_presence_req(struct p2p_data *p2p, const u8 *go_interface_addr,
38388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     const u8 *own_interface_addr, unsigned int freq,
38398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     u32 duration1, u32 interval1, u32 duration2,
38408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     u32 interval2)
38418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
38428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
38438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send Presence Request to "
38458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"GO " MACSTR " (own interface " MACSTR ") freq=%u dur1=%u "
38468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"int1=%u dur2=%u int2=%u",
38478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(go_interface_addr), MAC2STR(own_interface_addr),
38488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		freq, duration1, interval1, duration2, interval2);
38498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req = p2p_build_presence_req(duration1, interval1, duration2,
38518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     interval2);
38528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL)
38538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
38548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
38568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_send_action(p2p, freq, go_interface_addr, own_interface_addr,
38578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    go_interface_addr,
38588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpabuf_head(req), wpabuf_len(req), 200) < 0) {
38598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
38608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to send Action frame");
38618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(req);
38638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
38658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
38668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_presence_resp(u8 status, const u8 *noa,
38698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       size_t noa_len, u8 dialog_token)
38708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
38718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
38728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
38738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = wpabuf_alloc(100 + noa_len);
38758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
38768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
38778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_action_hdr(resp, P2P_PRESENCE_RESP, dialog_token);
38798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(resp);
38808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_status(resp, status);
38818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (noa) {
38828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(resp, P2P_ATTR_NOTICE_OF_ABSENCE);
38838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_le16(resp, noa_len);
38848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_data(resp, noa, noa_len);
38858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
38868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_noa(resp, 0, 0, 0, NULL, NULL);
38878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(resp, len);
38888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return resp;
38908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
38918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_req(struct p2p_data *p2p, const u8 *da,
38948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const u8 *sa, const u8 *data, size_t len,
38958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     int rx_freq)
38968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
38978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
38988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 status;
38998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
39008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t g;
39018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group *group = NULL;
39028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int parsed = 0;
39038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 noa[50];
39048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int noa_len;
39058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
39078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Received P2P Action - P2P Presence Request");
39088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (g = 0; g < p2p->num_groups; g++) {
39108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(da, p2p_group_get_interface_addr(p2p->groups[g]),
39118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      ETH_ALEN) == 0) {
39128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group = p2p->groups[g];
39138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
39148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
39158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group == NULL) {
39178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
39188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Ignore P2P Presence Request for unknown group "
39198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MACSTR, MAC2STR(da));
39208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
39218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse(data, len, &msg) < 0) {
39248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
39258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to parse P2P Presence Request");
39268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		status = P2P_SC_FAIL_INVALID_PARAMS;
39278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
39288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	parsed = 1;
39308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.noa == NULL) {
39328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
39338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No NoA attribute in P2P Presence Request");
39348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		status = P2P_SC_FAIL_INVALID_PARAMS;
39358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
39368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	status = p2p_group_presence_req(group, sa, msg.noa, msg.noa_len);
39398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail:
39418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->get_noa)
39428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		noa_len = p2p->cfg->get_noa(p2p->cfg->cb_ctx, da, noa,
39438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    sizeof(noa));
39448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
39458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		noa_len = -1;
39468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = p2p_build_presence_resp(status, noa_len > 0 ? noa : NULL,
39478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       noa_len > 0 ? noa_len : 0,
39488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       msg.dialog_token);
39498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (parsed)
39508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
39518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
39528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
39538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
39558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_send_action(p2p, rx_freq, sa, da, da,
39568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
39578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
39588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to send Action frame");
39598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(resp);
39618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_resp(struct p2p_data *p2p, const u8 *da,
39658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *sa, const u8 *data, size_t len)
39668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
39678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
39688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
39708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Received P2P Action - P2P Presence Response");
39718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse(data, len, &msg) < 0) {
39738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
39748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to parse P2P Presence Response");
39758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
39768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.status == NULL || msg.noa == NULL) {
39798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
39808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No Status or NoA attribute in P2P Presence "
39818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Response");
39828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
39838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
39848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*msg.status) {
39878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
39888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: P2P Presence Request was rejected: status %u",
39898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*msg.status);
39908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
39918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
39928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
39958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: P2P Presence Request was accepted");
39968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "P2P: P2P Presence Response - NoA",
39978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    msg.noa, msg.noa_len);
39988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: process NoA */
39998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
40008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
40018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_ext_listen_timeout(void *eloop_ctx, void *timeout_ctx)
40048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
40058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
40068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval) {
40088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Schedule next extended listen timeout */
40098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(p2p->ext_listen_interval_sec,
40108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p->ext_listen_interval_usec,
40118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p_ext_listen_timeout, p2p, NULL);
40128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
40138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_LISTEN_ONLY && p2p->ext_listen_only) {
40158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
40168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * This should not really happen, but it looks like the Listen
40178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * command may fail is something else (e.g., a scan) was
40188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * running at an inconvenient time. As a workaround, allow new
40198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Extended Listen operation to be started.
40208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
40218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Previous "
40228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Extended Listen operation had not been completed - "
40238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"try again");
40248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_only = 0;
40258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
40268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
40278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state != P2P_IDLE) {
40298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Skip Extended "
40308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Listen timeout in active state (%s)",
40318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_state_txt(p2p->state));
40328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
40338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
40348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Extended Listen timeout");
40368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_only = 1;
40378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_listen(p2p, p2p->ext_listen_period) < 0) {
40388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Failed to start "
40398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Listen state for Extended Listen Timing");
40408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_only = 0;
40418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
40428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
40438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_ext_listen(struct p2p_data *p2p, unsigned int period,
40468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   unsigned int interval)
40478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
40488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (period > 65535 || interval > 65535 || period > interval ||
40498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (period == 0 && interval > 0) || (period > 0 && interval == 0)) {
40508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
40518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Invalid Extended Listen Timing request: "
40528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"period=%u interval=%u", period, interval);
40538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
40548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
40558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_ext_listen_timeout, p2p, NULL);
40578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (interval == 0) {
40598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
40608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Disabling Extended Listen Timing");
40618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_period = 0;
40628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_interval = 0;
40638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
40648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
40658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
40678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Enabling Extended Listen Timing: period %u msec, "
40688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"interval %u msec", period, interval);
40698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_period = period;
40708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_interval = interval;
40718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_interval_sec = interval / 1000;
40728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_interval_usec = (interval % 1000) * 1000;
40738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(p2p->ext_listen_interval_sec,
40758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p->ext_listen_interval_usec,
40768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p_ext_listen_timeout, p2p, NULL);
40778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
40798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
40808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_deauth_notif(struct p2p_data *p2p, const u8 *bssid, u16 reason_code,
40838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      const u8 *ie, size_t ie_len)
40848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
40858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
40868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bssid == NULL || ie == NULL)
40888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
40898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
40918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg))
40928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
40938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.minor_reason_code == NULL)
40948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
40958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_INFO,
40978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Deauthentication notification BSSID " MACSTR
40988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" reason_code=%u minor_reason_code=%u",
40998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(bssid), reason_code, *msg.minor_reason_code);
41008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
41028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_disassoc_notif(struct p2p_data *p2p, const u8 *bssid, u16 reason_code,
41068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const u8 *ie, size_t ie_len)
41078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
41088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
41098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bssid == NULL || ie == NULL)
41118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
41128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
41148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg))
41158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
41168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.minor_reason_code == NULL)
41178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
41188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_INFO,
41208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Disassociation notification BSSID " MACSTR
41218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" reason_code=%u minor_reason_code=%u",
41228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(bssid), reason_code, *msg.minor_reason_code);
41238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
41258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_managed_oper(struct p2p_data *p2p, int enabled)
41298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
41308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (enabled) {
41318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Managed P2P "
41328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Device operations enabled");
41338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_INFRA_MANAGED;
41348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
41358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Managed P2P "
41368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Device operations disabled");
41378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab &= ~P2P_DEV_CAPAB_INFRA_MANAGED;
41388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
41398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel)
41438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
41448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_channel_to_freq(p2p->cfg->country, reg_class, channel) < 0)
41458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
41468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Set Listen channel: "
41488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"reg_class %u channel %u", reg_class, channel);
41498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->reg_class = reg_class;
41508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->channel = channel;
41518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
41538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_ssid_postfix(struct p2p_data *p2p, const u8 *postfix, size_t len)
41578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
41588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "P2P: New SSID postfix", postfix, len);
41598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (postfix == NULL) {
41608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->ssid_postfix_len = 0;
41618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
41628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
41638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > sizeof(p2p->cfg->ssid_postfix))
41648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
41658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->ssid_postfix, postfix, len);
41668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->ssid_postfix_len = len;
41678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
41688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
417175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenint p2p_set_oper_channel(struct p2p_data *p2p, u8 op_reg_class, u8 op_channel,
417275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			 int cfg_op_channel)
417375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
417475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p_channel_to_freq(p2p->cfg->country, op_reg_class, op_channel)
417575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	    < 0)
417675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return -1;
417775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
417875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, "P2P: Set Operating channel: "
417975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		"reg_class %u channel %u", op_reg_class, op_channel);
418075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->cfg->op_reg_class = op_reg_class;
418175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->cfg->op_channel = op_channel;
418275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->cfg->cfg_op_channel = cfg_op_channel;
418375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	return 0;
418475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
418575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
418675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
418704949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint p2p_set_pref_chan(struct p2p_data *p2p, unsigned int num_pref_chan,
418804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		      const struct p2p_channel *pref_chan)
418904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
419004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct p2p_channel *n;
419104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
419204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (pref_chan) {
419304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		n = os_malloc(num_pref_chan * sizeof(struct p2p_channel));
419404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (n == NULL)
419504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			return -1;
419604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(n, pref_chan,
419704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			  num_pref_chan * sizeof(struct p2p_channel));
419804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	} else
419904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		n = NULL;
420004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
420104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	os_free(p2p->cfg->pref_chan);
420204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p->cfg->pref_chan = n;
420304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p->cfg->num_pref_chan = num_pref_chan;
420404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
420504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return 0;
420604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
420704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
420804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
42098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_interface_addr(struct p2p_data *p2p, const u8 *dev_addr,
42108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   u8 *iface_addr)
42118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
42128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p_get_device(p2p, dev_addr);
42138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL || is_zero_ether_addr(dev->interface_addr))
42148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
42158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(iface_addr, dev->interface_addr, ETH_ALEN);
42168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
42178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
42188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_dev_addr(struct p2p_data *p2p, const u8 *iface_addr,
42218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   u8 *dev_addr)
42228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
42238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p_get_device_interface(p2p, iface_addr);
42248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
42258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
42268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev_addr, dev->info.p2p_device_addr, ETH_ALEN);
42278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
42288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
42298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_peer_filter(struct p2p_data *p2p, const u8 *addr)
42328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
42338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->peer_filter, addr, ETH_ALEN);
42348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (is_zero_ether_addr(p2p->peer_filter))
42358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Disable peer "
42368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"filter");
42378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
42388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Enable peer "
42398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"filter for " MACSTR, MAC2STR(p2p->peer_filter));
42408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
42418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_cross_connect(struct p2p_data *p2p, int enabled)
42448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
42458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Cross connection %s",
42468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		enabled ? "enabled" : "disabled");
42478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cross_connect == enabled)
42488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
42498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cross_connect = enabled;
42508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: may need to tear down any action group where we are GO(?) */
42518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
42528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_oper_freq(struct p2p_data *p2p, const u8 *iface_addr)
42558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
42568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p_get_device_interface(p2p, iface_addr);
42578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
42588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
42598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->oper_freq <= 0)
42608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
42618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return dev->oper_freq;
42628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
42638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_intra_bss_dist(struct p2p_data *p2p, int enabled)
42668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
42678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Intra BSS distribution %s",
42688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		enabled ? "enabled" : "disabled");
42698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->p2p_intra_bss = enabled;
42708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
42718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_update_channel_list(struct p2p_data *p2p, struct p2p_channels *chan)
42748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
42758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Update channel list");
42768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&p2p->cfg->channels, chan, sizeof(struct p2p_channels));
42778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
42788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_send_action(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
42818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    const u8 *src, const u8 *bssid, const u8 *buf,
42828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    size_t len, unsigned int wait_time)
42838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
42848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
42858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Delay Action "
42868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"frame TX until p2p_scan completes");
42878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->after_scan_tx) {
42888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Dropped "
42898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"previous pending Action frame TX");
42908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(p2p->after_scan_tx);
42918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
42928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = os_malloc(sizeof(*p2p->after_scan_tx) +
42938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       len);
42948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->after_scan_tx == NULL)
42958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
42968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx->freq = freq;
42978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx->dst, dst, ETH_ALEN);
42988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx->src, src, ETH_ALEN);
42998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx->bssid, bssid, ETH_ALEN);
43008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx->len = len;
43018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx->wait_time = wait_time;
43028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx + 1, buf, len);
43038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
43048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
43058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, dst, src, bssid,
43078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     buf, len, wait_time);
43088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
43098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_best_channels(struct p2p_data *p2p, int freq_24, int freq_5,
43128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   int freq_overall)
43138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
43148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Best channel: 2.4 GHz: %d,"
43158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  5 GHz: %d,  overall: %d", freq_24, freq_5, freq_overall);
43168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->best_freq_24 = freq_24;
43178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->best_freq_5 = freq_5;
43188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->best_freq_overall = freq_overall;
43198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
43208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * p2p_get_go_neg_peer(struct p2p_data *p2p)
43238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
43248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p == NULL || p2p->go_neg_peer == NULL)
43258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
43268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p->go_neg_peer->info.p2p_device_addr;
43278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
43288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst struct p2p_peer_info *
43318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtp2p_get_peer_found(struct p2p_data *p2p, const u8 *addr, int next)
43328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
43338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
43348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr) {
43368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, addr);
43378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!dev)
43388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
43398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!next) {
43418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev->flags & P2P_DEV_PROBE_REQ_ONLY)
43428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return NULL;
43438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return &dev->info;
43458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
43468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			do {
43478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev = dl_list_first(&dev->list,
43488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    struct p2p_device,
43498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    list);
43508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				if (&dev->list == &p2p->devices)
43518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					return NULL;
43528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} while (dev->flags & P2P_DEV_PROBE_REQ_ONLY);
43538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
43548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
43558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = dl_list_first(&p2p->devices, struct p2p_device, list);
43568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!dev)
43578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
43588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (dev->flags & P2P_DEV_PROBE_REQ_ONLY) {
43598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev = dl_list_first(&dev->list,
43608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    struct p2p_device,
43618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    list);
43628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (&dev->list == &p2p->devices)
43638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return NULL;
43648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
43658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
43668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return &dev->info;
43688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
43691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
43701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef ANDROID_P2P
43711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_search_in_progress(struct p2p_data *p2p)
43721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
43731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p == NULL)
43741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
43751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
43761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return p2p->state == P2P_SEARCH;
43771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
43781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif
43791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
43801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_in_progress(struct p2p_data *p2p)
43811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
43821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p == NULL)
43831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
438461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->state == P2P_SEARCH || p2p->state == P2P_SEARCH_WHEN_READY ||
438561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	    p2p->state == P2P_CONTINUE_SEARCH_WHEN_READY)
438661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return 2;
43871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return p2p->state != P2P_IDLE && p2p->state != P2P_PROVISIONING;
43881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
438961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
439061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
439161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid p2p_set_config_timeout(struct p2p_data *p2p, u8 go_timeout,
439261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			    u8 client_timeout)
439361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
439461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p) {
439561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->go_timeout = go_timeout;
439661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->client_timeout = client_timeout;
439761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
439861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
439961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
440061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
440161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid p2p_increase_search_delay(struct p2p_data *p2p, unsigned int delay)
440261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
440361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p && p2p->search_delay < delay)
440461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->search_delay = delay;
440561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
440661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
440761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
440861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
440961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
441061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void p2p_update_wfd_ie_groups(struct p2p_data *p2p)
441161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
441261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t g;
441361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct p2p_group *group;
441461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
441561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	for (g = 0; g < p2p->num_groups; g++) {
441661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		group = p2p->groups[g];
441761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_group_update_ies(group);
441861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
441961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
442061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
442161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
442261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_beacon(struct p2p_data *p2p, struct wpabuf *ie)
442361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
442461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_beacon);
442561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_beacon = ie;
442661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_update_wfd_ie_groups(p2p);
442761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
442861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
442961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
443061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
443161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_probe_req(struct p2p_data *p2p, struct wpabuf *ie)
443261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
443361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_probe_req);
443461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_probe_req = ie;
443561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
443661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
443761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
443861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
443961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_probe_resp(struct p2p_data *p2p, struct wpabuf *ie)
444061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
444161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_probe_resp);
444261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_probe_resp = ie;
444361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_update_wfd_ie_groups(p2p);
444461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
444561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
444661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
444761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
444861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_assoc_req(struct p2p_data *p2p, struct wpabuf *ie)
444961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
445061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_assoc_req);
445161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_assoc_req = ie;
445261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
445361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
445461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
445561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
445661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_invitation(struct p2p_data *p2p, struct wpabuf *ie)
445761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
445861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_invitation);
445961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_invitation = ie;
446061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
446161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
446261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
446361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
446461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_prov_disc_req(struct p2p_data *p2p, struct wpabuf *ie)
446561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
446661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_prov_disc_req);
446761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_prov_disc_req = ie;
446861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
446961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
447061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
447161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
447261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_prov_disc_resp(struct p2p_data *p2p, struct wpabuf *ie)
447361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
447461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_prov_disc_resp);
447561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_prov_disc_resp = ie;
447661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
447761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
447861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
447961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
448061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_go_neg(struct p2p_data *p2p, struct wpabuf *ie)
448161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
448261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_go_neg);
448361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_go_neg = ie;
448461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
448561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
448661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
448761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
448861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_dev_info(struct p2p_data *p2p, const struct wpabuf *elem)
448961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
449061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_dev_info);
449161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (elem) {
449261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_dev_info = wpabuf_dup(elem);
449361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->wfd_dev_info == NULL)
449461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
449561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else
449661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_dev_info = NULL;
449761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
449861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
449961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
450061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
450161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
450261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_assoc_bssid(struct p2p_data *p2p, const struct wpabuf *elem)
450361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
450461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_assoc_bssid);
450561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (elem) {
450661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_assoc_bssid = wpabuf_dup(elem);
450761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->wfd_assoc_bssid == NULL)
450861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
450961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else
451061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_assoc_bssid = NULL;
451161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
451261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
451361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
451461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
451561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
451661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_coupled_sink_info(struct p2p_data *p2p,
451761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				  const struct wpabuf *elem)
451861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
451961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_coupled_sink_info);
452061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (elem) {
452161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_coupled_sink_info = wpabuf_dup(elem);
452261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->wfd_coupled_sink_info == NULL)
452361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
452461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else
452561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_coupled_sink_info = NULL;
452661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
452761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
452861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
452961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
453061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
4531d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
4532d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
4533d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtint p2p_set_disc_int(struct p2p_data *p2p, int min_disc_int, int max_disc_int,
4534d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		     int max_disc_tu)
4535d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt{
4536d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (min_disc_int > max_disc_int || min_disc_int < 0 || max_disc_int < 0)
4537d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return -1;
4538d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
4539d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p->min_disc_int = min_disc_int;
4540d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p->max_disc_int = max_disc_int;
4541d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p->max_disc_tu = max_disc_tu;
4542d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Set discoverable interval: "
4543d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		"min=%d max=%d max_tu=%d", min_disc_int, max_disc_int,
4544d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		max_disc_tu);
4545d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
4546d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	return 0;
4547d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt}
4548