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);
2431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p->go_neg_peer)
2441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p->go_neg_peer->wps_method = WPS_NOT_READY;
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer = NULL;
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&res, 0, sizeof(res));
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.status = status;
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (peer) {
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(res.peer_device_addr, peer->info.p2p_device_addr,
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(res.peer_interface_addr, peer->intended_addr,
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->go_neg_completed(p2p->cfg->cb_ctx, &res);
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_listen_in_find(struct p2p_data *p2p)
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int r, tu;
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *ies;
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Starting short listen state (state=%s)",
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state));
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	freq = p2p_channel_to_freq(p2p->cfg->country, p2p->cfg->reg_class,
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   p2p->cfg->channel);
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq < 0) {
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Unknown regulatory class/channel");
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_random((u8 *) &r, sizeof(r));
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tu = (r % ((p2p->max_disc_int - p2p->min_disc_int) + 1) +
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	      p2p->min_disc_int) * 100;
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_freq = freq;
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_sec = 0;
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_usec = 1024 * tu;
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ies = p2p_build_probe_resp_ies(p2p);
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ies == NULL)
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->start_listen(p2p->cfg->cb_ctx, freq, 1024 * tu / 1000,
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    ies) < 0) {
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to start listen mode");
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_freq = 0;
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(ies);
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_listen(struct p2p_data *p2p, unsigned int timeout)
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *ies;
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Going to listen(only) state");
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	freq = p2p_channel_to_freq(p2p->cfg->country, p2p->cfg->reg_class,
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   p2p->cfg->channel);
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq < 0) {
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Unknown regulatory class/channel");
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_freq = freq;
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_sec = timeout / 1000;
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_usec = (timeout % 1000) * 1000;
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
32004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (p2p->start_after_scan == P2P_AFTER_SCAN_CONNECT) {
3211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
3221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				"P2P: p2p_scan running - connect is already "
3231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				"pending - skip listen");
3241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return 0;
3251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: p2p_scan running - delay start of listen state");
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->start_after_scan = P2P_AFTER_SCAN_LISTEN;
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ies = p2p_build_probe_resp_ies(p2p);
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ies == NULL)
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->start_listen(p2p->cfg->cb_ctx, freq, timeout, ies) < 0) {
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to start listen mode");
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_freq = 0;
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(ies);
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(ies);
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_LISTEN_ONLY);
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_device_clear_reported(struct p2p_data *p2p)
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list)
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~P2P_DEV_REPORTED;
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_get_device - Fetch a peer entry
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: P2P Device Address of the peer
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the device entry or %NULL if not found
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_device * p2p_get_device(struct p2p_data *p2p, const u8 *addr)
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(dev->info.p2p_device_addr, addr, ETH_ALEN) == 0)
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return dev;
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_get_device_interface - Fetch a peer entry based on P2P Interface Address
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: P2P Interface Address of the peer
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the device entry or %NULL if not found
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_device * p2p_get_device_interface(struct p2p_data *p2p,
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     const u8 *addr)
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(dev->interface_addr, addr, ETH_ALEN) == 0)
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return dev;
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_create_device - Create a peer entry
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: P2P Device Address of the peer
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the device entry or %NULL on failure
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * If there is already an entry for the peer, it will be returned instead of
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * creating a new one.
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct p2p_device * p2p_create_device(struct p2p_data *p2p,
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     const u8 *addr)
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev, *oldest = NULL;
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t count = 0;
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev)
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return dev;
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		count++;
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (oldest == NULL ||
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_time_before(&dev->last_seen, &oldest->last_seen))
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			oldest = dev;
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (count + 1 > p2p->cfg->max_peers && oldest) {
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Remove oldest peer entry to make room for a new "
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"peer");
423f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#ifdef ANDROID_P2P
424f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		/* SD_FAIR_POLICY: Update the current sd_dev_list pointer to next device */
425f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		if(&oldest->list == p2p->sd_dev_list)
426f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff			p2p->sd_dev_list = oldest->list.next;
427f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#endif
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dl_list_del(&oldest->list);
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_device_free(p2p, oldest);
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = os_zalloc(sizeof(*dev));
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_add(&p2p->devices, &dev->list);
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.p2p_device_addr, addr, ETH_ALEN);
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return dev;
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_copy_client_info(struct p2p_device *dev,
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 struct p2p_client_info *cli)
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.device_name, cli->dev_name, cli->dev_name_len);
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.device_name[cli->dev_name_len] = '\0';
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.dev_capab = cli->dev_capab;
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.config_methods = cli->config_methods;
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.pri_dev_type, cli->pri_dev_type, 8);
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.wps_sec_dev_type_list_len = 8 * cli->num_sec_dev_types;
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.wps_sec_dev_type_list, cli->sec_dev_types,
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  dev->info.wps_sec_dev_type_list_len);
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_add_group_clients(struct p2p_data *p2p, const u8 *go_dev_addr,
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const u8 *go_interface_addr, int freq,
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const u8 *gi, size_t gi_len)
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_info info;
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t c;
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gi == NULL)
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_group_info_parse(gi, gi_len, &info) < 0)
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Clear old data for this group; if the devices are still in the
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * group, the information will be restored in the loop following this.
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
4751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (os_memcmp(dev->member_in_go_iface, go_interface_addr,
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      ETH_ALEN) == 0) {
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(dev->member_in_go_iface, 0, ETH_ALEN);
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(dev->member_in_go_dev, 0, ETH_ALEN);
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (c = 0; c < info.num_clients; c++) {
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct p2p_client_info *cli = &info.client[c];
4841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (os_memcmp(cli->p2p_device_addr, p2p->cfg->dev_addr,
4851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      ETH_ALEN) == 0)
4861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			continue; /* ignore our own entry */
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, cli->p2p_device_addr);
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev) {
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev->flags & (P2P_DEV_GROUP_CLIENT_ONLY |
49004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					  P2P_DEV_PROBE_REQ_ONLY)) {
49104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				/*
49204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 * Update information since we have not
49304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 * received this directly from the client.
49404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 */
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p_copy_client_info(dev, cli);
49604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			} else {
49704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				/*
49804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 * Need to update P2P Client Discoverability
49904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 * flag since it is valid only in P2P Group
50004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 * Info attribute.
50104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 */
50204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				dev->info.dev_capab &=
50304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
50404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				dev->info.dev_capab |=
50504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					cli->dev_capab &
50604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
50704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			}
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev->flags & P2P_DEV_PROBE_REQ_ONLY) {
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev->flags &= ~P2P_DEV_PROBE_REQ_ONLY;
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev = p2p_create_device(p2p, cli->p2p_device_addr);
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev == NULL)
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				continue;
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->flags |= P2P_DEV_GROUP_CLIENT_ONLY;
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_copy_client_info(dev, cli);
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->oper_freq = freq;
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->cfg->dev_found(p2p->cfg->cb_ctx,
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    dev->info.p2p_device_addr,
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    &dev->info, 1);
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->interface_addr, cli->p2p_interface_addr,
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_get_time(&dev->last_seen);
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->member_in_go_dev, go_dev_addr, ETH_ALEN);
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->member_in_go_iface, go_interface_addr,
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_copy_wps_info(struct p2p_device *dev, int probe_req,
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      const struct p2p_message *msg)
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.device_name, msg->device_name,
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  sizeof(dev->info.device_name));
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->manufacturer &&
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->manufacturer_len < sizeof(dev->info.manufacturer)) {
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.manufacturer, 0,
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.manufacturer));
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.manufacturer, msg->manufacturer,
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->manufacturer_len);
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->model_name &&
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->model_name_len < sizeof(dev->info.model_name)) {
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.model_name, 0,
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.model_name));
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.model_name, msg->model_name,
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->model_name_len);
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->model_number &&
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->model_number_len < sizeof(dev->info.model_number)) {
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.model_number, 0,
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.model_number));
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.model_number, msg->model_number,
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->model_number_len);
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->serial_number &&
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->serial_number_len < sizeof(dev->info.serial_number)) {
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.serial_number, 0,
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.serial_number));
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.serial_number, msg->serial_number,
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->serial_number_len);
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->pri_dev_type)
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.pri_dev_type, msg->pri_dev_type,
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.pri_dev_type));
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (msg->wps_pri_dev_type)
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.pri_dev_type, msg->wps_pri_dev_type,
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.pri_dev_type));
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->wps_sec_dev_type_list) {
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.wps_sec_dev_type_list,
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->wps_sec_dev_type_list,
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->wps_sec_dev_type_list_len);
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_sec_dev_type_list_len =
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg->wps_sec_dev_type_list_len;
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->capability) {
59004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/*
59104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * P2P Client Discoverability bit is reserved in all frames
59204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * that use this function, so do not change its value here.
59304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 */
59404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->info.dev_capab &= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
59504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->info.dev_capab |= msg->capability[0] &
59604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.group_capab = msg->capability[1];
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->ext_listen_timing) {
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->ext_listen_period = WPA_GET_LE16(msg->ext_listen_timing);
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->ext_listen_interval =
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			WPA_GET_LE16(msg->ext_listen_timing + 2);
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
60504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!probe_req) {
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.config_methods = msg->config_methods ?
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg->config_methods : msg->wps_config_methods;
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
61404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * p2p_add_device - Add peer entries based on scan results or P2P frames
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: Source address of Beacon or Probe Response frame (may be either
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *	P2P Device Address or P2P Interface Address)
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @level: Signal level (signal strength of the received frame from the peer)
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @freq: Frequency on which the Beacon or Probe Response frame was received
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ies: IEs from the Beacon or Probe Response frame
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ies_len: Length of ies buffer in octets
62204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * @scan_res: Whether this was based on scan results
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * If the scan result is for a GO, the clients in the group will also be added
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to the peer table. This function can also be used with some other frames
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * like Provision Discovery Request that contains P2P Capability and P2P Device
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Info attributes.
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq, int level,
63104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   const u8 *ies, size_t ies_len, int scan_res)
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *p2p_dev_addr;
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ies, ies_len, &msg)) {
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to parse P2P IE for a device entry");
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.p2p_device_addr)
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_addr = msg.p2p_device_addr;
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (msg.device_id)
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_addr = msg.device_id;
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Ignore scan data without P2P Device Info or "
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P Device Id");
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!is_zero_ether_addr(p2p->peer_filter) &&
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(p2p_dev_addr, p2p->peer_filter, ETH_ALEN) != 0) {
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Do not add peer "
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"filter for " MACSTR " due to peer filter",
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(p2p_dev_addr));
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_create_device(p2p, p2p_dev_addr);
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&dev->last_seen);
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~(P2P_DEV_PROBE_REQ_ONLY | P2P_DEV_GROUP_CLIENT_ONLY);
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(addr, p2p_dev_addr, ETH_ALEN) != 0)
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->interface_addr, addr, ETH_ALEN);
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.ssid &&
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (msg.ssid[1] != P2P_WILDCARD_SSID_LEN ||
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     os_memcmp(msg.ssid + 2, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN)
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     != 0)) {
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->oper_ssid, msg.ssid + 2, msg.ssid[1]);
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->oper_ssid_len = msg.ssid[1];
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq >= 2412 && freq <= 2484 && msg.ds_params &&
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    *msg.ds_params >= 1 && *msg.ds_params <= 14) {
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int ds_freq;
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*msg.ds_params == 14)
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ds_freq = 2484;
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ds_freq = 2407 + *msg.ds_params * 5;
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freq != ds_freq) {
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Update Listen frequency based on DS "
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Parameter Set IE: %d -> %d MHz",
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				freq, ds_freq);
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq = ds_freq;
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
70004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (dev->listen_freq && dev->listen_freq != freq && scan_res) {
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Update Listen frequency based on scan "
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"results (" MACSTR " %d -> %d MHz (DS param %d)",
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr), dev->listen_freq,
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq, msg.ds_params ? *msg.ds_params : -1);
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
70704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (scan_res) {
70804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->listen_freq = freq;
70904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (msg.group_info)
71004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			dev->oper_freq = freq;
71104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
71275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	dev->info.level = level;
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_copy_wps_info(dev, 0, &msg);
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(dev->info.wps_vendor_ext[i]);
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_vendor_ext[i] = NULL;
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (msg.wps_vendor_ext[i] == NULL)
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_vendor_ext[i] = wpabuf_alloc_copy(
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg.wps_vendor_ext[i], msg.wps_vendor_ext_len[i]);
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->info.wps_vendor_ext[i] == NULL)
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
73061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (msg.wfd_subelems) {
73161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_free(dev->info.wfd_subelems);
73261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
73361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
73461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
73504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (scan_res) {
73604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p_add_group_clients(p2p, p2p_dev_addr, addr, freq,
73704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				      msg.group_info, msg.group_info_len);
73804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_pending_sd_req(p2p, dev))
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags |= P2P_DEV_SD_SCHEDULE;
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_REPORTED)
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Peer found with Listen frequency %d MHz", freq);
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_USER_REJECTED) {
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Do not report rejected device");
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->dev_found(p2p->cfg->cb_ctx, addr, &dev->info,
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    !(dev->flags & P2P_DEV_REPORTED_ONCE));
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev)
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
768497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt	if (p2p->go_neg_peer == dev) {
7691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/*
7701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * If GO Negotiation is in progress, report that it has failed.
7711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
772497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt		p2p_go_neg_failed(p2p, dev, -1);
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->go_neg_peer = NULL;
774497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt	}
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->invite_peer == dev)
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->invite_peer = NULL;
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->sd_peer == dev)
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->sd_peer = NULL;
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->pending_client_disc_go == dev)
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_client_disc_go = NULL;
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
782c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	/* dev_lost() device, but only if it was previously dev_found() */
783c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	if (dev->flags & P2P_DEV_REPORTED_ONCE)
784c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		p2p->cfg->dev_lost(p2p->cfg->cb_ctx,
785c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt				   dev->info.p2p_device_addr);
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(dev->info.wps_vendor_ext[i]);
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_vendor_ext[i] = NULL;
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
79261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(dev->info.wfd_subelems);
79361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(dev);
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_get_next_prog_freq(struct p2p_data *p2p)
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_channels *c;
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_reg_class *cla;
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t cl, ch;
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int found = 0;
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 reg_class;
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 channel;
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	c = &p2p->cfg->channels;
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (cl = 0; cl < c->reg_classes; cl++) {
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cla = &c->reg_class[cl];
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (cla->reg_class != p2p->last_prog_scan_class)
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (ch = 0; ch < cla->channels; ch++) {
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (cla->channel[ch] == p2p->last_prog_scan_chan) {
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				found = 1;
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (found)
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!found) {
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Start from beginning */
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reg_class = c->reg_class[0].reg_class;
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		channel = c->reg_class[0].channel[0];
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Pick the next channel */
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ch++;
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ch == cla->channels) {
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			cl++;
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (cl == c->reg_classes)
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				cl = 0;
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ch = 0;
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reg_class = c->reg_class[cl].reg_class;
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		channel = c->reg_class[cl].channel[ch];
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	freq = p2p_channel_to_freq(p2p->cfg->country, reg_class, channel);
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Next progressive search "
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"channel: reg_class %u channel %u -> %d MHz",
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reg_class, channel, freq);
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->last_prog_scan_class = reg_class;
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->last_prog_scan_chan = channel;
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq == 2412 || freq == 2437 || freq == 2462)
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* No need to add social channels */
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return freq;
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_search(struct p2p_data *p2p)
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq = 0;
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum p2p_scan_type type;
85704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	u16 pw_id = DEV_PW_DEFAULT;
85861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	int res;
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->drv_in_listen) {
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Driver is still "
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"in Listen state - wait for it to end before "
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"continuing");
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
86804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p->find_type == P2P_FIND_PROGRESSIVE &&
86904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    (freq = p2p_get_next_prog_freq(p2p)) > 0) {
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type = P2P_SCAN_SOCIAL_PLUS_ONE;
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting search "
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"(+ freq %u)", freq);
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type = P2P_SCAN_SOCIAL;
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting search");
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
87861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, type, freq,
87961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				 p2p->num_req_dev_types, p2p->req_dev_types,
88061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				 p2p->find_dev_id, pw_id);
88161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (res < 0) {
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Scan request failed");
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
88561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else if (res == 1) {
88661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Could not start "
88761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			"p2p_scan at this point - will try again after "
88861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			"previous scan completes");
88961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_set_state(p2p, P2P_CONTINUE_SEARCH_WHEN_READY);
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Running p2p_scan");
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->p2p_scan_running = 1;
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(P2P_SCAN_TIMEOUT, 0, p2p_scan_timeout,
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p, NULL);
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_find_timeout(void *eloop_ctx, void *timeout_ctx)
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Find timeout -> stop");
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_stop_find(p2p);
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_run_after_scan(struct p2p_data *p2p)
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum p2p_after_scan op;
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->after_scan_tx) {
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO: schedule p2p_run_after_scan to be called from TX
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * status callback(?) */
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send pending "
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Action frame at p2p_scan completion");
9181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p->cfg->send_action(p2p->cfg->cb_ctx,
9191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->freq,
9201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->dst,
9211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->src,
9221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->bssid,
9231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      (u8 *) (p2p->after_scan_tx + 1),
9241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->len,
9251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->wait_time);
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p2p->after_scan_tx);
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = NULL;
928f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#ifdef ANDROID_P2P
929f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		/* For SD frames, there is a scenario, where we can receive a SD request frame during p2p_scan.
930f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * At that moment, we will send the SD response from this context. After sending the SD response,
931f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * we need to continue p2p_find. But if we return 1 from here, p2p_find is going to be stopped.
932f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 */
933f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		return 0;
934f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#else
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
936f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#endif
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	op = p2p->start_after_scan;
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (op) {
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_AFTER_SCAN_NOTHING:
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_AFTER_SCAN_LISTEN:
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Start previously "
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"requested Listen state");
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_listen(p2p, p2p->pending_listen_sec * 1000 +
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   p2p->pending_listen_usec / 1000);
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_AFTER_SCAN_CONNECT:
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Start previously "
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"requested connect with " MACSTR,
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(p2p->after_scan_peer));
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, p2p->after_scan_peer);
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev == NULL) {
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer not "
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"known anymore");
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, dev);
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_scan_timeout(void *eloop_ctx, void *timeout_ctx)
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int running;
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan timeout "
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"(running=%d)", p2p->p2p_scan_running);
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	running = p2p->p2p_scan_running;
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Make sure we recover from missed scan results callback */
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->p2p_scan_running = 0;
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (running)
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_run_after_scan(p2p);
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_free_req_dev_types(struct p2p_data *p2p)
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->num_req_dev_types = 0;
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->req_dev_types);
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->req_dev_types = NULL;
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_find(struct p2p_data *p2p, unsigned int timeout,
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     enum p2p_discovery_type type,
993c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	     unsigned int num_req_dev_types, const u8 *req_dev_types,
99461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	     const u8 *dev_id, unsigned int search_delay)
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting find (type=%d)",
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type);
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan is "
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"already running");
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_req_dev_types(p2p);
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req_dev_types && num_req_dev_types) {
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->req_dev_types = os_malloc(num_req_dev_types *
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       WPS_DEV_TYPE_LEN);
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->req_dev_types == NULL)
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->req_dev_types, req_dev_types,
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  num_req_dev_types * WPS_DEV_TYPE_LEN);
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->num_req_dev_types = num_req_dev_types;
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1016c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (dev_id) {
1017c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		os_memcpy(p2p->find_dev_id_buf, dev_id, ETH_ALEN);
1018c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		p2p->find_dev_id = p2p->find_dev_id_buf;
1019c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	} else
1020c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		p2p->find_dev_id = NULL;
1021c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->find_type = type;
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_device_clear_reported(p2p);
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_SEARCH);
102861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->search_delay = search_delay;
102961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->in_search_delay = 0;
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
10311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p->last_p2p_find_timeout = timeout;
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (timeout)
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(timeout, 0, p2p_find_timeout,
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p, NULL);
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (type) {
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_FIND_START_WITH_FULL:
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_FIND_PROGRESSIVE:
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_FULL, 0,
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 p2p->num_req_dev_types,
104004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 p2p->req_dev_types, dev_id,
104104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 DEV_PW_DEFAULT);
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_FIND_ONLY_SOCIAL:
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_SOCIAL, 0,
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 p2p->num_req_dev_types,
104604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 p2p->req_dev_types, dev_id,
104704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 DEV_PW_DEFAULT);
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res == 0) {
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Running p2p_scan");
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->p2p_scan_running = 1;
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(P2P_SCAN_TIMEOUT, 0, p2p_scan_timeout,
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p, NULL);
10591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	} else if (res == 1) {
10601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Could not start "
10611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			"p2p_scan at this point - will try again after "
10621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			"previous scan completes");
10631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		res = 0;
10641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_set_state(p2p, P2P_SEARCH_WHEN_READY);
10651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Failed to start "
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"p2p_scan");
10691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
10701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10762fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt#ifdef ANDROID_P2P
10772fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidtint p2p_search_pending(struct p2p_data *p2p)
10782fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt{
10792fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt	if(p2p == NULL)
10802fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		return 0;
10812fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt
10822fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt	if(p2p->state == P2P_SEARCH_WHEN_READY)
10832fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		return 1;
10842fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt
10852fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt	return 0;
10862fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt}
10872fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt#endif
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_other_scan_completed(struct p2p_data *p2p)
10901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
109161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->state == P2P_CONTINUE_SEARCH_WHEN_READY) {
109261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_set_state(p2p, P2P_SEARCH);
109361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_search(p2p);
109461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return 1;
109561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
10961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p->state != P2P_SEARCH_WHEN_READY)
10971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
10981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting pending P2P find "
10991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		"now that previous scan was completed");
11001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p_find(p2p, p2p->last_p2p_find_timeout, p2p->find_type,
1101c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		     p2p->num_req_dev_types, p2p->req_dev_types,
110261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		     p2p->find_dev_id, p2p->search_delay) < 0)
11031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
11041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return 1;
11051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
11061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_stop_find_for_freq(struct p2p_data *p2p, int freq)
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Stopping find");
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
1113c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (p2p->state == P2P_SEARCH)
1114c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, P2P_EVENT_FIND_STOPPED);
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_IDLE);
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_req_dev_types(p2p);
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer = NULL;
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->sd_peer = NULL;
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->invite_peer = NULL;
112104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_stop_listen_for_freq(p2p, freq);
112204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
112304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
112404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
112504949598a23f501be6eec21697465fd46a28840aDmitry Shmidtvoid p2p_stop_listen_for_freq(struct p2p_data *p2p, int freq)
112604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq > 0 && p2p->drv_in_listen == freq && p2p->in_listen) {
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Skip stop_listen "
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"since we are on correct channel for response");
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
113204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p->in_listen) {
113304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->in_listen = 0;
113404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p_clear_timeout(p2p);
113504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
11361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p->drv_in_listen) {
11371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/*
11381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * The driver may not deliver callback to p2p_listen_end()
11391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * when the operation gets canceled, so clear the internal
11401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * variable that is tracking driver state.
11411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
11421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Clear "
11431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			"drv_in_listen (%d)", p2p->drv_in_listen);
11441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p->drv_in_listen = 0;
11451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_stop_find(struct p2p_data *p2p)
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_stop_find_for_freq(p2p, 0);
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_prepare_channel(struct p2p_data *p2p, unsigned int force_freq)
11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (force_freq) {
11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 op_reg_class, op_channel;
11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p_freq_to_channel(p2p->cfg->country, force_freq,
11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					&op_reg_class, &op_channel) < 0) {
11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Unsupported frequency %u MHz",
11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				force_freq);
11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!p2p_channels_includes(&p2p->cfg->channels, op_reg_class,
11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   op_channel)) {
11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Frequency %u MHz (oper_class %u "
11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"channel %u) not allowed for P2P",
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				force_freq, op_reg_class, op_channel);
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->op_reg_class = op_reg_class;
11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->op_channel = op_channel;
117704abaa93653bcee36d59576c90f283d4efdb0a64Dmitry Shmidt#ifndef ANDROID_P2P
11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->channels.reg_classes = 1;
11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->channels.reg_class[0].channels = 1;
11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->channels.reg_class[0].reg_class = p2p->op_reg_class;
11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->channels.reg_class[0].channel[0] = p2p->op_channel;
118204abaa93653bcee36d59576c90f283d4efdb0a64Dmitry Shmidt#else
118304abaa93653bcee36d59576c90f283d4efdb0a64Dmitry Shmidt		if(p2p->cfg->p2p_concurrency == P2P_MULTI_CHANNEL_CONCURRENT) {
118404abaa93653bcee36d59576c90f283d4efdb0a64Dmitry Shmidt			/* We we are requesting for a preferred channel. But since
118504abaa93653bcee36d59576c90f283d4efdb0a64Dmitry Shmidt			 * are multichannel concurrent, we have to poplulate the
118604abaa93653bcee36d59576c90f283d4efdb0a64Dmitry Shmidt			 * p2p_channels with list of channels that we support.
118704abaa93653bcee36d59576c90f283d4efdb0a64Dmitry Shmidt			 */
1188069fa2c39ec7120656a2ea8cca83c5ee41ddab60Irfan Sheriff#ifdef ANDROID_P2P
1189069fa2c39ec7120656a2ea8cca83c5ee41ddab60Irfan Sheriff			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "Full channel list");
1190069fa2c39ec7120656a2ea8cca83c5ee41ddab60Irfan Sheriff#endif
119104abaa93653bcee36d59576c90f283d4efdb0a64Dmitry Shmidt			os_memcpy(&p2p->channels, &p2p->cfg->channels,
119204abaa93653bcee36d59576c90f283d4efdb0a64Dmitry Shmidt				sizeof(struct p2p_channels));
119304abaa93653bcee36d59576c90f283d4efdb0a64Dmitry Shmidt		} else {
1194069fa2c39ec7120656a2ea8cca83c5ee41ddab60Irfan Sheriff#ifdef ANDROID_P2P
1195069fa2c39ec7120656a2ea8cca83c5ee41ddab60Irfan Sheriff			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "Single channel list %d", p2p->op_channel);
1196069fa2c39ec7120656a2ea8cca83c5ee41ddab60Irfan Sheriff#endif
119704abaa93653bcee36d59576c90f283d4efdb0a64Dmitry Shmidt			p2p->channels.reg_classes = 1;
119804abaa93653bcee36d59576c90f283d4efdb0a64Dmitry Shmidt			p2p->channels.reg_class[0].channels = 1;
119904abaa93653bcee36d59576c90f283d4efdb0a64Dmitry Shmidt			p2p->channels.reg_class[0].reg_class = p2p->op_reg_class;
120004abaa93653bcee36d59576c90f283d4efdb0a64Dmitry Shmidt			p2p->channels.reg_class[0].channel[0] = p2p->op_channel;
120104abaa93653bcee36d59576c90f283d4efdb0a64Dmitry Shmidt		}
120204abaa93653bcee36d59576c90f283d4efdb0a64Dmitry Shmidt#endif
12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 op_reg_class, op_channel;
12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!p2p->cfg->cfg_op_channel && p2p->best_freq_overall > 0 &&
12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    p2p_supported_freq(p2p, p2p->best_freq_overall) &&
12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    p2p_freq_to_channel(p2p->cfg->country,
12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					p2p->best_freq_overall,
12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					&op_reg_class, &op_channel) == 0) {
12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Select best overall channel as "
12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"operating channel preference");
12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->op_reg_class = op_reg_class;
12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->op_channel = op_channel;
12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (!p2p->cfg->cfg_op_channel && p2p->best_freq_5 > 0 &&
12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   p2p_supported_freq(p2p, p2p->best_freq_5) &&
12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   p2p_freq_to_channel(p2p->cfg->country,
12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       p2p->best_freq_5,
12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       &op_reg_class, &op_channel) ==
12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   0) {
12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Select best 5 GHz channel as "
12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"operating channel preference");
12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->op_reg_class = op_reg_class;
12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->op_channel = op_channel;
12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (!p2p->cfg->cfg_op_channel &&
12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   p2p->best_freq_24 > 0 &&
12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   p2p_supported_freq(p2p, p2p->best_freq_24) &&
12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   p2p_freq_to_channel(p2p->cfg->country,
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       p2p->best_freq_24,
12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       &op_reg_class, &op_channel) ==
12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   0) {
12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Select best 2.4 GHz channel as "
12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"operating channel preference");
12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->op_reg_class = op_reg_class;
12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->op_channel = op_channel;
12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->op_reg_class = p2p->cfg->op_reg_class;
12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->op_channel = p2p->cfg->op_channel;
12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(&p2p->channels, &p2p->cfg->channels,
12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(struct p2p_channels));
12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Own preference for operation channel: "
12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"Operating Class %u Channel %u%s",
12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->op_reg_class, p2p->op_channel,
12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		force_freq ? " (forced)" : "");
12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void p2p_set_dev_persistent(struct p2p_device *dev,
12581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   int persistent_group)
12591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
12601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	switch (persistent_group) {
12611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case 0:
12621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags &= ~(P2P_DEV_PREFER_PERSISTENT_GROUP |
12631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				P2P_DEV_PREFER_PERSISTENT_RECONN);
12641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
12651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case 1:
12661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP;
12671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags &= ~P2P_DEV_PREFER_PERSISTENT_RECONN;
12681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
12691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case 2:
12701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP |
12711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			P2P_DEV_PREFER_PERSISTENT_RECONN;
12721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
12731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
12741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
12751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
12761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		enum p2p_wps_method wps_method,
12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int go_intent, const u8 *own_interface_addr,
128004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		unsigned int force_freq, int persistent_group,
128104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		const u8 *force_ssid, size_t force_ssid_len,
128204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		int pd_before_go_neg)
12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Request to start group negotiation - peer=" MACSTR
12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  GO Intent=%d  Intended Interface Address=" MACSTR
1289069fa2c39ec7120656a2ea8cca83c5ee41ddab60Irfan Sheriff		" wps_method=%d persistent_group=%d pd_before_go_neg=%d force_freq %d",
12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
1291069fa2c39ec7120656a2ea8cca83c5ee41ddab60Irfan Sheriff		wps_method, persistent_group, pd_before_go_neg, force_freq);
12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_prepare_channel(p2p, force_freq) < 0)
12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Cannot connect to unknown P2P Device " MACSTR,
13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(peer_addr));
13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!(dev->info.dev_capab &
13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Cannot connect to P2P Device " MACSTR
13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				" that is in a group and is not discoverable",
13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(peer_addr));
13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->oper_freq <= 0) {
13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Cannot connect to P2P Device " MACSTR
13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				" with incomplete information",
13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(peer_addr));
13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * First, try to connect directly. If the peer does not
13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * acknowledge frames, assume it is sleeping and use device
13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * discoverability via the GO at that point.
13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
132804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p->ssid_set = 0;
132904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (force_ssid) {
133004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "P2P: Forced SSID",
133104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  force_ssid, force_ssid_len);
133204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(p2p->ssid, force_ssid, force_ssid_len);
133304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->ssid_len = force_ssid_len;
133404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->ssid_set = 1;
133504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
133604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_NOT_YET_READY;
13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_USER_REJECTED;
13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE;
13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM;
134104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (pd_before_go_neg)
134204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->flags |= P2P_DEV_PD_BEFORE_GO_NEG;
134304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	else
134404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->flags &= ~P2P_DEV_PD_BEFORE_GO_NEG;
13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->connect_reqs = 0;
13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_neg_req_sent = 0;
13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_state = UNKNOWN_GO;
13481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_set_dev_persistent(dev, persistent_group);
13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_intent = go_intent;
13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state != P2P_IDLE)
13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_stop_find(p2p);
13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->after_scan_tx) {
13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * We need to drop the pending frame to avoid issues with the
13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * new GO Negotiation, e.g., when the pending frame was from a
13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * previous attempt at starting a GO Negotiation.
13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Dropped "
13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"previous pending Action frame TX that was waiting "
13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"for p2p_scan completion");
13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p2p->after_scan_tx);
13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = NULL;
13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wps_method = wps_method;
13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->status = P2P_SC_SUCCESS;
13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (force_freq)
13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags |= P2P_DEV_FORCE_FREQ;
13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~P2P_DEV_FORCE_FREQ;
13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: p2p_scan running - delay connect send");
13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->start_after_scan = P2P_AFTER_SCAN_CONNECT;
13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_peer, peer_addr, ETH_ALEN);
13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_connect_send(p2p, dev);
13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  enum p2p_wps_method wps_method,
13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  int go_intent, const u8 *own_interface_addr,
139204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		  unsigned int force_freq, int persistent_group,
139304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		  const u8 *force_ssid, size_t force_ssid_len)
13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Request to authorize group negotiation - peer=" MACSTR
13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  GO Intent=%d  Intended Interface Address=" MACSTR
14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" wps_method=%d  persistent_group=%d",
14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wps_method, persistent_group);
14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_prepare_channel(p2p, force_freq) < 0)
14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Cannot authorize unknown P2P Device " MACSTR,
14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(peer_addr));
14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
141504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p->ssid_set = 0;
141604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (force_ssid) {
141704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "P2P: Forced SSID",
141804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  force_ssid, force_ssid_len);
141904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(p2p->ssid, force_ssid, force_ssid_len);
142004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->ssid_len = force_ssid_len;
142104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->ssid_set = 1;
142204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
142304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_NOT_YET_READY;
14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_USER_REJECTED;
14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_neg_req_sent = 0;
14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_state = UNKNOWN_GO;
14281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_set_dev_persistent(dev, persistent_group);
14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_intent = go_intent;
14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wps_method = wps_method;
14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->status = P2P_SC_SUCCESS;
14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (force_freq)
14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags |= P2P_DEV_FORCE_FREQ;
14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~P2P_DEV_FORCE_FREQ;
14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_add_dev_info(struct p2p_data *p2p, const u8 *addr,
14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      struct p2p_device *dev, struct p2p_message *msg)
14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&dev->last_seen);
14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_copy_wps_info(dev, 0, msg);
14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->listen_channel) {
14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int freq;
14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		freq = p2p_channel_to_freq((char *) msg->listen_channel,
14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   msg->listen_channel[3],
14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   msg->listen_channel[4]);
14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freq < 0) {
14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Unknown peer Listen channel: "
14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"country=%c%c(0x%02x) reg_class=%u channel=%u",
14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[0],
14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[1],
14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[2],
14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[3],
14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[4]);
14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Update "
14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"peer " MACSTR " Listen channel: %u -> %u MHz",
14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(dev->info.p2p_device_addr),
14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev->listen_freq, freq);
14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->listen_freq = freq;
14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
147461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (msg->wfd_subelems) {
147561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_free(dev->info.wfd_subelems);
147661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		dev->info.wfd_subelems = wpabuf_dup(msg->wfd_subelems);
147761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
147861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_PROBE_REQ_ONLY) {
14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~P2P_DEV_PROBE_REQ_ONLY;
14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Completed device entry based on data from "
14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"GO Negotiation Request");
14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Created device entry based on GO Neg Req: "
14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MACSTR " dev_capab=0x%x group_capab=0x%x name='%s' "
14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"listen_freq=%d",
14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr),
14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->info.dev_capab, dev->info.group_capab,
14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->info.device_name, dev->listen_freq);
14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_GROUP_CLIENT_ONLY;
14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_USER_REJECTED) {
14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Do not report rejected device");
14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->dev_found(p2p->cfg->cb_ctx, addr, &dev->info,
15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    !(dev->flags & P2P_DEV_REPORTED_ONCE));
15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_build_ssid(struct p2p_data *p2p, u8 *ssid, size_t *ssid_len)
15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_random((char *) &ssid[P2P_WILDCARD_SSID_LEN], 2);
15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&ssid[P2P_WILDCARD_SSID_LEN + 2],
15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  p2p->cfg->ssid_postfix, p2p->cfg->ssid_postfix_len);
15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*ssid_len = P2P_WILDCARD_SSID_LEN + 2 + p2p->cfg->ssid_postfix_len;
15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_go_params(struct p2p_data *p2p, struct p2p_go_neg_results *params)
15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_build_ssid(p2p, params->ssid, &params->ssid_len);
15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_random(params->passphrase, 8);
15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_go_complete(struct p2p_data *p2p, struct p2p_device *peer)
15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_go_neg_results res;
15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int go = peer->go_state == LOCAL_GO;
15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_channels intersection;
15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freqs;
15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i, j;
15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: GO Negotiation with " MACSTR " completed (%s will be "
15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"GO)", MAC2STR(peer->info.p2p_device_addr),
15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		go ? "local end" : "peer");
15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&res, 0, sizeof(res));
15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.role_go = go;
15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(res.peer_device_addr, peer->info.p2p_device_addr, ETH_ALEN);
15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(res.peer_interface_addr, peer->intended_addr, ETH_ALEN);
15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.wps_method = peer->wps_method;
15441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) {
15451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN)
15461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			res.persistent_group = 2;
15471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		else
15481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			res.persistent_group = 1;
15491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (go) {
15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Setup AP mode for WPS provisioning */
15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res.freq = p2p_channel_to_freq(p2p->cfg->country,
15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       p2p->op_reg_class,
15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       p2p->op_channel);
15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(res.ssid, p2p->ssid, p2p->ssid_len);
15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res.ssid_len = p2p->ssid_len;
15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_random(res.passphrase, 8);
15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res.freq = peer->oper_freq;
15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->ssid_len) {
15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(res.ssid, p2p->ssid, p2p->ssid_len);
15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res.ssid_len = p2p->ssid_len;
15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_channels_intersect(&p2p->channels, &peer->channels,
15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       &intersection);
15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	freqs = 0;
15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < intersection.reg_classes; i++) {
15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct p2p_reg_class *c = &intersection.reg_class[i];
15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freqs + 1 == P2P_MAX_CHANNELS)
15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < c->channels; j++) {
15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			int freq;
15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (freqs + 1 == P2P_MAX_CHANNELS)
15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq = p2p_channel_to_freq(peer->country, c->reg_class,
15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   c->channel[j]);
15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (freq < 0)
15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				continue;
15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res.freq_list[freqs++] = freq;
15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.peer_config_timeout = go ? peer->client_timeout : peer->go_timeout;
15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
15891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p->ssid_set = 0;
15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer->go_neg_req_sent = 0;
15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer->wps_method = WPS_NOT_READY;
15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_PROVISIONING);
15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->go_neg_completed(p2p->cfg->cb_ctx, &res);
15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_rx_p2p_action(struct p2p_data *p2p, const u8 *sa,
15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      const u8 *data, size_t len, int rx_freq)
16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: RX P2P Public Action from " MACSTR, MAC2STR(sa));
16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "P2P: P2P Public Action contents", data, len);
16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1)
16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data[0]) {
16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG_REQ:
16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_neg_req(p2p, sa, data + 1, len - 1, rx_freq);
16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG_RESP:
16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_neg_resp(p2p, sa, data + 1, len - 1, rx_freq);
16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG_CONF:
16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_neg_conf(p2p, sa, data + 1, len - 1);
16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITATION_REQ:
16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_invitation_req(p2p, sa, data + 1, len - 1,
16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   rx_freq);
16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITATION_RESP:
16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_invitation_resp(p2p, sa, data + 1, len - 1);
16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROV_DISC_REQ:
16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_prov_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROV_DISC_RESP:
16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_prov_disc_resp(p2p, sa, data + 1, len - 1);
16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_DEV_DISC_REQ:
16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_dev_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_DEV_DISC_RESP:
16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_dev_disc_resp(p2p, sa, data + 1, len - 1);
16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Unsupported P2P Public Action frame type %d",
16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data[0]);
16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void p2p_rx_action_public(struct p2p_data *p2p, const u8 *da,
16471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				 const u8 *sa, const u8 *bssid, const u8 *data,
16481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				 size_t len, int freq)
16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1)
16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data[0]) {
16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_VENDOR_SPECIFIC:
16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data++;
16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len--;
16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 3)
16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (WPA_GET_BE24(data) != OUI_WFA)
16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data += 3;
16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len -= 3;
16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 1)
16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*data != P2P_OUI_TYPE)
16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_p2p_action(p2p, sa, data + 1, len - 1, freq);
16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_INITIAL_REQ:
16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_initial_req(p2p, sa, data + 1, len - 1, freq);
16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_INITIAL_RESP:
16768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_initial_resp(p2p, sa, data + 1, len - 1, freq);
16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_COMEBACK_REQ:
16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_comeback_req(p2p, sa, data + 1, len - 1, freq);
16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_COMEBACK_RESP:
16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_comeback_resp(p2p, sa, data + 1, len - 1, freq);
16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_rx_action(struct p2p_data *p2p, const u8 *da, const u8 *sa,
16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *bssid, u8 category,
16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *data, size_t len, int freq)
16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (category == WLAN_ACTION_PUBLIC) {
16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_action_public(p2p, da, sa, bssid, data, len, freq);
16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (category != WLAN_ACTION_VENDOR_SPECIFIC)
16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 4)
17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (WPA_GET_BE24(data) != OUI_WFA)
17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data += 3;
17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len -= 3;
17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*data != P2P_OUI_TYPE)
17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data++;
17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len--;
17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P action frame */
17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: RX P2P Action from " MACSTR, MAC2STR(sa));
17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "P2P: P2P Action contents", data, len);
17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1)
17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data[0]) {
17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_NOA:
17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Received P2P Action - Notice of Absence");
17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO */
17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PRESENCE_REQ:
17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_presence_req(p2p, da, sa, data + 1, len - 1, freq);
17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PRESENCE_RESP:
17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_presence_resp(p2p, da, sa, data + 1, len - 1);
17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_DISC_REQ:
17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_disc_req(p2p, da, sa, data + 1, len - 1, freq);
17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Received P2P Action - unknown type %u", data[0]);
17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_start(void *eloop_ctx, void *timeout_ctx)
17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == NULL)
17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer->status = P2P_SC_SUCCESS;
17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_connect_send(p2p, p2p->go_neg_peer);
17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_invite_start(void *eloop_ctx, void *timeout_ctx)
17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->invite_peer == NULL)
17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_invite_send(p2p, p2p->invite_peer, p2p->invite_go_dev_addr);
17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_add_dev_from_probe_req(struct p2p_data *p2p, const u8 *addr,
17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const u8 *ie, size_t ie_len)
17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg) < 0 || msg.p2p_attributes == NULL)
17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* not a P2P probe */
17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.ssid == NULL || msg.ssid[1] != P2P_WILDCARD_SSID_LEN ||
17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(msg.ssid + 2, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN)
17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    != 0) {
17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* The Probe Request is not part of P2P Device Discovery. It is
17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * not known whether the source address of the frame is the P2P
17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Device Address or P2P Interface Address. Do not add a new
17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * peer entry based on this frames.
17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev) {
17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->country[0] == 0 && msg.listen_channel)
17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(dev->country, msg.listen_channel, 3);
17931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		os_get_time(&dev->last_seen);
17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* already known */
17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_create_device(p2p, addr);
17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&dev->last_seen);
18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_PROBE_REQ_ONLY;
18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.listen_channel) {
18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->country, msg.listen_channel, 3);
18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->listen_freq = p2p_channel_to_freq(dev->country,
18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       msg.listen_channel[3],
18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       msg.listen_channel[4]);
18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_copy_wps_info(dev, 1, &msg);
18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
181661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (msg.wfd_subelems) {
181761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_free(dev->info.wfd_subelems);
181861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
181961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
182061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Created device entry based on Probe Req: " MACSTR
18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" dev_capab=0x%x group_capab=0x%x name='%s' listen_freq=%d",
18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(dev->info.p2p_device_addr), dev->info.dev_capab,
18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.group_capab, dev->info.device_name,
18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->listen_freq);
18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_device * p2p_add_dev_from_go_neg_req(struct p2p_data *p2p,
18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						const u8 *addr,
18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						struct p2p_message *msg)
18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev) {
18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_get_time(&dev->last_seen);
18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return dev; /* already known */
18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_create_device(p2p, addr);
18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_add_dev_info(p2p, addr, dev, msg);
18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return dev;
18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int dev_type_match(const u8 *dev_type, const u8 *req_dev_type)
18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(dev_type, req_dev_type, WPS_DEV_TYPE_LEN) == 0)
18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(dev_type, req_dev_type, 2) == 0 &&
18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    WPA_GET_BE32(&req_dev_type[2]) == 0 &&
18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    WPA_GET_BE16(&req_dev_type[6]) == 0)
18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Category match with wildcard OUI/sub-category */
18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint dev_type_list_match(const u8 *dev_type, const u8 *req_dev_type[],
18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			size_t num_req_dev_type)
18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_req_dev_type; i++) {
18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev_type_match(dev_type, req_dev_type[i]))
18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 1;
18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_match_dev_type - Match local device type with requested type
18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wps: WPS TLVs from Probe Request frame (concatenated WPS IEs)
18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 on match, 0 on mismatch
18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function can be used to match the Requested Device Type attribute in
18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPS IE with the local device types for deciding whether to reply to a Probe
18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Request frame.
18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_match_dev_type(struct p2p_data *p2p, struct wpabuf *wps)
18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wps_parse_attr attr;
18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wps_parse_msg(wps, &attr))
18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* assume no Requested Device Type attributes */
18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (attr.num_req_dev_type == 0)
18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* no Requested Device Type attributes -> match */
18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev_type_list_match(p2p->cfg->pri_dev_type, attr.req_dev_type,
19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				attr.num_req_dev_type))
19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Own Primary Device Type matches */
19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < p2p->cfg->num_sec_dev_types; i++)
19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev_type_list_match(p2p->cfg->sec_dev_type[i],
19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					attr.req_dev_type,
19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					attr.num_req_dev_type))
19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Own Secondary Device Type matches */
19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* No matching device type found */
19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * p2p_build_probe_resp_ies(struct p2p_data *p2p)
19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
191804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	int pw_id = -1;
191961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t extra = 0;
192061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
192161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
192261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_probe_resp)
192361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		extra = wpabuf_len(p2p->wfd_ie_probe_resp);
192461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
192661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	buf = wpabuf_alloc(1000 + extra);
19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
193004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p->go_neg_peer) {
193104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/* Advertise immediate availability of WPS credential */
193204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		pw_id = p2p_wps_method_pw_id(p2p->go_neg_peer->wps_method);
193304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
193404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
193504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_build_wps_ie(p2p, buf, pw_id, 1);
19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
193761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
193861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_probe_resp)
193961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(buf, p2p->wfd_ie_probe_resp);
194061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
194161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P IE */
19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(buf);
194404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_buf_add_capability(buf, p2p->dev_capab &
194504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			       ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 0);
19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval)
19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_ext_listen_timing(buf, p2p->ext_listen_period,
19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      p2p->ext_listen_interval);
19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_device_info(buf, p2p, NULL);
19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(buf, len);
19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int is_11b(u8 rate)
19571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
19581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
19591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
19601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
19611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
19621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int supp_rates_11b_only(struct ieee802_11_elems *elems)
19631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
19641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int num_11b = 0, num_others = 0;
19651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int i;
19661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
19671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (elems->supp_rates == NULL && elems->ext_supp_rates == NULL)
19681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
19691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
19701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (i = 0; elems->supp_rates && i < elems->supp_rates_len; i++) {
19711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (is_11b(elems->supp_rates[i]))
19721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			num_11b++;
19731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		else
19741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			num_others++;
19751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
19761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
19771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (i = 0; elems->ext_supp_rates && i < elems->ext_supp_rates_len;
19781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	     i++) {
19791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (is_11b(elems->ext_supp_rates[i]))
19801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			num_11b++;
19811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		else
19821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			num_others++;
19831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
19841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
19851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return num_11b > 0 && num_others == 0;
19861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
19871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
19881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
198904949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic enum p2p_probe_req_status
199004949598a23f501be6eec21697465fd46a28840aDmitry Shmidtp2p_reply_probe(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
199104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		const u8 *bssid, const u8 *ie, size_t ie_len)
19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ieee802_11_elems elems;
19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ieee80211_mgmt *resp;
19961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_message msg;
19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *ies;
19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p->in_listen || !p2p->drv_in_listen) {
20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* not in Listen state - ignore Probe Request */
200104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_LISTEN;
20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ieee802_11_parse_elems((u8 *) ie, ie_len, &elems, 0) ==
20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ParseFailed) {
20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Ignore invalid Probe Request frames */
200704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_MALFORMED;
20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (elems.p2p == NULL) {
20118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* not a P2P probe - ignore it */
201204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_P2P;
20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (dst && !is_broadcast_ether_addr(dst) &&
20161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    os_memcmp(dst, p2p->cfg->dev_addr, ETH_ALEN) != 0) {
20171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Not sent to the broadcast address or our P2P Device Address
20181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
201904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
20201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
20211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (bssid && !is_broadcast_ether_addr(bssid)) {
20231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Not sent to the Wildcard BSSID */
202404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
20251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
20261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (elems.ssid == NULL || elems.ssid_len != P2P_WILDCARD_SSID_LEN ||
20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(elems.ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) !=
20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0) {
20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* not using P2P Wildcard SSID - ignore */
203104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (supp_rates_11b_only(&elems)) {
20351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Indicates support for 11b rates only */
203604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_P2P;
20371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
20381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
20401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg) < 0) {
20411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Could not parse P2P attributes */
204204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_P2P;
20431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
20441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (msg.device_id &&
204604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    os_memcmp(msg.device_id, p2p->cfg->dev_addr, ETH_ALEN) != 0) {
20471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Device ID did not match */
20481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_parse_free(&msg);
204904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
20501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
20511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Check Requested Device Type match */
20531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (msg.wps_attributes &&
20541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    !p2p_match_dev_type(p2p, msg.wps_attributes)) {
20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* No match with Requested Device Type */
20561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_parse_free(&msg);
205704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_parse_free(&msg);
20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
206104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (!p2p->cfg->send_probe_resp) {
206204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/* Response generated elsewhere */
206304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
206404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
20678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Reply to P2P Probe Request in Listen state");
20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
20708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * We do not really have a specific BSS that this frame is advertising,
20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * so build a frame that has some information in valid format. This is
20728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * really only used for discovery purposes, not to learn exact BSS
20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * parameters.
20748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
20758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ies = p2p_build_probe_resp_ies(p2p);
20768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ies == NULL)
207704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
20788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = wpabuf_alloc(200 + wpabuf_len(ies));
20808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL) {
20818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(ies);
208204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
20838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = NULL;
20868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = wpabuf_put(buf, resp->u.probe_resp.variable - (u8 *) resp);
20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
20898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   (WLAN_FC_STYPE_PROBE_RESP << 4));
20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(resp->da, addr, ETH_ALEN);
20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(resp->sa, p2p->cfg->dev_addr, ETH_ALEN);
20928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(resp->bssid, p2p->cfg->dev_addr, ETH_ALEN);
20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->u.probe_resp.beacon_int = host_to_le16(100);
20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* hardware or low-level driver will setup seq_ctrl and timestamp */
20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->u.probe_resp.capab_info =
20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		host_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE |
20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     WLAN_CAPABILITY_PRIVACY |
20988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     WLAN_CAPABILITY_SHORT_SLOT_TIME);
20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_SSID);
21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, P2P_WILDCARD_SSID_LEN);
21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(buf, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_SUPP_RATES);
21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 8);
21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, (60 / 5) | 0x80);
21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 90 / 5);
21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, (120 / 5) | 0x80);
21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 180 / 5);
21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, (240 / 5) | 0x80);
21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 360 / 5);
21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 480 / 5);
21138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 540 / 5);
21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_DS_PARAMS);
21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 1);
21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, p2p->cfg->channel);
21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_buf(buf, ies);
21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(ies);
21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_probe_resp(p2p->cfg->cb_ctx, buf);
21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(buf);
212504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
212604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return P2P_PREQ_NOT_PROCESSED;
21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
213004949598a23f501be6eec21697465fd46a28840aDmitry Shmidtenum p2p_probe_req_status
213104949598a23f501be6eec21697465fd46a28840aDmitry Shmidtp2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
213204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 const u8 *bssid, const u8 *ie, size_t ie_len)
21338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
213404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	enum p2p_probe_req_status res;
213504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_add_dev_from_probe_req(p2p, addr, ie, ie_len);
21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
213804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	res = p2p_reply_probe(p2p, addr, dst, bssid, ie, ie_len);
21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((p2p->state == P2P_CONNECT || p2p->state == P2P_CONNECT_LISTEN) &&
21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    p2p->go_neg_peer &&
21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(addr, p2p->go_neg_peer->info.p2p_device_addr, ETH_ALEN)
21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    == 0) {
21448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Received a Probe Request from GO Negotiation peer */
21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Found GO Negotiation peer - try to start GO "
21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"negotiation from timeout");
21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(0, 0, p2p_go_neg_start, p2p, NULL);
214904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_PROCESSED;
21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((p2p->state == P2P_INVITE || p2p->state == P2P_INVITE_LISTEN) &&
21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    p2p->invite_peer &&
21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(addr, p2p->invite_peer->info.p2p_device_addr, ETH_ALEN)
21558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    == 0) {
21568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Received a Probe Request from Invite peer */
21578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
21588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Found Invite peer - try to start Invite from "
21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"timeout");
21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(0, 0, p2p_invite_start, p2p, NULL);
216104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_PROCESSED;
21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
216404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return res;
21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_assoc_req_ie_wlan_ap(struct p2p_data *p2p, const u8 *bssid,
21698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    u8 *buf, size_t len, struct wpabuf *p2p_ie)
21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *tmp;
21728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *lpos;
21738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t tmplen;
21748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
21758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 group_capab;
21768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_ie == NULL)
21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* WLAN AP is not a P2P manager */
21798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
21818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (Re)Association Request - P2P IE
21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Capability attribute (shall be present)
21838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Interface attribute (present if concurrent device and
21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *	P2P Management is enabled)
21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp = wpabuf_alloc(200);
21878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp == NULL)
21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
21898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	lpos = p2p_buf_add_ie_hdr(tmp);
21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group_capab = 0;
21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->num_groups > 0) {
21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group_capab |= P2P_GROUP_CAPAB_GROUP_OWNER;
21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) &&
21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED) &&
21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    p2p->cross_connect)
21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_capability(tmp, p2p->dev_capab, group_capab);
22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) &&
22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED))
22028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_p2p_interface(tmp, p2p);
22038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(tmp, lpos);
22048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmplen = wpabuf_len(tmp);
22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmplen > len)
22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = -1;
22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(buf, wpabuf_head(tmp), tmplen);
22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = tmplen;
22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(tmp);
22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
22158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_assoc_req_ie(struct p2p_data *p2p, const u8 *bssid, u8 *buf,
22198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     size_t len, int p2p_group, struct wpabuf *p2p_ie)
22208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *tmp;
22228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *lpos;
22238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *peer;
22248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t tmplen;
22258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
222661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t extra = 0;
22278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p_group)
22298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return p2p_assoc_req_ie_wlan_ap(p2p, bssid, buf, len, p2p_ie);
22308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
223161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
223261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_assoc_req)
223361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		extra = wpabuf_len(p2p->wfd_ie_assoc_req);
223461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
223561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
22368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
22378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (Re)Association Request - P2P IE
22388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Capability attribute (shall be present)
22398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Extended Listen Timing (may be present)
22408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Device Info attribute (shall be present)
22418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
224261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	tmp = wpabuf_alloc(200 + extra);
22438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp == NULL)
22448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
22458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
224661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
224761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_assoc_req)
224861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(tmp, p2p->wfd_ie_assoc_req);
224961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
225061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
22518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer = bssid ? p2p_get_device(p2p, bssid) : NULL;
22528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	lpos = p2p_buf_add_ie_hdr(tmp);
22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_capability(tmp, p2p->dev_capab, 0);
22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval)
22568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_ext_listen_timing(tmp, p2p->ext_listen_period,
22578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      p2p->ext_listen_interval);
22588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_device_info(tmp, p2p, peer);
22598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(tmp, lpos);
22608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmplen = wpabuf_len(tmp);
22628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmplen > len)
22638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = -1;
22648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
22658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(buf, wpabuf_head(tmp), tmplen);
22668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = tmplen;
22678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(tmp);
22698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
22718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_scan_result_text(const u8 *ies, size_t ies_len, char *buf, char *end)
22758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *p2p_ie;
22778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
22788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len, P2P_IE_VENDOR_TYPE);
22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_ie == NULL)
22818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
22828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = p2p_attr_text(p2p_ie, buf, end);
22848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(p2p_ie);
22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
228904949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint p2p_parse_dev_addr_in_p2p_ie(struct wpabuf *p2p_ie, u8 *dev_addr)
2290c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{
2291c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	struct p2p_message msg;
2292c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
2293c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
229404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p_parse_p2p_ie(p2p_ie, &msg))
2295c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return -1;
2296c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
229704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (msg.p2p_device_addr) {
229804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(dev_addr, msg.p2p_device_addr, ETH_ALEN);
229904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 0;
230004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	} else if (msg.device_id) {
230104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(dev_addr, msg.device_id, ETH_ALEN);
230204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 0;
2303c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
230404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return -1;
230504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
2306c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
230704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
230804949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint p2p_parse_dev_addr(const u8 *ies, size_t ies_len, u8 *dev_addr)
230904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
231004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct wpabuf *p2p_ie;
231104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	int ret;
231204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
231304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
231404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					     P2P_IE_VENDOR_TYPE);
231504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p_ie == NULL)
231604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return -1;
231704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	ret = p2p_parse_dev_addr_in_p2p_ie(p2p_ie, dev_addr);
2318c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	wpabuf_free(p2p_ie);
231904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return ret;
2320c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt}
2321c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
2322c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
23238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_clear_go_neg(struct p2p_data *p2p)
23248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer = NULL;
23268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
23278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_IDLE);
23288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_wps_success_cb(struct p2p_data *p2p, const u8 *mac_addr)
23328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == NULL) {
23348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
23358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No pending Group Formation - "
23368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"ignore WPS registration success notification");
23378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* No pending Group Formation */
23388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(mac_addr, p2p->go_neg_peer->intended_addr, ETH_ALEN) !=
23418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0) {
23428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
23438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Ignore WPS registration success notification "
23448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"for " MACSTR " (GO Negotiation peer " MACSTR ")",
23458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(mac_addr),
23468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(p2p->go_neg_peer->intended_addr));
23478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* Ignore unexpected peer address */
23488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
23518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Group Formation completed successfully with " MACSTR,
23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(mac_addr));
23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_go_neg(p2p);
23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_group_formation_failed(struct p2p_data *p2p)
23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == NULL) {
23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No pending Group Formation - "
23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"ignore group formation failure notification");
23648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* No pending Group Formation */
23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Group Formation failed with " MACSTR,
23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(p2p->go_neg_peer->intended_addr));
23708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_go_neg(p2p);
23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_data * p2p_init(const struct p2p_config *cfg)
23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p;
23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->max_peers < 1)
23808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p = os_zalloc(sizeof(*p2p) + sizeof(*cfg));
23838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p == NULL)
23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
23858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg = (struct p2p_config *) (p2p + 1);
23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg, cfg, sizeof(*cfg));
23878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->dev_name)
23888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->dev_name = os_strdup(cfg->dev_name);
23898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->manufacturer)
23908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->manufacturer = os_strdup(cfg->manufacturer);
23918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->model_name)
23928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_name = os_strdup(cfg->model_name);
23938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->model_number)
23948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_number = os_strdup(cfg->model_number);
23958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->serial_number)
23968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->serial_number = os_strdup(cfg->serial_number);
239704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (cfg->pref_chan) {
239804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->cfg->pref_chan = os_malloc(cfg->num_pref_chan *
239904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt						sizeof(struct p2p_channel));
240004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (p2p->cfg->pref_chan) {
240104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			os_memcpy(p2p->cfg->pref_chan, cfg->pref_chan,
240204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  cfg->num_pref_chan *
240304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  sizeof(struct p2p_channel));
240404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		} else
240504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			p2p->cfg->num_pref_chan = 0;
240604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
240704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
2408f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#ifdef ANDROID_P2P
2409f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	/* 100ms listen time is too less to receive the response frames in some scenarios
2410f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	 * increasing min listen time to 200ms.
2411f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	 */
2412f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	p2p->min_disc_int = 2;
2413f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	/* SD_FAIR_POLICY: Initializing the SD current serviced pointer to NULL */
2414f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	p2p->sd_dev_list = NULL;
2415f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#else
24168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->min_disc_int = 1;
2417f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#endif
24188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->max_disc_int = 3;
24198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_random(&p2p->next_tie_breaker, 1);
24218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->next_tie_breaker &= 0x01;
24228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->sd_request)
24238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_SERVICE_DISCOVERY;
24248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->dev_capab |= P2P_DEV_CAPAB_INVITATION_PROCEDURE;
24258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->concurrent_operations)
24268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_CONCURRENT_OPER;
24278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->dev_capab |= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
24288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_init(&p2p->devices);
24308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(P2P_PEER_EXPIRATION_INTERVAL, 0,
24328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p_expiration_timeout, p2p, NULL);
24338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
243461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->go_timeout = 100;
243561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->client_timeout = 20;
243661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
24378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p;
24388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_deinit(struct p2p_data *p2p)
24428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
244361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
244461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_beacon);
244561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_probe_req);
244661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_probe_resp);
244761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_assoc_req);
244861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_invitation);
244961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_prov_disc_req);
245061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_prov_disc_resp);
245161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_go_neg);
245261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_dev_info);
245361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_assoc_bssid);
245461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_coupled_sink_info);
245561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
245661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
24578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_expiration_timeout, p2p, NULL);
24588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_ext_listen_timeout, p2p, NULL);
24598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
24608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_flush(p2p);
24618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_req_dev_types(p2p);
24628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->dev_name);
24638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->manufacturer);
24648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_name);
24658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_number);
24668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->serial_number);
246704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	os_free(p2p->cfg->pref_chan);
24688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->groups);
24698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(p2p->sd_resp);
24708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->after_scan_tx);
24718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_remove_wps_vendor_extensions(p2p);
24728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p);
24738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_flush(struct p2p_data *p2p)
24778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev, *prev;
247904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_stop_find(p2p);
24808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each_safe(dev, prev, &p2p->devices, struct p2p_device,
24818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      list) {
24828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dl_list_del(&dev->list);
24838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_device_free(p2p, dev);
24848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2485f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#ifdef ANDROID_P2P
2486f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	/* SD_FAIR_POLICY: Initializing the SD current serviced pointer to NULL */
2487f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	p2p->sd_dev_list = NULL;
2488f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#endif
24898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_sd_queries(p2p);
24908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->after_scan_tx);
24918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->after_scan_tx = NULL;
24928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_unauthorize(struct p2p_data *p2p, const u8 *addr)
24968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
24988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
25008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
25018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
25028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Unauthorizing " MACSTR,
25048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(addr));
25058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == dev)
25078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->go_neg_peer = NULL;
25088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wps_method = WPS_NOT_READY;
25108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE;
25118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM;
25128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Check if after_scan_tx is for this peer. If so free it */
25148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->after_scan_tx &&
25158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(addr, p2p->after_scan_tx->dst, ETH_ALEN) == 0) {
25168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p2p->after_scan_tx);
25178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = NULL;
25188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
25218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_dev_name(struct p2p_data *p2p, const char *dev_name)
25258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->dev_name);
25278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev_name) {
25288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->dev_name = os_strdup(dev_name);
25298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->dev_name == NULL)
25308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
25318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
25328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->dev_name = NULL;
25338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
25348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_manufacturer(struct p2p_data *p2p, const char *manufacturer)
25388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->manufacturer);
25408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->manufacturer = NULL;
25418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (manufacturer) {
25428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->manufacturer = os_strdup(manufacturer);
25438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->manufacturer == NULL)
25448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
25458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
25488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_model_name(struct p2p_data *p2p, const char *model_name)
25528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_name);
25548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->model_name = NULL;
25558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (model_name) {
25568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_name = os_strdup(model_name);
25578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->model_name == NULL)
25588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
25598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
25628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_model_number(struct p2p_data *p2p, const char *model_number)
25668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_number);
25688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->model_number = NULL;
25698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (model_number) {
25708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_number = os_strdup(model_number);
25718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->model_number == NULL)
25728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
25738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
25768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_serial_number(struct p2p_data *p2p, const char *serial_number)
25808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->serial_number);
25828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->serial_number = NULL;
25838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (serial_number) {
25848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->serial_number = os_strdup(serial_number);
25858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->serial_number == NULL)
25868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
25878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
25908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_config_methods(struct p2p_data *p2p, u16 config_methods)
25948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->config_methods = config_methods;
25968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_uuid(struct p2p_data *p2p, const u8 *uuid)
26008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->uuid, uuid, 16);
26028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_pri_dev_type(struct p2p_data *p2p, const u8 *pri_dev_type)
26068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->pri_dev_type, pri_dev_type, 8);
26088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_sec_dev_types(struct p2p_data *p2p, const u8 dev_types[][8],
26138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  size_t num_dev_types)
26148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (num_dev_types > P2P_SEC_DEVICE_TYPES)
26168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num_dev_types = P2P_SEC_DEVICE_TYPES;
26178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->num_sec_dev_types = num_dev_types;
26188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->sec_dev_type, dev_types, num_dev_types * 8);
26198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_remove_wps_vendor_extensions(struct p2p_data *p2p)
26248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
26268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
26288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(p2p->wps_vendor_ext[i]);
26298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->wps_vendor_ext[i] = NULL;
26308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_add_wps_vendor_extension(struct p2p_data *p2p,
26358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const struct wpabuf *vendor_ext)
26368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
26388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (vendor_ext == NULL)
26408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
26418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
26438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->wps_vendor_ext[i] == NULL)
26448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
26458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (i >= P2P_MAX_WPS_VENDOR_EXT)
26478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
26488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->wps_vendor_ext[i] = wpabuf_dup(vendor_ext);
26508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->wps_vendor_ext[i] == NULL)
26518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
26528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_country(struct p2p_data *p2p, const char *country)
26588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->country, country, 3);
26608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_continue_find(struct p2p_data *p2p)
26658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
2667f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#ifdef ANDROID_P2P
2668f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	int skip=1;
2669f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#endif
26708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_SEARCH);
26718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
2672f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#ifdef ANDROID_P2P
2673f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		/* SD_FAIR_POLICY: We need to give chance to all devices in the device list
2674f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * There may be a scenario, where a particular peer device have
2675f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * not registered any query response. When we send a SD request to such device,
2676f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * no response will be received. And if we continue to get probe responses from that device,
2677f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * and if that device happens to be on top in our device list,
2678f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * we will always continue to send SD requests always to that peer only.
2679f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * We will not be able to send SD requests to other devices in that case.
2680f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * This implementation keeps track of last serviced peer device.
2681f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * And then takes the next one from the device list, in the next iteration.
2682f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 */
2683f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		if (p2p->sd_dev_list && p2p->sd_dev_list != &p2p->devices) {
2684f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff			if(skip) {
2685f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff				if ((&dev->list == p2p->sd_dev_list) ) {
2686f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff					skip = 0;
2687f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff					if (dev->list.next == &p2p->devices)
2688f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff						p2p->sd_dev_list = NULL;
2689f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff				}
2690f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff				continue;
2691f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff			}
2692f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		}
2693f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		p2p->sd_dev_list = &dev->list;
2694f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		wpa_printf(MSG_DEBUG, "P2P: ### Servicing %p dev->flags 0x%x SD schedule %s devaddr " MACSTR,
2695f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff			p2p->sd_dev_list, dev->flags, dev->flags & P2P_DEV_SD_SCHEDULE ? "TRUE": "FALSE",
2696f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff			MAC2STR(dev->info.p2p_device_addr));
2697f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#endif
26988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->flags & P2P_DEV_SD_SCHEDULE) {
26998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (p2p_start_sd(p2p, dev) == 0)
27008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
27018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
27028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
27038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (dev->req_config_methods &&
27048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   !(dev->flags & P2P_DEV_PD_FOR_JOIN)) {
27058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send "
27061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				"pending Provision Discovery Request to "
27078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MACSTR " (config methods 0x%x)",
27088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(dev->info.p2p_device_addr),
27098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev->req_config_methods);
27101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (p2p_send_prov_disc_req(p2p, dev, 0, 0) == 0)
27118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
27128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
27138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_listen_in_find(p2p);
27168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_sd_cb(struct p2p_data *p2p, int success)
27208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
27228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Service Discovery Query TX callback: success=%d",
27238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
27248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
27258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!success) {
27278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->sd_peer) {
27288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE;
27298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->sd_peer = NULL;
27308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
27318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
27328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
27338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->sd_peer == NULL) {
27368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
27378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No SD peer entry known");
27388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
27398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
27408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Wait for response from the peer */
27438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_SD_DURING_FIND);
27448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_timeout(p2p, 0, 200000);
27458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
274775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
274875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen/**
274975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen * p2p_retry_pd - Retry any pending provision disc requests in IDLE state
275075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen * @p2p: P2P module context from p2p_init()
275175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen */
27521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void p2p_retry_pd(struct p2p_data *p2p)
275375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
275475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	struct p2p_device *dev;
275575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
275675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p->state != P2P_IDLE)
275775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
275875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
275975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
276075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * Retry the prov disc req attempt only for the peer that the user had
276175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * requested for and provided a join has not been initiated on it
276275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * in the meantime.
276375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
276475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
276575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
276675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (os_memcmp(p2p->pending_pd_devaddr,
276775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			      dev->info.p2p_device_addr, ETH_ALEN) != 0)
276875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			continue;
276975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (!dev->req_config_methods)
277075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			continue;
277175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (dev->flags & P2P_DEV_PD_FOR_JOIN)
277275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			continue;
277375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
277475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send "
27751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			"pending Provision Discovery Request to "
277675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			MACSTR " (config methods 0x%x)",
277775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			MAC2STR(dev->info.p2p_device_addr),
277875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			dev->req_config_methods);
27791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_send_prov_disc_req(p2p, dev, 0, 0);
278075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
278175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	}
278275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
278375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
278475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
27858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_prov_disc_cb(struct p2p_data *p2p, int success)
27868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
27888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Provision Discovery Request TX callback: success=%d",
27898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
279075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
279175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
279275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * Postpone resetting the pending action state till after we actually
279375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * time out. This allows us to take some action like notifying any
279475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * interested parties about no response to the request.
279575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 *
279675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * When the timer (below) goes off we check in IDLE, SEARCH, or
279775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * LISTEN_ONLY state, which are the only allowed states to issue a PD
279875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * requests in, if this was still pending and then raise notification.
279975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
28008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!success) {
280275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pending_action_state = P2P_NO_PENDING_ACTION;
280375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
280461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->user_initiated_pd &&
280561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		    (p2p->state == P2P_SEARCH || p2p->state == P2P_LISTEN_ONLY))
280661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		{
280761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			/* Retry request from timeout to avoid busy loops */
280861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p->pending_action_state = P2P_PENDING_PD;
280961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p_set_timeout(p2p, 0, 50000);
281061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		} else if (p2p->state != P2P_IDLE)
28118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_continue_find(p2p);
281275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		else if (p2p->user_initiated_pd) {
281375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p->pending_action_state = P2P_PENDING_PD;
28141a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#ifdef ANDROID_P2P
28151a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff			p2p_set_timeout(p2p, 0, 350000);
28161a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#else
281775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_set_timeout(p2p, 0, 300000);
28181a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#endif
281975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		}
28208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
28218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
282375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
282475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * This postponing, of resetting pending_action_state, needs to be
282575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * done only for user initiated PD requests and not internal ones.
282675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
282775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p->user_initiated_pd)
282875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pending_action_state = P2P_PENDING_PD;
282975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	else
283075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pending_action_state = P2P_NO_PENDING_ACTION;
283175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
28328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Wait for response from the peer */
28338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_SEARCH)
28348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_PD_DURING_FIND);
28351a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#ifdef ANDROID_P2P
28361a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff	p2p_set_timeout(p2p, 0, 350000);
28371a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#else
28388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_timeout(p2p, 0, 200000);
28391a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#endif
28408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_scan_res_handler(struct p2p_data *p2p, const u8 *bssid, int freq,
28448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 int level, const u8 *ies, size_t ies_len)
28458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
284604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_add_device(p2p, bssid, freq, level, ies, ies_len, 1);
28478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
28498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_scan_res_handled(struct p2p_data *p2p)
28538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p->p2p_scan_running) {
28558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan was not "
28568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"running, but scan results received");
28578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->p2p_scan_running = 0;
28598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
28608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_run_after_scan(p2p))
28628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
28638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_SEARCH)
28648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
28658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2868c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtvoid p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id)
28698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
287061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 *len;
287161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
287261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
287361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_probe_req)
287461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(ies, p2p->wfd_ie_probe_req);
287561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
287661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
287761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	len = p2p_buf_add_ie_hdr(ies);
287804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_buf_add_capability(ies, p2p->dev_capab &
287904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			       ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 0);
2880c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (dev_id)
2881c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		p2p_buf_add_device_id(ies, dev_id);
28828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->reg_class && p2p->cfg->channel)
28838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_listen_channel(ies, p2p->cfg->country,
28848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   p2p->cfg->reg_class,
28858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   p2p->cfg->channel);
28868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval)
28878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_ext_listen_timing(ies, p2p->ext_listen_period,
28888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      p2p->ext_listen_interval);
28898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: p2p_buf_add_operating_channel() if GO */
28908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(ies, len);
28918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtsize_t p2p_scan_ie_buf_len(struct p2p_data *p2p)
28951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
289661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t len = 100;
289761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
289861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
289961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p && p2p->wfd_ie_probe_req)
290061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		len += wpabuf_len(p2p->wfd_ie_probe_req);
290161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
290261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
290361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return len;
29041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
29051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
29061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
29078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_ie_text(struct wpabuf *p2p_ie, char *buf, char *end)
29088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_attr_text(p2p_ie, buf, end);
29108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_req_cb(struct p2p_data *p2p, int success)
29148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p->go_neg_peer;
29168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
29188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: GO Negotiation Request TX callback: success=%d",
29198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
29208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
29228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
29238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No pending GO Negotiation");
29248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
29258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (success) {
29288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->flags & P2P_DEV_USER_REJECTED) {
29298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_set_state(p2p, P2P_IDLE);
29308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
29318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
293204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	} else if (dev->go_neg_req_sent) {
293304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/* Cancel the increment from p2p_connect_send() on failure */
293498f9e76624da6bb96edc1982c423e4a119c5170aDmitry Shmidt		dev->go_neg_req_sent--;
293598f9e76624da6bb96edc1982c423e4a119c5170aDmitry Shmidt	}
29368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!success &&
29388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (dev->info.dev_capab & P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY) &&
29398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !is_zero_ether_addr(dev->member_in_go_dev)) {
29408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
29418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Peer " MACSTR " did not acknowledge request - "
29428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"try to use device discoverability through its GO",
29438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr));
29448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
29458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_send_dev_disc_req(p2p, dev);
29468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
29478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
29508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Use P2P find, if needed, to find the other device from its listen
29518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * channel.
29528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
29538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_CONNECT);
29541a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#ifdef ANDROID_P2P
29551a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff	p2p_set_timeout(p2p, 0, 350000);
29561a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#else
295761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_set_timeout(p2p, 0, success ? 200000 : 100000);
29581a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#endif
29598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_resp_cb(struct p2p_data *p2p, int success)
29638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
29658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: GO Negotiation Response TX callback: success=%d",
29668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
29678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p->go_neg_peer && p2p->state == P2P_PROVISIONING) {
29688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
29698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Ignore TX callback event - GO Negotiation is "
29708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"not running anymore");
29718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
29728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_CONNECT);
29741a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#ifdef ANDROID_P2P
29751a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff	p2p_set_timeout(p2p, 0, 350000);
29761a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#else
297761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_set_timeout(p2p, 0, 250000);
29781a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#endif
29798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_resp_failure_cb(struct p2p_data *p2p, int success)
29838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
29858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: GO Negotiation Response (failure) TX callback: "
29868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"success=%d", success);
29878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer && p2p->go_neg_peer->status != P2P_SC_SUCCESS) {
29888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_failed(p2p, p2p->go_neg_peer,
29898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  p2p->go_neg_peer->status);
29908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_conf_cb(struct p2p_data *p2p,
29958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       enum p2p_send_action_result result)
29968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
29988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
30008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: GO Negotiation Confirm TX callback: result=%d",
30018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		result);
30028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
30038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (result == P2P_SEND_ACTION_FAILED) {
30048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
30058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
30068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (result == P2P_SEND_ACTION_NO_ACK) {
30088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
30098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * It looks like the TX status for GO Negotiation Confirm is
30108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * often showing failure even when the peer has actually
30118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * received the frame. Since the peer may change channels
30128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * immediately after having received the frame, we may not see
30138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * an Ack for retries, so just dropping a single frame may
30148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * trigger this. To allow the group formation to succeed if the
30158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * peer did indeed receive the frame, continue regardless of
30168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * the TX status.
30178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
30188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
30198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Assume GO Negotiation Confirm TX was actually "
30208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"received by the peer even though Ack was not "
30218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"reported");
30228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p->go_neg_peer;
30258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
30268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
30278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_go_complete(p2p, dev);
30298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_send_action_cb(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
30338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const u8 *src, const u8 *bssid,
30348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			enum p2p_send_action_result result)
30358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum p2p_pending_action_state state;
30378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int success;
30388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
30408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Action frame TX callback (state=%d freq=%u dst=" MACSTR
30418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" src=" MACSTR " bssid=" MACSTR " result=%d",
30428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_action_state, freq, MAC2STR(dst), MAC2STR(src),
30438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(bssid), result);
30448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	success = result == P2P_SEND_ACTION_SUCCESS;
30458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	state = p2p->pending_action_state;
30468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
30478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (state) {
30488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_NO_PENDING_ACTION:
30498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_REQUEST:
30518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_req_cb(p2p, success);
30528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_RESPONSE:
30548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_resp_cb(p2p, success);
30558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_RESPONSE_FAILURE:
30578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_resp_failure_cb(p2p, success);
30588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_CONFIRM:
30608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_conf_cb(p2p, result);
30618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_SD:
30638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_sd_cb(p2p, success);
30648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_PD:
30668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_prov_disc_cb(p2p, success);
30678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_INVITATION_REQUEST:
30698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_invitation_req_cb(p2p, success);
30708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_INVITATION_RESPONSE:
30728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_invitation_resp_cb(p2p, success);
30738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_DEV_DISC_REQUEST:
30758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_disc_req_cb(p2p, success);
30768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_DEV_DISC_RESPONSE:
30788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_disc_resp_cb(p2p, success);
30798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_DISC_REQ:
30818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_disc_req_cb(p2p, success);
30828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_listen_cb(struct p2p_data *p2p, unsigned int freq,
30888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   unsigned int duration)
30898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq == p2p->pending_client_disc_freq) {
30918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
30928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Client discoverability remain-awake completed");
30938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_client_disc_freq = 0;
30948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
30958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq != p2p->pending_listen_freq) {
30988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
30998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Unexpected listen callback for freq=%u "
31008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"duration=%u (pending_listen_freq=%u)",
31018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq, duration, p2p->pending_listen_freq);
31028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
31038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
31068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Starting Listen timeout(%u,%u) on freq=%u based on "
31078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"callback",
31088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_sec, p2p->pending_listen_usec,
31098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_freq);
31108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->in_listen = 1;
31118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->drv_in_listen = freq;
31128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->pending_listen_sec || p2p->pending_listen_usec) {
31138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
31148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Add 20 msec extra wait to avoid race condition with driver
31158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * remain-on-channel end event, i.e., give driver more time to
31168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * complete the operation before our timeout expires.
31178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
31188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_timeout(p2p, p2p->pending_listen_sec,
31198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p->pending_listen_usec + 20000);
31208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_freq = 0;
31238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_listen_end(struct p2p_data *p2p, unsigned int freq)
31278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Driver ended Listen "
31298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"state (freq=%u)", freq);
31308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->drv_in_listen = 0;
31318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->in_listen)
31328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* Internal timeout will trigger the next step */
31338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_CONNECT_LISTEN && p2p->go_neg_peer) {
31358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->go_neg_peer->connect_reqs >= 120) {
31368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
31378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Timeout on sending GO Negotiation "
31388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Request without getting response");
31398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
31408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 0;
31418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_CONNECT);
31448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, p2p->go_neg_peer);
31458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
31468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (p2p->state == P2P_SEARCH) {
3147c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (p2p->p2p_scan_running) {
3148c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 /*
3149c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * Search is already in progress. This can happen if
3150c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * an Action frame RX is reported immediately after
3151c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * the end of a remain-on-channel operation and the
3152c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * response frame to that is sent using an offchannel
3153c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * operation while in p2p_find. Avoid an attempt to
3154c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * restart a scan here.
3155c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  */
3156c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan "
3157c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				"already in progress - do not try to start a "
3158c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				"new one");
3159c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			return 1;
3160c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		}
316104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (p2p->pending_listen_freq) {
316204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			/*
316304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 * Better wait a bit if the driver is unable to start
316404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 * offchannel operation for some reason. p2p_search()
316504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 * will be started from internal timeout.
316604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 */
316704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Listen "
316804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				"operation did not seem to start - delay "
316904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				"search phase to avoid busy loop");
317004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			p2p_set_timeout(p2p, 0, 100000);
317104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			return 1;
317204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
317361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->search_delay) {
317461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Delay "
317561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				"search operation by %u ms",
317661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				p2p->search_delay);
317761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p_set_timeout(p2p, p2p->search_delay / 1000,
317861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					(p2p->search_delay % 1000) * 1000);
317961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return 1;
318061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
31818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_search(p2p);
31828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
31838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
31868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_connect(struct p2p_data *p2p)
31908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
319204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p->go_neg_peer &&
319304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    (p2p->go_neg_peer->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM)) {
319404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Wait for GO "
319504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			"Negotiation Confirm timed out - assume GO "
319604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			"Negotiation failed");
319704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
319804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return;
319904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
32008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_CONNECT_LISTEN);
32018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_listen_in_find(p2p);
32028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_connect_listen(struct p2p_data *p2p)
32068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
32078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer) {
32088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->drv_in_listen) {
32098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Driver is "
32108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"still in Listen state; wait for it to "
32118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"complete");
32128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
32138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
32148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->go_neg_peer->connect_reqs >= 120) {
32168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
32178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Timeout on sending GO Negotiation "
32188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Request without getting response");
32198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
32208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
32218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
32228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_CONNECT);
32248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, p2p->go_neg_peer);
32258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
32268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
32278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_wait_peer_connect(struct p2p_data *p2p)
32318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
32328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
32338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * TODO: could remain constantly in Listen state for some time if there
32348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * are no other concurrent uses for the radio. For now, go to listen
32358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * state once per second to give other uses a chance to use the radio.
32368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
32378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_WAIT_PEER_IDLE);
32381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_set_timeout(p2p, 0, 500000);
32398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_wait_peer_idle(struct p2p_data *p2p)
32438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
32448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p->go_neg_peer;
32458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
32478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
32488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Unknown GO Neg peer - stop GO Neg wait");
32498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
32508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wait_count++;
32538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->wait_count >= 120) {
32548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
32558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Timeout on waiting peer to become ready for GO "
32568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Negotiation");
32578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_failed(p2p, dev, -1);
32588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
32598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
32628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Go to Listen state while waiting for the peer to become "
32638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"ready for GO Negotiation");
32648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_WAIT_PEER_CONNECT);
32658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_listen_in_find(p2p);
32668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_sd_during_find(struct p2p_data *p2p)
32708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
32718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
32728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Service Discovery Query timeout");
32738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->sd_peer) {
32748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
32758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE;
32768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->sd_peer = NULL;
32778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_continue_find(p2p);
32798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_prov_disc_during_find(struct p2p_data *p2p)
32838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
32848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
32858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Provision Discovery Request timeout");
32868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
32878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_continue_find(p2p);
32888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
329175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic void p2p_timeout_prov_disc_req(struct p2p_data *p2p)
329275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
329375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
329475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
329575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
329675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * For user initiated PD requests that we have not gotten any responses
329775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * for while in IDLE state, we retry them a couple of times before
329875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * giving up.
329975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
330075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (!p2p->user_initiated_pd)
330175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
330275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
330375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
330475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		"P2P: User initiated Provision Discovery Request timeout");
330575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
330675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p->pd_retries) {
330775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pd_retries--;
330875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p_retry_pd(p2p);
330975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	} else {
331075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->cfg->prov_disc_fail)
331175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx,
331275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen						 p2p->pending_pd_devaddr,
331375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen						 P2P_PROV_DISC_TIMEOUT);
331475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p_reset_pending_pd(p2p);
331575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	}
331675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
331775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
331875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
33198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_invite(struct p2p_data *p2p)
33208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
33228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_INVITE_LISTEN);
33238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->inv_role == P2P_INVITE_ROLE_ACTIVE_GO) {
33248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
33258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Better remain on operating channel instead of listen channel
33268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * when running a group.
33278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
33288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Inviting in "
33298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"active GO role - wait on operating channel");
33308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_timeout(p2p, 0, 100000);
33318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
33328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_listen_in_find(p2p);
33348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_invite_listen(struct p2p_data *p2p)
33388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->invite_peer && p2p->invite_peer->invitation_reqs < 100) {
33408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_INVITE);
33418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_invite_send(p2p, p2p->invite_peer,
33428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p->invite_go_dev_addr);
33438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
33448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->invite_peer) {
33458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
33468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Invitation Request retry limit reached");
33478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (p2p->cfg->invitation_result)
33488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p->cfg->invitation_result(
33498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					p2p->cfg->cb_ctx, -1, NULL);
33508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
33518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
33528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_state_timeout(void *eloop_ctx, void *timeout_ctx)
33578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
33598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Timeout (state=%s)",
33618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state));
33628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->in_listen = 0;
33648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (p2p->state) {
33668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_IDLE:
336775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/* Check if we timed out waiting for PD req */
336875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->pending_action_state == P2P_PENDING_PD)
336975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_timeout_prov_disc_req(p2p);
33708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
33718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SEARCH:
337275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/* Check if we timed out waiting for PD req */
337375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->pending_action_state == P2P_PENDING_PD)
337475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_timeout_prov_disc_req(p2p);
337561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->search_delay && !p2p->in_search_delay) {
337661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Delay "
337761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				"search operation by %u ms",
337861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				p2p->search_delay);
337961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p->in_search_delay = 1;
338061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p_set_timeout(p2p, p2p->search_delay / 1000,
338161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					(p2p->search_delay % 1000) * 1000);
338261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			break;
338361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
338461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->in_search_delay = 0;
33858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_search(p2p);
33868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
33878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT:
33888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_connect(p2p);
33898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
33908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT_LISTEN:
33918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_connect_listen(p2p);
33928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
33938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG:
33948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
33958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_LISTEN_ONLY:
339675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/* Check if we timed out waiting for PD req */
339775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->pending_action_state == P2P_PENDING_PD)
339875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_timeout_prov_disc_req(p2p);
339975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
34008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->ext_listen_only) {
34018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
34028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Extended Listen Timing - Listen State "
34038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"completed");
34048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->ext_listen_only = 0;
34058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_set_state(p2p, P2P_IDLE);
34068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
34078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_CONNECT:
34098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_wait_peer_connect(p2p);
34108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_IDLE:
34128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_wait_peer_idle(p2p);
34138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SD_DURING_FIND:
34158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_sd_during_find(p2p);
34168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROVISIONING:
34188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PD_DURING_FIND:
34208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_prov_disc_during_find(p2p);
34218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE:
34238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_invite(p2p);
34248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE_LISTEN:
34268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_invite_listen(p2p);
34278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case P2P_SEARCH_WHEN_READY:
34291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
343061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	case P2P_CONTINUE_SEARCH_WHEN_READY:
343161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		break;
34328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_reject(struct p2p_data *p2p, const u8 *peer_addr)
34378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
34398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
34418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Local request to reject "
34428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"connection attempts by peer " MACSTR, MAC2STR(peer_addr));
34438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
34448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR
34458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			" unknown", MAC2STR(peer_addr));
34468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
34478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->status = P2P_SC_FAIL_REJECTED_BY_USER;
34498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_USER_REJECTED;
34508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
34518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtconst char * p2p_wps_method_text(enum p2p_wps_method method)
34558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (method) {
34578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_NOT_READY:
34588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "not-ready";
34598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_PIN_DISPLAY:
34608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "Display";
34618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_PIN_KEYPAD:
34628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "Keypad";
34638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_PBC:
34648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "PBC";
34658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return "??";
34688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * p2p_go_state_text(enum p2p_go_state go_state)
34728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (go_state) {
34748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case UNKNOWN_GO:
34758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "unknown";
34768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case LOCAL_GO:
34778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "local";
34788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case  REMOTE_GO:
34798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "remote";
34808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return "??";
34838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtconst struct p2p_peer_info * p2p_get_peer_info(struct p2p_data *p2p,
34871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					       const u8 *addr, int next)
34888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
34908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr)
34928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, addr);
34938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
34948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = dl_list_first(&p2p->devices, struct p2p_device, list);
34958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev && next) {
34978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = dl_list_first(&dev->list, struct p2p_device, list);
34988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (&dev->list == &p2p->devices)
34998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev = NULL;
35008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
35018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
35031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return NULL;
35041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
35051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return &dev->info;
35061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
35071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
35081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
35091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_get_peer_info_txt(const struct p2p_peer_info *info,
35101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			  char *buf, size_t buflen)
35111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
35121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_device *dev;
35131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int res;
35141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	char *pos, *end;
35151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct os_time now;
35161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
35171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (info == NULL)
35188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
35198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	dev = (struct p2p_device *) (((u8 *) info) -
35211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				     offsetof(struct p2p_device, info));
35221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
35238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf;
35248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = buf + buflen;
35258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&now);
35278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = os_snprintf(pos, end - pos,
35288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "age=%d\n"
35298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "listen_freq=%d\n"
35308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "wps_method=%s\n"
35318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "interface_addr=" MACSTR "\n"
35328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "member_in_go_dev=" MACSTR "\n"
35338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "member_in_go_iface=" MACSTR "\n"
35348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "go_neg_req_sent=%d\n"
35358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "go_state=%s\n"
35368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dialog_token=%u\n"
35378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "intended_addr=" MACSTR "\n"
35388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "country=%c%c\n"
35398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "oper_freq=%d\n"
35408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "req_config_methods=0x%x\n"
35418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "flags=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n"
35428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "status=%d\n"
35438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "wait_count=%u\n"
35448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "invitation_reqs=%u\n",
35458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  (int) (now.sec - dev->last_seen.sec),
35468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->listen_freq,
35478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  p2p_wps_method_text(dev->wps_method),
35488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->interface_addr),
35498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->member_in_go_dev),
35508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->member_in_go_iface),
35518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->go_neg_req_sent,
35528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  p2p_go_state_text(dev->go_state),
35538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->dialog_token,
35548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->intended_addr),
35558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->country[0] ? dev->country[0] : '_',
35568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->country[1] ? dev->country[1] : '_',
35578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->oper_freq,
35588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->req_config_methods,
35598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PROBE_REQ_ONLY ?
35608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PROBE_REQ_ONLY]" : "",
35618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_REPORTED ? "[REPORTED]" : "",
35628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_NOT_YET_READY ?
35638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[NOT_YET_READY]" : "",
35648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_SD_INFO ? "[SD_INFO]" : "",
35658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_SD_SCHEDULE ? "[SD_SCHEDULE]" :
35668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "",
35678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PD_PEER_DISPLAY ?
35688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PD_PEER_DISPLAY]" : "",
35698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PD_PEER_KEYPAD ?
35708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PD_PEER_KEYPAD]" : "",
35718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_USER_REJECTED ?
35728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[USER_REJECTED]" : "",
35738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PEER_WAITING_RESPONSE ?
35748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PEER_WAITING_RESPONSE]" : "",
35758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PREFER_PERSISTENT_GROUP ?
35768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PREFER_PERSISTENT_GROUP]" : "",
35778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_WAIT_GO_NEG_RESPONSE ?
35788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[WAIT_GO_NEG_RESPONSE]" : "",
35798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM ?
35808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[WAIT_GO_NEG_CONFIRM]" : "",
35818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_GROUP_CLIENT_ONLY ?
35828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[GROUP_CLIENT_ONLY]" : "",
35838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_FORCE_FREQ ?
35848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[FORCE_FREQ]" : "",
35858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PD_FOR_JOIN ?
35868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PD_FOR_JOIN]" : "",
35878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->status,
35888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->wait_count,
35898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->invitation_reqs);
35908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0 || res >= end - pos)
35918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return pos - buf;
35928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += res;
35938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->ext_listen_period) {
35958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = os_snprintf(pos, end - pos,
35968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "ext_listen_period=%u\n"
35978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "ext_listen_interval=%u\n",
35988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  dev->ext_listen_period,
35998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  dev->ext_listen_interval);
36008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res < 0 || res >= end - pos)
36018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos - buf;
36028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += res;
36038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
36048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->oper_ssid_len) {
36068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = os_snprintf(pos, end - pos,
36078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "oper_ssid=%s\n",
36088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  wpa_ssid_txt(dev->oper_ssid,
36098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       dev->oper_ssid_len));
36108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res < 0 || res >= end - pos)
36118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos - buf;
36128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += res;
36138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
36148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
361561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
361661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (dev->info.wfd_subelems) {
361761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		res = os_snprintf(pos, end - pos, "wfd_subelems=");
361861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (res < 0 || res >= end - pos)
361961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return pos - buf;
362061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += res;
362161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
362261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += wpa_snprintf_hex(pos, end - pos,
362361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					wpabuf_head(dev->info.wfd_subelems),
362461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					wpabuf_len(dev->info.wfd_subelems));
362561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
362661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		res = os_snprintf(pos, end - pos, "\n");
362761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (res < 0 || res >= end - pos)
362861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return pos - buf;
362961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += res;
363061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
363161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
363261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
36338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return pos - buf;
36348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
36358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_peer_known(struct p2p_data *p2p, const u8 *addr)
36381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
36391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return p2p_get_device(p2p, addr) != NULL;
36401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
36411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
36421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
36438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_client_discoverability(struct p2p_data *p2p, int enabled)
36448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
36458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (enabled) {
36468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Client "
36478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"discoverability enabled");
36488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
36498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
36508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Client "
36518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"discoverability disabled");
36528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab &= ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
36538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
36548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
36558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_presence_req(u32 duration1, u32 interval1,
36588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      u32 duration2, u32 interval2)
36598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
36608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
36618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_noa_desc desc1, desc2, *ptr1 = NULL, *ptr2 = NULL;
36628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
36638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req = wpabuf_alloc(100);
36658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL)
36668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
36678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (duration1 || interval1) {
36698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(&desc1, 0, sizeof(desc1));
36708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc1.count_type = 1;
36718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc1.duration = duration1;
36728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc1.interval = interval1;
36738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ptr1 = &desc1;
36748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (duration2 || interval2) {
36768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(&desc2, 0, sizeof(desc2));
36778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc2.count_type = 2;
36788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc2.duration = duration2;
36798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc2.interval = interval2;
36808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ptr2 = &desc2;
36818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
36828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
36838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_action_hdr(req, P2P_PRESENCE_REQ, 1);
36858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(req);
36868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_noa(req, 0, 0, 0, ptr1, ptr2);
36878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(req, len);
36888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return req;
36908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
36918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_presence_req(struct p2p_data *p2p, const u8 *go_interface_addr,
36948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     const u8 *own_interface_addr, unsigned int freq,
36958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     u32 duration1, u32 interval1, u32 duration2,
36968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     u32 interval2)
36978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
36988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
36998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send Presence Request to "
37018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"GO " MACSTR " (own interface " MACSTR ") freq=%u dur1=%u "
37028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"int1=%u dur2=%u int2=%u",
37038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(go_interface_addr), MAC2STR(own_interface_addr),
37048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		freq, duration1, interval1, duration2, interval2);
37058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req = p2p_build_presence_req(duration1, interval1, duration2,
37078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     interval2);
37088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL)
37098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
37108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
37128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_send_action(p2p, freq, go_interface_addr, own_interface_addr,
37138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    go_interface_addr,
37148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpabuf_head(req), wpabuf_len(req), 200) < 0) {
37158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
37168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to send Action frame");
37178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(req);
37198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
37218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
37228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_presence_resp(u8 status, const u8 *noa,
37258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       size_t noa_len, u8 dialog_token)
37268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
37278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
37288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
37298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = wpabuf_alloc(100 + noa_len);
37318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
37328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
37338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_action_hdr(resp, P2P_PRESENCE_RESP, dialog_token);
37358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(resp);
37368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_status(resp, status);
37378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (noa) {
37388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(resp, P2P_ATTR_NOTICE_OF_ABSENCE);
37398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_le16(resp, noa_len);
37408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_data(resp, noa, noa_len);
37418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
37428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_noa(resp, 0, 0, 0, NULL, NULL);
37438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(resp, len);
37448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return resp;
37468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
37478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_req(struct p2p_data *p2p, const u8 *da,
37508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const u8 *sa, const u8 *data, size_t len,
37518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     int rx_freq)
37528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
37538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
37548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 status;
37558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
37568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t g;
37578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group *group = NULL;
37588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int parsed = 0;
37598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 noa[50];
37608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int noa_len;
37618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
37638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Received P2P Action - P2P Presence Request");
37648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (g = 0; g < p2p->num_groups; g++) {
37668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(da, p2p_group_get_interface_addr(p2p->groups[g]),
37678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      ETH_ALEN) == 0) {
37688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group = p2p->groups[g];
37698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
37708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
37718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group == NULL) {
37738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
37748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Ignore P2P Presence Request for unknown group "
37758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MACSTR, MAC2STR(da));
37768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
37778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse(data, len, &msg) < 0) {
37808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
37818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to parse P2P Presence Request");
37828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		status = P2P_SC_FAIL_INVALID_PARAMS;
37838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
37848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	parsed = 1;
37868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.noa == NULL) {
37888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
37898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No NoA attribute in P2P Presence Request");
37908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		status = P2P_SC_FAIL_INVALID_PARAMS;
37918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
37928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	status = p2p_group_presence_req(group, sa, msg.noa, msg.noa_len);
37958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail:
37978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->get_noa)
37988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		noa_len = p2p->cfg->get_noa(p2p->cfg->cb_ctx, da, noa,
37998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    sizeof(noa));
38008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
38018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		noa_len = -1;
38028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = p2p_build_presence_resp(status, noa_len > 0 ? noa : NULL,
38038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       noa_len > 0 ? noa_len : 0,
38048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       msg.dialog_token);
38058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (parsed)
38068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
38078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
38088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
38098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
38118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_send_action(p2p, rx_freq, sa, da, da,
38128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
38138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
38148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to send Action frame");
38158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(resp);
38178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
38188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_resp(struct p2p_data *p2p, const u8 *da,
38218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *sa, const u8 *data, size_t len)
38228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
38238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
38248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
38268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Received P2P Action - P2P Presence Response");
38278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse(data, len, &msg) < 0) {
38298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
38308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to parse P2P Presence Response");
38318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
38328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.status == NULL || msg.noa == NULL) {
38358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
38368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No Status or NoA attribute in P2P Presence "
38378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Response");
38388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
38398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
38408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*msg.status) {
38438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
38448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: P2P Presence Request was rejected: status %u",
38458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*msg.status);
38468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
38478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
38488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
38518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: P2P Presence Request was accepted");
38528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "P2P: P2P Presence Response - NoA",
38538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    msg.noa, msg.noa_len);
38548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: process NoA */
38558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
38568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
38578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_ext_listen_timeout(void *eloop_ctx, void *timeout_ctx)
38608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
38618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
38628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval) {
38648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Schedule next extended listen timeout */
38658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(p2p->ext_listen_interval_sec,
38668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p->ext_listen_interval_usec,
38678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p_ext_listen_timeout, p2p, NULL);
38688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_LISTEN_ONLY && p2p->ext_listen_only) {
38718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
38728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * This should not really happen, but it looks like the Listen
38738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * command may fail is something else (e.g., a scan) was
38748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * running at an inconvenient time. As a workaround, allow new
38758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Extended Listen operation to be started.
38768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
38778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Previous "
38788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Extended Listen operation had not been completed - "
38798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"try again");
38808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_only = 0;
38818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
38828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state != P2P_IDLE) {
38858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Skip Extended "
38868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Listen timeout in active state (%s)",
38878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_state_txt(p2p->state));
38888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
38898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Extended Listen timeout");
38928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_only = 1;
38938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_listen(p2p, p2p->ext_listen_period) < 0) {
38948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Failed to start "
38958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Listen state for Extended Listen Timing");
38968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_only = 0;
38978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
38998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_ext_listen(struct p2p_data *p2p, unsigned int period,
39028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   unsigned int interval)
39038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
39048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (period > 65535 || interval > 65535 || period > interval ||
39058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (period == 0 && interval > 0) || (period > 0 && interval == 0)) {
39068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
39078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Invalid Extended Listen Timing request: "
39088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"period=%u interval=%u", period, interval);
39098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
39108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_ext_listen_timeout, p2p, NULL);
39138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (interval == 0) {
39158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
39168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Disabling Extended Listen Timing");
39178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_period = 0;
39188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_interval = 0;
39198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
39208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
39238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Enabling Extended Listen Timing: period %u msec, "
39248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"interval %u msec", period, interval);
39258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_period = period;
39268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_interval = interval;
39278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_interval_sec = interval / 1000;
39288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_interval_usec = (interval % 1000) * 1000;
39298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(p2p->ext_listen_interval_sec,
39318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p->ext_listen_interval_usec,
39328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p_ext_listen_timeout, p2p, NULL);
39338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
39358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_deauth_notif(struct p2p_data *p2p, const u8 *bssid, u16 reason_code,
39398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      const u8 *ie, size_t ie_len)
39408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
39418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
39428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bssid == NULL || ie == NULL)
39448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
39458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
39478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg))
39488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
39498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.minor_reason_code == NULL)
39508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
39518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_INFO,
39538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Deauthentication notification BSSID " MACSTR
39548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" reason_code=%u minor_reason_code=%u",
39558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(bssid), reason_code, *msg.minor_reason_code);
39568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
39588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_disassoc_notif(struct p2p_data *p2p, const u8 *bssid, u16 reason_code,
39628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const u8 *ie, size_t ie_len)
39638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
39648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
39658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bssid == NULL || ie == NULL)
39678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
39688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
39708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg))
39718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
39728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.minor_reason_code == NULL)
39738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
39748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_INFO,
39768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Disassociation notification BSSID " MACSTR
39778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" reason_code=%u minor_reason_code=%u",
39788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(bssid), reason_code, *msg.minor_reason_code);
39798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
39818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_managed_oper(struct p2p_data *p2p, int enabled)
39858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
39868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (enabled) {
39878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Managed P2P "
39888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Device operations enabled");
39898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_INFRA_MANAGED;
39908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
39918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Managed P2P "
39928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Device operations disabled");
39938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab &= ~P2P_DEV_CAPAB_INFRA_MANAGED;
39948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel)
39998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
40008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_channel_to_freq(p2p->cfg->country, reg_class, channel) < 0)
40018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
40028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Set Listen channel: "
40048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"reg_class %u channel %u", reg_class, channel);
40058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->reg_class = reg_class;
40068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->channel = channel;
40078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
40098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
40108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_ssid_postfix(struct p2p_data *p2p, const u8 *postfix, size_t len)
40138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
40148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "P2P: New SSID postfix", postfix, len);
40158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (postfix == NULL) {
40168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->ssid_postfix_len = 0;
40178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
40188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
40198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > sizeof(p2p->cfg->ssid_postfix))
40208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
40218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->ssid_postfix, postfix, len);
40228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->ssid_postfix_len = len;
40238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
40248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
40258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
402775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenint p2p_set_oper_channel(struct p2p_data *p2p, u8 op_reg_class, u8 op_channel,
402875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			 int cfg_op_channel)
402975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
403075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p_channel_to_freq(p2p->cfg->country, op_reg_class, op_channel)
403175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	    < 0)
403275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return -1;
403375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
403475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, "P2P: Set Operating channel: "
403575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		"reg_class %u channel %u", op_reg_class, op_channel);
403675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->cfg->op_reg_class = op_reg_class;
403775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->cfg->op_channel = op_channel;
403875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->cfg->cfg_op_channel = cfg_op_channel;
403975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	return 0;
404075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
404175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
404275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
404304949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint p2p_set_pref_chan(struct p2p_data *p2p, unsigned int num_pref_chan,
404404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		      const struct p2p_channel *pref_chan)
404504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
404604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct p2p_channel *n;
404704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
404804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (pref_chan) {
404904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		n = os_malloc(num_pref_chan * sizeof(struct p2p_channel));
405004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (n == NULL)
405104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			return -1;
405204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(n, pref_chan,
405304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			  num_pref_chan * sizeof(struct p2p_channel));
405404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	} else
405504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		n = NULL;
405604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
405704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	os_free(p2p->cfg->pref_chan);
405804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p->cfg->pref_chan = n;
405904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p->cfg->num_pref_chan = num_pref_chan;
406004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
406104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return 0;
406204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
406304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
406404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
40658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_interface_addr(struct p2p_data *p2p, const u8 *dev_addr,
40668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   u8 *iface_addr)
40678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
40688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p_get_device(p2p, dev_addr);
40698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL || is_zero_ether_addr(dev->interface_addr))
40708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
40718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(iface_addr, dev->interface_addr, ETH_ALEN);
40728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
40738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
40748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_dev_addr(struct p2p_data *p2p, const u8 *iface_addr,
40778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   u8 *dev_addr)
40788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
40798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p_get_device_interface(p2p, iface_addr);
40808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
40818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
40828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev_addr, dev->info.p2p_device_addr, ETH_ALEN);
40838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
40848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
40858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_peer_filter(struct p2p_data *p2p, const u8 *addr)
40888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
40898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->peer_filter, addr, ETH_ALEN);
40908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (is_zero_ether_addr(p2p->peer_filter))
40918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Disable peer "
40928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"filter");
40938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
40948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Enable peer "
40958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"filter for " MACSTR, MAC2STR(p2p->peer_filter));
40968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
40978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_cross_connect(struct p2p_data *p2p, int enabled)
41008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
41018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Cross connection %s",
41028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		enabled ? "enabled" : "disabled");
41038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cross_connect == enabled)
41048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
41058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cross_connect = enabled;
41068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: may need to tear down any action group where we are GO(?) */
41078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_oper_freq(struct p2p_data *p2p, const u8 *iface_addr)
41118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
41128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p_get_device_interface(p2p, iface_addr);
41138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
41148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
41158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->oper_freq <= 0)
41168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
41178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return dev->oper_freq;
41188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_intra_bss_dist(struct p2p_data *p2p, int enabled)
41228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
41238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Intra BSS distribution %s",
41248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		enabled ? "enabled" : "disabled");
41258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->p2p_intra_bss = enabled;
41268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_update_channel_list(struct p2p_data *p2p, struct p2p_channels *chan)
41308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
41318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Update channel list");
41328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&p2p->cfg->channels, chan, sizeof(struct p2p_channels));
41338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_send_action(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
41378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    const u8 *src, const u8 *bssid, const u8 *buf,
41388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    size_t len, unsigned int wait_time)
41398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
41408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
41418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Delay Action "
41428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"frame TX until p2p_scan completes");
41438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->after_scan_tx) {
41448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Dropped "
41458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"previous pending Action frame TX");
41468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(p2p->after_scan_tx);
41478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
41488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = os_malloc(sizeof(*p2p->after_scan_tx) +
41498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       len);
41508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->after_scan_tx == NULL)
41518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
41528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx->freq = freq;
41538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx->dst, dst, ETH_ALEN);
41548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx->src, src, ETH_ALEN);
41558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx->bssid, bssid, ETH_ALEN);
41568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx->len = len;
41578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx->wait_time = wait_time;
41588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx + 1, buf, len);
41598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
41608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
41618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, dst, src, bssid,
41638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     buf, len, wait_time);
41648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_best_channels(struct p2p_data *p2p, int freq_24, int freq_5,
41688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   int freq_overall)
41698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
41708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Best channel: 2.4 GHz: %d,"
41718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  5 GHz: %d,  overall: %d", freq_24, freq_5, freq_overall);
41728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->best_freq_24 = freq_24;
41738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->best_freq_5 = freq_5;
41748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->best_freq_overall = freq_overall;
41758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * p2p_get_go_neg_peer(struct p2p_data *p2p)
41798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
41808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p == NULL || p2p->go_neg_peer == NULL)
41818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
41828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p->go_neg_peer->info.p2p_device_addr;
41838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst struct p2p_peer_info *
41878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtp2p_get_peer_found(struct p2p_data *p2p, const u8 *addr, int next)
41888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
41898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
41908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr) {
41928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, addr);
41938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!dev)
41948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
41958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!next) {
41978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev->flags & P2P_DEV_PROBE_REQ_ONLY)
41988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return NULL;
41998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return &dev->info;
42018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
42028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			do {
42038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev = dl_list_first(&dev->list,
42048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    struct p2p_device,
42058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    list);
42068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				if (&dev->list == &p2p->devices)
42078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					return NULL;
42088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} while (dev->flags & P2P_DEV_PROBE_REQ_ONLY);
42098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
42108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
42118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = dl_list_first(&p2p->devices, struct p2p_device, list);
42128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!dev)
42138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
42148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (dev->flags & P2P_DEV_PROBE_REQ_ONLY) {
42158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev = dl_list_first(&dev->list,
42168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    struct p2p_device,
42178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    list);
42188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (&dev->list == &p2p->devices)
42198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return NULL;
42208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
42218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
42228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return &dev->info;
42248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
42251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
42261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef ANDROID_P2P
42271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_search_in_progress(struct p2p_data *p2p)
42281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
42291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p == NULL)
42301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
42311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
42321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return p2p->state == P2P_SEARCH;
42331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
42341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif
42351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
42361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_in_progress(struct p2p_data *p2p)
42371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
42381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p == NULL)
42391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
424061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->state == P2P_SEARCH || p2p->state == P2P_SEARCH_WHEN_READY ||
424161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	    p2p->state == P2P_CONTINUE_SEARCH_WHEN_READY)
424261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return 2;
42431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return p2p->state != P2P_IDLE && p2p->state != P2P_PROVISIONING;
42441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
424561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
424661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
424761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid p2p_set_config_timeout(struct p2p_data *p2p, u8 go_timeout,
424861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			    u8 client_timeout)
424961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
425061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p) {
425161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->go_timeout = go_timeout;
425261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->client_timeout = client_timeout;
425361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
425461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
425561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
425661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
425761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid p2p_increase_search_delay(struct p2p_data *p2p, unsigned int delay)
425861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
425961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p && p2p->search_delay < delay)
426061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->search_delay = delay;
426161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
426261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
426361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
426461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
426561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
426661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void p2p_update_wfd_ie_groups(struct p2p_data *p2p)
426761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
426861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t g;
426961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct p2p_group *group;
427061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
427161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	for (g = 0; g < p2p->num_groups; g++) {
427261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		group = p2p->groups[g];
427361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_group_update_ies(group);
427461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
427561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
427661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
427761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
427861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_beacon(struct p2p_data *p2p, struct wpabuf *ie)
427961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
428061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_beacon);
428161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_beacon = ie;
428261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_update_wfd_ie_groups(p2p);
428361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
428461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
428561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
428661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
428761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_probe_req(struct p2p_data *p2p, struct wpabuf *ie)
428861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
428961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_probe_req);
429061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_probe_req = ie;
429161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
429261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
429361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
429461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
429561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_probe_resp(struct p2p_data *p2p, struct wpabuf *ie)
429661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
429761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_probe_resp);
429861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_probe_resp = ie;
429961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_update_wfd_ie_groups(p2p);
430061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
430161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
430261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
430361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
430461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_assoc_req(struct p2p_data *p2p, struct wpabuf *ie)
430561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
430661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_assoc_req);
430761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_assoc_req = ie;
430861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
430961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
431061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
431161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
431261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_invitation(struct p2p_data *p2p, struct wpabuf *ie)
431361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
431461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_invitation);
431561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_invitation = ie;
431661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
431761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
431861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
431961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
432061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_prov_disc_req(struct p2p_data *p2p, struct wpabuf *ie)
432161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
432261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_prov_disc_req);
432361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_prov_disc_req = ie;
432461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
432561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
432661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
432761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
432861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_prov_disc_resp(struct p2p_data *p2p, struct wpabuf *ie)
432961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
433061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_prov_disc_resp);
433161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_prov_disc_resp = ie;
433261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
433361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
433461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
433561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
433661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_go_neg(struct p2p_data *p2p, struct wpabuf *ie)
433761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
433861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_go_neg);
433961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_go_neg = ie;
434061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
434161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
434261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
434361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
434461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_dev_info(struct p2p_data *p2p, const struct wpabuf *elem)
434561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
434661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_dev_info);
434761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (elem) {
434861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_dev_info = wpabuf_dup(elem);
434961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->wfd_dev_info == NULL)
435061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
435161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else
435261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_dev_info = NULL;
435361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
435461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
435561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
435661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
435761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
435861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_assoc_bssid(struct p2p_data *p2p, const struct wpabuf *elem)
435961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
436061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_assoc_bssid);
436161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (elem) {
436261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_assoc_bssid = wpabuf_dup(elem);
436361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->wfd_assoc_bssid == NULL)
436461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
436561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else
436661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_assoc_bssid = NULL;
436761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
436861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
436961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
437061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
437161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
437261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_coupled_sink_info(struct p2p_data *p2p,
437361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				  const struct wpabuf *elem)
437461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
437561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_coupled_sink_info);
437661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (elem) {
437761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_coupled_sink_info = wpabuf_dup(elem);
437861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->wfd_coupled_sink_info == NULL)
437961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
438061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else
438161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_coupled_sink_info = NULL;
438261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
438361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
438461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
438561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
438661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
4387