p2p.c revision 391c59f0632df8db1c325da1d31d479b2eedce45
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"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps/wps_i.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p_i.h"
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_state_timeout(void *eloop_ctx, void *timeout_ctx);
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev);
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_req(struct p2p_data *p2p, const u8 *da,
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const u8 *sa, const u8 *data, size_t len,
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     int rx_freq);
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_resp(struct p2p_data *p2p, const u8 *da,
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *sa, const u8 *data,
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      size_t len);
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_ext_listen_timeout(void *eloop_ctx, void *timeout_ctx);
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_scan_timeout(void *eloop_ctx, void *timeout_ctx);
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_scan recovery timeout
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Many drivers are using 30 second timeout on scan results. Allow a bit larger
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * timeout for this to avoid hitting P2P timeout unnecessarily.
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define P2P_SCAN_TIMEOUT 35
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * P2P_PEER_EXPIRATION_AGE - Number of seconds after which inactive peer
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * entries will be removed
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
442fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt#ifdef ANDROID_P2P
452fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt#define P2P_PEER_EXPIRATION_AGE 30
462fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt#else
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define P2P_PEER_EXPIRATION_AGE 300
482fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt#endif
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define P2P_PEER_EXPIRATION_INTERVAL (P2P_PEER_EXPIRATION_AGE / 2)
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
522fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt#ifdef ANDROID_P2P
532fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidtint p2p_connection_in_progress(struct p2p_data *p2p)
542fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt{
552fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt	int ret = 0;
562fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt
572fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt	switch (p2p->state) {
582fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		case P2P_CONNECT:
592fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		case P2P_CONNECT_LISTEN:
602fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		case P2P_GO_NEG:
612fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		case P2P_WAIT_PEER_CONNECT:
6298f9e76624da6bb96edc1982c423e4a119c5170aDmitry Shmidt		case P2P_WAIT_PEER_IDLE:
632fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		case P2P_PROVISIONING:
642fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		case P2P_INVITE:
652fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		case P2P_INVITE_LISTEN:
662fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt			ret = 1;
672fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt			break;
682fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt
692fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		default:
7098f9e76624da6bb96edc1982c423e4a119c5170aDmitry Shmidt			wpa_printf(MSG_DEBUG, "p2p_connection_in_progress state %d", p2p->state);
712fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt			ret = 0;
722fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt	}
732fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt
742fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt	return ret;
752fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt}
762fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt#endif
772fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_expire_peers(struct p2p_data *p2p)
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev, *n;
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct os_time now;
82c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	size_t i;
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&now);
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each_safe(dev, n, &p2p->devices, struct p2p_device, list) {
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->last_seen.sec + P2P_PEER_EXPIRATION_AGE >= now.sec)
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
88c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
89c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (p2p->cfg->go_connected &&
90c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		    p2p->cfg->go_connected(p2p->cfg->cb_ctx,
91c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt					   dev->info.p2p_device_addr)) {
92c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			/*
93c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 * We are connected as a client to a group in which the
94c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 * peer is the GO, so do not expire the peer entry.
95c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 */
96c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			os_get_time(&dev->last_seen);
97c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			continue;
98c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		}
99c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
100c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		for (i = 0; i < p2p->num_groups; i++) {
101c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			if (p2p_group_is_client_connected(
102c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				    p2p->groups[i], dev->info.p2p_device_addr))
103c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				break;
104c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		}
105c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (i < p2p->num_groups) {
106c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			/*
107c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 * The peer is connected as a client in a group where
108c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 * we are the GO, so do not expire the peer entry.
109c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 */
110c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			os_get_time(&dev->last_seen);
111c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			continue;
112c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		}
113c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1142fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt#ifdef ANDROID_P2P
1152fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		/* If Connection is in progress, don't expire the peer
1162fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		*/
1172fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		if (p2p_connection_in_progress(p2p))
1182fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt			continue;
1192fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt#endif
1202fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt
121b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Expiring old peer entry " MACSTR,
122b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr));
123b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
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
183b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtconst char * p2p_get_state_txt(struct p2p_data *p2p)
184b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt{
185b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	return p2p_state_txt(p2p->state);
186b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt}
187b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt
188b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt
1891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtu16 p2p_get_provisioning_info(struct p2p_data *p2p, const u8 *addr)
1901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
1911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_device *dev = NULL;
1921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (!addr || !p2p)
1941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
1951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	dev = p2p_get_device(p2p, addr);
1971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (dev)
1981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return dev->wps_prov_info;
1991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	else
2001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
2011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
2021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20404949598a23f501be6eec21697465fd46a28840aDmitry Shmidtvoid p2p_clear_provisioning_info(struct p2p_data *p2p, const u8 *addr)
2051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
2061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_device *dev = NULL;
2071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (!addr || !p2p)
2091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
2101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
21104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	dev = p2p_get_device(p2p, addr);
2121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (dev)
2131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->wps_prov_info = 0;
2141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
2151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_state(struct p2p_data *p2p, int new_state)
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
219b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "State %s -> %s",
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state), p2p_state_txt(new_state));
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->state = new_state;
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_timeout(struct p2p_data *p2p, unsigned int sec, unsigned int usec)
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
227b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Set timeout (state=%s): %u.%06u sec",
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state), sec, usec);
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_state_timeout, p2p, NULL);
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(sec, usec, p2p_state_timeout, p2p, NULL);
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_clear_timeout(struct p2p_data *p2p)
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
236b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Clear timeout (state=%s)", p2p_state_txt(p2p->state));
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_state_timeout, p2p, NULL);
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_go_neg_failed(struct p2p_data *p2p, struct p2p_device *peer,
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       int status)
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_go_neg_results res;
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_IDLE);
2478c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	if (p2p->go_neg_peer) {
2488c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		p2p->go_neg_peer->flags &= ~P2P_DEV_PEER_WAITING_RESPONSE;
2491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p->go_neg_peer->wps_method = WPS_NOT_READY;
2508c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	}
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer = NULL;
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&res, 0, sizeof(res));
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.status = status;
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (peer) {
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(res.peer_device_addr, peer->info.p2p_device_addr,
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(res.peer_interface_addr, peer->intended_addr,
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->go_neg_completed(p2p->cfg->cb_ctx, &res);
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
265d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic void p2p_listen_in_find(struct p2p_data *p2p, int dev_disc)
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int r, tu;
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *ies;
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
271b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Starting short listen state (state=%s)",
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state));
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2744b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	freq = p2p_channel_to_freq(p2p->cfg->reg_class, p2p->cfg->channel);
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq < 0) {
276b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Unknown regulatory class/channel");
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_random((u8 *) &r, sizeof(r));
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tu = (r % ((p2p->max_disc_int - p2p->min_disc_int) + 1) +
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	      p2p->min_disc_int) * 100;
283d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (p2p->max_disc_tu >= 0 && tu > (unsigned int) p2p->max_disc_tu)
284d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		tu = p2p->max_disc_tu;
285d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (!dev_disc && tu < 100)
286d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		tu = 100; /* Need to wait in non-device discovery use cases */
287d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (p2p->cfg->max_listen && 1024 * tu / 1000 > p2p->cfg->max_listen)
288d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		tu = p2p->cfg->max_listen * 1000 / 1024;
289d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
290d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (tu == 0) {
291b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Skip listen state since duration was 0 TU");
292d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		p2p_set_timeout(p2p, 0, 0);
293d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return;
294d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_freq = freq;
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_sec = 0;
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_usec = 1024 * tu;
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ies = p2p_build_probe_resp_ies(p2p);
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ies == NULL)
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->start_listen(p2p->cfg->cb_ctx, freq, 1024 * tu / 1000,
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    ies) < 0) {
306b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to start listen mode");
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_freq = 0;
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(ies);
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_listen(struct p2p_data *p2p, unsigned int timeout)
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *ies;
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
318b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Going to listen(only) state");
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3204b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	freq = p2p_channel_to_freq(p2p->cfg->reg_class, p2p->cfg->channel);
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq < 0) {
322b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Unknown regulatory class/channel");
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_freq = freq;
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_sec = timeout / 1000;
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_usec = (timeout % 1000) * 1000;
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
33104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (p2p->start_after_scan == P2P_AFTER_SCAN_CONNECT) {
332b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "p2p_scan running - connect is already pending - skip listen");
3331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return 0;
3341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
335b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "p2p_scan running - delay start of listen state");
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->start_after_scan = P2P_AFTER_SCAN_LISTEN;
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ies = p2p_build_probe_resp_ies(p2p);
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ies == NULL)
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->start_listen(p2p->cfg->cb_ctx, freq, timeout, ies) < 0) {
345b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to start listen mode");
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_freq = 0;
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(ies);
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(ies);
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_LISTEN_ONLY);
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_device_clear_reported(struct p2p_data *p2p)
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list)
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~P2P_DEV_REPORTED;
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_get_device - Fetch a peer entry
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: P2P Device Address of the peer
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the device entry or %NULL if not found
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_device * p2p_get_device(struct p2p_data *p2p, const u8 *addr)
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(dev->info.p2p_device_addr, addr, ETH_ALEN) == 0)
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return dev;
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_get_device_interface - Fetch a peer entry based on P2P Interface Address
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: P2P Interface Address of the peer
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the device entry or %NULL if not found
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_device * p2p_get_device_interface(struct p2p_data *p2p,
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     const u8 *addr)
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(dev->interface_addr, addr, ETH_ALEN) == 0)
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return dev;
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_create_device - Create a peer entry
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: P2P Device Address of the peer
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the device entry or %NULL on failure
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * If there is already an entry for the peer, it will be returned instead of
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * creating a new one.
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct p2p_device * p2p_create_device(struct p2p_data *p2p,
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     const u8 *addr)
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev, *oldest = NULL;
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t count = 0;
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev)
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return dev;
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		count++;
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (oldest == NULL ||
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_time_before(&dev->last_seen, &oldest->last_seen))
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			oldest = dev;
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (count + 1 > p2p->cfg->max_peers && oldest) {
427b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Remove oldest peer entry to make room for a new peer");
428f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#ifdef ANDROID_P2P
429f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		/* SD_FAIR_POLICY: Update the current sd_dev_list pointer to next device */
430f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		if(&oldest->list == p2p->sd_dev_list)
431f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff			p2p->sd_dev_list = oldest->list.next;
432f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#endif
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dl_list_del(&oldest->list);
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_device_free(p2p, oldest);
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = os_zalloc(sizeof(*dev));
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_add(&p2p->devices, &dev->list);
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.p2p_device_addr, addr, ETH_ALEN);
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return dev;
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_copy_client_info(struct p2p_device *dev,
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 struct p2p_client_info *cli)
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.device_name, cli->dev_name, cli->dev_name_len);
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.device_name[cli->dev_name_len] = '\0';
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.dev_capab = cli->dev_capab;
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.config_methods = cli->config_methods;
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.pri_dev_type, cli->pri_dev_type, 8);
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.wps_sec_dev_type_list_len = 8 * cli->num_sec_dev_types;
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.wps_sec_dev_type_list, cli->sec_dev_types,
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  dev->info.wps_sec_dev_type_list_len);
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_add_group_clients(struct p2p_data *p2p, const u8 *go_dev_addr,
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const u8 *go_interface_addr, int freq,
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const u8 *gi, size_t gi_len)
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_info info;
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t c;
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gi == NULL)
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_group_info_parse(gi, gi_len, &info) < 0)
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Clear old data for this group; if the devices are still in the
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * group, the information will be restored in the loop following this.
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
4801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (os_memcmp(dev->member_in_go_iface, go_interface_addr,
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      ETH_ALEN) == 0) {
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(dev->member_in_go_iface, 0, ETH_ALEN);
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(dev->member_in_go_dev, 0, ETH_ALEN);
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (c = 0; c < info.num_clients; c++) {
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct p2p_client_info *cli = &info.client[c];
4891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (os_memcmp(cli->p2p_device_addr, p2p->cfg->dev_addr,
4901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      ETH_ALEN) == 0)
4911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			continue; /* ignore our own entry */
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, cli->p2p_device_addr);
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev) {
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev->flags & (P2P_DEV_GROUP_CLIENT_ONLY |
49504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					  P2P_DEV_PROBE_REQ_ONLY)) {
49604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				/*
49704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 * Update information since we have not
49804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 * received this directly from the client.
49904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 */
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p_copy_client_info(dev, cli);
50104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			} else {
50204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				/*
50304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 * Need to update P2P Client Discoverability
50404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 * flag since it is valid only in P2P Group
50504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 * Info attribute.
50604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 */
50704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				dev->info.dev_capab &=
50804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
50904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				dev->info.dev_capab |=
51004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					cli->dev_capab &
51104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
51204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			}
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev->flags & P2P_DEV_PROBE_REQ_ONLY) {
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev->flags &= ~P2P_DEV_PROBE_REQ_ONLY;
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev = p2p_create_device(p2p, cli->p2p_device_addr);
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev == NULL)
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				continue;
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->flags |= P2P_DEV_GROUP_CLIENT_ONLY;
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_copy_client_info(dev, cli);
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->oper_freq = freq;
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->cfg->dev_found(p2p->cfg->cb_ctx,
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    dev->info.p2p_device_addr,
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    &dev->info, 1);
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->interface_addr, cli->p2p_interface_addr,
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_get_time(&dev->last_seen);
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->member_in_go_dev, go_dev_addr, ETH_ALEN);
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->member_in_go_iface, go_interface_addr,
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
541b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidtstatic void p2p_copy_wps_info(struct p2p_data *p2p, struct p2p_device *dev,
542b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			      int probe_req, const struct p2p_message *msg)
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.device_name, msg->device_name,
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  sizeof(dev->info.device_name));
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->manufacturer &&
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->manufacturer_len < sizeof(dev->info.manufacturer)) {
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.manufacturer, 0,
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.manufacturer));
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.manufacturer, msg->manufacturer,
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->manufacturer_len);
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->model_name &&
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->model_name_len < sizeof(dev->info.model_name)) {
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.model_name, 0,
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.model_name));
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.model_name, msg->model_name,
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->model_name_len);
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->model_number &&
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->model_number_len < sizeof(dev->info.model_number)) {
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.model_number, 0,
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.model_number));
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.model_number, msg->model_number,
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->model_number_len);
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->serial_number &&
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->serial_number_len < sizeof(dev->info.serial_number)) {
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.serial_number, 0,
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.serial_number));
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.serial_number, msg->serial_number,
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->serial_number_len);
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->pri_dev_type)
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.pri_dev_type, msg->pri_dev_type,
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.pri_dev_type));
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (msg->wps_pri_dev_type)
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.pri_dev_type, msg->wps_pri_dev_type,
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.pri_dev_type));
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->wps_sec_dev_type_list) {
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.wps_sec_dev_type_list,
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->wps_sec_dev_type_list,
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->wps_sec_dev_type_list_len);
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_sec_dev_type_list_len =
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg->wps_sec_dev_type_list_len;
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->capability) {
59504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/*
59604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * P2P Client Discoverability bit is reserved in all frames
59704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * that use this function, so do not change its value here.
59804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 */
59904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->info.dev_capab &= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
60004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->info.dev_capab |= msg->capability[0] &
60104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.group_capab = msg->capability[1];
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->ext_listen_timing) {
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->ext_listen_period = WPA_GET_LE16(msg->ext_listen_timing);
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->ext_listen_interval =
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			WPA_GET_LE16(msg->ext_listen_timing + 2);
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
61004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!probe_req) {
612f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		u16 new_config_methods;
613f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		new_config_methods = msg->config_methods ?
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg->config_methods : msg->wps_config_methods;
615f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		if (new_config_methods &&
616f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		    dev->info.config_methods != new_config_methods) {
617b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Update peer " MACSTR
618b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				" config_methods 0x%x -> 0x%x",
619b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				MAC2STR(dev->info.p2p_device_addr),
620b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				dev->info.config_methods,
621b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				new_config_methods);
622f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			dev->info.config_methods = new_config_methods;
623f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		}
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
62904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * p2p_add_device - Add peer entries based on scan results or P2P frames
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: Source address of Beacon or Probe Response frame (may be either
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *	P2P Device Address or P2P Interface Address)
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @level: Signal level (signal strength of the received frame from the peer)
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @freq: Frequency on which the Beacon or Probe Response frame was received
635f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * @rx_time: Time when the result was received
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ies: IEs from the Beacon or Probe Response frame
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ies_len: Length of ies buffer in octets
63804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * @scan_res: Whether this was based on scan results
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * If the scan result is for a GO, the clients in the group will also be added
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to the peer table. This function can also be used with some other frames
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * like Provision Discovery Request that contains P2P Capability and P2P Device
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Info attributes.
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
646a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtint p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq,
647f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		   struct os_time *rx_time, int level, const u8 *ies,
648a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		   size_t ies_len, int scan_res)
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *p2p_dev_addr;
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
654f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	struct os_time time_now;
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ies, ies_len, &msg)) {
658b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to parse P2P IE for a device entry");
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.p2p_device_addr)
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_addr = msg.p2p_device_addr;
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (msg.device_id)
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_addr = msg.device_id;
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
668b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Ignore scan data without P2P Device Info or P2P Device Id");
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!is_zero_ether_addr(p2p->peer_filter) &&
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(p2p_dev_addr, p2p->peer_filter, ETH_ALEN) != 0) {
675b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Do not add peer filter for " MACSTR
676b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			" due to peer filter", MAC2STR(p2p_dev_addr));
677a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p_parse_free(&msg);
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_create_device(p2p, p2p_dev_addr);
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
686a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
687f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	if (rx_time == NULL) {
688f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		os_get_time(&time_now);
689f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		rx_time = &time_now;
690f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	}
691a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
692a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	/*
693a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	 * Update the device entry only if the new peer
694a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	 * entry is newer than the one previously stored.
695a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	 */
696f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	if (dev->last_seen.sec > 0 &&
697f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	    os_time_before(rx_time, &dev->last_seen)) {
698b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Do not update peer entry based on old frame (rx_time=%u.%06u last_seen=%u.%06u)",
699f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			(unsigned int) rx_time->sec,
700f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			(unsigned int) rx_time->usec,
701f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			(unsigned int) dev->last_seen.sec,
702f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			(unsigned int) dev->last_seen.usec);
703a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p_parse_free(&msg);
704a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
705a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
706a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
707f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	os_memcpy(&dev->last_seen, rx_time, sizeof(struct os_time));
708a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~(P2P_DEV_PROBE_REQ_ONLY | P2P_DEV_GROUP_CLIENT_ONLY);
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(addr, p2p_dev_addr, ETH_ALEN) != 0)
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->interface_addr, addr, ETH_ALEN);
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.ssid &&
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (msg.ssid[1] != P2P_WILDCARD_SSID_LEN ||
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     os_memcmp(msg.ssid + 2, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN)
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     != 0)) {
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->oper_ssid, msg.ssid + 2, msg.ssid[1]);
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->oper_ssid_len = msg.ssid[1];
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq >= 2412 && freq <= 2484 && msg.ds_params &&
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    *msg.ds_params >= 1 && *msg.ds_params <= 14) {
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int ds_freq;
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*msg.ds_params == 14)
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ds_freq = 2484;
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ds_freq = 2407 + *msg.ds_params * 5;
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freq != ds_freq) {
729b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Update Listen frequency based on DS Parameter Set IE: %d -> %d MHz",
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				freq, ds_freq);
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq = ds_freq;
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
73504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (dev->listen_freq && dev->listen_freq != freq && scan_res) {
736b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Update Listen frequency based on scan results ("
737b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			MACSTR " %d -> %d MHz (DS param %d)",
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr), dev->listen_freq,
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq, msg.ds_params ? *msg.ds_params : -1);
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
74104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (scan_res) {
74204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->listen_freq = freq;
74304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (msg.group_info)
74404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			dev->oper_freq = freq;
74504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
74675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	dev->info.level = level;
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
748b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_copy_wps_info(p2p, dev, 0, &msg);
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(dev->info.wps_vendor_ext[i]);
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_vendor_ext[i] = NULL;
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (msg.wps_vendor_ext[i] == NULL)
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_vendor_ext[i] = wpabuf_alloc_copy(
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg.wps_vendor_ext[i], msg.wps_vendor_ext_len[i]);
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->info.wps_vendor_ext[i] == NULL)
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
76461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (msg.wfd_subelems) {
76561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_free(dev->info.wfd_subelems);
76661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
76761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
76861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
76904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (scan_res) {
77004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p_add_group_clients(p2p, p2p_dev_addr, addr, freq,
77104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				      msg.group_info, msg.group_info_len);
77204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_pending_sd_req(p2p, dev))
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags |= P2P_DEV_SD_SCHEDULE;
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_REPORTED)
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
782b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Peer found with Listen frequency %d MHz (rx_time=%u.%06u)",
783b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		freq, (unsigned int) rx_time->sec,
784f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		(unsigned int) rx_time->usec);
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_USER_REJECTED) {
786b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Do not report rejected device");
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
790f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	if (dev->info.config_methods == 0 &&
791f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	    (freq == 2412 || freq == 2437 || freq == 2462)) {
792f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		/*
793f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * If we have only seen a Beacon frame from a GO, we do not yet
794f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * know what WPS config methods it supports. Since some
795f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * applications use config_methods value from P2P-DEVICE-FOUND
796f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * events, postpone reporting this peer until we've fully
797f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * discovered its capabilities.
798f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 *
799f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * At least for now, do this only if the peer was detected on
800f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * one of the social channels since that peer can be easily be
801f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * found again and there are no limitations of having to use
802f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * passive scan on this channels, so this can be done through
803f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * Probe Response frame that includes the config_methods
804f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * information.
805f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 */
806b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Do not report peer " MACSTR
807b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			" with unknown config methods", MAC2STR(addr));
808f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		return 0;
809f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	}
810f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->dev_found(p2p->cfg->cb_ctx, addr, &dev->info,
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    !(dev->flags & P2P_DEV_REPORTED_ONCE));
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev)
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
823497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt	if (p2p->go_neg_peer == dev) {
8241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/*
8251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * If GO Negotiation is in progress, report that it has failed.
8261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
827497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt		p2p_go_neg_failed(p2p, dev, -1);
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->go_neg_peer = NULL;
829497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt	}
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->invite_peer == dev)
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->invite_peer = NULL;
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->sd_peer == dev)
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->sd_peer = NULL;
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->pending_client_disc_go == dev)
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_client_disc_go = NULL;
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
837c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	/* dev_lost() device, but only if it was previously dev_found() */
838c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	if (dev->flags & P2P_DEV_REPORTED_ONCE)
839c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		p2p->cfg->dev_lost(p2p->cfg->cb_ctx,
840c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt				   dev->info.p2p_device_addr);
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(dev->info.wps_vendor_ext[i]);
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_vendor_ext[i] = NULL;
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
84761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(dev->info.wfd_subelems);
84861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(dev);
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_get_next_prog_freq(struct p2p_data *p2p)
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_channels *c;
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_reg_class *cla;
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t cl, ch;
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int found = 0;
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 reg_class;
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 channel;
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	c = &p2p->cfg->channels;
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (cl = 0; cl < c->reg_classes; cl++) {
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cla = &c->reg_class[cl];
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (cla->reg_class != p2p->last_prog_scan_class)
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (ch = 0; ch < cla->channels; ch++) {
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (cla->channel[ch] == p2p->last_prog_scan_chan) {
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				found = 1;
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (found)
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!found) {
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Start from beginning */
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reg_class = c->reg_class[0].reg_class;
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		channel = c->reg_class[0].channel[0];
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Pick the next channel */
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ch++;
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ch == cla->channels) {
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			cl++;
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (cl == c->reg_classes)
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				cl = 0;
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ch = 0;
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reg_class = c->reg_class[cl].reg_class;
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		channel = c->reg_class[cl].channel[ch];
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8954b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	freq = p2p_channel_to_freq(reg_class, channel);
896b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Next progressive search channel: reg_class %u channel %u -> %d MHz",
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reg_class, channel, freq);
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->last_prog_scan_class = reg_class;
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->last_prog_scan_chan = channel;
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq == 2412 || freq == 2437 || freq == 2462)
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* No need to add social channels */
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return freq;
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_search(struct p2p_data *p2p)
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq = 0;
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum p2p_scan_type type;
91104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	u16 pw_id = DEV_PW_DEFAULT;
91261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	int res;
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->drv_in_listen) {
915b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Driver is still in Listen state - wait for it to end before continuing");
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
92004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p->find_type == P2P_FIND_PROGRESSIVE &&
92104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    (freq = p2p_get_next_prog_freq(p2p)) > 0) {
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type = P2P_SCAN_SOCIAL_PLUS_ONE;
923b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Starting search (+ freq %u)", freq);
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type = P2P_SCAN_SOCIAL;
926b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Starting search");
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
92961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, type, freq,
93061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				 p2p->num_req_dev_types, p2p->req_dev_types,
93161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				 p2p->find_dev_id, pw_id);
93261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (res < 0) {
933b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Scan request failed");
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
93561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else if (res == 1) {
936b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Could not start p2p_scan at this point - will try again after previous scan completes");
93761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_set_state(p2p, P2P_CONTINUE_SEARCH_WHEN_READY);
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
939b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Running p2p_scan");
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->p2p_scan_running = 1;
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(P2P_SCAN_TIMEOUT, 0, p2p_scan_timeout,
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p, NULL);
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_find_timeout(void *eloop_ctx, void *timeout_ctx)
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
951b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Find timeout -> stop");
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_stop_find(p2p);
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_run_after_scan(struct p2p_data *p2p)
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum p2p_after_scan op;
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->after_scan_tx) {
9628da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt		p2p->after_scan_tx_in_progress = 1;
963b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Send pending Action frame at p2p_scan completion");
9641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p->cfg->send_action(p2p->cfg->cb_ctx,
9651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->freq,
9661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->dst,
9671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->src,
9681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->bssid,
9691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      (u8 *) (p2p->after_scan_tx + 1),
9701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->len,
9711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->wait_time);
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p2p->after_scan_tx);
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = NULL;
974f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#ifdef ANDROID_P2P
975f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		/* For SD frames, there is a scenario, where we can receive a SD request frame during p2p_scan.
976f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * At that moment, we will send the SD response from this context. After sending the SD response,
977f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * we need to continue p2p_find. But if we return 1 from here, p2p_find is going to be stopped.
978f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 */
979f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		return 0;
980f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#else
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
982f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#endif
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	op = p2p->start_after_scan;
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (op) {
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_AFTER_SCAN_NOTHING:
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_AFTER_SCAN_LISTEN:
991b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Start previously requested Listen state");
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_listen(p2p, p2p->pending_listen_sec * 1000 +
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   p2p->pending_listen_usec / 1000);
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_AFTER_SCAN_CONNECT:
996b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Start previously requested connect with " MACSTR,
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(p2p->after_scan_peer));
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, p2p->after_scan_peer);
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev == NULL) {
1000b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Peer not known anymore");
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, dev);
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_scan_timeout(void *eloop_ctx, void *timeout_ctx)
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int running;
1015b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "p2p_scan timeout (running=%d)", p2p->p2p_scan_running);
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	running = p2p->p2p_scan_running;
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Make sure we recover from missed scan results callback */
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->p2p_scan_running = 0;
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (running)
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_run_after_scan(p2p);
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_free_req_dev_types(struct p2p_data *p2p)
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->num_req_dev_types = 0;
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->req_dev_types);
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->req_dev_types = NULL;
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_find(struct p2p_data *p2p, unsigned int timeout,
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     enum p2p_discovery_type type,
1035c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	     unsigned int num_req_dev_types, const u8 *req_dev_types,
103661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	     const u8 *dev_id, unsigned int search_delay)
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1040b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Starting find (type=%d)", type);
1041f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	os_get_time(&p2p->find_start);
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
1043b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "p2p_scan is already running");
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_req_dev_types(p2p);
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req_dev_types && num_req_dev_types) {
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->req_dev_types = os_malloc(num_req_dev_types *
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       WPS_DEV_TYPE_LEN);
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->req_dev_types == NULL)
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->req_dev_types, req_dev_types,
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  num_req_dev_types * WPS_DEV_TYPE_LEN);
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->num_req_dev_types = num_req_dev_types;
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1057c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (dev_id) {
1058c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		os_memcpy(p2p->find_dev_id_buf, dev_id, ETH_ALEN);
1059c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		p2p->find_dev_id = p2p->find_dev_id_buf;
1060c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	} else
1061c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		p2p->find_dev_id = NULL;
1062c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->find_type = type;
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_device_clear_reported(p2p);
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_SEARCH);
106961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->search_delay = search_delay;
107061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->in_search_delay = 0;
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
10721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p->last_p2p_find_timeout = timeout;
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (timeout)
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(timeout, 0, p2p_find_timeout,
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p, NULL);
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (type) {
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_FIND_START_WITH_FULL:
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_FIND_PROGRESSIVE:
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_FULL, 0,
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 p2p->num_req_dev_types,
108104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 p2p->req_dev_types, dev_id,
108204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 DEV_PW_DEFAULT);
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_FIND_ONLY_SOCIAL:
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_SOCIAL, 0,
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 p2p->num_req_dev_types,
108704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 p2p->req_dev_types, dev_id,
108804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 DEV_PW_DEFAULT);
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res == 0) {
1095b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Running p2p_scan");
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->p2p_scan_running = 1;
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(P2P_SCAN_TIMEOUT, 0, p2p_scan_timeout,
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p, NULL);
11001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	} else if (res == 1) {
1101b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Could not start p2p_scan at this point - will try again after previous scan completes");
11021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		res = 0;
11031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_set_state(p2p, P2P_SEARCH_WHEN_READY);
11041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
1106b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to start p2p_scan");
11071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
11081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11142fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt#ifdef ANDROID_P2P
11152fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidtint p2p_search_pending(struct p2p_data *p2p)
11162fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt{
11172fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt	if(p2p == NULL)
11182fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		return 0;
11192fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt
11202fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt	if(p2p->state == P2P_SEARCH_WHEN_READY)
11212fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt		return 1;
11222fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt
11232fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt	return 0;
11242fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt}
11252fb777c379ad560c309c54b96c2c13291da23f54Dmitry Shmidt#endif
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_other_scan_completed(struct p2p_data *p2p)
11281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
112961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->state == P2P_CONTINUE_SEARCH_WHEN_READY) {
113061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_set_state(p2p, P2P_SEARCH);
113161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_search(p2p);
113261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return 1;
113361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
11341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p->state != P2P_SEARCH_WHEN_READY)
11351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
1136b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Starting pending P2P find now that previous scan was completed");
11371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p_find(p2p, p2p->last_p2p_find_timeout, p2p->find_type,
1138c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		     p2p->num_req_dev_types, p2p->req_dev_types,
1139f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		     p2p->find_dev_id, p2p->search_delay) < 0) {
1140b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p->cfg->find_stopped(p2p->cfg->cb_ctx);
11411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
1142f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	}
11431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return 1;
11441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
11451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_stop_find_for_freq(struct p2p_data *p2p, int freq)
11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1149b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Stopping find");
11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
1152a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (p2p->state == P2P_SEARCH ||
1153a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	    p2p->state == P2P_CONTINUE_SEARCH_WHEN_READY ||
1154a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	    p2p->state == P2P_SEARCH_WHEN_READY)
1155b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p->cfg->find_stopped(p2p->cfg->cb_ctx);
11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_IDLE);
11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_req_dev_types(p2p);
11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
11598c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	if (p2p->go_neg_peer)
11608c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		p2p->go_neg_peer->flags &= ~P2P_DEV_PEER_WAITING_RESPONSE;
11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer = NULL;
11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->sd_peer = NULL;
11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->invite_peer = NULL;
116404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_stop_listen_for_freq(p2p, freq);
116504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
116604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
116704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
116804949598a23f501be6eec21697465fd46a28840aDmitry Shmidtvoid p2p_stop_listen_for_freq(struct p2p_data *p2p, int freq)
116904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq > 0 && p2p->drv_in_listen == freq && p2p->in_listen) {
1171b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Skip stop_listen since we are on correct channel for response");
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
117404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p->in_listen) {
117504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->in_listen = 0;
117604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p_clear_timeout(p2p);
117704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
11781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p->drv_in_listen) {
11791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/*
11801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * The driver may not deliver callback to p2p_listen_end()
11811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * when the operation gets canceled, so clear the internal
11821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * variable that is tracking driver state.
11831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
1184b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Clear drv_in_listen (%d)", p2p->drv_in_listen);
11851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p->drv_in_listen = 0;
11861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1191391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtvoid p2p_stop_listen(struct p2p_data *p2p)
1192391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{
1193391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (p2p->state != P2P_LISTEN_ONLY) {
1194391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		p2p_dbg(p2p, "Skip stop_listen since not in listen_only state.");
1195391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		return;
1196391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	}
1197391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
1198391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	p2p_stop_listen_for_freq(p2p, 0);
1199391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	p2p_set_state(p2p, P2P_IDLE);
1200391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt}
1201391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
1202391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_stop_find(struct p2p_data *p2p)
12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_stop_find_for_freq(p2p, 0);
12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1209a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtstatic int p2p_prepare_channel_pref(struct p2p_data *p2p,
1210a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt				    unsigned int force_freq,
1211a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt				    unsigned int pref_freq)
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1213a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	u8 op_class, op_channel;
1214a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	unsigned int freq = force_freq ? force_freq : pref_freq;
12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1216b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	p2p_dbg(p2p, "Prepare channel pref - force_freq=%u pref_freq=%u",
1217b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		force_freq, pref_freq);
12184b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	if (p2p_freq_to_channel(freq, &op_class, &op_channel) < 0) {
1219b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Unsupported frequency %u MHz", freq);
1220a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
1221a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
1222a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1223a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (!p2p_channels_includes(&p2p->cfg->channels, op_class, op_channel)) {
1224b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Frequency %u MHz (oper_class %u channel %u) not allowed for P2P",
1225b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			freq, op_class, op_channel);
1226a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
1227a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
1228a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1229a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	p2p->op_reg_class = op_class;
1230a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	p2p->op_channel = op_channel;
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1232a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (force_freq) {
1233a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->channels.reg_classes = 1;
1234a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->channels.reg_class[0].channels = 1;
1235a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->channels.reg_class[0].reg_class = p2p->op_reg_class;
1236a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->channels.reg_class[0].channel[0] = p2p->op_channel;
1237a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	} else {
12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(&p2p->channels, &p2p->cfg->channels,
12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(struct p2p_channels));
12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1241a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1242a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	return 0;
1243a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt}
1244a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1245a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1246a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtstatic void p2p_prepare_channel_best(struct p2p_data *p2p)
1247a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{
1248a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	u8 op_class, op_channel;
1249a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1250b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	p2p_dbg(p2p, "Prepare channel best");
1251b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt
1252a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (!p2p->cfg->cfg_op_channel && p2p->best_freq_overall > 0 &&
1253a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	    p2p_supported_freq(p2p, p2p->best_freq_overall) &&
12544b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	    p2p_freq_to_channel(p2p->best_freq_overall, &op_class, &op_channel)
12554b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	    == 0) {
1256b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Select best overall channel as operating channel preference");
1257a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_reg_class = op_class;
1258a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_channel = op_channel;
1259a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	} else if (!p2p->cfg->cfg_op_channel && p2p->best_freq_5 > 0 &&
1260a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		   p2p_supported_freq(p2p, p2p->best_freq_5) &&
12614b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		   p2p_freq_to_channel(p2p->best_freq_5, &op_class, &op_channel)
12624b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		   == 0) {
1263b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Select best 5 GHz channel as operating channel preference");
1264a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_reg_class = op_class;
1265a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_channel = op_channel;
1266a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	} else if (!p2p->cfg->cfg_op_channel && p2p->best_freq_24 > 0 &&
1267a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		   p2p_supported_freq(p2p, p2p->best_freq_24) &&
12684b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		   p2p_freq_to_channel(p2p->best_freq_24, &op_class,
12694b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt				       &op_channel) == 0) {
1270b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Select best 2.4 GHz channel as operating channel preference");
1271a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_reg_class = op_class;
1272a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_channel = op_channel;
1273b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	} else if (p2p->cfg->num_pref_chan > 0 &&
1274b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		   p2p_channels_includes(&p2p->cfg->channels,
1275b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt					 p2p->cfg->pref_chan[0].op_class,
1276b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt					 p2p->cfg->pref_chan[0].chan)) {
1277b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		p2p_dbg(p2p, "Select first pref_chan entry as operating channel preference");
1278b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		p2p->op_reg_class = p2p->cfg->pref_chan[0].op_class;
1279b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		p2p->op_channel = p2p->cfg->pref_chan[0].chan;
1280a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	} else {
1281b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		p2p_dbg(p2p, "Select pre-configured channel as operating channel preference");
1282a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_reg_class = p2p->cfg->op_reg_class;
1283a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_channel = p2p->cfg->op_channel;
1284a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
1285a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1286a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	os_memcpy(&p2p->channels, &p2p->cfg->channels,
1287a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		  sizeof(struct p2p_channels));
1288a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt}
1289a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1290a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1291a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt/**
1292a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * p2p_prepare_channel - Select operating channel for GO Negotiation
1293a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @p2p: P2P module context from p2p_init()
1294a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @dev: Selected peer device
1295a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @force_freq: Forced frequency in MHz or 0 if not forced
1296a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @pref_freq: Preferred frequency in MHz or 0 if no preference
1297a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Returns: 0 on success, -1 on failure (channel not supported for P2P)
1298a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *
1299a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * This function is used to do initial operating channel selection for GO
1300a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Negotiation prior to having received peer information. The selected channel
1301a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * may be further optimized in p2p_reselect_channel() once the peer information
1302a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * is available.
1303a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt */
13047a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidtint p2p_prepare_channel(struct p2p_data *p2p, struct p2p_device *dev,
13057a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt			unsigned int force_freq, unsigned int pref_freq)
1306a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{
1307b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	p2p_dbg(p2p, "Prepare channel - force_freq=%u pref_freq=%u",
1308b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		force_freq, pref_freq);
1309a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (force_freq || pref_freq) {
1310a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		if (p2p_prepare_channel_pref(p2p, force_freq, pref_freq) < 0)
1311a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			return -1;
1312a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	} else {
1313a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p_prepare_channel_best(p2p);
1314a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
1315b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Own preference for operation channel: Operating Class %u Channel %u%s",
13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->op_reg_class, p2p->op_channel,
13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		force_freq ? " (forced)" : "");
13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1319a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (force_freq)
1320a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		dev->flags |= P2P_DEV_FORCE_FREQ;
1321a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	else
1322a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		dev->flags &= ~P2P_DEV_FORCE_FREQ;
1323a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void p2p_set_dev_persistent(struct p2p_device *dev,
13291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   int persistent_group)
13301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
13311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	switch (persistent_group) {
13321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case 0:
13331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags &= ~(P2P_DEV_PREFER_PERSISTENT_GROUP |
13341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				P2P_DEV_PREFER_PERSISTENT_RECONN);
13351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
13361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case 1:
13371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP;
13381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags &= ~P2P_DEV_PREFER_PERSISTENT_RECONN;
13391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
13401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case 2:
13411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP |
13421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			P2P_DEV_PREFER_PERSISTENT_RECONN;
13431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
13441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
13451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
13461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
13471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		enum p2p_wps_method wps_method,
13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int go_intent, const u8 *own_interface_addr,
135104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		unsigned int force_freq, int persistent_group,
135204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		const u8 *force_ssid, size_t force_ssid_len,
1353d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		int pd_before_go_neg, unsigned int pref_freq)
13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1357b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Request to start group negotiation - peer=" MACSTR
13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  GO Intent=%d  Intended Interface Address=" MACSTR
1359d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		" wps_method=%d persistent_group=%d pd_before_go_neg=%d",
13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
1361d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wps_method, persistent_group, pd_before_go_neg);
13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
1365b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Cannot connect to unknown P2P Device " MACSTR,
13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(peer_addr));
13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1370a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (p2p_prepare_channel(p2p, dev, force_freq, pref_freq) < 0)
1371a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
1372a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!(dev->info.dev_capab &
13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
1376b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Cannot connect to P2P Device " MACSTR
13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				" that is in a group and is not discoverable",
13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(peer_addr));
13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->oper_freq <= 0) {
1382b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Cannot connect to P2P Device " MACSTR
13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				" with incomplete information",
13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(peer_addr));
13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * First, try to connect directly. If the peer does not
13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * acknowledge frames, assume it is sleeping and use device
13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * discoverability via the GO at that point.
13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
139504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p->ssid_set = 0;
139604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (force_ssid) {
139704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "P2P: Forced SSID",
139804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  force_ssid, force_ssid_len);
139904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(p2p->ssid, force_ssid, force_ssid_len);
140004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->ssid_len = force_ssid_len;
140104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->ssid_set = 1;
140204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
140304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_NOT_YET_READY;
14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_USER_REJECTED;
14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE;
14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM;
140804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (pd_before_go_neg)
140904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->flags |= P2P_DEV_PD_BEFORE_GO_NEG;
1410a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	else {
141104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->flags &= ~P2P_DEV_PD_BEFORE_GO_NEG;
1412a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		/*
14139cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt		 * Assign dialog token and tie breaker here to use the same
14149cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt		 * values in each retry within the same GO Negotiation exchange.
1415a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		 */
1416a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		dev->dialog_token++;
1417a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		if (dev->dialog_token == 0)
1418a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			dev->dialog_token = 1;
14199cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt		dev->tie_breaker = p2p->next_tie_breaker;
14209cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt		p2p->next_tie_breaker = !p2p->next_tie_breaker;
1421a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->connect_reqs = 0;
14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_neg_req_sent = 0;
14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_state = UNKNOWN_GO;
14251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_set_dev_persistent(dev, persistent_group);
14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_intent = go_intent;
14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state != P2P_IDLE)
14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_stop_find(p2p);
14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->after_scan_tx) {
14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * We need to drop the pending frame to avoid issues with the
14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * new GO Negotiation, e.g., when the pending frame was from a
14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * previous attempt at starting a GO Negotiation.
14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
1438b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Dropped previous pending Action frame TX that was waiting for p2p_scan completion");
14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p2p->after_scan_tx);
14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = NULL;
14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wps_method = wps_method;
14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->status = P2P_SC_SUCCESS;
14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
1447b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "p2p_scan running - delay connect send");
14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->start_after_scan = P2P_AFTER_SCAN_CONNECT;
14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_peer, peer_addr, ETH_ALEN);
14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_connect_send(p2p, dev);
14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  enum p2p_wps_method wps_method,
14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  int go_intent, const u8 *own_interface_addr,
146104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		  unsigned int force_freq, int persistent_group,
1462d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		  const u8 *force_ssid, size_t force_ssid_len,
1463d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		  unsigned int pref_freq)
14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1467b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Request to authorize group negotiation - peer=" MACSTR
14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  GO Intent=%d  Intended Interface Address=" MACSTR
14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" wps_method=%d  persistent_group=%d",
14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wps_method, persistent_group);
14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
1475b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Cannot authorize unknown P2P Device " MACSTR,
14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(peer_addr));
14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1480a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (p2p_prepare_channel(p2p, dev, force_freq, pref_freq) < 0)
1481a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
1482a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
148304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p->ssid_set = 0;
148404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (force_ssid) {
148504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "P2P: Forced SSID",
148604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  force_ssid, force_ssid_len);
148704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(p2p->ssid, force_ssid, force_ssid_len);
148804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->ssid_len = force_ssid_len;
148904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->ssid_set = 1;
149004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
149104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_NOT_YET_READY;
14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_USER_REJECTED;
14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_neg_req_sent = 0;
14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_state = UNKNOWN_GO;
14961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_set_dev_persistent(dev, persistent_group);
14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_intent = go_intent;
14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wps_method = wps_method;
15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->status = P2P_SC_SUCCESS;
15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_add_dev_info(struct p2p_data *p2p, const u8 *addr,
15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      struct p2p_device *dev, struct p2p_message *msg)
15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&dev->last_seen);
15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1512b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_copy_wps_info(p2p, dev, 0, msg);
15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->listen_channel) {
15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int freq;
15164b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		freq = p2p_channel_to_freq(msg->listen_channel[3],
15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   msg->listen_channel[4]);
15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freq < 0) {
1519b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Unknown peer Listen channel: "
15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"country=%c%c(0x%02x) reg_class=%u channel=%u",
15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[0],
15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[1],
15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[2],
15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[3],
15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[4]);
15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
1527b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Update peer " MACSTR
1528b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				" Listen channel: %u -> %u MHz",
15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(dev->info.p2p_device_addr),
15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev->listen_freq, freq);
15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->listen_freq = freq;
15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
153561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (msg->wfd_subelems) {
153661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_free(dev->info.wfd_subelems);
153761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		dev->info.wfd_subelems = wpabuf_dup(msg->wfd_subelems);
153861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
153961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_PROBE_REQ_ONLY) {
15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~P2P_DEV_PROBE_REQ_ONLY;
1542b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Completed device entry based on data from GO Negotiation Request");
15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
1544b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Created device entry based on GO Neg Req: "
15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MACSTR " dev_capab=0x%x group_capab=0x%x name='%s' "
15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"listen_freq=%d",
15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr),
15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->info.dev_capab, dev->info.group_capab,
15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->info.device_name, dev->listen_freq);
15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_GROUP_CLIENT_ONLY;
15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_USER_REJECTED) {
1555b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Do not report rejected device");
15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->dev_found(p2p->cfg->cb_ctx, addr, &dev->info,
15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    !(dev->flags & P2P_DEV_REPORTED_ONCE));
15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_build_ssid(struct p2p_data *p2p, u8 *ssid, size_t *ssid_len)
15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_random((char *) &ssid[P2P_WILDCARD_SSID_LEN], 2);
15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&ssid[P2P_WILDCARD_SSID_LEN + 2],
15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  p2p->cfg->ssid_postfix, p2p->cfg->ssid_postfix_len);
15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*ssid_len = P2P_WILDCARD_SSID_LEN + 2 + p2p->cfg->ssid_postfix_len;
15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_go_params(struct p2p_data *p2p, struct p2p_go_neg_results *params)
15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_build_ssid(p2p, params->ssid, &params->ssid_len);
15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_random(params->passphrase, 8);
15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_go_complete(struct p2p_data *p2p, struct p2p_device *peer)
15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_go_neg_results res;
15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int go = peer->go_state == LOCAL_GO;
15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_channels intersection;
15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freqs;
15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i, j;
15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1591b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "GO Negotiation with " MACSTR " completed (%s will be GO)",
1592b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		MAC2STR(peer->info.p2p_device_addr), go ? "local end" : "peer");
15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&res, 0, sizeof(res));
15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.role_go = go;
15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(res.peer_device_addr, peer->info.p2p_device_addr, ETH_ALEN);
15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(res.peer_interface_addr, peer->intended_addr, ETH_ALEN);
15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.wps_method = peer->wps_method;
15991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) {
16001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN)
16011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			res.persistent_group = 2;
16021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		else
16031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			res.persistent_group = 1;
16041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (go) {
16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Setup AP mode for WPS provisioning */
16084b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		res.freq = p2p_channel_to_freq(p2p->op_reg_class,
16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       p2p->op_channel);
16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(res.ssid, p2p->ssid, p2p->ssid_len);
16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res.ssid_len = p2p->ssid_len;
16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_random(res.passphrase, 8);
16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res.freq = peer->oper_freq;
16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->ssid_len) {
16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(res.ssid, p2p->ssid, p2p->ssid_len);
16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res.ssid_len = p2p->ssid_len;
16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_channels_intersect(&p2p->channels, &peer->channels,
16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       &intersection);
16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	freqs = 0;
16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < intersection.reg_classes; i++) {
16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct p2p_reg_class *c = &intersection.reg_class[i];
16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freqs + 1 == P2P_MAX_CHANNELS)
16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < c->channels; j++) {
16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			int freq;
16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (freqs + 1 == P2P_MAX_CHANNELS)
16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
16324b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt			freq = p2p_channel_to_freq(c->reg_class, c->channel[j]);
16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (freq < 0)
16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				continue;
16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res.freq_list[freqs++] = freq;
16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.peer_config_timeout = go ? peer->client_timeout : peer->go_timeout;
16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
16421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p->ssid_set = 0;
16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer->go_neg_req_sent = 0;
16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer->wps_method = WPS_NOT_READY;
16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_PROVISIONING);
16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->go_neg_completed(p2p->cfg->cb_ctx, &res);
16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_rx_p2p_action(struct p2p_data *p2p, const u8 *sa,
16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      const u8 *data, size_t len, int rx_freq)
16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1654b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "RX P2P Public Action from " MACSTR, MAC2STR(sa));
16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "P2P: P2P Public Action contents", data, len);
16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1)
16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data[0]) {
16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG_REQ:
16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_neg_req(p2p, sa, data + 1, len - 1, rx_freq);
16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG_RESP:
16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_neg_resp(p2p, sa, data + 1, len - 1, rx_freq);
16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG_CONF:
16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_neg_conf(p2p, sa, data + 1, len - 1);
16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITATION_REQ:
16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_invitation_req(p2p, sa, data + 1, len - 1,
16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   rx_freq);
16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITATION_RESP:
16758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_invitation_resp(p2p, sa, data + 1, len - 1);
16768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROV_DISC_REQ:
16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_prov_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROV_DISC_RESP:
16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_prov_disc_resp(p2p, sa, data + 1, len - 1);
16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_DEV_DISC_REQ:
16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_dev_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_DEV_DISC_RESP:
16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_dev_disc_resp(p2p, sa, data + 1, len - 1);
16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
1690b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Unsupported P2P Public Action frame type %d",
16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data[0]);
16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void p2p_rx_action_public(struct p2p_data *p2p, const u8 *da,
16981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				 const u8 *sa, const u8 *bssid, const u8 *data,
16991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				 size_t len, int freq)
17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1)
17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data[0]) {
17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_VENDOR_SPECIFIC:
17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data++;
17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len--;
17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 3)
17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (WPA_GET_BE24(data) != OUI_WFA)
17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data += 3;
17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len -= 3;
17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 1)
17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*data != P2P_OUI_TYPE)
17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_p2p_action(p2p, sa, data + 1, len - 1, freq);
17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_INITIAL_REQ:
17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_initial_req(p2p, sa, data + 1, len - 1, freq);
17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_INITIAL_RESP:
17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_initial_resp(p2p, sa, data + 1, len - 1, freq);
17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_COMEBACK_REQ:
17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_comeback_req(p2p, sa, data + 1, len - 1, freq);
17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_COMEBACK_RESP:
17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_comeback_resp(p2p, sa, data + 1, len - 1, freq);
17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_rx_action(struct p2p_data *p2p, const u8 *da, const u8 *sa,
17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *bssid, u8 category,
17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *data, size_t len, int freq)
17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (category == WLAN_ACTION_PUBLIC) {
17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_action_public(p2p, da, sa, bssid, data, len, freq);
17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (category != WLAN_ACTION_VENDOR_SPECIFIC)
17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 4)
17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (WPA_GET_BE24(data) != OUI_WFA)
17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data += 3;
17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len -= 3;
17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*data != P2P_OUI_TYPE)
17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data++;
17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len--;
17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P action frame */
1765b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "RX P2P Action from " MACSTR, MAC2STR(sa));
17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "P2P: P2P Action contents", data, len);
17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1)
17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data[0]) {
17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_NOA:
1772b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Received P2P Action - Notice of Absence");
17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO */
17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PRESENCE_REQ:
17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_presence_req(p2p, da, sa, data + 1, len - 1, freq);
17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PRESENCE_RESP:
17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_presence_resp(p2p, da, sa, data + 1, len - 1);
17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_DISC_REQ:
17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_disc_req(p2p, da, sa, data + 1, len - 1, freq);
17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
1785b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Received P2P Action - unknown type %u", data[0]);
17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_start(void *eloop_ctx, void *timeout_ctx)
17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == NULL)
17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer->status = P2P_SC_SUCCESS;
17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_connect_send(p2p, p2p->go_neg_peer);
17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_invite_start(void *eloop_ctx, void *timeout_ctx)
18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->invite_peer == NULL)
18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_invite_send(p2p, p2p->invite_peer, p2p->invite_go_dev_addr);
18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_add_dev_from_probe_req(struct p2p_data *p2p, const u8 *addr,
18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const u8 *ie, size_t ie_len)
18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg) < 0 || msg.p2p_attributes == NULL)
18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* not a P2P probe */
18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.ssid == NULL || msg.ssid[1] != P2P_WILDCARD_SSID_LEN ||
18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(msg.ssid + 2, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN)
18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    != 0) {
18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* The Probe Request is not part of P2P Device Discovery. It is
18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * not known whether the source address of the frame is the P2P
18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Device Address or P2P Interface Address. Do not add a new
18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * peer entry based on this frames.
18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev) {
18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->country[0] == 0 && msg.listen_channel)
18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(dev->country, msg.listen_channel, 3);
18411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		os_get_time(&dev->last_seen);
18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* already known */
18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_create_device(p2p, addr);
18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&dev->last_seen);
18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_PROBE_REQ_ONLY;
18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.listen_channel) {
18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->country, msg.listen_channel, 3);
18574b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		dev->listen_freq = p2p_channel_to_freq(msg.listen_channel[3],
18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       msg.listen_channel[4]);
18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1861b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_copy_wps_info(p2p, dev, 1, &msg);
18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
186361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (msg.wfd_subelems) {
186461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_free(dev->info.wfd_subelems);
186561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
186661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
186761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1870b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Created device entry based on Probe Req: " MACSTR
18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" dev_capab=0x%x group_capab=0x%x name='%s' listen_freq=%d",
18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(dev->info.p2p_device_addr), dev->info.dev_capab,
18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.group_capab, dev->info.device_name,
18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->listen_freq);
18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_device * p2p_add_dev_from_go_neg_req(struct p2p_data *p2p,
18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						const u8 *addr,
18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						struct p2p_message *msg)
18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev) {
18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_get_time(&dev->last_seen);
18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return dev; /* already known */
18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_create_device(p2p, addr);
18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_add_dev_info(p2p, addr, dev, msg);
18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return dev;
18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int dev_type_match(const u8 *dev_type, const u8 *req_dev_type)
19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(dev_type, req_dev_type, WPS_DEV_TYPE_LEN) == 0)
19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(dev_type, req_dev_type, 2) == 0 &&
19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    WPA_GET_BE32(&req_dev_type[2]) == 0 &&
19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    WPA_GET_BE16(&req_dev_type[6]) == 0)
19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Category match with wildcard OUI/sub-category */
19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint dev_type_list_match(const u8 *dev_type, const u8 *req_dev_type[],
19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			size_t num_req_dev_type)
19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_req_dev_type; i++) {
19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev_type_match(dev_type, req_dev_type[i]))
19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 1;
19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_match_dev_type - Match local device type with requested type
19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wps: WPS TLVs from Probe Request frame (concatenated WPS IEs)
19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 on match, 0 on mismatch
19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function can be used to match the Requested Device Type attribute in
19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPS IE with the local device types for deciding whether to reply to a Probe
19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Request frame.
19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_match_dev_type(struct p2p_data *p2p, struct wpabuf *wps)
19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wps_parse_attr attr;
19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wps_parse_msg(wps, &attr))
19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* assume no Requested Device Type attributes */
19418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (attr.num_req_dev_type == 0)
19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* no Requested Device Type attributes -> match */
19448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev_type_list_match(p2p->cfg->pri_dev_type, attr.req_dev_type,
19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				attr.num_req_dev_type))
19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Own Primary Device Type matches */
19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < p2p->cfg->num_sec_dev_types; i++)
19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev_type_list_match(p2p->cfg->sec_dev_type[i],
19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					attr.req_dev_type,
19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					attr.num_req_dev_type))
19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Own Secondary Device Type matches */
19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* No matching device type found */
19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * p2p_build_probe_resp_ies(struct p2p_data *p2p)
19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
196404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	int pw_id = -1;
196561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t extra = 0;
196661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
196761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
196861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_probe_resp)
196961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		extra = wpabuf_len(p2p->wfd_ie_probe_resp);
197061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
197261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	buf = wpabuf_alloc(1000 + extra);
19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
197604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p->go_neg_peer) {
197704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/* Advertise immediate availability of WPS credential */
197804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		pw_id = p2p_wps_method_pw_id(p2p->go_neg_peer->wps_method);
197904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
198004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
198104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_build_wps_ie(p2p, buf, pw_id, 1);
19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
198361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
198461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_probe_resp)
198561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(buf, p2p->wfd_ie_probe_resp);
198661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
198761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P IE */
19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(buf);
199004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_buf_add_capability(buf, p2p->dev_capab &
199104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			       ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 0);
19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval)
19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_ext_listen_timing(buf, p2p->ext_listen_period,
19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      p2p->ext_listen_interval);
19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_device_info(buf, p2p, NULL);
19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(buf, len);
19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
200204949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic enum p2p_probe_req_status
200304949598a23f501be6eec21697465fd46a28840aDmitry Shmidtp2p_reply_probe(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
200404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		const u8 *bssid, const u8 *ie, size_t ie_len)
20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ieee802_11_elems elems;
20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ieee80211_mgmt *resp;
20091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_message msg;
20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *ies;
20118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p->in_listen || !p2p->drv_in_listen) {
20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* not in Listen state - ignore Probe Request */
201404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_LISTEN;
20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ieee802_11_parse_elems((u8 *) ie, ie_len, &elems, 0) ==
20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ParseFailed) {
20198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Ignore invalid Probe Request frames */
202004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_MALFORMED;
20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (elems.p2p == NULL) {
20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* not a P2P probe - ignore it */
202504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_P2P;
20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (dst && !is_broadcast_ether_addr(dst) &&
20291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    os_memcmp(dst, p2p->cfg->dev_addr, ETH_ALEN) != 0) {
20301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Not sent to the broadcast address or our P2P Device Address
20311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
203204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
20331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
20341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (bssid && !is_broadcast_ether_addr(bssid)) {
20361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Not sent to the Wildcard BSSID */
203704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
20381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
20391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (elems.ssid == NULL || elems.ssid_len != P2P_WILDCARD_SSID_LEN ||
20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(elems.ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) !=
20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0) {
20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* not using P2P Wildcard SSID - ignore */
204404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (supp_rates_11b_only(&elems)) {
20481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Indicates support for 11b rates only */
204904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_P2P;
20501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
20511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
20531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg) < 0) {
20541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Could not parse P2P attributes */
205504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_P2P;
20561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
20571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (msg.device_id &&
205904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    os_memcmp(msg.device_id, p2p->cfg->dev_addr, ETH_ALEN) != 0) {
20601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Device ID did not match */
20611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_parse_free(&msg);
206204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
20631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
20641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Check Requested Device Type match */
20661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (msg.wps_attributes &&
20671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    !p2p_match_dev_type(p2p, msg.wps_attributes)) {
20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* No match with Requested Device Type */
20691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_parse_free(&msg);
207004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_parse_free(&msg);
20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
207404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (!p2p->cfg->send_probe_resp) {
207504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/* Response generated elsewhere */
207604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
207704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
20788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2079b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Reply to P2P Probe Request in Listen state");
20808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
20828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * We do not really have a specific BSS that this frame is advertising,
20838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * so build a frame that has some information in valid format. This is
20848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * really only used for discovery purposes, not to learn exact BSS
20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * parameters.
20868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ies = p2p_build_probe_resp_ies(p2p);
20888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ies == NULL)
208904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = wpabuf_alloc(200 + wpabuf_len(ies));
20928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL) {
20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(ies);
209404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = NULL;
20988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = wpabuf_put(buf, resp->u.probe_resp.variable - (u8 *) resp);
20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   (WLAN_FC_STYPE_PROBE_RESP << 4));
21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(resp->da, addr, ETH_ALEN);
21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(resp->sa, p2p->cfg->dev_addr, ETH_ALEN);
21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(resp->bssid, p2p->cfg->dev_addr, ETH_ALEN);
21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->u.probe_resp.beacon_int = host_to_le16(100);
21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* hardware or low-level driver will setup seq_ctrl and timestamp */
21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->u.probe_resp.capab_info =
21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		host_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE |
21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     WLAN_CAPABILITY_PRIVACY |
21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     WLAN_CAPABILITY_SHORT_SLOT_TIME);
21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_SSID);
21138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, P2P_WILDCARD_SSID_LEN);
21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(buf, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_SUPP_RATES);
21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 8);
21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, (60 / 5) | 0x80);
21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 90 / 5);
21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, (120 / 5) | 0x80);
21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 180 / 5);
21228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, (240 / 5) | 0x80);
21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 360 / 5);
21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 480 / 5);
21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 540 / 5);
21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_DS_PARAMS);
21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 1);
21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, p2p->cfg->channel);
21308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_buf(buf, ies);
21328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(ies);
21338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_probe_resp(p2p->cfg->cb_ctx, buf);
21358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(buf);
213704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
213804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return P2P_PREQ_NOT_PROCESSED;
21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
214204949598a23f501be6eec21697465fd46a28840aDmitry Shmidtenum p2p_probe_req_status
214304949598a23f501be6eec21697465fd46a28840aDmitry Shmidtp2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
214404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 const u8 *bssid, const u8 *ie, size_t ie_len)
21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
214604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	enum p2p_probe_req_status res;
214704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_add_dev_from_probe_req(p2p, addr, ie, ie_len);
21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
215004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	res = p2p_reply_probe(p2p, addr, dst, bssid, ie, ie_len);
21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((p2p->state == P2P_CONNECT || p2p->state == P2P_CONNECT_LISTEN) &&
21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    p2p->go_neg_peer &&
21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(addr, p2p->go_neg_peer->info.p2p_device_addr, ETH_ALEN)
21559cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt	    == 0 &&
21569cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt	    !(p2p->go_neg_peer->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM)) {
21578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Received a Probe Request from GO Negotiation peer */
2158b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Found GO Negotiation peer - try to start GO negotiation from timeout");
21599cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt		eloop_cancel_timeout(p2p_go_neg_start, p2p, NULL);
21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(0, 0, p2p_go_neg_start, p2p, NULL);
216104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_PROCESSED;
21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((p2p->state == P2P_INVITE || p2p->state == P2P_INVITE_LISTEN) &&
21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    p2p->invite_peer &&
21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(addr, p2p->invite_peer->info.p2p_device_addr, ETH_ALEN)
21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    == 0) {
21688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Received a Probe Request from Invite peer */
2169b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Found Invite peer - try to start Invite from timeout");
21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(0, 0, p2p_invite_start, p2p, NULL);
217104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_PROCESSED;
21728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
217404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return res;
21758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_assoc_req_ie_wlan_ap(struct p2p_data *p2p, const u8 *bssid,
21798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    u8 *buf, size_t len, struct wpabuf *p2p_ie)
21808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *tmp;
21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *lpos;
21838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t tmplen;
21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 group_capab;
21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_ie == NULL)
21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* WLAN AP is not a P2P manager */
21898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (Re)Association Request - P2P IE
21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Capability attribute (shall be present)
21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Interface attribute (present if concurrent device and
21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *	P2P Management is enabled)
21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp = wpabuf_alloc(200);
21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp == NULL)
21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
21998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	lpos = p2p_buf_add_ie_hdr(tmp);
22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group_capab = 0;
22028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->num_groups > 0) {
22038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group_capab |= P2P_GROUP_CAPAB_GROUP_OWNER;
22048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) &&
22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED) &&
22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    p2p->cross_connect)
22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_capability(tmp, p2p->dev_capab, group_capab);
22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) &&
22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED))
22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_p2p_interface(tmp, p2p);
22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(tmp, lpos);
22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmplen = wpabuf_len(tmp);
22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmplen > len)
22178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = -1;
22188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
22198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(buf, wpabuf_head(tmp), tmplen);
22208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = tmplen;
22218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(tmp);
22238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
22258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_assoc_req_ie(struct p2p_data *p2p, const u8 *bssid, u8 *buf,
22298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     size_t len, int p2p_group, struct wpabuf *p2p_ie)
22308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *tmp;
22328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *lpos;
22338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *peer;
22348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t tmplen;
22358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
223661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t extra = 0;
22378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p_group)
22398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return p2p_assoc_req_ie_wlan_ap(p2p, bssid, buf, len, p2p_ie);
22408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
224161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
224261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_assoc_req)
224361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		extra = wpabuf_len(p2p->wfd_ie_assoc_req);
224461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
224561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
22468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
22478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (Re)Association Request - P2P IE
22488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Capability attribute (shall be present)
22498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Extended Listen Timing (may be present)
22508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Device Info attribute (shall be present)
22518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
225261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	tmp = wpabuf_alloc(200 + extra);
22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp == NULL)
22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
225661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
225761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_assoc_req)
225861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(tmp, p2p->wfd_ie_assoc_req);
225961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
226061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
22618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer = bssid ? p2p_get_device(p2p, bssid) : NULL;
22628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	lpos = p2p_buf_add_ie_hdr(tmp);
22648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_capability(tmp, p2p->dev_capab, 0);
22658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval)
22668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_ext_listen_timing(tmp, p2p->ext_listen_period,
22678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      p2p->ext_listen_interval);
22688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_device_info(tmp, p2p, peer);
22698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(tmp, lpos);
22708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmplen = wpabuf_len(tmp);
22728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmplen > len)
22738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = -1;
22748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
22758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(buf, wpabuf_head(tmp), tmplen);
22768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = tmplen;
22778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(tmp);
22798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
22818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_scan_result_text(const u8 *ies, size_t ies_len, char *buf, char *end)
22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *p2p_ie;
22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
22888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len, P2P_IE_VENDOR_TYPE);
22908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_ie == NULL)
22918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
22928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = p2p_attr_text(p2p_ie, buf, end);
22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(p2p_ie);
22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
22968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
229904949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint p2p_parse_dev_addr_in_p2p_ie(struct wpabuf *p2p_ie, u8 *dev_addr)
2300c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{
2301c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	struct p2p_message msg;
2302c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
2303c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
230404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p_parse_p2p_ie(p2p_ie, &msg))
2305c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return -1;
2306c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
230704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (msg.p2p_device_addr) {
230804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(dev_addr, msg.p2p_device_addr, ETH_ALEN);
230904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 0;
231004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	} else if (msg.device_id) {
231104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(dev_addr, msg.device_id, ETH_ALEN);
231204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 0;
2313c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
231404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return -1;
231504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
2316c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
231704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
231804949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint p2p_parse_dev_addr(const u8 *ies, size_t ies_len, u8 *dev_addr)
231904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
232004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct wpabuf *p2p_ie;
232104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	int ret;
232204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
232304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
232404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					     P2P_IE_VENDOR_TYPE);
232504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p_ie == NULL)
232604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return -1;
232704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	ret = p2p_parse_dev_addr_in_p2p_ie(p2p_ie, dev_addr);
2328c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	wpabuf_free(p2p_ie);
232904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return ret;
2330c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt}
2331c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
2332c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
23338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_clear_go_neg(struct p2p_data *p2p)
23348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer = NULL;
23368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
23378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_IDLE);
23388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_wps_success_cb(struct p2p_data *p2p, const u8 *mac_addr)
23428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == NULL) {
2344b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "No pending Group Formation - ignore WPS registration success notification");
23458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* No pending Group Formation */
23468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(mac_addr, p2p->go_neg_peer->intended_addr, ETH_ALEN) !=
23498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0) {
2350b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Ignore WPS registration success notification for "
2351b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			MACSTR " (GO Negotiation peer " MACSTR ")",
23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(mac_addr),
23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(p2p->go_neg_peer->intended_addr));
23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* Ignore unexpected peer address */
23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2357b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Group Formation completed successfully with " MACSTR,
23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(mac_addr));
23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_go_neg(p2p);
23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_group_formation_failed(struct p2p_data *p2p)
23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == NULL) {
2367b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "No pending Group Formation - ignore group formation failure notification");
23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* No pending Group Formation */
23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2371b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Group Formation failed with " MACSTR,
23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(p2p->go_neg_peer->intended_addr));
23738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_go_neg(p2p);
23758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_data * p2p_init(const struct p2p_config *cfg)
23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p;
23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->max_peers < 1)
23838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p = os_zalloc(sizeof(*p2p) + sizeof(*cfg));
23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p == NULL)
23878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
23888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg = (struct p2p_config *) (p2p + 1);
23898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg, cfg, sizeof(*cfg));
23908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->dev_name)
23918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->dev_name = os_strdup(cfg->dev_name);
23928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->manufacturer)
23938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->manufacturer = os_strdup(cfg->manufacturer);
23948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->model_name)
23958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_name = os_strdup(cfg->model_name);
23968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->model_number)
23978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_number = os_strdup(cfg->model_number);
23988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->serial_number)
23998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->serial_number = os_strdup(cfg->serial_number);
240004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (cfg->pref_chan) {
240104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->cfg->pref_chan = os_malloc(cfg->num_pref_chan *
240204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt						sizeof(struct p2p_channel));
240304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (p2p->cfg->pref_chan) {
240404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			os_memcpy(p2p->cfg->pref_chan, cfg->pref_chan,
240504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  cfg->num_pref_chan *
240604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  sizeof(struct p2p_channel));
240704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		} else
240804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			p2p->cfg->num_pref_chan = 0;
240904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
241004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
2411f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#ifdef ANDROID_P2P
2412f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	/* 100ms listen time is too less to receive the response frames in some scenarios
2413f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	 * increasing min listen time to 200ms.
2414f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	 */
2415f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	p2p->min_disc_int = 2;
2416f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	/* SD_FAIR_POLICY: Initializing the SD current serviced pointer to NULL */
2417f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	p2p->sd_dev_list = NULL;
2418f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#else
24198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->min_disc_int = 1;
2420f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#endif
24218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->max_disc_int = 3;
2422d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p->max_disc_tu = -1;
24238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_random(&p2p->next_tie_breaker, 1);
24258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->next_tie_breaker &= 0x01;
24268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->sd_request)
24278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_SERVICE_DISCOVERY;
24288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->dev_capab |= P2P_DEV_CAPAB_INVITATION_PROCEDURE;
24298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->concurrent_operations)
24308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_CONCURRENT_OPER;
24318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->dev_capab |= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
24328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_init(&p2p->devices);
24348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(P2P_PEER_EXPIRATION_INTERVAL, 0,
24368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p_expiration_timeout, p2p, NULL);
24378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
243861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->go_timeout = 100;
243961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->client_timeout = 20;
244061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
24418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p;
24428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_deinit(struct p2p_data *p2p)
24468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
244761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
244861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_beacon);
244961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_probe_req);
245061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_probe_resp);
245161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_assoc_req);
245261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_invitation);
245361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_prov_disc_req);
245461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_prov_disc_resp);
245561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_go_neg);
245661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_dev_info);
245761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_assoc_bssid);
245861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_coupled_sink_info);
245961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
246061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
24618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_expiration_timeout, p2p, NULL);
24628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_ext_listen_timeout, p2p, NULL);
24638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
24649cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt	eloop_cancel_timeout(p2p_go_neg_start, p2p, NULL);
24658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_flush(p2p);
24668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_req_dev_types(p2p);
24678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->dev_name);
24688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->manufacturer);
24698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_name);
24708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_number);
24718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->serial_number);
247204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	os_free(p2p->cfg->pref_chan);
24738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->groups);
24748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(p2p->sd_resp);
24758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->after_scan_tx);
24768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_remove_wps_vendor_extensions(p2p);
24778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p);
24788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_flush(struct p2p_data *p2p)
24828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev, *prev;
248404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_stop_find(p2p);
24858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each_safe(dev, prev, &p2p->devices, struct p2p_device,
24868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      list) {
24878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dl_list_del(&dev->list);
24888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_device_free(p2p, dev);
24898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2490f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#ifdef ANDROID_P2P
2491f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	/* SD_FAIR_POLICY: Initializing the SD current serviced pointer to NULL */
2492f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	p2p->sd_dev_list = NULL;
2493f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#endif
24948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_sd_queries(p2p);
24958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->after_scan_tx);
24968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->after_scan_tx = NULL;
24978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_unauthorize(struct p2p_data *p2p, const u8 *addr)
25018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
25038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
25058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
25068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
25078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2508b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Unauthorizing " MACSTR, MAC2STR(addr));
25098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == dev)
25118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->go_neg_peer = NULL;
25128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wps_method = WPS_NOT_READY;
25148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE;
25158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM;
25168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Check if after_scan_tx is for this peer. If so free it */
25188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->after_scan_tx &&
25198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(addr, p2p->after_scan_tx->dst, ETH_ALEN) == 0) {
25208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p2p->after_scan_tx);
25218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = NULL;
25228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
25258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_dev_name(struct p2p_data *p2p, const char *dev_name)
25298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->dev_name);
25318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev_name) {
25328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->dev_name = os_strdup(dev_name);
25338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->dev_name == NULL)
25348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
25358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
25368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->dev_name = NULL;
25378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
25388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_manufacturer(struct p2p_data *p2p, const char *manufacturer)
25428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->manufacturer);
25448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->manufacturer = NULL;
25458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (manufacturer) {
25468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->manufacturer = os_strdup(manufacturer);
25478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->manufacturer == NULL)
25488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
25498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
25528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_model_name(struct p2p_data *p2p, const char *model_name)
25568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_name);
25588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->model_name = NULL;
25598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (model_name) {
25608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_name = os_strdup(model_name);
25618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->model_name == NULL)
25628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
25638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
25668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_model_number(struct p2p_data *p2p, const char *model_number)
25708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_number);
25728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->model_number = NULL;
25738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (model_number) {
25748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_number = os_strdup(model_number);
25758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->model_number == NULL)
25768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
25778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
25808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_serial_number(struct p2p_data *p2p, const char *serial_number)
25848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->serial_number);
25868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->serial_number = NULL;
25878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (serial_number) {
25888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->serial_number = os_strdup(serial_number);
25898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->serial_number == NULL)
25908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
25918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
25948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_config_methods(struct p2p_data *p2p, u16 config_methods)
25988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->config_methods = config_methods;
26008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_uuid(struct p2p_data *p2p, const u8 *uuid)
26048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->uuid, uuid, 16);
26068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_pri_dev_type(struct p2p_data *p2p, const u8 *pri_dev_type)
26108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->pri_dev_type, pri_dev_type, 8);
26128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_sec_dev_types(struct p2p_data *p2p, const u8 dev_types[][8],
26178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  size_t num_dev_types)
26188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (num_dev_types > P2P_SEC_DEVICE_TYPES)
26208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num_dev_types = P2P_SEC_DEVICE_TYPES;
26218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->num_sec_dev_types = num_dev_types;
26228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->sec_dev_type, dev_types, num_dev_types * 8);
26238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_remove_wps_vendor_extensions(struct p2p_data *p2p)
26288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
26308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
26328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(p2p->wps_vendor_ext[i]);
26338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->wps_vendor_ext[i] = NULL;
26348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_add_wps_vendor_extension(struct p2p_data *p2p,
26398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const struct wpabuf *vendor_ext)
26408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
26428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (vendor_ext == NULL)
26448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
26458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
26478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->wps_vendor_ext[i] == NULL)
26488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
26498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (i >= P2P_MAX_WPS_VENDOR_EXT)
26518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
26528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->wps_vendor_ext[i] = wpabuf_dup(vendor_ext);
26548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->wps_vendor_ext[i] == NULL)
26558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
26568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_country(struct p2p_data *p2p, const char *country)
26628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->country, country, 3);
26648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_continue_find(struct p2p_data *p2p)
26698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
2671f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#ifdef ANDROID_P2P
2672f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff	int skip=1;
2673f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#endif
26748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_SEARCH);
26758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
2676f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#ifdef ANDROID_P2P
2677f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		/* SD_FAIR_POLICY: We need to give chance to all devices in the device list
2678f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * There may be a scenario, where a particular peer device have
2679f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * not registered any query response. When we send a SD request to such device,
2680f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * no response will be received. And if we continue to get probe responses from that device,
2681f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * and if that device happens to be on top in our device list,
2682f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * we will always continue to send SD requests always to that peer only.
2683f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * We will not be able to send SD requests to other devices in that case.
2684f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * This implementation keeps track of last serviced peer device.
2685f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 * And then takes the next one from the device list, in the next iteration.
2686f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		 */
2687f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		if (p2p->sd_dev_list && p2p->sd_dev_list != &p2p->devices) {
2688f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff			if(skip) {
2689f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff				if ((&dev->list == p2p->sd_dev_list) ) {
2690f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff					skip = 0;
2691f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff					if (dev->list.next == &p2p->devices)
2692f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff						p2p->sd_dev_list = NULL;
2693f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff				}
2694f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff				continue;
2695f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff			}
2696f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		}
2697f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		p2p->sd_dev_list = &dev->list;
2698f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff		wpa_printf(MSG_DEBUG, "P2P: ### Servicing %p dev->flags 0x%x SD schedule %s devaddr " MACSTR,
2699f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff			p2p->sd_dev_list, dev->flags, dev->flags & P2P_DEV_SD_SCHEDULE ? "TRUE": "FALSE",
2700f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff			MAC2STR(dev->info.p2p_device_addr));
2701f44b9c4a18d17fbd39901f76a014c32006570fb8Irfan Sheriff#endif
27028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->flags & P2P_DEV_SD_SCHEDULE) {
27038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (p2p_start_sd(p2p, dev) == 0)
27048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
27058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
27068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
27078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (dev->req_config_methods &&
27088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   !(dev->flags & P2P_DEV_PD_FOR_JOIN)) {
2709b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Send pending Provision Discovery Request to "
27108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MACSTR " (config methods 0x%x)",
27118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(dev->info.p2p_device_addr),
27128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev->req_config_methods);
27131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (p2p_send_prov_disc_req(p2p, dev, 0, 0) == 0)
27148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
27158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
27168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2718d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p_listen_in_find(p2p, 1);
27198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_sd_cb(struct p2p_data *p2p, int success)
27238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2724b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Service Discovery Query TX callback: success=%d",
27258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
27268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
27278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!success) {
27298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->sd_peer) {
27308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE;
27318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->sd_peer = NULL;
27328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
27338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
27348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
27358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->sd_peer == NULL) {
2738b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "No SD peer entry known");
27398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
27408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
27418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Wait for response from the peer */
27448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_SD_DURING_FIND);
27458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_timeout(p2p, 0, 200000);
27468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
274875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
274975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen/**
275075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen * p2p_retry_pd - Retry any pending provision disc requests in IDLE state
275175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen * @p2p: P2P module context from p2p_init()
275275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen */
27531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void p2p_retry_pd(struct p2p_data *p2p)
275475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
275575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	struct p2p_device *dev;
275675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
275775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p->state != P2P_IDLE)
275875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
275975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
276075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
276175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * Retry the prov disc req attempt only for the peer that the user had
2762d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	 * requested.
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
2772b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Send pending Provision Discovery Request to "
277375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			MACSTR " (config methods 0x%x)",
277475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			MAC2STR(dev->info.p2p_device_addr),
277575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			dev->req_config_methods);
2776d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		p2p_send_prov_disc_req(p2p, dev,
2777d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				       dev->flags & P2P_DEV_PD_FOR_JOIN, 0);
277875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
277975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	}
278075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
278175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
278275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
27838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_prov_disc_cb(struct p2p_data *p2p, int success)
27848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2785b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Provision Discovery Request TX callback: success=%d",
27868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
278775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
278875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
278975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * Postpone resetting the pending action state till after we actually
279075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * time out. This allows us to take some action like notifying any
279175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * interested parties about no response to the request.
279275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 *
279375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * When the timer (below) goes off we check in IDLE, SEARCH, or
279475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * LISTEN_ONLY state, which are the only allowed states to issue a PD
279575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * requests in, if this was still pending and then raise notification.
279675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
27978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!success) {
279975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pending_action_state = P2P_NO_PENDING_ACTION;
280075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
280161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->user_initiated_pd &&
280261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		    (p2p->state == P2P_SEARCH || p2p->state == P2P_LISTEN_ONLY))
280361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		{
280461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			/* Retry request from timeout to avoid busy loops */
280561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p->pending_action_state = P2P_PENDING_PD;
280661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p_set_timeout(p2p, 0, 50000);
280761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		} else if (p2p->state != P2P_IDLE)
28088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_continue_find(p2p);
280975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		else if (p2p->user_initiated_pd) {
281075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p->pending_action_state = P2P_PENDING_PD;
28111a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#ifdef ANDROID_P2P
28121a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff			p2p_set_timeout(p2p, 0, 350000);
28131a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#else
281475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_set_timeout(p2p, 0, 300000);
28151a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#endif
281675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		}
28178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
28188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
282075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
282175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * This postponing, of resetting pending_action_state, needs to be
282275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * done only for user initiated PD requests and not internal ones.
282375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
282475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p->user_initiated_pd)
282575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pending_action_state = P2P_PENDING_PD;
282675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	else
282775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pending_action_state = P2P_NO_PENDING_ACTION;
282875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
28298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Wait for response from the peer */
28308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_SEARCH)
28318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_PD_DURING_FIND);
28321a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#ifdef ANDROID_P2P
28331a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff	p2p_set_timeout(p2p, 0, 350000);
28341a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#else
28358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_timeout(p2p, 0, 200000);
28361a2ce111ade9563d99ed7bb8156d6148ffd6c3a3Irfan Sheriff#endif
28378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_scan_res_handler(struct p2p_data *p2p, const u8 *bssid, int freq,
2841f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			 struct os_time *rx_time, int level, const u8 *ies,
2842a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			 size_t ies_len)
28438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2844f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	if (os_time_before(rx_time, &p2p->find_start)) {
2845f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		/*
2846f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * The driver may have cached (e.g., in cfg80211 BSS table) the
2847f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * scan results for relatively long time. To avoid reporting
2848f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * stale information, update P2P peers only based on results
2849f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * that have based on frames received after the last p2p_find
2850f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * operation was started.
2851f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 */
2852b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Ignore old scan result for " MACSTR
2853b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			" (rx_time=%u.%06u)",
2854f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			MAC2STR(bssid), (unsigned int) rx_time->sec,
2855f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			(unsigned int) rx_time->usec);
2856f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		return 0;
2857f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	}
2858f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
2859f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	p2p_add_device(p2p, bssid, freq, rx_time, level, ies, ies_len, 1);
28608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
28628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_scan_res_handled(struct p2p_data *p2p)
28668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p->p2p_scan_running) {
2868b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "p2p_scan was not running, but scan results received");
28698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->p2p_scan_running = 0;
28718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
28728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_run_after_scan(p2p))
28748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
28758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_SEARCH)
28768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
28778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2880c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtvoid p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id)
28818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
288261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 *len;
288361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
288461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
288561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_probe_req)
288661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(ies, p2p->wfd_ie_probe_req);
288761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
288861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
288961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	len = p2p_buf_add_ie_hdr(ies);
289004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_buf_add_capability(ies, p2p->dev_capab &
289104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			       ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 0);
2892c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (dev_id)
2893c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		p2p_buf_add_device_id(ies, dev_id);
28948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->reg_class && p2p->cfg->channel)
28958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_listen_channel(ies, p2p->cfg->country,
28968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   p2p->cfg->reg_class,
28978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   p2p->cfg->channel);
28988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval)
28998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_ext_listen_timing(ies, p2p->ext_listen_period,
29008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      p2p->ext_listen_interval);
29018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: p2p_buf_add_operating_channel() if GO */
29028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(ies, len);
29038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtsize_t p2p_scan_ie_buf_len(struct p2p_data *p2p)
29071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
290861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t len = 100;
290961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
291061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
291161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p && p2p->wfd_ie_probe_req)
291261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		len += wpabuf_len(p2p->wfd_ie_probe_req);
291361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
291461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
291561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return len;
29161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
29171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
29181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
29198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_ie_text(struct wpabuf *p2p_ie, char *buf, char *end)
29208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_attr_text(p2p_ie, buf, end);
29228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_req_cb(struct p2p_data *p2p, int success)
29268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p->go_neg_peer;
29288c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	int timeout;
29298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2930b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "GO Negotiation Request TX callback: success=%d", success);
29318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
2933b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "No pending GO Negotiation");
29348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
29358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (success) {
29388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->flags & P2P_DEV_USER_REJECTED) {
29398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_set_state(p2p, P2P_IDLE);
29408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
29418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
294204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	} else if (dev->go_neg_req_sent) {
294304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/* Cancel the increment from p2p_connect_send() on failure */
294498f9e76624da6bb96edc1982c423e4a119c5170aDmitry Shmidt		dev->go_neg_req_sent--;
294598f9e76624da6bb96edc1982c423e4a119c5170aDmitry Shmidt	}
29468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!success &&
29488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (dev->info.dev_capab & P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY) &&
29498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !is_zero_ether_addr(dev->member_in_go_dev)) {
2950b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Peer " MACSTR " did not acknowledge request - try to use device discoverability through its GO",
29518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr));
29528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
29538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_send_dev_disc_req(p2p, dev);
29548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
29558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
29588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Use P2P find, if needed, to find the other device from its listen
29598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * channel.
29608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
29618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_CONNECT);
29628c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	timeout = success ? 500000 : 100000;
29638c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	if (!success && p2p->go_neg_peer &&
29648c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	    (p2p->go_neg_peer->flags & P2P_DEV_PEER_WAITING_RESPONSE)) {
29658c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		unsigned int r;
29668c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		/*
29678c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		 * Peer is expected to wait our response and we will skip the
29688c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		 * listen phase. Add some randomness to the wait time here to
29698c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		 * make it less likely to hit cases where we could end up in
29708c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		 * sync with peer not listening.
29718c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		 */
29728c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		os_get_random((u8 *) &r, sizeof(r));
29738c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		timeout += r % 100000;
29748c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	}
29758c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	p2p_set_timeout(p2p, 0, timeout);
29768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_resp_cb(struct p2p_data *p2p, int success)
29808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2981b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "GO Negotiation Response TX callback: success=%d",
29828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
29838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p->go_neg_peer && p2p->state == P2P_PROVISIONING) {
2984b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Ignore TX callback event - GO Negotiation is not running anymore");
29858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
29868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_CONNECT);
29888c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	p2p_set_timeout(p2p, 0, 500000);
29898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29924b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidtstatic void p2p_go_neg_resp_failure_cb(struct p2p_data *p2p, int success,
29934b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt				       const u8 *addr)
29948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2995b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "GO Negotiation Response (failure) TX callback: success=%d", success);
29968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer && p2p->go_neg_peer->status != P2P_SC_SUCCESS) {
29978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_failed(p2p, p2p->go_neg_peer,
29988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  p2p->go_neg_peer->status);
29994b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	} else if (success) {
30004b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		struct p2p_device *dev;
30014b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		dev = p2p_get_device(p2p, addr);
30024b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		if (dev &&
30034b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		    dev->status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE)
30044b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt			dev->flags |= P2P_DEV_PEER_WAITING_RESPONSE;
30058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_conf_cb(struct p2p_data *p2p,
30108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       enum p2p_send_action_result result)
30118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
30138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3014b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "GO Negotiation Confirm TX callback: result=%d", result);
30158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
30168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (result == P2P_SEND_ACTION_FAILED) {
30178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
30188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
30198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (result == P2P_SEND_ACTION_NO_ACK) {
30218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
30228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * It looks like the TX status for GO Negotiation Confirm is
30238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * often showing failure even when the peer has actually
30248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * received the frame. Since the peer may change channels
30258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * immediately after having received the frame, we may not see
30268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * an Ack for retries, so just dropping a single frame may
30278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * trigger this. To allow the group formation to succeed if the
30288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * peer did indeed receive the frame, continue regardless of
30298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * the TX status.
30308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
3031b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Assume GO Negotiation Confirm TX was actually received by the peer even though Ack was not reported");
30328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p->go_neg_peer;
30358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
30368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
30378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_go_complete(p2p, dev);
30398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_send_action_cb(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
30438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const u8 *src, const u8 *bssid,
30448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			enum p2p_send_action_result result)
30458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum p2p_pending_action_state state;
30478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int success;
30488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3049b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Action frame TX callback (state=%d freq=%u dst=" MACSTR
30508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" src=" MACSTR " bssid=" MACSTR " result=%d",
30518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_action_state, freq, MAC2STR(dst), MAC2STR(src),
30528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(bssid), result);
30538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	success = result == P2P_SEND_ACTION_SUCCESS;
30548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	state = p2p->pending_action_state;
30558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
30568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (state) {
30578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_NO_PENDING_ACTION:
30588da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt		if (p2p->after_scan_tx_in_progress) {
30598da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt			p2p->after_scan_tx_in_progress = 0;
30608da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt			if (p2p->start_after_scan != P2P_AFTER_SCAN_NOTHING &&
30618da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt			    p2p_run_after_scan(p2p))
30628da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt				break;
30638da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt			if (p2p->state == P2P_SEARCH) {
3064b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				p2p_dbg(p2p, "Continue find after after_scan_tx completion");
30658da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt				p2p_continue_find(p2p);
30668da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt			}
30678da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt		}
30688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_REQUEST:
30708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_req_cb(p2p, success);
30718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_RESPONSE:
30738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_resp_cb(p2p, success);
30748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_RESPONSE_FAILURE:
30764b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		p2p_go_neg_resp_failure_cb(p2p, success, dst);
30778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_CONFIRM:
30798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_conf_cb(p2p, result);
30808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_SD:
30828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_sd_cb(p2p, success);
30838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_PD:
30858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_prov_disc_cb(p2p, success);
30868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_INVITATION_REQUEST:
30888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_invitation_req_cb(p2p, success);
30898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_INVITATION_RESPONSE:
30918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_invitation_resp_cb(p2p, success);
30928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_DEV_DISC_REQUEST:
30948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_disc_req_cb(p2p, success);
30958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_DEV_DISC_RESPONSE:
30978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_disc_resp_cb(p2p, success);
30988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_DISC_REQ:
31008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_disc_req_cb(p2p, success);
31018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
31028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31038da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt
31048da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt	p2p->after_scan_tx_in_progress = 0;
31058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_listen_cb(struct p2p_data *p2p, unsigned int freq,
31098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   unsigned int duration)
31108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq == p2p->pending_client_disc_freq) {
3112b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Client discoverability remain-awake completed");
31138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_client_disc_freq = 0;
31148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
31158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq != p2p->pending_listen_freq) {
3118b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Unexpected listen callback for freq=%u duration=%u (pending_listen_freq=%u)",
31198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq, duration, p2p->pending_listen_freq);
31208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
31218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3123b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Starting Listen timeout(%u,%u) on freq=%u based on callback",
31248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_sec, p2p->pending_listen_usec,
31258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_freq);
31268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->in_listen = 1;
31278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->drv_in_listen = freq;
31288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->pending_listen_sec || p2p->pending_listen_usec) {
31298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
31308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Add 20 msec extra wait to avoid race condition with driver
31318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * remain-on-channel end event, i.e., give driver more time to
31328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * complete the operation before our timeout expires.
31338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
31348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_timeout(p2p, p2p->pending_listen_sec,
31358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p->pending_listen_usec + 20000);
31368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_freq = 0;
31398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_listen_end(struct p2p_data *p2p, unsigned int freq)
31438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3144b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Driver ended Listen state (freq=%u)", freq);
31458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->drv_in_listen = 0;
31468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->in_listen)
31478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* Internal timeout will trigger the next step */
31488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_CONNECT_LISTEN && p2p->go_neg_peer) {
31508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->go_neg_peer->connect_reqs >= 120) {
3151b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Timeout on sending GO Negotiation Request without getting response");
31528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
31538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 0;
31548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_CONNECT);
31578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, p2p->go_neg_peer);
31588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
31598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (p2p->state == P2P_SEARCH) {
3160c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (p2p->p2p_scan_running) {
3161c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 /*
3162c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * Search is already in progress. This can happen if
3163c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * an Action frame RX is reported immediately after
3164c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * the end of a remain-on-channel operation and the
3165c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * response frame to that is sent using an offchannel
3166c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * operation while in p2p_find. Avoid an attempt to
3167c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * restart a scan here.
3168c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  */
3169b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "p2p_scan already in progress - do not try to start a new one");
3170c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			return 1;
3171c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		}
317204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (p2p->pending_listen_freq) {
317304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			/*
317404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 * Better wait a bit if the driver is unable to start
317504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 * offchannel operation for some reason. p2p_search()
317604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 * will be started from internal timeout.
317704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 */
3178b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Listen operation did not seem to start - delay search phase to avoid busy loop");
317904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			p2p_set_timeout(p2p, 0, 100000);
318004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			return 1;
318104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
318261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->search_delay) {
3183b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Delay search operation by %u ms",
318461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				p2p->search_delay);
318561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p_set_timeout(p2p, p2p->search_delay / 1000,
318661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					(p2p->search_delay % 1000) * 1000);
318761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return 1;
318861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
31898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_search(p2p);
31908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
31918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
31948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_connect(struct p2p_data *p2p)
31988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
320004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p->go_neg_peer &&
320104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    (p2p->go_neg_peer->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM)) {
3202b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Wait for GO Negotiation Confirm timed out - assume GO Negotiation failed");
320304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
320404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return;
320504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
32068c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	if (p2p->go_neg_peer &&
32078c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	    (p2p->go_neg_peer->flags & P2P_DEV_PEER_WAITING_RESPONSE) &&
32088c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	    p2p->go_neg_peer->connect_reqs < 120) {
3209b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Peer expected to wait our response - skip listen");
32108c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		p2p_connect_send(p2p, p2p->go_neg_peer);
32118c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		return;
32128c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	}
32138c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt
32148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_CONNECT_LISTEN);
3215d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p_listen_in_find(p2p, 0);
32168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_connect_listen(struct p2p_data *p2p)
32208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
32218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer) {
32228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->drv_in_listen) {
3223b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Driver is still in Listen state; wait for it to complete");
32248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
32258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
32268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->go_neg_peer->connect_reqs >= 120) {
3228b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Timeout on sending GO Negotiation Request without getting response");
32298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
32308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
32318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
32328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_CONNECT);
32348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, p2p->go_neg_peer);
32358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
32368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
32378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_wait_peer_connect(struct p2p_data *p2p)
32418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
32428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
32438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * TODO: could remain constantly in Listen state for some time if there
32448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * are no other concurrent uses for the radio. For now, go to listen
32458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * state once per second to give other uses a chance to use the radio.
32468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
32478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_WAIT_PEER_IDLE);
32481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_set_timeout(p2p, 0, 500000);
32498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_wait_peer_idle(struct p2p_data *p2p)
32538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
32548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p->go_neg_peer;
32558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
3257b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Unknown GO Neg peer - stop GO Neg wait");
32588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
32598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wait_count++;
32628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->wait_count >= 120) {
3263b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Timeout on waiting peer to become ready for GO Negotiation");
32648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_failed(p2p, dev, -1);
32658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
32668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3268b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Go to Listen state while waiting for the peer to become ready for GO Negotiation");
32698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_WAIT_PEER_CONNECT);
3270d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p_listen_in_find(p2p, 0);
32718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_sd_during_find(struct p2p_data *p2p)
32758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3276b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Service Discovery Query timeout");
32778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->sd_peer) {
32788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
32798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE;
32808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->sd_peer = NULL;
32818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_continue_find(p2p);
32838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_prov_disc_during_find(struct p2p_data *p2p)
32878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3288b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Provision Discovery Request timeout");
32898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
32908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_continue_find(p2p);
32918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
329475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic void p2p_timeout_prov_disc_req(struct p2p_data *p2p)
329575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
329675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
329775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
329875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
329975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * For user initiated PD requests that we have not gotten any responses
330075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * for while in IDLE state, we retry them a couple of times before
330175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * giving up.
330275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
330375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (!p2p->user_initiated_pd)
330475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
330575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
3306b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "User initiated Provision Discovery Request timeout");
330775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
330875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p->pd_retries) {
330975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pd_retries--;
331075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p_retry_pd(p2p);
331175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	} else {
3312d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		struct p2p_device *dev;
3313d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		int for_join = 0;
3314d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
3315d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
3316d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			if (os_memcmp(p2p->pending_pd_devaddr,
3317d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				      dev->info.p2p_device_addr, ETH_ALEN) != 0)
3318d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				continue;
3319d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			if (dev->req_config_methods &&
3320d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			    (dev->flags & P2P_DEV_PD_FOR_JOIN))
3321d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				for_join = 1;
3322d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		}
3323d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
332475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->cfg->prov_disc_fail)
332575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx,
332675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen						 p2p->pending_pd_devaddr,
3327d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt						 for_join ?
3328d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt						 P2P_PROV_DISC_TIMEOUT_JOIN :
332975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen						 P2P_PROV_DISC_TIMEOUT);
333075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p_reset_pending_pd(p2p);
333175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	}
333275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
333375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
333475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
33358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_invite(struct p2p_data *p2p)
33368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
33388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_INVITE_LISTEN);
33398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->inv_role == P2P_INVITE_ROLE_ACTIVE_GO) {
33408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
33418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Better remain on operating channel instead of listen channel
33428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * when running a group.
33438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
3344b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Inviting in active GO role - wait on operating channel");
33458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_timeout(p2p, 0, 100000);
33468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
33478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3348d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p_listen_in_find(p2p, 0);
33498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_invite_listen(struct p2p_data *p2p)
33538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->invite_peer && p2p->invite_peer->invitation_reqs < 100) {
33558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_INVITE);
33568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_invite_send(p2p, p2p->invite_peer,
33578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p->invite_go_dev_addr);
33588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
33598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->invite_peer) {
3360b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Invitation Request retry limit reached");
33618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (p2p->cfg->invitation_result)
33628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p->cfg->invitation_result(
3363700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt					p2p->cfg->cb_ctx, -1, NULL, NULL,
3364700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt					p2p->invite_peer->info.p2p_device_addr);
33658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
33668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
33678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_state_timeout(void *eloop_ctx, void *timeout_ctx)
33728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
33748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3375b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Timeout (state=%s)", p2p_state_txt(p2p->state));
33768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->in_listen = 0;
33788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (p2p->state) {
33808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_IDLE:
338175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/* Check if we timed out waiting for PD req */
338275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->pending_action_state == P2P_PENDING_PD)
338375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_timeout_prov_disc_req(p2p);
33848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
33858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SEARCH:
338675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/* Check if we timed out waiting for PD req */
338775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->pending_action_state == P2P_PENDING_PD)
338875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_timeout_prov_disc_req(p2p);
338961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->search_delay && !p2p->in_search_delay) {
3390b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Delay search operation by %u ms",
339161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				p2p->search_delay);
339261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p->in_search_delay = 1;
339361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p_set_timeout(p2p, p2p->search_delay / 1000,
339461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					(p2p->search_delay % 1000) * 1000);
339561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			break;
339661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
339761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->in_search_delay = 0;
33988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_search(p2p);
33998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT:
34018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_connect(p2p);
34028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT_LISTEN:
34048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_connect_listen(p2p);
34058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG:
34078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_LISTEN_ONLY:
340975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/* Check if we timed out waiting for PD req */
341075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->pending_action_state == P2P_PENDING_PD)
341175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_timeout_prov_disc_req(p2p);
341275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
34138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->ext_listen_only) {
3414b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Extended Listen Timing - Listen State completed");
34158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->ext_listen_only = 0;
34168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_set_state(p2p, P2P_IDLE);
34178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
34188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_CONNECT:
34208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_wait_peer_connect(p2p);
34218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_IDLE:
34238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_wait_peer_idle(p2p);
34248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SD_DURING_FIND:
34268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_sd_during_find(p2p);
34278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROVISIONING:
34298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PD_DURING_FIND:
34318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_prov_disc_during_find(p2p);
34328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE:
34348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_invite(p2p);
34358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE_LISTEN:
34378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_invite_listen(p2p);
34388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case P2P_SEARCH_WHEN_READY:
34401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
344161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	case P2P_CONTINUE_SEARCH_WHEN_READY:
344261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		break;
34438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_reject(struct p2p_data *p2p, const u8 *peer_addr)
34488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
34508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
3452b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Local request to reject connection attempts by peer "
3453b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		MACSTR, MAC2STR(peer_addr));
34548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
3455b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Peer " MACSTR " unknown", MAC2STR(peer_addr));
34568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
34578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->status = P2P_SC_FAIL_REJECTED_BY_USER;
34598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_USER_REJECTED;
34608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
34618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtconst char * p2p_wps_method_text(enum p2p_wps_method method)
34658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (method) {
34678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_NOT_READY:
34688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "not-ready";
34698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_PIN_DISPLAY:
34708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "Display";
34718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_PIN_KEYPAD:
34728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "Keypad";
34738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_PBC:
34748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "PBC";
34758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return "??";
34788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * p2p_go_state_text(enum p2p_go_state go_state)
34828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (go_state) {
34848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case UNKNOWN_GO:
34858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "unknown";
34868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case LOCAL_GO:
34878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "local";
34888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case  REMOTE_GO:
34898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "remote";
34908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return "??";
34938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtconst struct p2p_peer_info * p2p_get_peer_info(struct p2p_data *p2p,
34971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					       const u8 *addr, int next)
34988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
35008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr)
35028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, addr);
35038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
35048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = dl_list_first(&p2p->devices, struct p2p_device, list);
35058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev && next) {
35078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = dl_list_first(&dev->list, struct p2p_device, list);
35088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (&dev->list == &p2p->devices)
35098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev = NULL;
35108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
35118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
35131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return NULL;
35141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
35151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return &dev->info;
35161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
35171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
35181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
35191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_get_peer_info_txt(const struct p2p_peer_info *info,
35201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			  char *buf, size_t buflen)
35211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
35221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_device *dev;
35231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int res;
35241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	char *pos, *end;
35251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct os_time now;
35261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
35271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (info == NULL)
35288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
35298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	dev = (struct p2p_device *) (((u8 *) info) -
35311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				     offsetof(struct p2p_device, info));
35321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
35338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf;
35348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = buf + buflen;
35358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&now);
35378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = os_snprintf(pos, end - pos,
35388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "age=%d\n"
35398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "listen_freq=%d\n"
35408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "wps_method=%s\n"
35418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "interface_addr=" MACSTR "\n"
35428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "member_in_go_dev=" MACSTR "\n"
35438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "member_in_go_iface=" MACSTR "\n"
35448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "go_neg_req_sent=%d\n"
35458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "go_state=%s\n"
35468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dialog_token=%u\n"
35478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "intended_addr=" MACSTR "\n"
35488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "country=%c%c\n"
35498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "oper_freq=%d\n"
35508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "req_config_methods=0x%x\n"
35518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "flags=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n"
35528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "status=%d\n"
35538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "wait_count=%u\n"
35548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "invitation_reqs=%u\n",
35558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  (int) (now.sec - dev->last_seen.sec),
35568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->listen_freq,
35578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  p2p_wps_method_text(dev->wps_method),
35588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->interface_addr),
35598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->member_in_go_dev),
35608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->member_in_go_iface),
35618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->go_neg_req_sent,
35628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  p2p_go_state_text(dev->go_state),
35638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->dialog_token,
35648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->intended_addr),
35658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->country[0] ? dev->country[0] : '_',
35668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->country[1] ? dev->country[1] : '_',
35678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->oper_freq,
35688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->req_config_methods,
35698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PROBE_REQ_ONLY ?
35708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PROBE_REQ_ONLY]" : "",
35718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_REPORTED ? "[REPORTED]" : "",
35728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_NOT_YET_READY ?
35738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[NOT_YET_READY]" : "",
35748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_SD_INFO ? "[SD_INFO]" : "",
35758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_SD_SCHEDULE ? "[SD_SCHEDULE]" :
35768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "",
35778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PD_PEER_DISPLAY ?
35788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PD_PEER_DISPLAY]" : "",
35798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PD_PEER_KEYPAD ?
35808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PD_PEER_KEYPAD]" : "",
35818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_USER_REJECTED ?
35828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[USER_REJECTED]" : "",
35838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PEER_WAITING_RESPONSE ?
35848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PEER_WAITING_RESPONSE]" : "",
35858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PREFER_PERSISTENT_GROUP ?
35868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PREFER_PERSISTENT_GROUP]" : "",
35878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_WAIT_GO_NEG_RESPONSE ?
35888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[WAIT_GO_NEG_RESPONSE]" : "",
35898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM ?
35908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[WAIT_GO_NEG_CONFIRM]" : "",
35918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_GROUP_CLIENT_ONLY ?
35928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[GROUP_CLIENT_ONLY]" : "",
35938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_FORCE_FREQ ?
35948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[FORCE_FREQ]" : "",
35958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PD_FOR_JOIN ?
35968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PD_FOR_JOIN]" : "",
35978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->status,
35988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->wait_count,
35998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->invitation_reqs);
36008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0 || res >= end - pos)
36018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return pos - buf;
36028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += res;
36038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->ext_listen_period) {
36058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = os_snprintf(pos, end - pos,
36068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "ext_listen_period=%u\n"
36078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "ext_listen_interval=%u\n",
36088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  dev->ext_listen_period,
36098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  dev->ext_listen_interval);
36108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res < 0 || res >= end - pos)
36118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos - buf;
36128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += res;
36138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
36148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->oper_ssid_len) {
36168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = os_snprintf(pos, end - pos,
36178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "oper_ssid=%s\n",
36188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  wpa_ssid_txt(dev->oper_ssid,
36198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       dev->oper_ssid_len));
36208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res < 0 || res >= end - pos)
36218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos - buf;
36228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += res;
36238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
36248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
362561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
362661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (dev->info.wfd_subelems) {
362761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		res = os_snprintf(pos, end - pos, "wfd_subelems=");
362861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (res < 0 || res >= end - pos)
362961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return pos - buf;
363061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += res;
363161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
363261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += wpa_snprintf_hex(pos, end - pos,
363361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					wpabuf_head(dev->info.wfd_subelems),
363461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					wpabuf_len(dev->info.wfd_subelems));
363561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
363661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		res = os_snprintf(pos, end - pos, "\n");
363761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (res < 0 || res >= end - pos)
363861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return pos - buf;
363961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += res;
364061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
364161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
364261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
36438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return pos - buf;
36448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
36458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_peer_known(struct p2p_data *p2p, const u8 *addr)
36481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
36491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return p2p_get_device(p2p, addr) != NULL;
36501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
36511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
36521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
36538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_client_discoverability(struct p2p_data *p2p, int enabled)
36548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
36558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (enabled) {
3656b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Client discoverability enabled");
36578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
36588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
3659b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Client discoverability disabled");
36608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab &= ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
36618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
36628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
36638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_presence_req(u32 duration1, u32 interval1,
36668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      u32 duration2, u32 interval2)
36678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
36688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
36698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_noa_desc desc1, desc2, *ptr1 = NULL, *ptr2 = NULL;
36708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
36718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req = wpabuf_alloc(100);
36738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL)
36748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
36758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (duration1 || interval1) {
36778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(&desc1, 0, sizeof(desc1));
36788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc1.count_type = 1;
36798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc1.duration = duration1;
36808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc1.interval = interval1;
36818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ptr1 = &desc1;
36828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (duration2 || interval2) {
36848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(&desc2, 0, sizeof(desc2));
36858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc2.count_type = 2;
36868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc2.duration = duration2;
36878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc2.interval = interval2;
36888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ptr2 = &desc2;
36898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
36908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
36918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_action_hdr(req, P2P_PRESENCE_REQ, 1);
36938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(req);
36948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_noa(req, 0, 0, 0, ptr1, ptr2);
36958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(req, len);
36968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return req;
36988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
36998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_presence_req(struct p2p_data *p2p, const u8 *go_interface_addr,
37028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     const u8 *own_interface_addr, unsigned int freq,
37038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     u32 duration1, u32 interval1, u32 duration2,
37048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     u32 interval2)
37058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
37068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
37078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3708b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Send Presence Request to GO " MACSTR
3709b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		" (own interface " MACSTR ") freq=%u dur1=%u int1=%u "
3710b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		"dur2=%u int2=%u",
37118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(go_interface_addr), MAC2STR(own_interface_addr),
37128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		freq, duration1, interval1, duration2, interval2);
37138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req = p2p_build_presence_req(duration1, interval1, duration2,
37158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     interval2);
37168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL)
37178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
37188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
37208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_send_action(p2p, freq, go_interface_addr, own_interface_addr,
37218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    go_interface_addr,
37228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpabuf_head(req), wpabuf_len(req), 200) < 0) {
3723b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to send Action frame");
37248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(req);
37268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
37288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
37298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_presence_resp(u8 status, const u8 *noa,
37328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       size_t noa_len, u8 dialog_token)
37338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
37348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
37358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
37368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = wpabuf_alloc(100 + noa_len);
37388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
37398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
37408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_action_hdr(resp, P2P_PRESENCE_RESP, dialog_token);
37428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(resp);
37438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_status(resp, status);
37448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (noa) {
37458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(resp, P2P_ATTR_NOTICE_OF_ABSENCE);
37468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_le16(resp, noa_len);
37478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_data(resp, noa, noa_len);
37488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
37498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_noa(resp, 0, 0, 0, NULL, NULL);
37508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(resp, len);
37518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return resp;
37538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
37548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_req(struct p2p_data *p2p, const u8 *da,
37578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const u8 *sa, const u8 *data, size_t len,
37588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     int rx_freq)
37598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
37608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
37618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 status;
37628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
37638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t g;
37648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group *group = NULL;
37658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int parsed = 0;
37668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 noa[50];
37678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int noa_len;
37688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3769b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Received P2P Action - P2P Presence Request");
37708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (g = 0; g < p2p->num_groups; g++) {
37728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(da, p2p_group_get_interface_addr(p2p->groups[g]),
37738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      ETH_ALEN) == 0) {
37748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group = p2p->groups[g];
37758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
37768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
37778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group == NULL) {
3779b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Ignore P2P Presence Request for unknown group "
37808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MACSTR, MAC2STR(da));
37818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
37828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse(data, len, &msg) < 0) {
3785b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to parse P2P Presence Request");
37868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		status = P2P_SC_FAIL_INVALID_PARAMS;
37878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
37888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	parsed = 1;
37908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.noa == NULL) {
3792b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "No NoA attribute in P2P Presence Request");
37938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		status = P2P_SC_FAIL_INVALID_PARAMS;
37948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
37958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	status = p2p_group_presence_req(group, sa, msg.noa, msg.noa_len);
37988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail:
38008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->get_noa)
38018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		noa_len = p2p->cfg->get_noa(p2p->cfg->cb_ctx, da, noa,
38028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    sizeof(noa));
38038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
38048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		noa_len = -1;
38058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = p2p_build_presence_resp(status, noa_len > 0 ? noa : NULL,
38068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       noa_len > 0 ? noa_len : 0,
38078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       msg.dialog_token);
38088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (parsed)
38098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
38108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
38118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
38128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
38148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_send_action(p2p, rx_freq, sa, da, da,
38158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
3816b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to send Action frame");
38178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(resp);
38198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
38208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_resp(struct p2p_data *p2p, const u8 *da,
38238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *sa, const u8 *data, size_t len)
38248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
38258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
38268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3827b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Received P2P Action - P2P Presence Response");
38288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse(data, len, &msg) < 0) {
3830b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to parse P2P Presence Response");
38318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
38328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.status == NULL || msg.noa == NULL) {
3835b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "No Status or NoA attribute in P2P Presence Response");
38368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
38378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
38388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*msg.status) {
3841b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "P2P Presence Request was rejected: status %u",
38428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*msg.status);
38438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
38448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
38458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3847b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "P2P Presence Request was accepted");
38488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "P2P: P2P Presence Response - NoA",
38498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    msg.noa, msg.noa_len);
38508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: process NoA */
38518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
38528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
38538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_ext_listen_timeout(void *eloop_ctx, void *timeout_ctx)
38568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
38578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
38588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval) {
38608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Schedule next extended listen timeout */
38618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(p2p->ext_listen_interval_sec,
38628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p->ext_listen_interval_usec,
38638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p_ext_listen_timeout, p2p, NULL);
38648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_LISTEN_ONLY && p2p->ext_listen_only) {
38678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
38688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * This should not really happen, but it looks like the Listen
38698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * command may fail is something else (e.g., a scan) was
38708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * running at an inconvenient time. As a workaround, allow new
38718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Extended Listen operation to be started.
38728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
3873b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Previous Extended Listen operation had not been completed - try again");
38748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_only = 0;
38758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
38768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state != P2P_IDLE) {
3879b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Skip Extended Listen timeout in active state (%s)", p2p_state_txt(p2p->state));
38808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
38818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3883b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Extended Listen timeout");
38848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_only = 1;
38858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_listen(p2p, p2p->ext_listen_period) < 0) {
3886b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to start Listen state for Extended Listen Timing");
38878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_only = 0;
38888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
38908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_ext_listen(struct p2p_data *p2p, unsigned int period,
38938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   unsigned int interval)
38948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
38958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (period > 65535 || interval > 65535 || period > interval ||
38968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (period == 0 && interval > 0) || (period > 0 && interval == 0)) {
3897b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Invalid Extended Listen Timing request: period=%u interval=%u",
3898b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			period, interval);
38998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
39008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_ext_listen_timeout, p2p, NULL);
39038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (interval == 0) {
3905b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Disabling Extended Listen Timing");
39068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_period = 0;
39078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_interval = 0;
39088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
39098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3911b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Enabling Extended Listen Timing: period %u msec, interval %u msec",
3912b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		period, interval);
39138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_period = period;
39148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_interval = interval;
39158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_interval_sec = interval / 1000;
39168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_interval_usec = (interval % 1000) * 1000;
39178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(p2p->ext_listen_interval_sec,
39198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p->ext_listen_interval_usec,
39208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p_ext_listen_timeout, p2p, NULL);
39218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
39238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_deauth_notif(struct p2p_data *p2p, const u8 *bssid, u16 reason_code,
39278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      const u8 *ie, size_t ie_len)
39288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
39298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
39308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bssid == NULL || ie == NULL)
39328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
39338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
39358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg))
39368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
39378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.minor_reason_code == NULL)
39388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
39398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3940b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Deauthentication notification BSSID " MACSTR
39418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" reason_code=%u minor_reason_code=%u",
39428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(bssid), reason_code, *msg.minor_reason_code);
39438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
39458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_disassoc_notif(struct p2p_data *p2p, const u8 *bssid, u16 reason_code,
39498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const u8 *ie, size_t ie_len)
39508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
39518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
39528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bssid == NULL || ie == NULL)
39548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
39558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
39578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg))
39588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
39598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.minor_reason_code == NULL)
39608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
39618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3962b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Disassociation notification BSSID " MACSTR
39638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" reason_code=%u minor_reason_code=%u",
39648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(bssid), reason_code, *msg.minor_reason_code);
39658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
39678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_managed_oper(struct p2p_data *p2p, int enabled)
39718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
39728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (enabled) {
3973b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Managed P2P Device operations enabled");
39748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_INFRA_MANAGED;
39758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
3976b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Managed P2P Device operations disabled");
39778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab &= ~P2P_DEV_CAPAB_INFRA_MANAGED;
39788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel)
39838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
39844b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	if (p2p_channel_to_freq(reg_class, channel) < 0)
39858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
39868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3987b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Set Listen channel: reg_class %u channel %u",
3988b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		reg_class, channel);
39898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->reg_class = reg_class;
39908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->channel = channel;
39918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
39938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_ssid_postfix(struct p2p_data *p2p, const u8 *postfix, size_t len)
39978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3998b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "New SSID postfix: %s", wpa_ssid_txt(postfix, len));
39998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (postfix == NULL) {
40008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->ssid_postfix_len = 0;
40018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
40028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
40038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > sizeof(p2p->cfg->ssid_postfix))
40048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
40058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->ssid_postfix, postfix, len);
40068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->ssid_postfix_len = len;
40078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
40088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
40098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
401175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenint p2p_set_oper_channel(struct p2p_data *p2p, u8 op_reg_class, u8 op_channel,
401275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			 int cfg_op_channel)
401375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
40144b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	if (p2p_channel_to_freq(op_reg_class, op_channel) < 0)
401575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return -1;
401675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
4017b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Set Operating channel: reg_class %u channel %u",
4018b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		op_reg_class, op_channel);
401975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->cfg->op_reg_class = op_reg_class;
402075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->cfg->op_channel = op_channel;
402175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->cfg->cfg_op_channel = cfg_op_channel;
402275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	return 0;
402375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
402475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
402575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
402604949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint p2p_set_pref_chan(struct p2p_data *p2p, unsigned int num_pref_chan,
402704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		      const struct p2p_channel *pref_chan)
402804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
402904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct p2p_channel *n;
403004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
403104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (pref_chan) {
403204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		n = os_malloc(num_pref_chan * sizeof(struct p2p_channel));
403304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (n == NULL)
403404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			return -1;
403504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(n, pref_chan,
403604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			  num_pref_chan * sizeof(struct p2p_channel));
403704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	} else
403804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		n = NULL;
403904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
404004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	os_free(p2p->cfg->pref_chan);
404104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p->cfg->pref_chan = n;
404204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p->cfg->num_pref_chan = num_pref_chan;
404304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
404404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return 0;
404504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
404604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
404704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
40488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_interface_addr(struct p2p_data *p2p, const u8 *dev_addr,
40498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   u8 *iface_addr)
40508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
40518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p_get_device(p2p, dev_addr);
40528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL || is_zero_ether_addr(dev->interface_addr))
40538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
40548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(iface_addr, dev->interface_addr, ETH_ALEN);
40558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
40568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
40578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_dev_addr(struct p2p_data *p2p, const u8 *iface_addr,
40608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   u8 *dev_addr)
40618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
40628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p_get_device_interface(p2p, iface_addr);
40638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
40648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
40658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev_addr, dev->info.p2p_device_addr, ETH_ALEN);
40668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
40678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
40688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_peer_filter(struct p2p_data *p2p, const u8 *addr)
40718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
40728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->peer_filter, addr, ETH_ALEN);
40738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (is_zero_ether_addr(p2p->peer_filter))
4074b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Disable peer filter");
40758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
4076b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Enable peer filter for " MACSTR,
4077b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			MAC2STR(p2p->peer_filter));
40788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
40798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_cross_connect(struct p2p_data *p2p, int enabled)
40828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4083b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Cross connection %s", enabled ? "enabled" : "disabled");
40848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cross_connect == enabled)
40858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
40868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cross_connect = enabled;
40878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: may need to tear down any action group where we are GO(?) */
40888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
40898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_oper_freq(struct p2p_data *p2p, const u8 *iface_addr)
40928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
40938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p_get_device_interface(p2p, iface_addr);
40948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
40958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
40968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->oper_freq <= 0)
40978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
40988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return dev->oper_freq;
40998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_intra_bss_dist(struct p2p_data *p2p, int enabled)
41038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4104b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Intra BSS distribution %s",
41058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		enabled ? "enabled" : "disabled");
41068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->p2p_intra_bss = enabled;
41078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_update_channel_list(struct p2p_data *p2p, struct p2p_channels *chan)
41118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4112b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Update channel list");
41138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&p2p->cfg->channels, chan, sizeof(struct p2p_channels));
41148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_send_action(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
41188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    const u8 *src, const u8 *bssid, const u8 *buf,
41198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    size_t len, unsigned int wait_time)
41208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
41218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
4122b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Delay Action frame TX until p2p_scan completes");
41238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->after_scan_tx) {
4124b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Dropped previous pending Action frame TX");
41258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(p2p->after_scan_tx);
41268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
41278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = os_malloc(sizeof(*p2p->after_scan_tx) +
41288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       len);
41298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->after_scan_tx == NULL)
41308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
41318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx->freq = freq;
41328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx->dst, dst, ETH_ALEN);
41338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx->src, src, ETH_ALEN);
41348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx->bssid, bssid, ETH_ALEN);
41358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx->len = len;
41368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx->wait_time = wait_time;
41378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx + 1, buf, len);
41388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
41398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
41408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, dst, src, bssid,
41428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     buf, len, wait_time);
41438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_best_channels(struct p2p_data *p2p, int freq_24, int freq_5,
41478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   int freq_overall)
41488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4149b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Best channel: 2.4 GHz: %d,  5 GHz: %d,  overall: %d",
4150b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		freq_24, freq_5, freq_overall);
41518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->best_freq_24 = freq_24;
41528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->best_freq_5 = freq_5;
41538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->best_freq_overall = freq_overall;
41548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4157700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidtvoid p2p_set_own_freq_preference(struct p2p_data *p2p, int freq)
4158700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt{
4159b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Own frequency preference: %d MHz", freq);
4160700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	p2p->own_freq_preference = freq;
4161700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt}
4162700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt
4163700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt
41648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * p2p_get_go_neg_peer(struct p2p_data *p2p)
41658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
41668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p == NULL || p2p->go_neg_peer == NULL)
41678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
41688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p->go_neg_peer->info.p2p_device_addr;
41698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst struct p2p_peer_info *
41738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtp2p_get_peer_found(struct p2p_data *p2p, const u8 *addr, int next)
41748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
41758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
41768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr) {
41788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, addr);
41798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!dev)
41808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
41818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!next) {
41838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev->flags & P2P_DEV_PROBE_REQ_ONLY)
41848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return NULL;
41858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return &dev->info;
41878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
41888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			do {
41898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev = dl_list_first(&dev->list,
41908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    struct p2p_device,
41918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    list);
41928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				if (&dev->list == &p2p->devices)
41938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					return NULL;
41948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} while (dev->flags & P2P_DEV_PROBE_REQ_ONLY);
41958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
41968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
41978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = dl_list_first(&p2p->devices, struct p2p_device, list);
41988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!dev)
41998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
42008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (dev->flags & P2P_DEV_PROBE_REQ_ONLY) {
42018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev = dl_list_first(&dev->list,
42028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    struct p2p_device,
42038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    list);
42048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (&dev->list == &p2p->devices)
42058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return NULL;
42068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
42078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
42088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return &dev->info;
42108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
42111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
42121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef ANDROID_P2P
42131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_search_in_progress(struct p2p_data *p2p)
42141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
42151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p == NULL)
42161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
42171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
42181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return p2p->state == P2P_SEARCH;
42191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
42201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif
42211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
42221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_in_progress(struct p2p_data *p2p)
42231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
42241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p == NULL)
42251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
422661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->state == P2P_SEARCH || p2p->state == P2P_SEARCH_WHEN_READY ||
422761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	    p2p->state == P2P_CONTINUE_SEARCH_WHEN_READY)
422861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return 2;
42291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return p2p->state != P2P_IDLE && p2p->state != P2P_PROVISIONING;
42301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
423161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
423261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
423361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid p2p_set_config_timeout(struct p2p_data *p2p, u8 go_timeout,
423461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			    u8 client_timeout)
423561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
423661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p) {
423761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->go_timeout = go_timeout;
423861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->client_timeout = client_timeout;
423961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
424061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
424161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
424261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
424361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid p2p_increase_search_delay(struct p2p_data *p2p, unsigned int delay)
424461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
424561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p && p2p->search_delay < delay)
424661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->search_delay = delay;
424761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
424861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
424961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
425061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
425161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
425261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void p2p_update_wfd_ie_groups(struct p2p_data *p2p)
425361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
425461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t g;
425561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct p2p_group *group;
425661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
425761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	for (g = 0; g < p2p->num_groups; g++) {
425861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		group = p2p->groups[g];
425961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_group_update_ies(group);
426061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
426161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
426261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
426361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
426461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_beacon(struct p2p_data *p2p, struct wpabuf *ie)
426561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
426661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_beacon);
426761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_beacon = ie;
426861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_update_wfd_ie_groups(p2p);
426961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
427061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
427161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
427261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
427361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_probe_req(struct p2p_data *p2p, struct wpabuf *ie)
427461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
427561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_probe_req);
427661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_probe_req = ie;
427761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
427861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
427961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
428061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
428161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_probe_resp(struct p2p_data *p2p, struct wpabuf *ie)
428261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
428361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_probe_resp);
428461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_probe_resp = ie;
428561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_update_wfd_ie_groups(p2p);
428661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
428761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
428861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
428961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
429061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_assoc_req(struct p2p_data *p2p, struct wpabuf *ie)
429161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
429261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_assoc_req);
429361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_assoc_req = ie;
429461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
429561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
429661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
429761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
429861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_invitation(struct p2p_data *p2p, struct wpabuf *ie)
429961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
430061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_invitation);
430161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_invitation = ie;
430261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
430361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
430461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
430561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
430661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_prov_disc_req(struct p2p_data *p2p, struct wpabuf *ie)
430761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
430861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_prov_disc_req);
430961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_prov_disc_req = ie;
431061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
431161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
431261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
431361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
431461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_prov_disc_resp(struct p2p_data *p2p, struct wpabuf *ie)
431561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
431661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_prov_disc_resp);
431761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_prov_disc_resp = ie;
431861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
431961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
432061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
432161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
432261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_go_neg(struct p2p_data *p2p, struct wpabuf *ie)
432361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
432461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_go_neg);
432561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_go_neg = ie;
432661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
432761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
432861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
432961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
433061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_dev_info(struct p2p_data *p2p, const struct wpabuf *elem)
433161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
433261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_dev_info);
433361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (elem) {
433461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_dev_info = wpabuf_dup(elem);
433561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->wfd_dev_info == NULL)
433661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
433761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else
433861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_dev_info = NULL;
433961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
434061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
434161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
434261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
434361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
434461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_assoc_bssid(struct p2p_data *p2p, const struct wpabuf *elem)
434561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
434661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_assoc_bssid);
434761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (elem) {
434861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_assoc_bssid = wpabuf_dup(elem);
434961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->wfd_assoc_bssid == NULL)
435061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
435161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else
435261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_assoc_bssid = NULL;
435361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
435461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
435561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
435661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
435761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
435861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_coupled_sink_info(struct p2p_data *p2p,
435961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				  const struct wpabuf *elem)
436061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
436161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_coupled_sink_info);
436261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (elem) {
436361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_coupled_sink_info = wpabuf_dup(elem);
436461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->wfd_coupled_sink_info == NULL)
436561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
436661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else
436761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_coupled_sink_info = NULL;
436861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
436961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
437061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
437161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
437261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
4373d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
4374d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
4375d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtint p2p_set_disc_int(struct p2p_data *p2p, int min_disc_int, int max_disc_int,
4376d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		     int max_disc_tu)
4377d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt{
4378d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (min_disc_int > max_disc_int || min_disc_int < 0 || max_disc_int < 0)
4379d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return -1;
4380d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
4381d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p->min_disc_int = min_disc_int;
4382d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p->max_disc_int = max_disc_int;
4383d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p->max_disc_tu = max_disc_tu;
4384b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Set discoverable interval: min=%d max=%d max_tu=%d",
4385b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		min_disc_int, max_disc_int, max_disc_tu);
4386d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
4387d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	return 0;
4388d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt}
4389b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
4390b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
4391b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidtvoid p2p_dbg(struct p2p_data *p2p, const char *fmt, ...)
4392b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt{
4393b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_list ap;
4394b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	char buf[500];
4395b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
4396b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	if (!p2p->cfg->debug_print)
4397b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		return;
4398b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
4399b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_start(ap, fmt);
4400b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	vsnprintf(buf, sizeof(buf), fmt, ap);
4401b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	buf[sizeof(buf) - 1] = '\0';
4402b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_end(ap);
4403b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p->cfg->debug_print(p2p->cfg->cb_ctx, MSG_DEBUG, buf);
4404b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt}
4405b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
4406b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
4407b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidtvoid p2p_info(struct p2p_data *p2p, const char *fmt, ...)
4408b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt{
4409b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_list ap;
4410b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	char buf[500];
4411b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
4412b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	if (!p2p->cfg->debug_print)
4413b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		return;
4414b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
4415b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_start(ap, fmt);
4416b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	vsnprintf(buf, sizeof(buf), fmt, ap);
4417b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	buf[sizeof(buf) - 1] = '\0';
4418b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_end(ap);
4419b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p->cfg->debug_print(p2p->cfg->cb_ctx, MSG_INFO, buf);
4420b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt}
4421b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
4422b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
4423b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidtvoid p2p_err(struct p2p_data *p2p, const char *fmt, ...)
4424b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt{
4425b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_list ap;
4426b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	char buf[500];
4427b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
4428b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	if (!p2p->cfg->debug_print)
4429b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		return;
4430b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
4431b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_start(ap, fmt);
4432b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	vsnprintf(buf, sizeof(buf), fmt, ap);
4433b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	buf[sizeof(buf) - 1] = '\0';
4434b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_end(ap);
4435b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p->cfg->debug_print(p2p->cfg->cb_ctx, MSG_ERROR, buf);
4436b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt}
4437