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"
152e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt#include "common/wpa_ctrl.h"
16216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt#include "crypto/sha256.h"
17216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt#include "crypto/crypto.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps/wps_i.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p_i.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_state_timeout(void *eloop_ctx, void *timeout_ctx);
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev);
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_req(struct p2p_data *p2p, const u8 *da,
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const u8 *sa, const u8 *data, size_t len,
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     int rx_freq);
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_resp(struct p2p_data *p2p, const u8 *da,
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *sa, const u8 *data,
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      size_t len);
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_ext_listen_timeout(void *eloop_ctx, void *timeout_ctx);
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_scan_timeout(void *eloop_ctx, void *timeout_ctx);
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_scan recovery timeout
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Many drivers are using 30 second timeout on scan results. Allow a bit larger
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * timeout for this to avoid hitting P2P timeout unnecessarily.
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define P2P_SCAN_TIMEOUT 35
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * P2P_PEER_EXPIRATION_AGE - Number of seconds after which inactive peer
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * entries will be removed
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
472093d0658d2f0f8b5a98df7accc97fff3b2bb7d5Dmitry Shmidt#ifndef P2P_PEER_EXPIRATION_AGE
482093d0658d2f0f8b5a98df7accc97fff3b2bb7d5Dmitry Shmidt#define P2P_PEER_EXPIRATION_AGE 60
491846323989242844f0e857458a8939fa5836429cDmitry Shmidt#endif /* P2P_PEER_EXPIRATION_AGE */
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define P2P_PEER_EXPIRATION_INTERVAL (P2P_PEER_EXPIRATION_AGE / 2)
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_expire_peers(struct p2p_data *p2p)
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev, *n;
56fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	struct os_reltime now;
57c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	size_t i;
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
59fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	os_get_reltime(&now);
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each_safe(dev, n, &p2p->devices, struct p2p_device, list) {
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->last_seen.sec + P2P_PEER_EXPIRATION_AGE >= now.sec)
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
63c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
649e3f8ee32a0c11c56b11985805b5492d04886a99Dmitry Shmidt		if (dev == p2p->go_neg_peer) {
659e3f8ee32a0c11c56b11985805b5492d04886a99Dmitry Shmidt			/*
669e3f8ee32a0c11c56b11985805b5492d04886a99Dmitry Shmidt			 * GO Negotiation is in progress with the peer, so
679e3f8ee32a0c11c56b11985805b5492d04886a99Dmitry Shmidt			 * don't expire the peer entry until GO Negotiation
689e3f8ee32a0c11c56b11985805b5492d04886a99Dmitry Shmidt			 * fails or times out.
699e3f8ee32a0c11c56b11985805b5492d04886a99Dmitry Shmidt			 */
709e3f8ee32a0c11c56b11985805b5492d04886a99Dmitry Shmidt			continue;
719e3f8ee32a0c11c56b11985805b5492d04886a99Dmitry Shmidt		}
729e3f8ee32a0c11c56b11985805b5492d04886a99Dmitry Shmidt
73c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (p2p->cfg->go_connected &&
74c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		    p2p->cfg->go_connected(p2p->cfg->cb_ctx,
75c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt					   dev->info.p2p_device_addr)) {
76c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			/*
77c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 * We are connected as a client to a group in which the
78c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 * peer is the GO, so do not expire the peer entry.
79c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 */
80fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			os_get_reltime(&dev->last_seen);
81c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			continue;
82c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		}
83c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
84c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		for (i = 0; i < p2p->num_groups; i++) {
85c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			if (p2p_group_is_client_connected(
86c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				    p2p->groups[i], dev->info.p2p_device_addr))
87c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				break;
88c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		}
89c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (i < p2p->num_groups) {
90c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			/*
91c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 * The peer is connected as a client in a group where
92c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 * we are the GO, so do not expire the peer entry.
93c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 */
94fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			os_get_reltime(&dev->last_seen);
95c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			continue;
96c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		}
97c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
98b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Expiring old peer entry " MACSTR,
99b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr));
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dl_list_del(&dev->list);
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_device_free(p2p, dev);
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_expiration_timeout(void *eloop_ctx, void *timeout_ctx)
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_expire_peers(p2p);
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(P2P_PEER_EXPIRATION_INTERVAL, 0,
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p_expiration_timeout, p2p, NULL);
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * p2p_state_txt(int state)
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (state) {
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_IDLE:
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "IDLE";
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SEARCH:
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "SEARCH";
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT:
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "CONNECT";
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT_LISTEN:
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "CONNECT_LISTEN";
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG:
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "GO_NEG";
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_LISTEN_ONLY:
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "LISTEN_ONLY";
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_CONNECT:
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "WAIT_PEER_CONNECT";
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_IDLE:
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "WAIT_PEER_IDLE";
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SD_DURING_FIND:
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "SD_DURING_FIND";
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROVISIONING:
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "PROVISIONING";
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PD_DURING_FIND:
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "PD_DURING_FIND";
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE:
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "INVITE";
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE_LISTEN:
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "INVITE_LISTEN";
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "?";
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
150b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtconst char * p2p_get_state_txt(struct p2p_data *p2p)
151b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt{
152b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	return p2p_state_txt(p2p->state);
153b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt}
154b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt
155b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt
156216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtstruct p2ps_advertisement * p2p_get_p2ps_adv_list(struct p2p_data *p2p)
157216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt{
158216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	return p2p ? p2p->p2ps_adv_list : NULL;
159216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt}
160216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
161216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
162216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtvoid p2p_set_intended_addr(struct p2p_data *p2p, const u8 *intended_addr)
163216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt{
164216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (p2p && intended_addr)
165216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		os_memcpy(p2p->intended_addr, intended_addr, ETH_ALEN);
166216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt}
167216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
168216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
1691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtu16 p2p_get_provisioning_info(struct p2p_data *p2p, const u8 *addr)
1701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
1711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_device *dev = NULL;
1721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (!addr || !p2p)
1741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
1751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	dev = p2p_get_device(p2p, addr);
1771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (dev)
1781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return dev->wps_prov_info;
1791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	else
1801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
1811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
1821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
18404949598a23f501be6eec21697465fd46a28840aDmitry Shmidtvoid p2p_clear_provisioning_info(struct p2p_data *p2p, const u8 *addr)
1851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
1861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_device *dev = NULL;
1871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
18804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (!addr || !p2p)
1891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
1901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
19104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	dev = p2p_get_device(p2p, addr);
1921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (dev)
1931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->wps_prov_info = 0;
1941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
1951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_state(struct p2p_data *p2p, int new_state)
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
199b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "State %s -> %s",
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state), p2p_state_txt(new_state));
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->state = new_state;
20243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt
20343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	if (new_state == P2P_IDLE && p2p->pending_channel) {
20443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		p2p_dbg(p2p, "Apply change in listen channel");
20543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		p2p->cfg->reg_class = p2p->pending_reg_class;
20643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		p2p->cfg->channel = p2p->pending_channel;
20743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		p2p->pending_reg_class = 0;
20843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		p2p->pending_channel = 0;
20943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	}
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_timeout(struct p2p_data *p2p, unsigned int sec, unsigned int usec)
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
215b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Set timeout (state=%s): %u.%06u sec",
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state), sec, usec);
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_state_timeout, p2p, NULL);
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(sec, usec, p2p_state_timeout, p2p, NULL);
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_clear_timeout(struct p2p_data *p2p)
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
224b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Clear timeout (state=%s)", p2p_state_txt(p2p->state));
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_state_timeout, p2p, NULL);
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtvoid p2p_go_neg_failed(struct p2p_data *p2p, int status)
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_go_neg_results res;
2326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	struct p2p_device *peer = p2p->go_neg_peer;
2336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
2346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (!peer)
2356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return;
2366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
2376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	eloop_cancel_timeout(p2p_go_neg_wait_timeout, p2p, NULL);
2386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (p2p->state != P2P_SEARCH) {
2396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		/*
2406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 * Clear timeouts related to GO Negotiation if no new p2p_find
2416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 * has been started.
2426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 */
2436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_clear_timeout(p2p);
2446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
2458c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	}
2466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
2476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	peer->flags &= ~P2P_DEV_PEER_WAITING_RESPONSE;
2486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	peer->wps_method = WPS_NOT_READY;
2496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	peer->oob_pw_id = 0;
2506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpabuf_free(peer->go_neg_conf);
2516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	peer->go_neg_conf = NULL;
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer = NULL;
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&res, 0, sizeof(res));
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.status = status;
2566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	os_memcpy(res.peer_device_addr, peer->info.p2p_device_addr, ETH_ALEN);
2576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	os_memcpy(res.peer_interface_addr, peer->intended_addr, ETH_ALEN);
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->go_neg_completed(p2p->cfg->cb_ctx, &res);
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
262d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic void p2p_listen_in_find(struct p2p_data *p2p, int dev_disc)
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int r, tu;
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *ies;
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
268b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Starting short listen state (state=%s)",
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state));
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2713c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt	if (p2p->pending_listen_freq) {
2723c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt		/* We have a pending p2p_listen request */
2733c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt		p2p_dbg(p2p, "p2p_listen command pending already");
2743c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt		return;
2753c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt	}
2763c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt
2774b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	freq = p2p_channel_to_freq(p2p->cfg->reg_class, p2p->cfg->channel);
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq < 0) {
279b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Unknown regulatory class/channel");
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
283661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	if (os_get_random((u8 *) &r, sizeof(r)) < 0)
284661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		r = 0;
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tu = (r % ((p2p->max_disc_int - p2p->min_disc_int) + 1) +
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	      p2p->min_disc_int) * 100;
287d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (p2p->max_disc_tu >= 0 && tu > (unsigned int) p2p->max_disc_tu)
288d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		tu = p2p->max_disc_tu;
289d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (!dev_disc && tu < 100)
290d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		tu = 100; /* Need to wait in non-device discovery use cases */
291d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (p2p->cfg->max_listen && 1024 * tu / 1000 > p2p->cfg->max_listen)
292d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		tu = p2p->cfg->max_listen * 1000 / 1024;
293d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
294d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (tu == 0) {
295b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Skip listen state since duration was 0 TU");
296d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		p2p_set_timeout(p2p, 0, 0);
297d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return;
298d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
300a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	ies = p2p_build_probe_resp_ies(p2p, NULL, 0);
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ies == NULL)
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3043c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt	p2p->pending_listen_freq = freq;
3053c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt	p2p->pending_listen_sec = 0;
3063c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt	p2p->pending_listen_usec = 1024 * tu;
3073c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->start_listen(p2p->cfg->cb_ctx, freq, 1024 * tu / 1000,
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    ies) < 0) {
310b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to start listen mode");
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_freq = 0;
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(ies);
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_listen(struct p2p_data *p2p, unsigned int timeout)
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *ies;
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
322b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Going to listen(only) state");
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3243c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt	if (p2p->pending_listen_freq) {
3253c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt		/* We have a pending p2p_listen request */
3263c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt		p2p_dbg(p2p, "p2p_listen command pending already");
3273c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt		return -1;
3283c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt	}
3293c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt
3304b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	freq = p2p_channel_to_freq(p2p->cfg->reg_class, p2p->cfg->channel);
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq < 0) {
332b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Unknown regulatory class/channel");
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_sec = timeout / 1000;
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_usec = (timeout % 1000) * 1000;
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
34004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (p2p->start_after_scan == P2P_AFTER_SCAN_CONNECT) {
341b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "p2p_scan running - connect is already pending - skip listen");
3421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return 0;
3431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
344b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "p2p_scan running - delay start of listen state");
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->start_after_scan = P2P_AFTER_SCAN_LISTEN;
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
349a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	ies = p2p_build_probe_resp_ies(p2p, NULL, 0);
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ies == NULL)
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3533c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt	p2p->pending_listen_freq = freq;
3543c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->start_listen(p2p->cfg->cb_ctx, freq, timeout, ies) < 0) {
356b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to start listen mode");
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_freq = 0;
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(ies);
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(ies);
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_LISTEN_ONLY);
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_device_clear_reported(struct p2p_data *p2p)
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
3726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~P2P_DEV_REPORTED;
3746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		dev->sd_reqs = 0;
3756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_get_device - Fetch a peer entry
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: P2P Device Address of the peer
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the device entry or %NULL if not found
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_device * p2p_get_device(struct p2p_data *p2p, const u8 *addr)
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(dev->info.p2p_device_addr, addr, ETH_ALEN) == 0)
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return dev;
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_get_device_interface - Fetch a peer entry based on P2P Interface Address
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: P2P Interface Address of the peer
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the device entry or %NULL if not found
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_device * p2p_get_device_interface(struct p2p_data *p2p,
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     const u8 *addr)
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(dev->interface_addr, addr, ETH_ALEN) == 0)
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return dev;
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_create_device - Create a peer entry
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: P2P Device Address of the peer
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the device entry or %NULL on failure
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * If there is already an entry for the peer, it will be returned instead of
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * creating a new one.
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct p2p_device * p2p_create_device(struct p2p_data *p2p,
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     const u8 *addr)
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev, *oldest = NULL;
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t count = 0;
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev)
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return dev;
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		count++;
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (oldest == NULL ||
436fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		    os_reltime_before(&dev->last_seen, &oldest->last_seen))
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			oldest = dev;
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (count + 1 > p2p->cfg->max_peers && oldest) {
440b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Remove oldest peer entry to make room for a new peer");
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dl_list_del(&oldest->list);
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_device_free(p2p, oldest);
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = os_zalloc(sizeof(*dev));
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_add(&p2p->devices, &dev->list);
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.p2p_device_addr, addr, ETH_ALEN);
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return dev;
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_copy_client_info(struct p2p_device *dev,
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 struct p2p_client_info *cli)
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.device_name, cli->dev_name, cli->dev_name_len);
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.device_name[cli->dev_name_len] = '\0';
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.dev_capab = cli->dev_capab;
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.config_methods = cli->config_methods;
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.pri_dev_type, cli->pri_dev_type, 8);
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.wps_sec_dev_type_list_len = 8 * cli->num_sec_dev_types;
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.wps_sec_dev_type_list, cli->sec_dev_types,
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  dev->info.wps_sec_dev_type_list_len);
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_add_group_clients(struct p2p_data *p2p, const u8 *go_dev_addr,
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const u8 *go_interface_addr, int freq,
471a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt				 const u8 *gi, size_t gi_len,
472a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt				 struct os_reltime *rx_time)
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_info info;
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t c;
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gi == NULL)
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_group_info_parse(gi, gi_len, &info) < 0)
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Clear old data for this group; if the devices are still in the
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * group, the information will be restored in the loop following this.
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
4891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (os_memcmp(dev->member_in_go_iface, go_interface_addr,
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      ETH_ALEN) == 0) {
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(dev->member_in_go_iface, 0, ETH_ALEN);
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(dev->member_in_go_dev, 0, ETH_ALEN);
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (c = 0; c < info.num_clients; c++) {
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct p2p_client_info *cli = &info.client[c];
4981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (os_memcmp(cli->p2p_device_addr, p2p->cfg->dev_addr,
4991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      ETH_ALEN) == 0)
5001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			continue; /* ignore our own entry */
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, cli->p2p_device_addr);
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev) {
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev->flags & (P2P_DEV_GROUP_CLIENT_ONLY |
50404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					  P2P_DEV_PROBE_REQ_ONLY)) {
50504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				/*
50604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 * Update information since we have not
50704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 * received this directly from the client.
50804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 */
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p_copy_client_info(dev, cli);
51004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			} else {
51104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				/*
51204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 * Need to update P2P Client Discoverability
51304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 * flag since it is valid only in P2P Group
51404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 * Info attribute.
51504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 */
51604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				dev->info.dev_capab &=
51704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
51804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				dev->info.dev_capab |=
51904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					cli->dev_capab &
52004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
52104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			}
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev->flags & P2P_DEV_PROBE_REQ_ONLY) {
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev->flags &= ~P2P_DEV_PROBE_REQ_ONLY;
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev = p2p_create_device(p2p, cli->p2p_device_addr);
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev == NULL)
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				continue;
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->flags |= P2P_DEV_GROUP_CLIENT_ONLY;
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_copy_client_info(dev, cli);
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->oper_freq = freq;
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->cfg->dev_found(p2p->cfg->cb_ctx,
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    dev->info.p2p_device_addr,
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    &dev->info, 1);
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->interface_addr, cli->p2p_interface_addr,
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
540a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		os_memcpy(&dev->last_seen, rx_time, sizeof(struct os_reltime));
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->member_in_go_dev, go_dev_addr, ETH_ALEN);
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->member_in_go_iface, go_interface_addr,
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
544a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		dev->flags |= P2P_DEV_LAST_SEEN_AS_GROUP_CLIENT;
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
551b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidtstatic void p2p_copy_wps_info(struct p2p_data *p2p, struct p2p_device *dev,
552b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			      int probe_req, const struct p2p_message *msg)
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.device_name, msg->device_name,
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  sizeof(dev->info.device_name));
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->manufacturer &&
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->manufacturer_len < sizeof(dev->info.manufacturer)) {
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.manufacturer, 0,
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.manufacturer));
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.manufacturer, msg->manufacturer,
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->manufacturer_len);
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->model_name &&
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->model_name_len < sizeof(dev->info.model_name)) {
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.model_name, 0,
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.model_name));
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.model_name, msg->model_name,
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->model_name_len);
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->model_number &&
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->model_number_len < sizeof(dev->info.model_number)) {
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.model_number, 0,
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.model_number));
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.model_number, msg->model_number,
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->model_number_len);
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->serial_number &&
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->serial_number_len < sizeof(dev->info.serial_number)) {
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.serial_number, 0,
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.serial_number));
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.serial_number, msg->serial_number,
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->serial_number_len);
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->pri_dev_type)
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.pri_dev_type, msg->pri_dev_type,
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.pri_dev_type));
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (msg->wps_pri_dev_type)
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.pri_dev_type, msg->wps_pri_dev_type,
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.pri_dev_type));
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->wps_sec_dev_type_list) {
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.wps_sec_dev_type_list,
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->wps_sec_dev_type_list,
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->wps_sec_dev_type_list_len);
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_sec_dev_type_list_len =
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg->wps_sec_dev_type_list_len;
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->capability) {
60504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/*
60604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * P2P Client Discoverability bit is reserved in all frames
60704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * that use this function, so do not change its value here.
60804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 */
60904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->info.dev_capab &= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
61004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->info.dev_capab |= msg->capability[0] &
61104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.group_capab = msg->capability[1];
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->ext_listen_timing) {
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->ext_listen_period = WPA_GET_LE16(msg->ext_listen_timing);
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->ext_listen_interval =
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			WPA_GET_LE16(msg->ext_listen_timing + 2);
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
62004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!probe_req) {
622f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		u16 new_config_methods;
623f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		new_config_methods = msg->config_methods ?
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg->config_methods : msg->wps_config_methods;
625f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		if (new_config_methods &&
626f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		    dev->info.config_methods != new_config_methods) {
627b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Update peer " MACSTR
628b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				" config_methods 0x%x -> 0x%x",
629b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				MAC2STR(dev->info.p2p_device_addr),
630b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				dev->info.config_methods,
631b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				new_config_methods);
632f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			dev->info.config_methods = new_config_methods;
633f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		}
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6382e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidtstatic void p2p_update_peer_vendor_elems(struct p2p_device *dev, const u8 *ies,
6392e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt					 size_t ies_len)
6402e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt{
6412e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	const u8 *pos, *end;
6422e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	u8 id, len;
6432e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
6442e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	wpabuf_free(dev->info.vendor_elems);
6452e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	dev->info.vendor_elems = NULL;
6462e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
6472e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	end = ies + ies_len;
6482e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
6492e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	for (pos = ies; pos + 1 < end; pos += len) {
6502e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		id = *pos++;
6512e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		len = *pos++;
6522e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
6532e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		if (pos + len > end)
6542e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			break;
6552e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
6562e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		if (id != WLAN_EID_VENDOR_SPECIFIC || len < 3)
6572e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			continue;
6582e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
6592e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		if (len >= 4) {
6602e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			u32 type = WPA_GET_BE32(pos);
6612e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
6622e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			if (type == WPA_IE_VENDOR_TYPE ||
6632e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			    type == WMM_IE_VENDOR_TYPE ||
6642e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			    type == WPS_IE_VENDOR_TYPE ||
6652e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			    type == P2P_IE_VENDOR_TYPE ||
6662e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			    type == WFD_IE_VENDOR_TYPE)
6672e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt				continue;
6682e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		}
6692e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
6702e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		/* Unknown vendor element - make raw IE data available */
6712e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		if (wpabuf_resize(&dev->info.vendor_elems, 2 + len) < 0)
6722e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			break;
6732e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		wpabuf_put_data(dev->info.vendor_elems, pos - 2, 2 + len);
6742e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	}
6752e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt}
6762e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
6772e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
6786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int p2p_compare_wfd_info(struct p2p_device *dev,
6796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			      const struct p2p_message *msg)
6806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
6816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (dev->info.wfd_subelems && msg->wfd_subelems) {
6826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (dev->info.wfd_subelems->used != msg->wfd_subelems->used)
6836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return 1;
6846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
6856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return os_memcmp(dev->info.wfd_subelems->buf,
6866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				 msg->wfd_subelems->buf,
6876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				 dev->info.wfd_subelems->used);
6886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
6896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (dev->info.wfd_subelems || msg->wfd_subelems)
6906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 1;
6916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
6926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return 0;
6936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
6946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
6956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
69704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * p2p_add_device - Add peer entries based on scan results or P2P frames
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: Source address of Beacon or Probe Response frame (may be either
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *	P2P Device Address or P2P Interface Address)
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @level: Signal level (signal strength of the received frame from the peer)
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @freq: Frequency on which the Beacon or Probe Response frame was received
703f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * @rx_time: Time when the result was received
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ies: IEs from the Beacon or Probe Response frame
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ies_len: Length of ies buffer in octets
70604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * @scan_res: Whether this was based on scan results
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * If the scan result is for a GO, the clients in the group will also be added
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to the peer table. This function can also be used with some other frames
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * like Provision Discovery Request that contains P2P Capability and P2P Device
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Info attributes.
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
714a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtint p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq,
715fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		   struct os_reltime *rx_time, int level, const u8 *ies,
716a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		   size_t ies_len, int scan_res)
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *p2p_dev_addr;
7216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	int wfd_changed;
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
723fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	struct os_reltime time_now;
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ies, ies_len, &msg)) {
727b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to parse P2P IE for a device entry");
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.p2p_device_addr)
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_addr = msg.p2p_device_addr;
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (msg.device_id)
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_addr = msg.device_id;
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
737b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Ignore scan data without P2P Device Info or P2P Device Id");
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!is_zero_ether_addr(p2p->peer_filter) &&
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(p2p_dev_addr, p2p->peer_filter, ETH_ALEN) != 0) {
744b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Do not add peer filter for " MACSTR
745b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			" due to peer filter", MAC2STR(p2p_dev_addr));
746a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p_parse_free(&msg);
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_create_device(p2p, p2p_dev_addr);
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
755a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
756f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	if (rx_time == NULL) {
757fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		os_get_reltime(&time_now);
758f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		rx_time = &time_now;
759f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	}
760a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
761a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	/*
762a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	 * Update the device entry only if the new peer
763a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	 * entry is newer than the one previously stored, or if
764a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	 * the device was previously seen as a P2P Client in a group
765a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	 * and the new entry isn't older than a threshold.
766a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	 */
767f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	if (dev->last_seen.sec > 0 &&
768a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	    os_reltime_before(rx_time, &dev->last_seen) &&
769a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	    (!(dev->flags & P2P_DEV_LAST_SEEN_AS_GROUP_CLIENT) ||
770a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	     os_reltime_expired(&dev->last_seen, rx_time,
771a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt				P2P_DEV_GROUP_CLIENT_RESP_THRESHOLD))) {
772a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		p2p_dbg(p2p,
773a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			"Do not update peer entry based on old frame (rx_time=%u.%06u last_seen=%u.%06u flags=0x%x)",
774f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			(unsigned int) rx_time->sec,
775f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			(unsigned int) rx_time->usec,
776f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			(unsigned int) dev->last_seen.sec,
777a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			(unsigned int) dev->last_seen.usec,
778a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			dev->flags);
779a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p_parse_free(&msg);
780a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
781a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
782a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
783fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	os_memcpy(&dev->last_seen, rx_time, sizeof(struct os_reltime));
784a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
785a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	dev->flags &= ~(P2P_DEV_PROBE_REQ_ONLY | P2P_DEV_GROUP_CLIENT_ONLY |
786a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			P2P_DEV_LAST_SEEN_AS_GROUP_CLIENT);
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(addr, p2p_dev_addr, ETH_ALEN) != 0)
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->interface_addr, addr, ETH_ALEN);
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.ssid &&
791fdb708a37d8f7f1483e3cd4e8ded974f53fedaceJouni Malinen	    msg.ssid[1] <= sizeof(dev->oper_ssid) &&
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (msg.ssid[1] != P2P_WILDCARD_SSID_LEN ||
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     os_memcmp(msg.ssid + 2, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN)
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     != 0)) {
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->oper_ssid, msg.ssid + 2, msg.ssid[1]);
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->oper_ssid_len = msg.ssid[1];
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
799216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (msg.adv_service_instance && msg.adv_service_instance_len) {
800216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		wpabuf_free(dev->info.p2ps_instance);
801216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		dev->info.p2ps_instance = wpabuf_alloc_copy(
802216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			msg.adv_service_instance, msg.adv_service_instance_len);
803216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
804216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq >= 2412 && freq <= 2484 && msg.ds_params &&
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    *msg.ds_params >= 1 && *msg.ds_params <= 14) {
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int ds_freq;
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*msg.ds_params == 14)
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ds_freq = 2484;
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ds_freq = 2407 + *msg.ds_params * 5;
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freq != ds_freq) {
813b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Update Listen frequency based on DS Parameter Set IE: %d -> %d MHz",
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				freq, ds_freq);
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq = ds_freq;
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
81904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (dev->listen_freq && dev->listen_freq != freq && scan_res) {
820b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Update Listen frequency based on scan results ("
821b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			MACSTR " %d -> %d MHz (DS param %d)",
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr), dev->listen_freq,
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq, msg.ds_params ? *msg.ds_params : -1);
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
82504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (scan_res) {
82604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->listen_freq = freq;
82704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (msg.group_info)
82804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			dev->oper_freq = freq;
82904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
83075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	dev->info.level = level;
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
832b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_copy_wps_info(p2p, dev, 0, &msg);
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(dev->info.wps_vendor_ext[i]);
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_vendor_ext[i] = NULL;
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (msg.wps_vendor_ext[i] == NULL)
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_vendor_ext[i] = wpabuf_alloc_copy(
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg.wps_vendor_ext[i], msg.wps_vendor_ext_len[i]);
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->info.wps_vendor_ext[i] == NULL)
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wfd_changed = p2p_compare_wfd_info(dev, &msg);
8496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
85061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (msg.wfd_subelems) {
85161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_free(dev->info.wfd_subelems);
85261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
85361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
85461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
85504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (scan_res) {
85604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p_add_group_clients(p2p, p2p_dev_addr, addr, freq,
857a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt				      msg.group_info, msg.group_info_len,
858a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt				      rx_time);
85904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8632e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	p2p_update_peer_vendor_elems(dev, ies, ies_len);
8642e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
865216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (dev->flags & P2P_DEV_REPORTED && !wfd_changed &&
866216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	    (!msg.adv_service_instance ||
867216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	     (dev->flags & P2P_DEV_P2PS_REPORTED)))
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
870b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Peer found with Listen frequency %d MHz (rx_time=%u.%06u)",
871b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		freq, (unsigned int) rx_time->sec,
872f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		(unsigned int) rx_time->usec);
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_USER_REJECTED) {
874b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Do not report rejected device");
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
878f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	if (dev->info.config_methods == 0 &&
879f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	    (freq == 2412 || freq == 2437 || freq == 2462)) {
880f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		/*
881f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * If we have only seen a Beacon frame from a GO, we do not yet
882f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * know what WPS config methods it supports. Since some
883f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * applications use config_methods value from P2P-DEVICE-FOUND
884f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * events, postpone reporting this peer until we've fully
885f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * discovered its capabilities.
886f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 *
887f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * At least for now, do this only if the peer was detected on
888f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * one of the social channels since that peer can be easily be
889f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * found again and there are no limitations of having to use
890f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * passive scan on this channels, so this can be done through
891f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * Probe Response frame that includes the config_methods
892f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * information.
893f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 */
894b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Do not report peer " MACSTR
895b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			" with unknown config methods", MAC2STR(addr));
896f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		return 0;
897f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	}
898f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->dev_found(p2p->cfg->cb_ctx, addr, &dev->info,
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    !(dev->flags & P2P_DEV_REPORTED_ONCE));
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
903216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (msg.adv_service_instance)
904216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		dev->flags |= P2P_DEV_P2PS_REPORTED;
905216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev)
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
914497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt	if (p2p->go_neg_peer == dev) {
9151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/*
9161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * If GO Negotiation is in progress, report that it has failed.
9171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
9186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_go_neg_failed(p2p, -1);
919497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt	}
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->invite_peer == dev)
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->invite_peer = NULL;
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->sd_peer == dev)
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->sd_peer = NULL;
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->pending_client_disc_go == dev)
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_client_disc_go = NULL;
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
927c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	/* dev_lost() device, but only if it was previously dev_found() */
928c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	if (dev->flags & P2P_DEV_REPORTED_ONCE)
929c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		p2p->cfg->dev_lost(p2p->cfg->cb_ctx,
930c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt				   dev->info.p2p_device_addr);
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(dev->info.wps_vendor_ext[i]);
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_vendor_ext[i] = NULL;
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
93761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(dev->info.wfd_subelems);
9382e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	wpabuf_free(dev->info.vendor_elems);
939413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt	wpabuf_free(dev->go_neg_conf);
940216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	wpabuf_free(dev->info.p2ps_instance);
94161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(dev);
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_get_next_prog_freq(struct p2p_data *p2p)
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_channels *c;
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_reg_class *cla;
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t cl, ch;
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int found = 0;
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 reg_class;
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 channel;
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	c = &p2p->cfg->channels;
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (cl = 0; cl < c->reg_classes; cl++) {
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cla = &c->reg_class[cl];
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (cla->reg_class != p2p->last_prog_scan_class)
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (ch = 0; ch < cla->channels; ch++) {
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (cla->channel[ch] == p2p->last_prog_scan_chan) {
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				found = 1;
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (found)
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!found) {
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Start from beginning */
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reg_class = c->reg_class[0].reg_class;
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		channel = c->reg_class[0].channel[0];
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Pick the next channel */
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ch++;
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ch == cla->channels) {
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			cl++;
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (cl == c->reg_classes)
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				cl = 0;
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ch = 0;
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reg_class = c->reg_class[cl].reg_class;
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		channel = c->reg_class[cl].channel[ch];
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9884b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	freq = p2p_channel_to_freq(reg_class, channel);
989b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Next progressive search channel: reg_class %u channel %u -> %d MHz",
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reg_class, channel, freq);
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->last_prog_scan_class = reg_class;
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->last_prog_scan_chan = channel;
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq == 2412 || freq == 2437 || freq == 2462)
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* No need to add social channels */
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return freq;
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_search(struct p2p_data *p2p)
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq = 0;
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum p2p_scan_type type;
100404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	u16 pw_id = DEV_PW_DEFAULT;
100561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	int res;
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->drv_in_listen) {
1008b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Driver is still in Listen state - wait for it to end before continuing");
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
101304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p->find_type == P2P_FIND_PROGRESSIVE &&
101404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    (freq = p2p_get_next_prog_freq(p2p)) > 0) {
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type = P2P_SCAN_SOCIAL_PLUS_ONE;
1016b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Starting search (+ freq %u)", freq);
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type = P2P_SCAN_SOCIAL;
1019b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Starting search");
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
102261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, type, freq,
102361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				 p2p->num_req_dev_types, p2p->req_dev_types,
102461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				 p2p->find_dev_id, pw_id);
102561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (res < 0) {
10266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_dbg(p2p, "Scan request schedule failed");
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_find_timeout(void *eloop_ctx, void *timeout_ctx)
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
1035b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Find timeout -> stop");
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_stop_find(p2p);
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtvoid p2p_notify_scan_trigger_status(struct p2p_data *p2p, int status)
10416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
10426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (status != 0) {
10436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_dbg(p2p, "Scan request failed");
10446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		/* Do continue find even for the first p2p_find_scan */
10456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_continue_find(p2p);
10466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	} else {
10476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_dbg(p2p, "Running p2p_scan");
10486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p->p2p_scan_running = 1;
10496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
10506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		eloop_register_timeout(P2P_SCAN_TIMEOUT, 0, p2p_scan_timeout,
10516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				       p2p, NULL);
10526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
10536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
10546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
10556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_run_after_scan(struct p2p_data *p2p)
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum p2p_after_scan op;
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->after_scan_tx) {
10628da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt		p2p->after_scan_tx_in_progress = 1;
1063b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Send pending Action frame at p2p_scan completion");
10641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p->cfg->send_action(p2p->cfg->cb_ctx,
10651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->freq,
10661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->dst,
10671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->src,
10681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->bssid,
10691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      (u8 *) (p2p->after_scan_tx + 1),
10701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->len,
10711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->wait_time);
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p2p->after_scan_tx);
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = NULL;
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	op = p2p->start_after_scan;
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (op) {
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_AFTER_SCAN_NOTHING:
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_AFTER_SCAN_LISTEN:
1083b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Start previously requested Listen state");
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_listen(p2p, p2p->pending_listen_sec * 1000 +
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   p2p->pending_listen_usec / 1000);
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_AFTER_SCAN_CONNECT:
1088b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Start previously requested connect with " MACSTR,
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(p2p->after_scan_peer));
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, p2p->after_scan_peer);
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev == NULL) {
1092b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Peer not known anymore");
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, dev);
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_scan_timeout(void *eloop_ctx, void *timeout_ctx)
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int running;
1107b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "p2p_scan timeout (running=%d)", p2p->p2p_scan_running);
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	running = p2p->p2p_scan_running;
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Make sure we recover from missed scan results callback */
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->p2p_scan_running = 0;
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (running)
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_run_after_scan(p2p);
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_free_req_dev_types(struct p2p_data *p2p)
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->num_req_dev_types = 0;
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->req_dev_types);
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->req_dev_types = NULL;
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1125216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtstatic int p2ps_gen_hash(struct p2p_data *p2p, const char *str, u8 *hash)
1126216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt{
1127216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	u8 buf[SHA256_MAC_LEN];
1128216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	char str_buf[256];
1129216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	const u8 *adv_array;
1130216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	size_t i, adv_len;
1131216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
1132216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (!str || !hash)
1133216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		return 0;
1134216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
1135216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (!str[0]) {
1136216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		os_memcpy(hash, p2p->wild_card_hash, P2PS_HASH_LEN);
1137216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		return 1;
1138216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
1139216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
1140216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_array = (u8 *) str_buf;
1141216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_len = os_strlen(str);
1142a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	if (adv_len >= sizeof(str_buf))
1143a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		return 0;
1144216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
1145216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	for (i = 0; str[i] && i < adv_len; i++) {
1146216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (str[i] >= 'A' && str[i] <= 'Z')
1147216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			str_buf[i] = str[i] - 'A' + 'a';
1148216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		else
1149216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			str_buf[i] = str[i];
1150216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
1151216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
1152216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (sha256_vector(1, &adv_array, &adv_len, buf))
1153216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		return 0;
1154216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
1155216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	os_memcpy(hash, buf, P2PS_HASH_LEN);
1156216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	return 1;
1157216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt}
1158216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
1159216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_find(struct p2p_data *p2p, unsigned int timeout,
11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     enum p2p_discovery_type type,
1162c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	     unsigned int num_req_dev_types, const u8 *req_dev_types,
1163216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	     const u8 *dev_id, unsigned int search_delay,
1164203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt	     u8 seek_count, const char **seek, int freq)
11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1168b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Starting find (type=%d)", type);
1169fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	os_get_reltime(&p2p->find_start);
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
1171b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "p2p_scan is already running");
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_req_dev_types(p2p);
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req_dev_types && num_req_dev_types) {
11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->req_dev_types = os_malloc(num_req_dev_types *
11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       WPS_DEV_TYPE_LEN);
11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->req_dev_types == NULL)
11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->req_dev_types, req_dev_types,
11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  num_req_dev_types * WPS_DEV_TYPE_LEN);
11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->num_req_dev_types = num_req_dev_types;
11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1185c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (dev_id) {
1186c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		os_memcpy(p2p->find_dev_id_buf, dev_id, ETH_ALEN);
1187c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		p2p->find_dev_id = p2p->find_dev_id_buf;
1188c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	} else
1189c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		p2p->find_dev_id = NULL;
1190c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1191216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (seek_count == 0 || !seek) {
1192216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		/* Not an ASP search */
1193216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p->p2ps_seek = 0;
1194216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	} else if (seek_count == 1 && seek && (!seek[0] || !seek[0][0])) {
1195216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		/*
1196216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		 * An empty seek string means no hash values, but still an ASP
1197216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		 * search.
1198216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		 */
1199a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		p2p_dbg(p2p, "ASP search");
1200216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p->p2ps_seek_count = 0;
1201216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p->p2ps_seek = 1;
1202216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	} else if (seek && seek_count <= P2P_MAX_QUERY_HASH) {
1203216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		u8 buf[P2PS_HASH_LEN];
1204a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		int i, count = 0;
1205216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
1206216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		for (i = 0; i < seek_count; i++) {
1207216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			if (!p2ps_gen_hash(p2p, seek[i], buf))
1208216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				continue;
1209216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
1210a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			p2p_dbg(p2p, "Seek service %s hash " MACSTR,
1211a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt				seek[i], MAC2STR(buf));
1212a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			os_memcpy(&p2p->p2ps_seek_hash[count * P2PS_HASH_LEN],
1213a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt				  buf, P2PS_HASH_LEN);
1214a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			count++;
1215216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		}
1216a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt
1217a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		p2p->p2ps_seek_count = count;
1218216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p->p2ps_seek = 1;
1219216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	} else {
1220216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p->p2ps_seek_count = 0;
1221216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p->p2ps_seek = 1;
1222216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
1223216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
1224216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	/* Special case to perform wildcard search */
1225216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (p2p->p2ps_seek_count == 0 && p2p->p2ps_seek) {
1226216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p->p2ps_seek_count = 1;
1227a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		os_memcpy(&p2p->p2ps_seek_hash, p2p->wild_card_hash,
1228a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			  P2PS_HASH_LEN);
1229216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
1230216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->find_type = type;
12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_device_clear_reported(p2p);
12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_SEARCH);
123761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->search_delay = search_delay;
123861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->in_search_delay = 0;
12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
12401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p->last_p2p_find_timeout = timeout;
12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (timeout)
12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(timeout, 0, p2p_find_timeout,
12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p, NULL);
12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (type) {
12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_FIND_START_WITH_FULL:
1246203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt		if (freq > 0) {
1247203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt			/*
1248203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt			 * Start with the specified channel and then move to
1249203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt			 * social channels only scans.
1250203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt			 */
1251203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt			res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx,
1252203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt						 P2P_SCAN_SPECIFIC, freq,
1253203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt						 p2p->num_req_dev_types,
1254203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt						 p2p->req_dev_types, dev_id,
1255203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt						 DEV_PW_DEFAULT);
1256203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt			break;
1257203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt		}
1258203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt		/* fall through */
12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_FIND_PROGRESSIVE:
12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_FULL, 0,
12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 p2p->num_req_dev_types,
126204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 p2p->req_dev_types, dev_id,
126304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 DEV_PW_DEFAULT);
12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_FIND_ONLY_SOCIAL:
12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_SOCIAL, 0,
12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 p2p->num_req_dev_types,
126804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 p2p->req_dev_types, dev_id,
126904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 DEV_PW_DEFAULT);
12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (res != 0 && p2p->p2p_scan_running) {
1276fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		p2p_dbg(p2p, "Failed to start p2p_scan - another p2p_scan was already running");
1277fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		/* wait for the previous p2p_scan to complete */
127896be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt		res = 0; /* do not report failure */
12796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	} else if (res != 0) {
1280b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to start p2p_scan");
12811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
12821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_stop_find_for_freq(struct p2p_data *p2p, int freq)
12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1291b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Stopping find");
12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
1294216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (p2p->state == P2P_SEARCH || p2p->state == P2P_SD_DURING_FIND)
1295b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p->cfg->find_stopped(p2p->cfg->cb_ctx);
1296216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
1297216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	p2p->p2ps_seek_count = 0;
1298216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_IDLE);
13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_req_dev_types(p2p);
13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
13028c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	if (p2p->go_neg_peer)
13038c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		p2p->go_neg_peer->flags &= ~P2P_DEV_PEER_WAITING_RESPONSE;
13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer = NULL;
13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->sd_peer = NULL;
13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->invite_peer = NULL;
130704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_stop_listen_for_freq(p2p, freq);
13087f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt	p2p->send_action_in_progress = 0;
130904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
131004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
131104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
131204949598a23f501be6eec21697465fd46a28840aDmitry Shmidtvoid p2p_stop_listen_for_freq(struct p2p_data *p2p, int freq)
131304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq > 0 && p2p->drv_in_listen == freq && p2p->in_listen) {
1315b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Skip stop_listen since we are on correct channel for response");
13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
131804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p->in_listen) {
131904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->in_listen = 0;
132004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p_clear_timeout(p2p);
132104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
13221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p->drv_in_listen) {
13231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/*
13241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * The driver may not deliver callback to p2p_listen_end()
13251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * when the operation gets canceled, so clear the internal
13261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * variable that is tracking driver state.
13271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
1328b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Clear drv_in_listen (%d)", p2p->drv_in_listen);
13291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p->drv_in_listen = 0;
13301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1335391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtvoid p2p_stop_listen(struct p2p_data *p2p)
1336391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{
1337391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (p2p->state != P2P_LISTEN_ONLY) {
1338391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		p2p_dbg(p2p, "Skip stop_listen since not in listen_only state.");
1339391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		return;
1340391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	}
1341391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
1342391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	p2p_stop_listen_for_freq(p2p, 0);
1343391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	p2p_set_state(p2p, P2P_IDLE);
1344391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt}
1345391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
1346391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_stop_find(struct p2p_data *p2p)
13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13493c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt	p2p->pending_listen_freq = 0;
13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_stop_find_for_freq(p2p, 0);
13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1354a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtstatic int p2p_prepare_channel_pref(struct p2p_data *p2p,
1355a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt				    unsigned int force_freq,
135668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt				    unsigned int pref_freq, int go)
13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1358a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	u8 op_class, op_channel;
1359a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	unsigned int freq = force_freq ? force_freq : pref_freq;
13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
136168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p_dbg(p2p, "Prepare channel pref - force_freq=%u pref_freq=%u go=%d",
136268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		force_freq, pref_freq, go);
13634b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	if (p2p_freq_to_channel(freq, &op_class, &op_channel) < 0) {
1364b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Unsupported frequency %u MHz", freq);
1365a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
1366a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
1367a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
136868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	if (!p2p_channels_includes(&p2p->cfg->channels, op_class, op_channel) &&
136968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	    (go || !p2p_channels_includes(&p2p->cfg->cli_channels, op_class,
137068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt					  op_channel))) {
1371b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Frequency %u MHz (oper_class %u channel %u) not allowed for P2P",
1372b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			freq, op_class, op_channel);
1373a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
1374a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
1375a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1376a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	p2p->op_reg_class = op_class;
1377a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	p2p->op_channel = op_channel;
13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1379a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (force_freq) {
1380a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->channels.reg_classes = 1;
1381a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->channels.reg_class[0].channels = 1;
1382a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->channels.reg_class[0].reg_class = p2p->op_reg_class;
1383a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->channels.reg_class[0].channel[0] = p2p->op_channel;
1384a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	} else {
13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(&p2p->channels, &p2p->cfg->channels,
13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(struct p2p_channels));
13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1388a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1389a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	return 0;
1390a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt}
1391a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1392a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1393a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtstatic void p2p_prepare_channel_best(struct p2p_data *p2p)
1394a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{
1395a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	u8 op_class, op_channel;
1396a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	const int op_classes_5ghz[] = { 124, 125, 115, 0 };
1397a0d265f81180f341d22511538fa18166e1bbce9fDmitry Shmidt	const int op_classes_ht40[] = { 126, 127, 116, 117, 0 };
1398e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	const int op_classes_vht[] = { 128, 0 };
1399a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1400b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	p2p_dbg(p2p, "Prepare channel best");
1401b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt
1402a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (!p2p->cfg->cfg_op_channel && p2p->best_freq_overall > 0 &&
1403a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	    p2p_supported_freq(p2p, p2p->best_freq_overall) &&
14044b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	    p2p_freq_to_channel(p2p->best_freq_overall, &op_class, &op_channel)
14054b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	    == 0) {
1406b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Select best overall channel as operating channel preference");
1407a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_reg_class = op_class;
1408a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_channel = op_channel;
1409a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	} else if (!p2p->cfg->cfg_op_channel && p2p->best_freq_5 > 0 &&
1410a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		   p2p_supported_freq(p2p, p2p->best_freq_5) &&
14114b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		   p2p_freq_to_channel(p2p->best_freq_5, &op_class, &op_channel)
14124b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		   == 0) {
1413b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Select best 5 GHz channel as operating channel preference");
1414a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_reg_class = op_class;
1415a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_channel = op_channel;
1416a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	} else if (!p2p->cfg->cfg_op_channel && p2p->best_freq_24 > 0 &&
1417a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		   p2p_supported_freq(p2p, p2p->best_freq_24) &&
14184b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		   p2p_freq_to_channel(p2p->best_freq_24, &op_class,
14194b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt				       &op_channel) == 0) {
1420b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Select best 2.4 GHz channel as operating channel preference");
1421a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_reg_class = op_class;
1422a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_channel = op_channel;
1423b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	} else if (p2p->cfg->num_pref_chan > 0 &&
1424b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		   p2p_channels_includes(&p2p->cfg->channels,
1425b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt					 p2p->cfg->pref_chan[0].op_class,
1426b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt					 p2p->cfg->pref_chan[0].chan)) {
1427b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		p2p_dbg(p2p, "Select first pref_chan entry as operating channel preference");
1428b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		p2p->op_reg_class = p2p->cfg->pref_chan[0].op_class;
1429b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		p2p->op_channel = p2p->cfg->pref_chan[0].chan;
1430e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	} else if (p2p_channel_select(&p2p->cfg->channels, op_classes_vht,
1431e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt				      &p2p->op_reg_class, &p2p->op_channel) ==
1432e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		   0) {
1433e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		p2p_dbg(p2p, "Select possible VHT channel (op_class %u channel %u) as operating channel preference",
1434e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt			p2p->op_reg_class, p2p->op_channel);
1435e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	} else if (p2p_channel_select(&p2p->cfg->channels, op_classes_ht40,
1436e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt				      &p2p->op_reg_class, &p2p->op_channel) ==
1437e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		   0) {
1438e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		p2p_dbg(p2p, "Select possible HT40 channel (op_class %u channel %u) as operating channel preference",
1439e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt			p2p->op_reg_class, p2p->op_channel);
1440e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	} else if (p2p_channel_select(&p2p->cfg->channels, op_classes_5ghz,
1441e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt				      &p2p->op_reg_class, &p2p->op_channel) ==
1442e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		   0) {
1443e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		p2p_dbg(p2p, "Select possible 5 GHz channel (op_class %u channel %u) as operating channel preference",
1444e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt			p2p->op_reg_class, p2p->op_channel);
1445d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt	} else if (p2p_channels_includes(&p2p->cfg->channels,
1446d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt					 p2p->cfg->op_reg_class,
1447d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt					 p2p->cfg->op_channel)) {
1448b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		p2p_dbg(p2p, "Select pre-configured channel as operating channel preference");
1449a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_reg_class = p2p->cfg->op_reg_class;
1450a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_channel = p2p->cfg->op_channel;
1451d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt	} else if (p2p_channel_random_social(&p2p->cfg->channels,
1452d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt					     &p2p->op_reg_class,
1453d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt					     &p2p->op_channel) == 0) {
1454661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		p2p_dbg(p2p, "Select random available social channel (op_class %u channel %u) as operating channel preference",
1455661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt			p2p->op_reg_class, p2p->op_channel);
1456d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt	} else {
1457d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt		/* Select any random available channel from the first available
1458d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt		 * operating class */
1459d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt		p2p_channel_select(&p2p->cfg->channels, NULL,
1460d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt				   &p2p->op_reg_class,
1461d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt				   &p2p->op_channel);
1462d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt		p2p_dbg(p2p, "Select random available channel %d from operating class %d as operating channel preference",
1463d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt			p2p->op_channel, p2p->op_reg_class);
1464a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
1465a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1466a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	os_memcpy(&p2p->channels, &p2p->cfg->channels,
1467a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		  sizeof(struct p2p_channels));
1468a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt}
1469a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1470a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1471a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt/**
1472a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * p2p_prepare_channel - Select operating channel for GO Negotiation
1473a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @p2p: P2P module context from p2p_init()
1474a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @dev: Selected peer device
1475a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @force_freq: Forced frequency in MHz or 0 if not forced
1476a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @pref_freq: Preferred frequency in MHz or 0 if no preference
147768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt * @go: Whether the local end will be forced to be GO
1478a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Returns: 0 on success, -1 on failure (channel not supported for P2P)
1479a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *
1480a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * This function is used to do initial operating channel selection for GO
1481a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Negotiation prior to having received peer information. The selected channel
1482a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * may be further optimized in p2p_reselect_channel() once the peer information
1483a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * is available.
1484a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt */
14857a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidtint p2p_prepare_channel(struct p2p_data *p2p, struct p2p_device *dev,
148668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt			unsigned int force_freq, unsigned int pref_freq, int go)
1487a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{
148868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p_dbg(p2p, "Prepare channel - force_freq=%u pref_freq=%u go=%d",
148968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		force_freq, pref_freq, go);
1490a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (force_freq || pref_freq) {
149168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		if (p2p_prepare_channel_pref(p2p, force_freq, pref_freq, go) <
149268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		    0)
1493a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			return -1;
1494a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	} else {
1495a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p_prepare_channel_best(p2p);
1496a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
149768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p_channels_dump(p2p, "prepared channels", &p2p->channels);
149868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	if (go)
149968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		p2p_channels_remove_freqs(&p2p->channels, &p2p->no_go_freq);
150068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	else if (!force_freq)
15016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_channels_union_inplace(&p2p->channels,
15026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt					   &p2p->cfg->cli_channels);
150368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p_channels_dump(p2p, "after go/cli filter/add", &p2p->channels);
150468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt
1505b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Own preference for operation channel: Operating Class %u Channel %u%s",
15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->op_reg_class, p2p->op_channel,
15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		force_freq ? " (forced)" : "");
15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1509a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (force_freq)
1510a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		dev->flags |= P2P_DEV_FORCE_FREQ;
1511a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	else
1512a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		dev->flags &= ~P2P_DEV_FORCE_FREQ;
1513a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void p2p_set_dev_persistent(struct p2p_device *dev,
15191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   int persistent_group)
15201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
15211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	switch (persistent_group) {
15221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case 0:
15231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags &= ~(P2P_DEV_PREFER_PERSISTENT_GROUP |
15241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				P2P_DEV_PREFER_PERSISTENT_RECONN);
15251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
15261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case 1:
15271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP;
15281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags &= ~P2P_DEV_PREFER_PERSISTENT_RECONN;
15291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
15301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case 2:
15311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP |
15321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			P2P_DEV_PREFER_PERSISTENT_RECONN;
15331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
15341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
15351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
15361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
15371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		enum p2p_wps_method wps_method,
15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int go_intent, const u8 *own_interface_addr,
154104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		unsigned int force_freq, int persistent_group,
154204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		const u8 *force_ssid, size_t force_ssid_len,
1543cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		int pd_before_go_neg, unsigned int pref_freq, u16 oob_pw_id)
15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1547b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Request to start group negotiation - peer=" MACSTR
15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  GO Intent=%d  Intended Interface Address=" MACSTR
1549cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		" wps_method=%d persistent_group=%d pd_before_go_neg=%d "
1550cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		"oob_pw_id=%u",
15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
1552cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		wps_method, persistent_group, pd_before_go_neg, oob_pw_id);
15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
1556b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Cannot connect to unknown P2P Device " MACSTR,
15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(peer_addr));
15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
156168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	if (p2p_prepare_channel(p2p, dev, force_freq, pref_freq,
156268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt				go_intent == 15) < 0)
1563a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
1564a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!(dev->info.dev_capab &
15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
1568b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Cannot connect to P2P Device " MACSTR
15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				" that is in a group and is not discoverable",
15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(peer_addr));
15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->oper_freq <= 0) {
1574b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Cannot connect to P2P Device " MACSTR
15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				" with incomplete information",
15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(peer_addr));
15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * First, try to connect directly. If the peer does not
15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * acknowledge frames, assume it is sleeping and use device
15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * discoverability via the GO at that point.
15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
158704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p->ssid_set = 0;
158804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (force_ssid) {
158904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "P2P: Forced SSID",
159004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  force_ssid, force_ssid_len);
159104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(p2p->ssid, force_ssid, force_ssid_len);
159204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->ssid_len = force_ssid_len;
159304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->ssid_set = 1;
159404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
159504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_NOT_YET_READY;
15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_USER_REJECTED;
15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE;
15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM;
160004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (pd_before_go_neg)
160104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->flags |= P2P_DEV_PD_BEFORE_GO_NEG;
1602a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	else {
160304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->flags &= ~P2P_DEV_PD_BEFORE_GO_NEG;
1604a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		/*
16059cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt		 * Assign dialog token and tie breaker here to use the same
16069cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt		 * values in each retry within the same GO Negotiation exchange.
1607a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		 */
1608a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		dev->dialog_token++;
1609a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		if (dev->dialog_token == 0)
1610a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			dev->dialog_token = 1;
16119cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt		dev->tie_breaker = p2p->next_tie_breaker;
16129cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt		p2p->next_tie_breaker = !p2p->next_tie_breaker;
1613a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->connect_reqs = 0;
16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_neg_req_sent = 0;
16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_state = UNKNOWN_GO;
16171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_set_dev_persistent(dev, persistent_group);
16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_intent = go_intent;
16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state != P2P_IDLE)
16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_stop_find(p2p);
16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->after_scan_tx) {
16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * We need to drop the pending frame to avoid issues with the
16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * new GO Negotiation, e.g., when the pending frame was from a
16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * previous attempt at starting a GO Negotiation.
16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
1630b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Dropped previous pending Action frame TX that was waiting for p2p_scan completion");
16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p2p->after_scan_tx);
16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = NULL;
16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wps_method = wps_method;
1636cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	dev->oob_pw_id = oob_pw_id;
16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->status = P2P_SC_SUCCESS;
16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
1640b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "p2p_scan running - delay connect send");
16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->start_after_scan = P2P_AFTER_SCAN_CONNECT;
16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_peer, peer_addr, ETH_ALEN);
16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_connect_send(p2p, dev);
16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  enum p2p_wps_method wps_method,
16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  int go_intent, const u8 *own_interface_addr,
165404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		  unsigned int force_freq, int persistent_group,
1655d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		  const u8 *force_ssid, size_t force_ssid_len,
1656cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		  unsigned int pref_freq, u16 oob_pw_id)
16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1660b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Request to authorize group negotiation - peer=" MACSTR
16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  GO Intent=%d  Intended Interface Address=" MACSTR
1662cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		" wps_method=%d  persistent_group=%d oob_pw_id=%u",
16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
1664cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		wps_method, persistent_group, oob_pw_id);
16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
1668b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Cannot authorize unknown P2P Device " MACSTR,
16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(peer_addr));
16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
167368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	if (p2p_prepare_channel(p2p, dev, force_freq, pref_freq, go_intent ==
167468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt				15) < 0)
1675a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
1676a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
167704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p->ssid_set = 0;
167804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (force_ssid) {
167904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "P2P: Forced SSID",
168004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  force_ssid, force_ssid_len);
168104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(p2p->ssid, force_ssid, force_ssid_len);
168204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->ssid_len = force_ssid_len;
168304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->ssid_set = 1;
168404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
168504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_NOT_YET_READY;
16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_USER_REJECTED;
16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_neg_req_sent = 0;
16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_state = UNKNOWN_GO;
16901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_set_dev_persistent(dev, persistent_group);
16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_intent = go_intent;
16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wps_method = wps_method;
1695cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	dev->oob_pw_id = oob_pw_id;
16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->status = P2P_SC_SUCCESS;
16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_add_dev_info(struct p2p_data *p2p, const u8 *addr,
17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      struct p2p_device *dev, struct p2p_message *msg)
17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1705fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	os_get_reltime(&dev->last_seen);
17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1707b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_copy_wps_info(p2p, dev, 0, msg);
17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->listen_channel) {
17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int freq;
17114b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		freq = p2p_channel_to_freq(msg->listen_channel[3],
17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   msg->listen_channel[4]);
17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freq < 0) {
1714b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Unknown peer Listen channel: "
17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"country=%c%c(0x%02x) reg_class=%u channel=%u",
17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[0],
17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[1],
17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[2],
17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[3],
17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[4]);
17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
1722b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Update peer " MACSTR
1723b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				" Listen channel: %u -> %u MHz",
17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(dev->info.p2p_device_addr),
17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev->listen_freq, freq);
17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->listen_freq = freq;
17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
173061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (msg->wfd_subelems) {
173161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_free(dev->info.wfd_subelems);
173261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		dev->info.wfd_subelems = wpabuf_dup(msg->wfd_subelems);
173361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
173461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_PROBE_REQ_ONLY) {
17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~P2P_DEV_PROBE_REQ_ONLY;
1737b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Completed device entry based on data from GO Negotiation Request");
17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
1739b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Created device entry based on GO Neg Req: "
17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MACSTR " dev_capab=0x%x group_capab=0x%x name='%s' "
17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"listen_freq=%d",
17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr),
17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->info.dev_capab, dev->info.group_capab,
17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->info.device_name, dev->listen_freq);
17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_GROUP_CLIENT_ONLY;
17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_USER_REJECTED) {
1750b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Do not report rejected device");
17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->dev_found(p2p->cfg->cb_ctx, addr, &dev->info,
17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    !(dev->flags & P2P_DEV_REPORTED_ONCE));
17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_build_ssid(struct p2p_data *p2p, u8 *ssid, size_t *ssid_len)
17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_random((char *) &ssid[P2P_WILDCARD_SSID_LEN], 2);
17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&ssid[P2P_WILDCARD_SSID_LEN + 2],
17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  p2p->cfg->ssid_postfix, p2p->cfg->ssid_postfix_len);
17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*ssid_len = P2P_WILDCARD_SSID_LEN + 2 + p2p->cfg->ssid_postfix_len;
17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_go_params(struct p2p_data *p2p, struct p2p_go_neg_results *params)
17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1772216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (p2p->ssid_set) {
1773216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		os_memcpy(params->ssid, p2p->ssid, p2p->ssid_len);
1774216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		params->ssid_len = p2p->ssid_len;
1775216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	} else {
1776216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p_build_ssid(p2p, params->ssid, &params->ssid_len);
1777216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
1778216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	p2p->ssid_set = 0;
1779216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
17802271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	p2p_random(params->passphrase, p2p->cfg->passphrase_len);
17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_go_complete(struct p2p_data *p2p, struct p2p_device *peer)
17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_go_neg_results res;
17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int go = peer->go_state == LOCAL_GO;
17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_channels intersection;
17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1791b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "GO Negotiation with " MACSTR " completed (%s will be GO)",
1792b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		MAC2STR(peer->info.p2p_device_addr), go ? "local end" : "peer");
17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&res, 0, sizeof(res));
17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.role_go = go;
17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(res.peer_device_addr, peer->info.p2p_device_addr, ETH_ALEN);
17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(res.peer_interface_addr, peer->intended_addr, ETH_ALEN);
17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.wps_method = peer->wps_method;
17991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) {
18001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN)
18011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			res.persistent_group = 2;
18021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		else
18031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			res.persistent_group = 1;
18041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (go) {
18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Setup AP mode for WPS provisioning */
18084b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		res.freq = p2p_channel_to_freq(p2p->op_reg_class,
18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       p2p->op_channel);
18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(res.ssid, p2p->ssid, p2p->ssid_len);
18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res.ssid_len = p2p->ssid_len;
18122271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		p2p_random(res.passphrase, p2p->cfg->passphrase_len);
18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res.freq = peer->oper_freq;
18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->ssid_len) {
18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(res.ssid, p2p->ssid, p2p->ssid_len);
18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res.ssid_len = p2p->ssid_len;
18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
182168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p_channels_dump(p2p, "own channels", &p2p->channels);
182268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p_channels_dump(p2p, "peer channels", &peer->channels);
18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_channels_intersect(&p2p->channels, &peer->channels,
18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       &intersection);
182568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	if (go) {
182668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		p2p_channels_remove_freqs(&intersection, &p2p->no_go_freq);
182768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		p2p_channels_dump(p2p, "intersection after no-GO removal",
182868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt				  &intersection);
182968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	}
18306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
18316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	p2p_channels_to_freqs(&intersection, res.freq_list,
18326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			      P2P_MAX_CHANNELS);
18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.peer_config_timeout = go ? peer->client_timeout : peer->go_timeout;
18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
18371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p->ssid_set = 0;
18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer->go_neg_req_sent = 0;
18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer->wps_method = WPS_NOT_READY;
1840cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	peer->oob_pw_id = 0;
1841413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt	wpabuf_free(peer->go_neg_conf);
1842413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt	peer->go_neg_conf = NULL;
18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_PROVISIONING);
18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->go_neg_completed(p2p->cfg->cb_ctx, &res);
18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_rx_p2p_action(struct p2p_data *p2p, const u8 *sa,
18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      const u8 *data, size_t len, int rx_freq)
18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1852b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "RX P2P Public Action from " MACSTR, MAC2STR(sa));
18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "P2P: P2P Public Action contents", data, len);
18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1)
18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data[0]) {
18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG_REQ:
18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_neg_req(p2p, sa, data + 1, len - 1, rx_freq);
18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG_RESP:
18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_neg_resp(p2p, sa, data + 1, len - 1, rx_freq);
18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG_CONF:
18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_neg_conf(p2p, sa, data + 1, len - 1);
18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITATION_REQ:
18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_invitation_req(p2p, sa, data + 1, len - 1,
18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   rx_freq);
18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITATION_RESP:
18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_invitation_resp(p2p, sa, data + 1, len - 1);
18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROV_DISC_REQ:
18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_prov_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROV_DISC_RESP:
18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_prov_disc_resp(p2p, sa, data + 1, len - 1);
18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_DEV_DISC_REQ:
18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_dev_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_DEV_DISC_RESP:
18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_dev_disc_resp(p2p, sa, data + 1, len - 1);
18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
1888b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Unsupported P2P Public Action frame type %d",
18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data[0]);
18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void p2p_rx_action_public(struct p2p_data *p2p, const u8 *da,
18961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				 const u8 *sa, const u8 *bssid, const u8 *data,
18971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				 size_t len, int freq)
18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1)
19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data[0]) {
19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_VENDOR_SPECIFIC:
19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data++;
19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len--;
1906a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt		if (len < 4)
19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
1908a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt		if (WPA_GET_BE32(data) != P2P_IE_VENDOR_TYPE)
19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1911a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt		data += 4;
1912a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt		len -= 4;
19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1914a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt		p2p_rx_p2p_action(p2p, sa, data, len, freq);
19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_INITIAL_REQ:
19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_initial_req(p2p, sa, data + 1, len - 1, freq);
19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_INITIAL_RESP:
19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_initial_resp(p2p, sa, data + 1, len - 1, freq);
19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_COMEBACK_REQ:
19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_comeback_req(p2p, sa, data + 1, len - 1, freq);
19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_COMEBACK_RESP:
19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_comeback_resp(p2p, sa, data + 1, len - 1, freq);
19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_rx_action(struct p2p_data *p2p, const u8 *da, const u8 *sa,
19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *bssid, u8 category,
19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *data, size_t len, int freq)
19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (category == WLAN_ACTION_PUBLIC) {
19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_action_public(p2p, da, sa, bssid, data, len, freq);
19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (category != WLAN_ACTION_VENDOR_SPECIFIC)
19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 4)
19458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1947a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt	if (WPA_GET_BE32(data) != P2P_IE_VENDOR_TYPE)
19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1949a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt	data += 4;
1950a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt	len -= 4;
19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P action frame */
1953b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "RX P2P Action from " MACSTR, MAC2STR(sa));
19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "P2P: P2P Action contents", data, len);
19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1)
19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data[0]) {
19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_NOA:
1960b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Received P2P Action - Notice of Absence");
19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO */
19628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PRESENCE_REQ:
19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_presence_req(p2p, da, sa, data + 1, len - 1, freq);
19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PRESENCE_RESP:
19678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_presence_resp(p2p, da, sa, data + 1, len - 1);
19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_DISC_REQ:
19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_disc_req(p2p, da, sa, data + 1, len - 1, freq);
19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
1973b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Received P2P Action - unknown type %u", data[0]);
19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_start(void *eloop_ctx, void *timeout_ctx)
19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == NULL)
19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1984661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	if (p2p->pending_listen_freq) {
1985661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		p2p_dbg(p2p, "Clear pending_listen_freq for p2p_go_neg_start");
1986661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		p2p->pending_listen_freq = 0;
1987661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	}
19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer->status = P2P_SC_SUCCESS;
1990661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	/*
1991661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	 * Set new timeout to make sure a previously set one does not expire
1992661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	 * too quickly while waiting for the GO Negotiation to complete.
1993661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	 */
1994661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	p2p_set_timeout(p2p, 0, 500000);
19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_connect_send(p2p, p2p->go_neg_peer);
19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_invite_start(void *eloop_ctx, void *timeout_ctx)
20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->invite_peer == NULL)
20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2004661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	if (p2p->pending_listen_freq) {
2005661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		p2p_dbg(p2p, "Clear pending_listen_freq for p2p_invite_start");
2006661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		p2p->pending_listen_freq = 0;
2007661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	}
20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
2009cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	p2p_invite_send(p2p, p2p->invite_peer, p2p->invite_go_dev_addr,
2010cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			p2p->invite_dev_pw_id);
20118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_add_dev_from_probe_req(struct p2p_data *p2p, const u8 *addr,
20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const u8 *ie, size_t ie_len)
20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
20198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg) < 0 || msg.p2p_attributes == NULL)
20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* not a P2P probe */
20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.ssid == NULL || msg.ssid[1] != P2P_WILDCARD_SSID_LEN ||
20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(msg.ssid + 2, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN)
20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    != 0) {
20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* The Probe Request is not part of P2P Device Discovery. It is
20318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * not known whether the source address of the frame is the P2P
20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Device Address or P2P Interface Address. Do not add a new
20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * peer entry based on this frames.
20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev) {
20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->country[0] == 0 && msg.listen_channel)
20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(dev->country, msg.listen_channel, 3);
2043fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		os_get_reltime(&dev->last_seen);
20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* already known */
20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_create_device(p2p, addr);
20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2054fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	os_get_reltime(&dev->last_seen);
20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_PROBE_REQ_ONLY;
20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.listen_channel) {
20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->country, msg.listen_channel, 3);
20594b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		dev->listen_freq = p2p_channel_to_freq(msg.listen_channel[3],
20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       msg.listen_channel[4]);
20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2063b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_copy_wps_info(p2p, dev, 1, &msg);
20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
206561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (msg.wfd_subelems) {
206661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_free(dev->info.wfd_subelems);
206761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
206861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
206961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
20708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2072b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Created device entry based on Probe Req: " MACSTR
20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" dev_capab=0x%x group_capab=0x%x name='%s' listen_freq=%d",
20748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(dev->info.p2p_device_addr), dev->info.dev_capab,
20758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.group_capab, dev->info.device_name,
20768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->listen_freq);
20778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_device * p2p_add_dev_from_go_neg_req(struct p2p_data *p2p,
20818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						const u8 *addr,
20828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						struct p2p_message *msg)
20838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev) {
2088fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		os_get_reltime(&dev->last_seen);
20898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return dev; /* already known */
20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_create_device(p2p, addr);
20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_add_dev_info(p2p, addr, dev, msg);
20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return dev;
20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int dev_type_match(const u8 *dev_type, const u8 *req_dev_type)
21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(dev_type, req_dev_type, WPS_DEV_TYPE_LEN) == 0)
21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(dev_type, req_dev_type, 2) == 0 &&
21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    WPA_GET_BE32(&req_dev_type[2]) == 0 &&
21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    WPA_GET_BE16(&req_dev_type[6]) == 0)
21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Category match with wildcard OUI/sub-category */
21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint dev_type_list_match(const u8 *dev_type, const u8 *req_dev_type[],
21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			size_t num_req_dev_type)
21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_req_dev_type; i++) {
21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev_type_match(dev_type, req_dev_type[i]))
21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 1;
21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_match_dev_type - Match local device type with requested type
21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wps: WPS TLVs from Probe Request frame (concatenated WPS IEs)
21308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 on match, 0 on mismatch
21318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
21328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function can be used to match the Requested Device Type attribute in
21338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPS IE with the local device types for deciding whether to reply to a Probe
21348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Request frame.
21358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_match_dev_type(struct p2p_data *p2p, struct wpabuf *wps)
21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wps_parse_attr attr;
21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wps_parse_msg(wps, &attr))
21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* assume no Requested Device Type attributes */
21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (attr.num_req_dev_type == 0)
21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* no Requested Device Type attributes -> match */
21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev_type_list_match(p2p->cfg->pri_dev_type, attr.req_dev_type,
21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				attr.num_req_dev_type))
21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Own Primary Device Type matches */
21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	for (i = 0; i < p2p->cfg->num_sec_dev_types; i++) {
21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev_type_list_match(p2p->cfg->sec_dev_type[i],
21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					attr.req_dev_type,
21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					attr.num_req_dev_type))
21556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return 1; /* Own Secondary Device Type matches */
21566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
21578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* No matching device type found */
21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2163a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidtstruct wpabuf * p2p_build_probe_resp_ies(struct p2p_data *p2p,
2164a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt					 const u8 *query_hash,
2165a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt					 u8 query_count)
21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
21688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
216904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	int pw_id = -1;
217061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t extra = 0;
217161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
217261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
217361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_probe_resp)
217461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		extra = wpabuf_len(p2p->wfd_ie_probe_resp);
217561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
21768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21772e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_PROBE_RESP_P2P])
21782e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_PROBE_RESP_P2P]);
21792e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
2180a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	if (query_count)
2181216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		extra += MAX_SVC_ADV_IE_LEN;
2182216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
218361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	buf = wpabuf_alloc(1000 + extra);
21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
218704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p->go_neg_peer) {
218804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/* Advertise immediate availability of WPS credential */
218904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		pw_id = p2p_wps_method_pw_id(p2p->go_neg_peer->wps_method);
219004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
219104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
219268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	if (p2p_build_wps_ie(p2p, buf, pw_id, 1) < 0) {
219368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		p2p_dbg(p2p, "Failed to build WPS IE for Probe Response");
219468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		wpabuf_free(buf);
219568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		return NULL;
219668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	}
21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
219861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
219961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_probe_resp)
220061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(buf, p2p->wfd_ie_probe_resp);
220161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
220261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
22032e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_PROBE_RESP_P2P])
22042e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		wpabuf_put_buf(buf,
22052e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			       p2p->vendor_elem[VENDOR_ELEM_PROBE_RESP_P2P]);
22062e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P IE */
22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(buf);
220904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_buf_add_capability(buf, p2p->dev_capab &
221004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			       ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 0);
22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval)
22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_ext_listen_timing(buf, p2p->ext_listen_period,
22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      p2p->ext_listen_interval);
22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_device_info(buf, p2p, NULL);
22158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(buf, len);
22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2217a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	if (query_count) {
2218a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		p2p_buf_add_service_instance(buf, p2p, query_count, query_hash,
2219216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt					     p2p->p2ps_adv_list);
2220216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
2221216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
22228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
22238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2226216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtstatic int p2p_service_find_asp(struct p2p_data *p2p, const u8 *hash)
2227216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt{
2228216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	struct p2ps_advertisement *adv_data;
2229a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	int any_wfa;
2230216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2231216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	p2p_dbg(p2p, "ASP find - ASP list: %p", p2p->p2ps_adv_list);
2232216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2233a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	/* Wildcard org.wi-fi.wfds matches any WFA spec defined service */
2234a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	any_wfa = os_memcmp(hash, p2p->wild_card_hash, P2PS_HASH_LEN) == 0;
2235216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2236216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_data = p2p->p2ps_adv_list;
2237216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	while (adv_data) {
2238216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (os_memcmp(hash, adv_data->hash, P2PS_HASH_LEN) == 0)
2239a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			return 1; /* exact hash match */
2240a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		if (any_wfa &&
2241a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		    os_strncmp(adv_data->svc_name, P2PS_WILD_HASH_STR,
2242a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			       os_strlen(P2PS_WILD_HASH_STR)) == 0)
2243a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			return 1; /* WFA service match */
2244216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		adv_data = adv_data->next;
2245216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
2246216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2247216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	return 0;
2248216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt}
2249216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2250216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
225104949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic enum p2p_probe_req_status
225204949598a23f501be6eec21697465fd46a28840aDmitry Shmidtp2p_reply_probe(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
2253a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		const u8 *bssid, const u8 *ie, size_t ie_len,
2254a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		unsigned int rx_freq)
22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ieee802_11_elems elems;
22578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
22588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ieee80211_mgmt *resp;
22591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_message msg;
22608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *ies;
2261a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	u8 channel, op_class;
22628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ieee802_11_parse_elems((u8 *) ie, ie_len, &elems, 0) ==
22648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ParseFailed) {
22658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Ignore invalid Probe Request frames */
2266ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt		p2p_dbg(p2p, "Could not parse Probe Request frame - ignore it");
226704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_MALFORMED;
22688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (elems.p2p == NULL) {
22718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* not a P2P probe - ignore it */
2272ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt		p2p_dbg(p2p, "Not a P2P probe - ignore it");
227304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_P2P;
22748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (dst && !is_broadcast_ether_addr(dst) &&
22771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    os_memcmp(dst, p2p->cfg->dev_addr, ETH_ALEN) != 0) {
22781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Not sent to the broadcast address or our P2P Device Address
22791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
2280ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt		p2p_dbg(p2p, "Probe Req DA " MACSTR " not ours - ignore it",
2281ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt			MAC2STR(dst));
228204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
22831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
22841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
22851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (bssid && !is_broadcast_ether_addr(bssid)) {
22861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Not sent to the Wildcard BSSID */
2287ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt		p2p_dbg(p2p, "Probe Req BSSID " MACSTR " not wildcard - ignore it",
2288ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt			MAC2STR(bssid));
228904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
22901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
22911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
22928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (elems.ssid == NULL || elems.ssid_len != P2P_WILDCARD_SSID_LEN ||
22938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(elems.ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) !=
22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0) {
22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* not using P2P Wildcard SSID - ignore */
2296ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt		p2p_dbg(p2p, "Probe Req not using P2P Wildcard SSID - ignore it");
229704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (supp_rates_11b_only(&elems)) {
23011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Indicates support for 11b rates only */
2302ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt		p2p_dbg(p2p, "Probe Req with 11b rates only supported - ignore it");
230304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_P2P;
23041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
23051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
23061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
23071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg) < 0) {
23081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Could not parse P2P attributes */
2309ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt		p2p_dbg(p2p, "Could not parse P2P attributes in Probe Req - ignore it");
231004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_P2P;
23111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
23121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2313216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (msg.service_hash && msg.service_hash_count) {
2314216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		const u8 *hash = msg.service_hash;
2315216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		u8 i;
2316a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		int p2ps_svc_found = 0;
2317216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
23184171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt		p2p_dbg(p2p, "in_listen=%d drv_in_listen=%d when received P2PS Probe Request at %u MHz; own Listen channel %u, pending listen freq %u MHz",
23194171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt			p2p->in_listen, p2p->drv_in_listen, rx_freq,
23204171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt			p2p->cfg->channel, p2p->pending_listen_freq);
23214171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt
23224171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt		if (!p2p->in_listen && !p2p->drv_in_listen &&
23234171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt		    p2p->pending_listen_freq && rx_freq &&
23244171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt		    rx_freq != p2p->pending_listen_freq) {
23254171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt			p2p_dbg(p2p, "Do not reply to Probe Request frame that was received on %u MHz while waiting to start Listen state on %u MHz",
23264171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt				rx_freq, p2p->pending_listen_freq);
23274171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt			p2p_parse_free(&msg);
23284171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt			return P2P_PREQ_NOT_LISTEN;
23294171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt		}
23304171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt
2331216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		for (i = 0; i < msg.service_hash_count; i++) {
2332216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			if (p2p_service_find_asp(p2p, hash)) {
2333a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt				p2p_dbg(p2p, "Service Hash match found: "
2334a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt					MACSTR, MAC2STR(hash));
2335a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt				p2ps_svc_found = 1;
2336a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt				break;
2337216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			}
2338216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			hash += P2PS_HASH_LEN;
2339216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		}
2340216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2341216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		/* Probed hash unknown */
2342a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		if (!p2ps_svc_found) {
2343a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			p2p_dbg(p2p, "No Service Hash match found");
2344216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			p2p_parse_free(&msg);
2345216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			return P2P_PREQ_NOT_PROCESSED;
2346216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		}
2347216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	} else {
2348216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		/* This is not a P2PS Probe Request */
2349216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p_dbg(p2p, "No P2PS Hash in Probe Request");
2350216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2351216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (!p2p->in_listen || !p2p->drv_in_listen) {
2352216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			/* not in Listen state - ignore Probe Request */
2353216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			p2p_dbg(p2p, "Not in Listen state (in_listen=%d drv_in_listen=%d) - ignore Probe Request",
2354216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				p2p->in_listen, p2p->drv_in_listen);
2355216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			p2p_parse_free(&msg);
2356216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			return P2P_PREQ_NOT_LISTEN;
2357216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		}
2358216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
2359216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
23601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (msg.device_id &&
236104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    os_memcmp(msg.device_id, p2p->cfg->dev_addr, ETH_ALEN) != 0) {
23621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Device ID did not match */
2363ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt		p2p_dbg(p2p, "Probe Req requested Device ID " MACSTR " did not match - ignore it",
2364ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt			MAC2STR(msg.device_id));
23651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_parse_free(&msg);
236604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
23671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
23681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Check Requested Device Type match */
23701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (msg.wps_attributes &&
23711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    !p2p_match_dev_type(p2p, msg.wps_attributes)) {
23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* No match with Requested Device Type */
2373ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt		p2p_dbg(p2p, "Probe Req requestred Device Type did not match - ignore it");
23741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_parse_free(&msg);
237504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
237804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (!p2p->cfg->send_probe_resp) {
237904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/* Response generated elsewhere */
2380ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt		p2p_dbg(p2p, "Probe Resp generated elsewhere - do not generate additional response");
2381a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		p2p_parse_free(&msg);
238204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
238304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2385b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Reply to P2P Probe Request in Listen state");
23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
23888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * We do not really have a specific BSS that this frame is advertising,
23898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * so build a frame that has some information in valid format. This is
23908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * really only used for discovery purposes, not to learn exact BSS
23918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * parameters.
23928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
2393a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	ies = p2p_build_probe_resp_ies(p2p, msg.service_hash,
2394a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt				       msg.service_hash_count);
2395a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	p2p_parse_free(&msg);
23968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ies == NULL)
239704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
23988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = wpabuf_alloc(200 + wpabuf_len(ies));
24008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL) {
24018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(ies);
240204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
24038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24054171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt	resp = wpabuf_put(buf, offsetof(struct ieee80211_mgmt,
24064171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt					u.probe_resp.variable));
24078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
24098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   (WLAN_FC_STYPE_PROBE_RESP << 4));
24108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(resp->da, addr, ETH_ALEN);
24118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(resp->sa, p2p->cfg->dev_addr, ETH_ALEN);
24128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(resp->bssid, p2p->cfg->dev_addr, ETH_ALEN);
24138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->u.probe_resp.beacon_int = host_to_le16(100);
24148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* hardware or low-level driver will setup seq_ctrl and timestamp */
24158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->u.probe_resp.capab_info =
24168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		host_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE |
24178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     WLAN_CAPABILITY_PRIVACY |
24188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     WLAN_CAPABILITY_SHORT_SLOT_TIME);
24198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_SSID);
24218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, P2P_WILDCARD_SSID_LEN);
24228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(buf, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
24238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_SUPP_RATES);
24258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 8);
24268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, (60 / 5) | 0x80);
24278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 90 / 5);
24288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, (120 / 5) | 0x80);
24298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 180 / 5);
24308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, (240 / 5) | 0x80);
24318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 360 / 5);
24328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 480 / 5);
24338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 540 / 5);
24348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2435a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	if (!rx_freq) {
2436a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		channel = p2p->cfg->channel;
2437a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	} else if (p2p_freq_to_channel(rx_freq, &op_class, &channel)) {
2438a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		wpabuf_free(ies);
2439a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		wpabuf_free(buf);
2440a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
2441a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	}
2442a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt
24438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_DS_PARAMS);
24448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 1);
2445a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	wpabuf_put_u8(buf, channel);
24468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_buf(buf, ies);
24488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(ies);
24498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2450a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	p2p->cfg->send_probe_resp(p2p->cfg->cb_ctx, buf, rx_freq);
24518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(buf);
245304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
2454a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	return P2P_PREQ_PROCESSED;
24558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
245804949598a23f501be6eec21697465fd46a28840aDmitry Shmidtenum p2p_probe_req_status
245904949598a23f501be6eec21697465fd46a28840aDmitry Shmidtp2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
2460a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		 const u8 *bssid, const u8 *ie, size_t ie_len,
2461a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		 unsigned int rx_freq)
24628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
246304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	enum p2p_probe_req_status res;
246404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
24658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_add_dev_from_probe_req(p2p, addr, ie, ie_len);
24668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2467a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	res = p2p_reply_probe(p2p, addr, dst, bssid, ie, ie_len, rx_freq);
2468a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	if (res != P2P_PREQ_PROCESSED && res != P2P_PREQ_NOT_PROCESSED)
2469a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		return res;
24708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2471a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	/*
2472a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	 * Activate a pending GO Negotiation/Invite flow if a received Probe
2473a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	 * Request frame is from an expected peer. Some devices may share the
2474a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	 * same address for P2P and non-P2P STA running simultaneously. The
2475a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	 * P2P_PREQ_PROCESSED and P2P_PREQ_NOT_PROCESSED p2p_reply_probe()
2476a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	 * return values verified above ensure we are handling a Probe Request
2477a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	 * frame from a P2P peer.
2478a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	 */
24798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((p2p->state == P2P_CONNECT || p2p->state == P2P_CONNECT_LISTEN) &&
24808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    p2p->go_neg_peer &&
24818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(addr, p2p->go_neg_peer->info.p2p_device_addr, ETH_ALEN)
24829cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt	    == 0 &&
24839cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt	    !(p2p->go_neg_peer->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM)) {
24848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Received a Probe Request from GO Negotiation peer */
2485b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Found GO Negotiation peer - try to start GO negotiation from timeout");
24869cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt		eloop_cancel_timeout(p2p_go_neg_start, p2p, NULL);
24878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(0, 0, p2p_go_neg_start, p2p, NULL);
2488a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		return res;
24898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((p2p->state == P2P_INVITE || p2p->state == P2P_INVITE_LISTEN) &&
24928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    p2p->invite_peer &&
24933c4793790bf06f1fe08a2ddf604c9caa855151f1Dmitry Shmidt	    (p2p->invite_peer->flags & P2P_DEV_WAIT_INV_REQ_ACK) &&
24948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(addr, p2p->invite_peer->info.p2p_device_addr, ETH_ALEN)
24958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    == 0) {
24968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Received a Probe Request from Invite peer */
2497b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Found Invite peer - try to start Invite from timeout");
24987f93d6fa14a343127754c33a03cf2f641b6ff6e4Dmitry Shmidt		eloop_cancel_timeout(p2p_invite_start, p2p, NULL);
24998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(0, 0, p2p_invite_start, p2p, NULL);
2500a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		return res;
25018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
250304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return res;
25048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_assoc_req_ie_wlan_ap(struct p2p_data *p2p, const u8 *bssid,
25088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    u8 *buf, size_t len, struct wpabuf *p2p_ie)
25098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *tmp;
25118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *lpos;
25128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t tmplen;
25138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
25148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 group_capab;
251505df46a3aef489a33f92efb91b091c1aa6d16f95Dmitry Shmidt	struct p2p_message msg;
25168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_ie == NULL)
25188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* WLAN AP is not a P2P manager */
25198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
252005df46a3aef489a33f92efb91b091c1aa6d16f95Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
252105df46a3aef489a33f92efb91b091c1aa6d16f95Dmitry Shmidt	if (p2p_parse_p2p_ie(p2p_ie, &msg) < 0)
252205df46a3aef489a33f92efb91b091c1aa6d16f95Dmitry Shmidt		return 0;
252305df46a3aef489a33f92efb91b091c1aa6d16f95Dmitry Shmidt
252405df46a3aef489a33f92efb91b091c1aa6d16f95Dmitry Shmidt	p2p_dbg(p2p, "BSS P2P manageability %s",
252505df46a3aef489a33f92efb91b091c1aa6d16f95Dmitry Shmidt		msg.manageability ? "enabled" : "disabled");
252605df46a3aef489a33f92efb91b091c1aa6d16f95Dmitry Shmidt
252705df46a3aef489a33f92efb91b091c1aa6d16f95Dmitry Shmidt	if (!msg.manageability)
252805df46a3aef489a33f92efb91b091c1aa6d16f95Dmitry Shmidt		return 0;
252905df46a3aef489a33f92efb91b091c1aa6d16f95Dmitry Shmidt
25308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
25318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (Re)Association Request - P2P IE
25328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Capability attribute (shall be present)
25338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Interface attribute (present if concurrent device and
25348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *	P2P Management is enabled)
25358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
25368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp = wpabuf_alloc(200);
25378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp == NULL)
25388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
25398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	lpos = p2p_buf_add_ie_hdr(tmp);
25418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group_capab = 0;
25428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->num_groups > 0) {
25438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group_capab |= P2P_GROUP_CAPAB_GROUP_OWNER;
25448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) &&
25458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED) &&
25468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    p2p->cross_connect)
25478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
25488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_capability(tmp, p2p->dev_capab, group_capab);
25508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) &&
25518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED))
25528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_p2p_interface(tmp, p2p);
25538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(tmp, lpos);
25548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmplen = wpabuf_len(tmp);
25568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmplen > len)
25578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = -1;
25588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
25598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(buf, wpabuf_head(tmp), tmplen);
25608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = tmplen;
25618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(tmp);
25638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
25658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_assoc_req_ie(struct p2p_data *p2p, const u8 *bssid, u8 *buf,
25698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     size_t len, int p2p_group, struct wpabuf *p2p_ie)
25708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *tmp;
25728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *lpos;
25738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *peer;
25748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t tmplen;
25758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
257661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t extra = 0;
25778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p_group)
25798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return p2p_assoc_req_ie_wlan_ap(p2p, bssid, buf, len, p2p_ie);
25808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
258161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
258261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_assoc_req)
258361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		extra = wpabuf_len(p2p->wfd_ie_assoc_req);
258461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
258561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
25862e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_REQ])
25872e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_REQ]);
25882e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
25898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
25908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (Re)Association Request - P2P IE
25918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Capability attribute (shall be present)
25928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Extended Listen Timing (may be present)
25938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Device Info attribute (shall be present)
25948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
259561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	tmp = wpabuf_alloc(200 + extra);
25968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp == NULL)
25978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
25988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
259961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
260061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_assoc_req)
260161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(tmp, p2p->wfd_ie_assoc_req);
260261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
260361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
26042e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_REQ])
26052e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		wpabuf_put_buf(tmp,
26062e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			       p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_REQ]);
26072e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
26088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer = bssid ? p2p_get_device(p2p, bssid) : NULL;
26098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	lpos = p2p_buf_add_ie_hdr(tmp);
26118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_capability(tmp, p2p->dev_capab, 0);
26128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval)
26138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_ext_listen_timing(tmp, p2p->ext_listen_period,
26148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      p2p->ext_listen_interval);
26158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_device_info(tmp, p2p, peer);
26168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(tmp, lpos);
26178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmplen = wpabuf_len(tmp);
26198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmplen > len)
26208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = -1;
26218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
26228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(buf, wpabuf_head(tmp), tmplen);
26238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = tmplen;
26248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(tmp);
26268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
26288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_scan_result_text(const u8 *ies, size_t ies_len, char *buf, char *end)
26328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *p2p_ie;
26348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
26358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len, P2P_IE_VENDOR_TYPE);
26378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_ie == NULL)
26388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
26398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = p2p_attr_text(p2p_ie, buf, end);
26418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(p2p_ie);
26428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
26438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2646216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtstruct p2ps_advertisement *
2647216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtp2p_service_p2ps_id(struct p2p_data *p2p, u32 adv_id)
2648216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt{
2649216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	struct p2ps_advertisement *adv_data;
2650216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2651216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (!p2p)
2652216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		return NULL;
2653216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2654216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_data = p2p->p2ps_adv_list;
2655216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	while (adv_data) {
2656216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (adv_data->id == adv_id)
2657216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			return adv_data;
2658216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		adv_data = adv_data->next;
2659216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
2660216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2661216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	return NULL;
2662216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt}
2663216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2664216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2665216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtint p2p_service_del_asp(struct p2p_data *p2p, u32 adv_id)
2666216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt{
2667216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	struct p2ps_advertisement *adv_data;
2668216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	struct p2ps_advertisement **prior;
2669216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2670216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (!p2p)
2671216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		return -1;
2672216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2673216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_data = p2p->p2ps_adv_list;
2674216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	prior = &p2p->p2ps_adv_list;
2675216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	while (adv_data) {
2676216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (adv_data->id == adv_id) {
2677216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			p2p_dbg(p2p, "Delete ASP adv_id=0x%x", adv_id);
2678216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			*prior = adv_data->next;
2679216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			os_free(adv_data);
2680216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			return 0;
2681216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		}
2682216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		prior = &adv_data->next;
2683216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		adv_data = adv_data->next;
2684216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
2685216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2686216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	return -1;
2687216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt}
2688216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2689216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2690216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtint p2p_service_add_asp(struct p2p_data *p2p, int auto_accept, u32 adv_id,
2691216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			const char *adv_str, u8 svc_state, u16 config_methods,
2692216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			const char *svc_info)
2693216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt{
2694216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	struct p2ps_advertisement *adv_data, *tmp, **prev;
2695216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	u8 buf[P2PS_HASH_LEN];
2696216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	size_t adv_data_len, adv_len, info_len = 0;
2697216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2698216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (!p2p || !adv_str || !adv_str[0])
2699216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		return -1;
2700216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2701216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (!(config_methods & p2p->cfg->config_methods)) {
2702216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p_dbg(p2p, "Config methods not supported svc: 0x%x dev: 0x%x",
2703216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			config_methods, p2p->cfg->config_methods);
2704216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		return -1;
2705216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
2706216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2707216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (!p2ps_gen_hash(p2p, adv_str, buf))
2708216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		return -1;
2709216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2710216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (svc_info)
2711216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		info_len = os_strlen(svc_info);
2712216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_len = os_strlen(adv_str);
2713216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_data_len = sizeof(struct p2ps_advertisement) + adv_len + 1 +
2714216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		info_len + 1;
2715216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2716216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_data = os_zalloc(adv_data_len);
2717216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (!adv_data)
2718216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		return -1;
2719216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2720216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	os_memcpy(adv_data->hash, buf, P2PS_HASH_LEN);
2721216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_data->id = adv_id;
2722216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_data->state = svc_state;
2723216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_data->config_methods = config_methods & p2p->cfg->config_methods;
2724216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_data->auto_accept = (u8) auto_accept;
2725216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	os_memcpy(adv_data->svc_name, adv_str, adv_len);
2726216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2727216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (svc_info && info_len) {
2728216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		adv_data->svc_info = &adv_data->svc_name[adv_len + 1];
2729216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		os_memcpy(adv_data->svc_info, svc_info, info_len);
2730216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
2731216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2732216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	/*
2733216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	 * Group Advertisements by service string. They do not need to be
2734216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	 * sorted, but groups allow easier Probe Response instance grouping
2735216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	 */
2736216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	tmp = p2p->p2ps_adv_list;
2737216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	prev = &p2p->p2ps_adv_list;
2738216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	while (tmp) {
2739216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (tmp->id == adv_data->id) {
2740216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			if (os_strcmp(tmp->svc_name, adv_data->svc_name) != 0) {
2741216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				os_free(adv_data);
2742216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				return -1;
2743216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			}
2744216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			adv_data->next = tmp->next;
2745216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			*prev = adv_data;
2746216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			os_free(tmp);
2747216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			goto inserted;
2748216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		} else {
2749216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			if (os_strcmp(tmp->svc_name, adv_data->svc_name) == 0) {
2750216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				adv_data->next = tmp->next;
2751216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				tmp->next = adv_data;
2752216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				goto inserted;
2753216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			}
2754216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		}
2755216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		prev = &tmp->next;
2756216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		tmp = tmp->next;
2757216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
2758216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2759216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	/* No svc_name match found */
2760216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_data->next = p2p->p2ps_adv_list;
2761216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	p2p->p2ps_adv_list = adv_data;
2762216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2763216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtinserted:
2764216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	p2p_dbg(p2p,
2765216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		"Added ASP advertisement adv_id=0x%x config_methods=0x%x svc_state=0x%x adv_str='%s'",
2766216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		adv_id, adv_data->config_methods, svc_state, adv_str);
2767216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2768216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	return 0;
2769216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt}
2770216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2771216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2772dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidtvoid p2p_service_flush_asp(struct p2p_data *p2p)
2773dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt{
2774dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt	struct p2ps_advertisement *adv, *prev;
2775dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt
2776dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt	if (!p2p)
2777dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt		return;
2778dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt
2779dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt	adv = p2p->p2ps_adv_list;
2780dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt	while (adv) {
2781dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt		prev = adv;
2782dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt		adv = adv->next;
2783dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt		os_free(prev);
2784dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt	}
2785dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt
2786dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt	p2p->p2ps_adv_list = NULL;
2787dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt	p2p_dbg(p2p, "All ASP advertisements flushed");
2788dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt}
2789dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt
2790dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt
279104949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint p2p_parse_dev_addr_in_p2p_ie(struct wpabuf *p2p_ie, u8 *dev_addr)
2792c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{
2793c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	struct p2p_message msg;
2794c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
2795c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
279604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p_parse_p2p_ie(p2p_ie, &msg))
2797c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return -1;
2798c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
279904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (msg.p2p_device_addr) {
280004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(dev_addr, msg.p2p_device_addr, ETH_ALEN);
280104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 0;
280204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	} else if (msg.device_id) {
280304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(dev_addr, msg.device_id, ETH_ALEN);
280404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 0;
2805c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
280604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return -1;
280704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
2808c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
280904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
281004949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint p2p_parse_dev_addr(const u8 *ies, size_t ies_len, u8 *dev_addr)
281104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
281204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct wpabuf *p2p_ie;
281304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	int ret;
281404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
281504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
281604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					     P2P_IE_VENDOR_TYPE);
281704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p_ie == NULL)
281804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return -1;
281904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	ret = p2p_parse_dev_addr_in_p2p_ie(p2p_ie, dev_addr);
2820c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	wpabuf_free(p2p_ie);
282104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return ret;
2822c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt}
2823c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
2824c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
28258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_clear_go_neg(struct p2p_data *p2p)
28268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer = NULL;
28288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
28298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_IDLE);
28308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_wps_success_cb(struct p2p_data *p2p, const u8 *mac_addr)
28348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == NULL) {
2836b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "No pending Group Formation - ignore WPS registration success notification");
28378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* No pending Group Formation */
28388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(mac_addr, p2p->go_neg_peer->intended_addr, ETH_ALEN) !=
28418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0) {
2842b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Ignore WPS registration success notification for "
2843b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			MACSTR " (GO Negotiation peer " MACSTR ")",
28448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(mac_addr),
28458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(p2p->go_neg_peer->intended_addr));
28468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* Ignore unexpected peer address */
28478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2849b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Group Formation completed successfully with " MACSTR,
28508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(mac_addr));
28518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_go_neg(p2p);
28538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_group_formation_failed(struct p2p_data *p2p)
28578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == NULL) {
2859b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "No pending Group Formation - ignore group formation failure notification");
28608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* No pending Group Formation */
28618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2863b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Group Formation failed with " MACSTR,
28648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(p2p->go_neg_peer->intended_addr));
28658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_go_neg(p2p);
28678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_data * p2p_init(const struct p2p_config *cfg)
28718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p;
28738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28742271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	if (cfg->max_peers < 1 ||
28752271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	    cfg->passphrase_len < 8 || cfg->passphrase_len > 63)
28768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
28778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p = os_zalloc(sizeof(*p2p) + sizeof(*cfg));
28798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p == NULL)
28808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
28818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg = (struct p2p_config *) (p2p + 1);
28828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg, cfg, sizeof(*cfg));
28838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->dev_name)
28848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->dev_name = os_strdup(cfg->dev_name);
28858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->manufacturer)
28868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->manufacturer = os_strdup(cfg->manufacturer);
28878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->model_name)
28888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_name = os_strdup(cfg->model_name);
28898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->model_number)
28908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_number = os_strdup(cfg->model_number);
28918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->serial_number)
28928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->serial_number = os_strdup(cfg->serial_number);
289304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (cfg->pref_chan) {
289404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->cfg->pref_chan = os_malloc(cfg->num_pref_chan *
289504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt						sizeof(struct p2p_channel));
289604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (p2p->cfg->pref_chan) {
289704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			os_memcpy(p2p->cfg->pref_chan, cfg->pref_chan,
289804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  cfg->num_pref_chan *
289904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  sizeof(struct p2p_channel));
290004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		} else
290104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			p2p->cfg->num_pref_chan = 0;
290204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
290304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
2904216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	p2ps_gen_hash(p2p, P2PS_WILD_HASH_STR, p2p->wild_card_hash);
2905216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
29068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->min_disc_int = 1;
29078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->max_disc_int = 3;
2908d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p->max_disc_tu = -1;
29098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2910661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	if (os_get_random(&p2p->next_tie_breaker, 1) < 0)
2911661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		p2p->next_tie_breaker = 0;
29128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->next_tie_breaker &= 0x01;
29138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->sd_request)
29148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_SERVICE_DISCOVERY;
29158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->dev_capab |= P2P_DEV_CAPAB_INVITATION_PROCEDURE;
29168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->concurrent_operations)
29178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_CONCURRENT_OPER;
29188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->dev_capab |= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
29198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_init(&p2p->devices);
29218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(P2P_PEER_EXPIRATION_INTERVAL, 0,
29238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p_expiration_timeout, p2p, NULL);
29248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
292561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->go_timeout = 100;
292661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->client_timeout = 20;
292713ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt	p2p->num_p2p_sd_queries = 0;
292861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
292968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p_dbg(p2p, "initialized");
293068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p_channels_dump(p2p, "channels", &p2p->cfg->channels);
293168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p_channels_dump(p2p, "cli_channels", &p2p->cfg->cli_channels);
293268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt
29338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p;
29348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_deinit(struct p2p_data *p2p)
29388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
293961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
294061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_beacon);
294161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_probe_req);
294261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_probe_resp);
294361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_assoc_req);
294461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_invitation);
294561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_prov_disc_req);
294661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_prov_disc_resp);
294761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_go_neg);
294861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_dev_info);
294961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_assoc_bssid);
295061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_coupled_sink_info);
295161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
295261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
29538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_expiration_timeout, p2p, NULL);
29548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_ext_listen_timeout, p2p, NULL);
29558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
29569cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt	eloop_cancel_timeout(p2p_go_neg_start, p2p, NULL);
29576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	eloop_cancel_timeout(p2p_go_neg_wait_timeout, p2p, NULL);
29588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_flush(p2p);
29598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_req_dev_types(p2p);
29608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->dev_name);
29618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->manufacturer);
29628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_name);
29638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_number);
29648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->serial_number);
296504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	os_free(p2p->cfg->pref_chan);
29668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->groups);
2967a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	p2ps_prov_free(p2p);
29688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(p2p->sd_resp);
29698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->after_scan_tx);
29708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_remove_wps_vendor_extensions(p2p);
297168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	os_free(p2p->no_go_freq.range);
2972dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt	p2p_service_flush_asp(p2p);
2973216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
29748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p);
29758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_flush(struct p2p_data *p2p)
29798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev, *prev;
298104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_stop_find(p2p);
29828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each_safe(dev, prev, &p2p->devices, struct p2p_device,
29838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      list) {
29848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dl_list_del(&dev->list);
29858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_device_free(p2p, dev);
29868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_sd_queries(p2p);
29888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->after_scan_tx);
29898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->after_scan_tx = NULL;
29908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_unauthorize(struct p2p_data *p2p, const u8 *addr)
29948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
29968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
29988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
29998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
30008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3001b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Unauthorizing " MACSTR, MAC2STR(addr));
30028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (p2p->go_neg_peer == dev) {
30046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		eloop_cancel_timeout(p2p_go_neg_wait_timeout, p2p, NULL);
30058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->go_neg_peer = NULL;
30066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
30078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wps_method = WPS_NOT_READY;
3009cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	dev->oob_pw_id = 0;
30108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE;
30118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM;
30128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Check if after_scan_tx is for this peer. If so free it */
30148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->after_scan_tx &&
30158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(addr, p2p->after_scan_tx->dst, ETH_ALEN) == 0) {
30168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p2p->after_scan_tx);
30178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = NULL;
30188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
30218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_dev_name(struct p2p_data *p2p, const char *dev_name)
30258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->dev_name);
30278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev_name) {
30288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->dev_name = os_strdup(dev_name);
30298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->dev_name == NULL)
30308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
30318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
30328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->dev_name = NULL;
30338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
30348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_manufacturer(struct p2p_data *p2p, const char *manufacturer)
30388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->manufacturer);
30408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->manufacturer = NULL;
30418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (manufacturer) {
30428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->manufacturer = os_strdup(manufacturer);
30438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->manufacturer == NULL)
30448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
30458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
30488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_model_name(struct p2p_data *p2p, const char *model_name)
30528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_name);
30548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->model_name = NULL;
30558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (model_name) {
30568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_name = os_strdup(model_name);
30578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->model_name == NULL)
30588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
30598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
30628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_model_number(struct p2p_data *p2p, const char *model_number)
30668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_number);
30688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->model_number = NULL;
30698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (model_number) {
30708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_number = os_strdup(model_number);
30718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->model_number == NULL)
30728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
30738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
30768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_serial_number(struct p2p_data *p2p, const char *serial_number)
30808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->serial_number);
30828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->serial_number = NULL;
30838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (serial_number) {
30848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->serial_number = os_strdup(serial_number);
30858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->serial_number == NULL)
30868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
30878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
30908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_config_methods(struct p2p_data *p2p, u16 config_methods)
30948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->config_methods = config_methods;
30968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_uuid(struct p2p_data *p2p, const u8 *uuid)
31008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->uuid, uuid, 16);
31028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_pri_dev_type(struct p2p_data *p2p, const u8 *pri_dev_type)
31068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->pri_dev_type, pri_dev_type, 8);
31088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
31098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_sec_dev_types(struct p2p_data *p2p, const u8 dev_types[][8],
31138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  size_t num_dev_types)
31148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (num_dev_types > P2P_SEC_DEVICE_TYPES)
31168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num_dev_types = P2P_SEC_DEVICE_TYPES;
31178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->num_sec_dev_types = num_dev_types;
31188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->sec_dev_type, dev_types, num_dev_types * 8);
31198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
31208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_remove_wps_vendor_extensions(struct p2p_data *p2p)
31248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
31268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
31288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(p2p->wps_vendor_ext[i]);
31298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->wps_vendor_ext[i] = NULL;
31308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_add_wps_vendor_extension(struct p2p_data *p2p,
31358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const struct wpabuf *vendor_ext)
31368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
31388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (vendor_ext == NULL)
31408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
31418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
31438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->wps_vendor_ext[i] == NULL)
31448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
31458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (i >= P2P_MAX_WPS_VENDOR_EXT)
31478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
31488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->wps_vendor_ext[i] = wpabuf_dup(vendor_ext);
31508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->wps_vendor_ext[i] == NULL)
31518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
31528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
31548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_country(struct p2p_data *p2p, const char *country)
31588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->country, country, 3);
31608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
31618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int p2p_pre_find_operation(struct p2p_data *p2p, struct p2p_device *dev)
31656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
31666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (dev->sd_pending_bcast_queries == 0) {
31676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		/* Initialize with total number of registered broadcast
31686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 * SD queries. */
31696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		dev->sd_pending_bcast_queries = p2p->num_p2p_sd_queries;
31706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
31716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
31726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (p2p_start_sd(p2p, dev) == 0)
31736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 1;
31746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
31756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (dev->req_config_methods &&
31766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	    !(dev->flags & P2P_DEV_PD_FOR_JOIN)) {
31776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_dbg(p2p, "Send pending Provision Discovery Request to "
31786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			MACSTR " (config methods 0x%x)",
31796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			MAC2STR(dev->info.p2p_device_addr),
31806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			dev->req_config_methods);
31816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (p2p_send_prov_disc_req(p2p, dev, 0, 0) == 0)
31826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return 1;
31836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
31846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
31856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return 0;
31866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
31876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
31886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
31898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_continue_find(struct p2p_data *p2p)
31908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
31926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	int found;
31936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
31948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_SEARCH);
31956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
31966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	/* Continue from the device following the last iteration */
31976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	found = 0;
31988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
31996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (dev == p2p->last_p2p_find_oper) {
32006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			found = 1;
32016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			continue;
32026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		}
32036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (!found)
32046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			continue;
32056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (p2p_pre_find_operation(p2p, dev) > 0) {
32066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			p2p->last_p2p_find_oper = dev;
32076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return;
320813ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt		}
32096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
321013ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt
32116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	/*
32126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * Wrap around to the beginning of the list and continue until the last
32136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * iteration device.
32146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 */
32156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
32166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (p2p_pre_find_operation(p2p, dev) > 0) {
32176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			p2p->last_p2p_find_oper = dev;
321813ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt			return;
32198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
32206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (dev == p2p->last_p2p_find_oper)
32216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			break;
32228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3224d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p_listen_in_find(p2p, 1);
32258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_sd_cb(struct p2p_data *p2p, int success)
32298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3230b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Service Discovery Query TX callback: success=%d",
32318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
32328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
32338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!success) {
32356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (p2p->sd_peer)
32366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
323713ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt		p2p->sd_peer = NULL;
3238216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (p2p->state != P2P_IDLE)
3239216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			p2p_continue_find(p2p);
32408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
32418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->sd_peer == NULL) {
3244b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "No SD peer entry known");
3245216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (p2p->state != P2P_IDLE)
3246216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			p2p_continue_find(p2p);
32478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
32488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3250807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	if (p2p->sd_query && p2p->sd_query->for_all_peers) {
3251661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		/* Update the pending broadcast SD query count for this device
3252661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		 */
3253661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		p2p->sd_peer->sd_pending_bcast_queries--;
3254661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt
3255661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		/*
3256661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		 * If there are no pending broadcast queries for this device,
3257661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		 * mark it as done (-1).
3258661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		 */
3259661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		if (p2p->sd_peer->sd_pending_bcast_queries == 0)
3260661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt			p2p->sd_peer->sd_pending_bcast_queries = -1;
3261661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	}
3262661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt
32638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Wait for response from the peer */
32648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_SD_DURING_FIND);
32658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_timeout(p2p, 0, 200000);
32668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
326875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
326975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen/**
327075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen * p2p_retry_pd - Retry any pending provision disc requests in IDLE state
327175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen * @p2p: P2P module context from p2p_init()
327275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen */
32731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void p2p_retry_pd(struct p2p_data *p2p)
327475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
327575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	struct p2p_device *dev;
327675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
327775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
327875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * Retry the prov disc req attempt only for the peer that the user had
3279d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	 * requested.
328075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
328175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
328275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
328375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (os_memcmp(p2p->pending_pd_devaddr,
328475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			      dev->info.p2p_device_addr, ETH_ALEN) != 0)
328575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			continue;
328675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (!dev->req_config_methods)
328775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			continue;
328875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
3289b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Send pending Provision Discovery Request to "
329075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			MACSTR " (config methods 0x%x)",
329175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			MAC2STR(dev->info.p2p_device_addr),
329275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			dev->req_config_methods);
3293d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		p2p_send_prov_disc_req(p2p, dev,
3294051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt				       dev->flags & P2P_DEV_PD_FOR_JOIN,
3295051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt				       p2p->pd_force_freq);
329675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
329775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	}
329875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
329975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
330075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
33018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_prov_disc_cb(struct p2p_data *p2p, int success)
33028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3303b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Provision Discovery Request TX callback: success=%d",
33048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
330575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
330675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
330775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * Postpone resetting the pending action state till after we actually
330875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * time out. This allows us to take some action like notifying any
330975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * interested parties about no response to the request.
331075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 *
331175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * When the timer (below) goes off we check in IDLE, SEARCH, or
331275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * LISTEN_ONLY state, which are the only allowed states to issue a PD
331375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * requests in, if this was still pending and then raise notification.
331475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
33158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!success) {
331775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pending_action_state = P2P_NO_PENDING_ACTION;
331875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
331961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->user_initiated_pd &&
332061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		    (p2p->state == P2P_SEARCH || p2p->state == P2P_LISTEN_ONLY))
332161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		{
332261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			/* Retry request from timeout to avoid busy loops */
332361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p->pending_action_state = P2P_PENDING_PD;
332461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p_set_timeout(p2p, 0, 50000);
332561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		} else if (p2p->state != P2P_IDLE)
33268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_continue_find(p2p);
332775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		else if (p2p->user_initiated_pd) {
332875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p->pending_action_state = P2P_PENDING_PD;
332975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_set_timeout(p2p, 0, 300000);
333075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		}
33318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
33328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
333475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
333575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * This postponing, of resetting pending_action_state, needs to be
333675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * done only for user initiated PD requests and not internal ones.
333775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
333875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p->user_initiated_pd)
333975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pending_action_state = P2P_PENDING_PD;
334075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	else
334175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pending_action_state = P2P_NO_PENDING_ACTION;
334275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
33438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Wait for response from the peer */
33448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_SEARCH)
33458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_PD_DURING_FIND);
33468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_timeout(p2p, 0, 200000);
33478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3350216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtstatic int p2p_check_after_scan_tx_continuation(struct p2p_data *p2p)
3351216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt{
3352216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (p2p->after_scan_tx_in_progress) {
3353216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p->after_scan_tx_in_progress = 0;
3354216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (p2p->start_after_scan != P2P_AFTER_SCAN_NOTHING &&
3355216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		    p2p_run_after_scan(p2p))
3356216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			return 1;
3357216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (p2p->state == P2P_SEARCH) {
3358216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			p2p_dbg(p2p, "Continue find after after_scan_tx completion");
3359216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			p2p_continue_find(p2p);
3360216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		}
3361216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
3362216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3363216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	return 0;
3364216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt}
3365216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3366216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3367216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtstatic void p2p_prov_disc_resp_cb(struct p2p_data *p2p, int success)
3368216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt{
3369216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	p2p_dbg(p2p, "Provision Discovery Response TX callback: success=%d",
3370216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		success);
3371216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3372216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (p2p->send_action_in_progress) {
3373216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p->send_action_in_progress = 0;
3374216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
3375216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
3376216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3377216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
3378216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3379216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (!success)
3380216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		goto continue_search;
3381216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3382216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (!p2p->cfg->prov_disc_resp_cb ||
3383216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	    p2p->cfg->prov_disc_resp_cb(p2p->cfg->cb_ctx) < 1)
3384216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		goto continue_search;
3385216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3386216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	p2p_dbg(p2p,
3387216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		"Post-Provision Discovery operations started - do not try to continue other P2P operations");
3388216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	return;
3389216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3390216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtcontinue_search:
3391216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	p2p_check_after_scan_tx_continuation(p2p);
3392216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt}
3393216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3394216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
33958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_scan_res_handler(struct p2p_data *p2p, const u8 *bssid, int freq,
3396fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			 struct os_reltime *rx_time, int level, const u8 *ies,
3397a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			 size_t ies_len)
33988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3399fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (os_reltime_before(rx_time, &p2p->find_start)) {
3400f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		/*
3401f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * The driver may have cached (e.g., in cfg80211 BSS table) the
3402f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * scan results for relatively long time. To avoid reporting
3403f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * stale information, update P2P peers only based on results
3404f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * that have based on frames received after the last p2p_find
3405f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * operation was started.
3406f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 */
3407b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Ignore old scan result for " MACSTR
3408b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			" (rx_time=%u.%06u)",
3409f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			MAC2STR(bssid), (unsigned int) rx_time->sec,
3410f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			(unsigned int) rx_time->usec);
3411f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		return 0;
3412f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	}
3413f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
3414f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	p2p_add_device(p2p, bssid, freq, rx_time, level, ies, ies_len, 1);
34158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
34178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_scan_res_handled(struct p2p_data *p2p)
34218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p->p2p_scan_running) {
3423b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "p2p_scan was not running, but scan results received");
34248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->p2p_scan_running = 0;
34268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
34278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_run_after_scan(p2p))
34298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
34308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_SEARCH)
34318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
34328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3435c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtvoid p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id)
34368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3437216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	u8 dev_capab;
343861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 *len;
343961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
344061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
344161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_probe_req)
344261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(ies, p2p->wfd_ie_probe_req);
344361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
344461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
34452e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_PROBE_REQ_P2P])
34462e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		wpabuf_put_buf(ies,
34472e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			       p2p->vendor_elem[VENDOR_ELEM_PROBE_REQ_P2P]);
34482e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
344961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	len = p2p_buf_add_ie_hdr(ies);
3450216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3451216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	dev_capab = p2p->dev_capab & ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
3452216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3453216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	/* P2PS requires Probe Request frames to include SD bit */
3454216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (p2p->p2ps_seek && p2p->p2ps_seek_count)
3455216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		dev_capab |= P2P_DEV_CAPAB_SERVICE_DISCOVERY;
3456216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3457216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	p2p_buf_add_capability(ies, dev_capab, 0);
3458216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3459c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (dev_id)
3460c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		p2p_buf_add_device_id(ies, dev_id);
34618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->reg_class && p2p->cfg->channel)
34628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_listen_channel(ies, p2p->cfg->country,
34638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   p2p->cfg->reg_class,
34648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   p2p->cfg->channel);
34658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval)
34668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_ext_listen_timing(ies, p2p->ext_listen_period,
34678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      p2p->ext_listen_interval);
3468216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3469216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (p2p->p2ps_seek && p2p->p2ps_seek_count)
3470216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p_buf_add_service_hash(ies, p2p);
3471216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
34728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: p2p_buf_add_operating_channel() if GO */
34738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(ies, len);
34748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtsize_t p2p_scan_ie_buf_len(struct p2p_data *p2p)
34781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
347961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t len = 100;
348061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
348161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
348261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p && p2p->wfd_ie_probe_req)
348361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		len += wpabuf_len(p2p->wfd_ie_probe_req);
348461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
348561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
34862e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	if (p2p && p2p->vendor_elem &&
34872e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	    p2p->vendor_elem[VENDOR_ELEM_PROBE_REQ_P2P])
34882e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		len += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_PROBE_REQ_P2P]);
34892e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
349061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return len;
34911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
34921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
34931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
34948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_ie_text(struct wpabuf *p2p_ie, char *buf, char *end)
34958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_attr_text(p2p_ie, buf, end);
34978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_req_cb(struct p2p_data *p2p, int success)
35018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
35028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p->go_neg_peer;
35038c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	int timeout;
35048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3505b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "GO Negotiation Request TX callback: success=%d", success);
35068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
3508b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "No pending GO Negotiation");
35098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
35108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
35118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (success) {
35138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->flags & P2P_DEV_USER_REJECTED) {
35148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_set_state(p2p, P2P_IDLE);
35158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
35168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
351704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	} else if (dev->go_neg_req_sent) {
351804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/* Cancel the increment from p2p_connect_send() on failure */
351998f9e76624da6bb96edc1982c423e4a119c5170aDmitry Shmidt		dev->go_neg_req_sent--;
352098f9e76624da6bb96edc1982c423e4a119c5170aDmitry Shmidt	}
35218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!success &&
35238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (dev->info.dev_capab & P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY) &&
35248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !is_zero_ether_addr(dev->member_in_go_dev)) {
3525b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Peer " MACSTR " did not acknowledge request - try to use device discoverability through its GO",
35268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr));
35278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
35288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_send_dev_disc_req(p2p, dev);
35298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
35308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
35318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
35338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Use P2P find, if needed, to find the other device from its listen
35348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * channel.
35358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
35368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_CONNECT);
35378c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	timeout = success ? 500000 : 100000;
35388c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	if (!success && p2p->go_neg_peer &&
35398c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	    (p2p->go_neg_peer->flags & P2P_DEV_PEER_WAITING_RESPONSE)) {
35408c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		unsigned int r;
35418c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		/*
35428c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		 * Peer is expected to wait our response and we will skip the
35438c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		 * listen phase. Add some randomness to the wait time here to
35448c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		 * make it less likely to hit cases where we could end up in
35458c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		 * sync with peer not listening.
35468c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		 */
3547661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		if (os_get_random((u8 *) &r, sizeof(r)) < 0)
3548661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt			r = 0;
35498c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		timeout += r % 100000;
35508c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	}
35518c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	p2p_set_timeout(p2p, 0, timeout);
35528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
35538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_resp_cb(struct p2p_data *p2p, int success)
35568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3557b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "GO Negotiation Response TX callback: success=%d",
35588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
35598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p->go_neg_peer && p2p->state == P2P_PROVISIONING) {
3560b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Ignore TX callback event - GO Negotiation is not running anymore");
35618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
35628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
35638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_CONNECT);
35648c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	p2p_set_timeout(p2p, 0, 500000);
35658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
35668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35684b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidtstatic void p2p_go_neg_resp_failure_cb(struct p2p_data *p2p, int success,
35694b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt				       const u8 *addr)
35708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3571b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "GO Negotiation Response (failure) TX callback: success=%d", success);
35728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer && p2p->go_neg_peer->status != P2P_SC_SUCCESS) {
35736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_go_neg_failed(p2p, p2p->go_neg_peer->status);
3574203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt		return;
3575203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt	}
3576203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt
3577203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt	if (success) {
35784b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		struct p2p_device *dev;
35794b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		dev = p2p_get_device(p2p, addr);
35804b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		if (dev &&
358134c1202b3e71c63661a850aad81f663e40e48ca1Dmitry Shmidt		    dev->status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE)
35824b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt			dev->flags |= P2P_DEV_PEER_WAITING_RESPONSE;
35838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3584203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt
3585203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt	if (p2p->state == P2P_SEARCH || p2p->state == P2P_SD_DURING_FIND)
3586203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt		p2p_continue_find(p2p);
35878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
35888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_conf_cb(struct p2p_data *p2p,
35918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       enum p2p_send_action_result result)
35928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
35938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
35948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3595b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "GO Negotiation Confirm TX callback: result=%d", result);
35968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (result == P2P_SEND_ACTION_FAILED) {
3597413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
35986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_go_neg_failed(p2p, -1);
35998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
36008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3601413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt
3602413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt	dev = p2p->go_neg_peer;
3603413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt
36048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (result == P2P_SEND_ACTION_NO_ACK) {
36058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
3606413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt		 * Retry GO Negotiation Confirmation
3607413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt		 * P2P_GO_NEG_CNF_MAX_RETRY_COUNT times if we did not receive
3608413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt		 * ACK for confirmation.
3609413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt		 */
3610413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt		if (dev && dev->go_neg_conf &&
3611413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt		    dev->go_neg_conf_sent <= P2P_GO_NEG_CNF_MAX_RETRY_COUNT) {
3612413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt			p2p_dbg(p2p, "GO Negotiation Confirm retry %d",
3613413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt				dev->go_neg_conf_sent);
3614413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt			p2p->pending_action_state = P2P_PENDING_GO_NEG_CONFIRM;
3615413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt			if (p2p_send_action(p2p, dev->go_neg_conf_freq,
3616413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt					    dev->info.p2p_device_addr,
3617413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt					    p2p->cfg->dev_addr,
3618413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt					    dev->info.p2p_device_addr,
3619413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt					    wpabuf_head(dev->go_neg_conf),
3620413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt					    wpabuf_len(dev->go_neg_conf), 0) >=
3621413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt			    0) {
3622413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt				dev->go_neg_conf_sent++;
3623413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt				return;
3624413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt			}
3625413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt			p2p_dbg(p2p, "Failed to re-send Action frame");
3626413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt
3627413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt			/*
3628413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt			 * Continue with the assumption that the first attempt
3629413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt			 * went through and just the ACK frame was lost.
3630413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt			 */
3631413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt		}
3632413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt
3633413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt		/*
36348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * It looks like the TX status for GO Negotiation Confirm is
36358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * often showing failure even when the peer has actually
36368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * received the frame. Since the peer may change channels
36378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * immediately after having received the frame, we may not see
36388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * an Ack for retries, so just dropping a single frame may
36398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * trigger this. To allow the group formation to succeed if the
36408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * peer did indeed receive the frame, continue regardless of
36418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * the TX status.
36428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
3643b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Assume GO Negotiation Confirm TX was actually received by the peer even though Ack was not reported");
36448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
36458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3646413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
3647413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt
36488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
36498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
36508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_go_complete(p2p, dev);
36528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
36538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_send_action_cb(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
36568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const u8 *src, const u8 *bssid,
36578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			enum p2p_send_action_result result)
36588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
36598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum p2p_pending_action_state state;
36608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int success;
36618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3662b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Action frame TX callback (state=%d freq=%u dst=" MACSTR
3663216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		" src=" MACSTR " bssid=" MACSTR " result=%d p2p_state=%s)",
36648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_action_state, freq, MAC2STR(dst), MAC2STR(src),
3665216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		MAC2STR(bssid), result, p2p_state_txt(p2p->state));
36668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	success = result == P2P_SEND_ACTION_SUCCESS;
36678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	state = p2p->pending_action_state;
36688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
36698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (state) {
36708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_NO_PENDING_ACTION:
36714582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt		if (p2p->send_action_in_progress) {
36724582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt			p2p->send_action_in_progress = 0;
36734582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt			p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
36744582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt		}
3675216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p_check_after_scan_tx_continuation(p2p);
36768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
36778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_REQUEST:
36788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_req_cb(p2p, success);
36798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
36808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_RESPONSE:
36818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_resp_cb(p2p, success);
36828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
36838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_RESPONSE_FAILURE:
36844b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		p2p_go_neg_resp_failure_cb(p2p, success, dst);
36858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
36868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_CONFIRM:
36878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_conf_cb(p2p, result);
36888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
36898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_SD:
36908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_sd_cb(p2p, success);
36918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
36928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_PD:
36938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_prov_disc_cb(p2p, success);
36948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3695216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	case P2P_PENDING_PD_RESPONSE:
3696216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p_prov_disc_resp_cb(p2p, success);
3697216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		break;
36988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_INVITATION_REQUEST:
36998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_invitation_req_cb(p2p, success);
37008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
37018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_INVITATION_RESPONSE:
37028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_invitation_resp_cb(p2p, success);
37038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
37048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_DEV_DISC_REQUEST:
37058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_disc_req_cb(p2p, success);
37068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
37078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_DEV_DISC_RESPONSE:
37088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_disc_resp_cb(p2p, success);
37098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
37108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_DISC_REQ:
37118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_disc_req_cb(p2p, success);
37128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
37138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37148da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt
37158da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt	p2p->after_scan_tx_in_progress = 0;
37168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
37178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_listen_cb(struct p2p_data *p2p, unsigned int freq,
37208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   unsigned int duration)
37218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
37228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq == p2p->pending_client_disc_freq) {
3723b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Client discoverability remain-awake completed");
37248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_client_disc_freq = 0;
37258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
37268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq != p2p->pending_listen_freq) {
3729b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Unexpected listen callback for freq=%u duration=%u (pending_listen_freq=%u)",
37308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq, duration, p2p->pending_listen_freq);
37318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
37328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3734b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Starting Listen timeout(%u,%u) on freq=%u based on callback",
37358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_sec, p2p->pending_listen_usec,
37368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_freq);
37378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->in_listen = 1;
37388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->drv_in_listen = freq;
37398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->pending_listen_sec || p2p->pending_listen_usec) {
37408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
37418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Add 20 msec extra wait to avoid race condition with driver
37428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * remain-on-channel end event, i.e., give driver more time to
37438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * complete the operation before our timeout expires.
37448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
37458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_timeout(p2p, p2p->pending_listen_sec,
37468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p->pending_listen_usec + 20000);
37478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_freq = 0;
37508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
37518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_listen_end(struct p2p_data *p2p, unsigned int freq)
37548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3755b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Driver ended Listen state (freq=%u)", freq);
37568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->drv_in_listen = 0;
37578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->in_listen)
37588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* Internal timeout will trigger the next step */
37598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_CONNECT_LISTEN && p2p->go_neg_peer) {
37618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->go_neg_peer->connect_reqs >= 120) {
3762b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Timeout on sending GO Negotiation Request without getting response");
37636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			p2p_go_neg_failed(p2p, -1);
37648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 0;
37658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
37668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_CONNECT);
37688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, p2p->go_neg_peer);
37698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
37708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (p2p->state == P2P_SEARCH) {
3771c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (p2p->p2p_scan_running) {
3772c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 /*
3773c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * Search is already in progress. This can happen if
3774c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * an Action frame RX is reported immediately after
3775c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * the end of a remain-on-channel operation and the
3776c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * response frame to that is sent using an offchannel
3777c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * operation while in p2p_find. Avoid an attempt to
3778c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * restart a scan here.
3779c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  */
3780b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "p2p_scan already in progress - do not try to start a new one");
3781c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			return 1;
3782c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		}
378304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (p2p->pending_listen_freq) {
378404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			/*
378504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 * Better wait a bit if the driver is unable to start
378604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 * offchannel operation for some reason. p2p_search()
378704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 * will be started from internal timeout.
378804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 */
3789b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Listen operation did not seem to start - delay search phase to avoid busy loop");
379004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			p2p_set_timeout(p2p, 0, 100000);
379104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			return 1;
379204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
379361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->search_delay) {
3794b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Delay search operation by %u ms",
379561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				p2p->search_delay);
379661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p_set_timeout(p2p, p2p->search_delay / 1000,
379761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					(p2p->search_delay % 1000) * 1000);
379861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return 1;
379961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
38008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_search(p2p);
38018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
38028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
38058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
38068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_connect(struct p2p_data *p2p)
38098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
38108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
381104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p->go_neg_peer &&
381204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    (p2p->go_neg_peer->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM)) {
3813b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Wait for GO Negotiation Confirm timed out - assume GO Negotiation failed");
38146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_go_neg_failed(p2p, -1);
381504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return;
381604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
38178c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	if (p2p->go_neg_peer &&
38188c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	    (p2p->go_neg_peer->flags & P2P_DEV_PEER_WAITING_RESPONSE) &&
38198c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	    p2p->go_neg_peer->connect_reqs < 120) {
3820b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Peer expected to wait our response - skip listen");
38218c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		p2p_connect_send(p2p, p2p->go_neg_peer);
38228c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		return;
38238c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	}
3824cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (p2p->go_neg_peer && p2p->go_neg_peer->oob_go_neg_freq > 0) {
3825cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dbg(p2p, "Skip connect-listen since GO Neg channel known (OOB)");
3826cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_set_state(p2p, P2P_CONNECT_LISTEN);
3827cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_set_timeout(p2p, 0, 30000);
3828cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		return;
3829cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
38308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_CONNECT_LISTEN);
3831d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p_listen_in_find(p2p, 0);
38328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
38338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_connect_listen(struct p2p_data *p2p)
38368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
38378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer) {
38388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->drv_in_listen) {
3839b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Driver is still in Listen state; wait for it to complete");
38408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
38418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
38428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->go_neg_peer->connect_reqs >= 120) {
3844b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Timeout on sending GO Negotiation Request without getting response");
38456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			p2p_go_neg_failed(p2p, -1);
38468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
38478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
38488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_CONNECT);
38508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, p2p->go_neg_peer);
38518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
38528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
38538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
38548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_wait_peer_connect(struct p2p_data *p2p)
38578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
38588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_WAIT_PEER_IDLE);
38591846323989242844f0e857458a8939fa5836429cDmitry Shmidt
38601846323989242844f0e857458a8939fa5836429cDmitry Shmidt	if (p2p->cfg->is_concurrent_session_active &&
38611846323989242844f0e857458a8939fa5836429cDmitry Shmidt	    p2p->cfg->is_concurrent_session_active(p2p->cfg->cb_ctx))
38621846323989242844f0e857458a8939fa5836429cDmitry Shmidt		p2p_set_timeout(p2p, 0, 500000);
38631846323989242844f0e857458a8939fa5836429cDmitry Shmidt	else
38641846323989242844f0e857458a8939fa5836429cDmitry Shmidt		p2p_set_timeout(p2p, 0, 200000);
38658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
38668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_wait_peer_idle(struct p2p_data *p2p)
38698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
38708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p->go_neg_peer;
38718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
3873b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Unknown GO Neg peer - stop GO Neg wait");
38748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
38758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3877b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Go to Listen state while waiting for the peer to become ready for GO Negotiation");
38788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_WAIT_PEER_CONNECT);
3879d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p_listen_in_find(p2p, 0);
38808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
38818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_sd_during_find(struct p2p_data *p2p)
38848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3885b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Service Discovery Query timeout");
38868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->sd_peer) {
38878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
38888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->sd_peer = NULL;
38898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_continue_find(p2p);
38918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
38928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_prov_disc_during_find(struct p2p_data *p2p)
38958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3896b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Provision Discovery Request timeout");
38978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
38988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_continue_find(p2p);
38998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
390275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic void p2p_timeout_prov_disc_req(struct p2p_data *p2p)
390375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
3904216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	u32 adv_id = 0;
3905216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	u8 *adv_mac = NULL;
3906216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
390775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
390875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
390975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
391075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * For user initiated PD requests that we have not gotten any responses
391175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * for while in IDLE state, we retry them a couple of times before
391275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * giving up.
391375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
391475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (!p2p->user_initiated_pd)
391575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
391675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
3917b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "User initiated Provision Discovery Request timeout");
391875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
391975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p->pd_retries) {
392075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pd_retries--;
392175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p_retry_pd(p2p);
392275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	} else {
3923d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		struct p2p_device *dev;
3924d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		int for_join = 0;
3925d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
3926d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
3927d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			if (os_memcmp(p2p->pending_pd_devaddr,
3928d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				      dev->info.p2p_device_addr, ETH_ALEN) != 0)
3929d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				continue;
3930d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			if (dev->req_config_methods &&
3931d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			    (dev->flags & P2P_DEV_PD_FOR_JOIN))
3932d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				for_join = 1;
3933d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		}
3934d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
3935216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (p2p->p2ps_prov) {
3936216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			adv_id = p2p->p2ps_prov->adv_id;
3937216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			adv_mac = p2p->p2ps_prov->adv_mac;
3938216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		}
3939216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
394075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->cfg->prov_disc_fail)
394175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx,
394275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen						 p2p->pending_pd_devaddr,
3943d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt						 for_join ?
3944d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt						 P2P_PROV_DISC_TIMEOUT_JOIN :
3945216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt						 P2P_PROV_DISC_TIMEOUT,
3946216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt						 adv_id, adv_mac, NULL);
394775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p_reset_pending_pd(p2p);
394875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	}
394975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
395075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
395175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
39528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_invite(struct p2p_data *p2p)
39538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
39548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
39558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_INVITE_LISTEN);
39568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->inv_role == P2P_INVITE_ROLE_ACTIVE_GO) {
39578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
39588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Better remain on operating channel instead of listen channel
39598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * when running a group.
39608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
3961b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Inviting in active GO role - wait on operating channel");
39628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_timeout(p2p, 0, 100000);
39638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
39648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3965d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p_listen_in_find(p2p, 0);
39668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_invite_listen(struct p2p_data *p2p)
39708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
39718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->invite_peer && p2p->invite_peer->invitation_reqs < 100) {
39728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_INVITE);
39738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_invite_send(p2p, p2p->invite_peer,
3974cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				p2p->invite_go_dev_addr, p2p->invite_dev_pw_id);
39758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
39768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->invite_peer) {
3977b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Invitation Request retry limit reached");
39788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (p2p->cfg->invitation_result)
39798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p->cfg->invitation_result(
3980700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt					p2p->cfg->cb_ctx, -1, NULL, NULL,
3981e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt					p2p->invite_peer->info.p2p_device_addr,
398215907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt					0, 0);
39838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
39848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
39858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_state_timeout(void *eloop_ctx, void *timeout_ctx)
39908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
39918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
39928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3993b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Timeout (state=%s)", p2p_state_txt(p2p->state));
39948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->in_listen = 0;
39966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (p2p->drv_in_listen) {
39976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_dbg(p2p, "Driver is still in listen state - stop it");
39986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
39996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
40008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (p2p->state) {
40028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_IDLE:
400375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/* Check if we timed out waiting for PD req */
400475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->pending_action_state == P2P_PENDING_PD)
400575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_timeout_prov_disc_req(p2p);
40068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
40078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SEARCH:
400875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/* Check if we timed out waiting for PD req */
400975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->pending_action_state == P2P_PENDING_PD)
401075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_timeout_prov_disc_req(p2p);
401161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->search_delay && !p2p->in_search_delay) {
4012b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Delay search operation by %u ms",
401361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				p2p->search_delay);
401461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p->in_search_delay = 1;
401561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p_set_timeout(p2p, p2p->search_delay / 1000,
401661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					(p2p->search_delay % 1000) * 1000);
401761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			break;
401861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
401961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->in_search_delay = 0;
40208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_search(p2p);
40218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
40228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT:
40238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_connect(p2p);
40248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
40258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT_LISTEN:
40268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_connect_listen(p2p);
40278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
40288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG:
40298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
40308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_LISTEN_ONLY:
403175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/* Check if we timed out waiting for PD req */
403275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->pending_action_state == P2P_PENDING_PD)
403375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_timeout_prov_disc_req(p2p);
403475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
40358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->ext_listen_only) {
4036b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Extended Listen Timing - Listen State completed");
40378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->ext_listen_only = 0;
40388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_set_state(p2p, P2P_IDLE);
40398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
40408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
40418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_CONNECT:
40428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_wait_peer_connect(p2p);
40438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
40448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_IDLE:
40458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_wait_peer_idle(p2p);
40468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
40478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SD_DURING_FIND:
40488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_sd_during_find(p2p);
40498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
40508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROVISIONING:
40518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
40528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PD_DURING_FIND:
40538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_prov_disc_during_find(p2p);
40548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
40558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE:
40568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_invite(p2p);
40578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
40588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE_LISTEN:
40598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_invite_listen(p2p);
40608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
40618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
40628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
40638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_reject(struct p2p_data *p2p, const u8 *peer_addr)
40668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
40678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
40688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
4070b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Local request to reject connection attempts by peer "
4071b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		MACSTR, MAC2STR(peer_addr));
40728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
4073b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Peer " MACSTR " unknown", MAC2STR(peer_addr));
40748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
40758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
40768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->status = P2P_SC_FAIL_REJECTED_BY_USER;
40778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_USER_REJECTED;
40788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
40798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
40808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtconst char * p2p_wps_method_text(enum p2p_wps_method method)
40838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
40848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (method) {
40858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_NOT_READY:
40868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "not-ready";
40878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_PIN_DISPLAY:
40888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "Display";
40898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_PIN_KEYPAD:
40908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "Keypad";
40918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_PBC:
40928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "PBC";
4093cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	case WPS_NFC:
4094cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		return "NFC";
4095216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	case WPS_P2PS:
4096216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		return "P2PS";
40978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
40988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return "??";
41008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * p2p_go_state_text(enum p2p_go_state go_state)
41048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
41058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (go_state) {
41068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case UNKNOWN_GO:
41078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "unknown";
41088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case LOCAL_GO:
41098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "local";
41108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case  REMOTE_GO:
41118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "remote";
41128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
41138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return "??";
41158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtconst struct p2p_peer_info * p2p_get_peer_info(struct p2p_data *p2p,
41191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					       const u8 *addr, int next)
41208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
41218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
41228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr)
41248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, addr);
41258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
41268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = dl_list_first(&p2p->devices, struct p2p_device, list);
41278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev && next) {
41298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = dl_list_first(&dev->list, struct p2p_device, list);
41308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (&dev->list == &p2p->devices)
41318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev = NULL;
41328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
41338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
41351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return NULL;
41361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
41371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return &dev->info;
41381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
41391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
41401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
41411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_get_peer_info_txt(const struct p2p_peer_info *info,
41421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			  char *buf, size_t buflen)
41431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
41441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_device *dev;
41451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int res;
41461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	char *pos, *end;
4147fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	struct os_reltime now;
41481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
41491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (info == NULL)
41508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
41518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	dev = (struct p2p_device *) (((u8 *) info) -
41531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				     offsetof(struct p2p_device, info));
41541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
41558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf;
41568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = buf + buflen;
41578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4158fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	os_get_reltime(&now);
41598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = os_snprintf(pos, end - pos,
41608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "age=%d\n"
41618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "listen_freq=%d\n"
41628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "wps_method=%s\n"
41638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "interface_addr=" MACSTR "\n"
41648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "member_in_go_dev=" MACSTR "\n"
41658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "member_in_go_iface=" MACSTR "\n"
41668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "go_neg_req_sent=%d\n"
41678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "go_state=%s\n"
41688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dialog_token=%u\n"
41698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "intended_addr=" MACSTR "\n"
41708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "country=%c%c\n"
41718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "oper_freq=%d\n"
41728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "req_config_methods=0x%x\n"
4173a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			  "flags=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n"
41748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "status=%d\n"
41758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "invitation_reqs=%u\n",
41768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  (int) (now.sec - dev->last_seen.sec),
41778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->listen_freq,
41788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  p2p_wps_method_text(dev->wps_method),
41798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->interface_addr),
41808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->member_in_go_dev),
41818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->member_in_go_iface),
41828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->go_neg_req_sent,
41838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  p2p_go_state_text(dev->go_state),
41848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->dialog_token,
41858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->intended_addr),
41868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->country[0] ? dev->country[0] : '_',
41878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->country[1] ? dev->country[1] : '_',
41888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->oper_freq,
41898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->req_config_methods,
41908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PROBE_REQ_ONLY ?
41918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PROBE_REQ_ONLY]" : "",
41928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_REPORTED ? "[REPORTED]" : "",
41938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_NOT_YET_READY ?
41948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[NOT_YET_READY]" : "",
41958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PD_PEER_DISPLAY ?
41968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PD_PEER_DISPLAY]" : "",
41978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PD_PEER_KEYPAD ?
41988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PD_PEER_KEYPAD]" : "",
4199216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			  dev->flags & P2P_DEV_PD_PEER_P2PS ?
4200216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			  "[PD_PEER_P2PS]" : "",
42018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_USER_REJECTED ?
42028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[USER_REJECTED]" : "",
42038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PEER_WAITING_RESPONSE ?
42048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PEER_WAITING_RESPONSE]" : "",
42058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PREFER_PERSISTENT_GROUP ?
42068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PREFER_PERSISTENT_GROUP]" : "",
42078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_WAIT_GO_NEG_RESPONSE ?
42088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[WAIT_GO_NEG_RESPONSE]" : "",
42098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM ?
42108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[WAIT_GO_NEG_CONFIRM]" : "",
42118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_GROUP_CLIENT_ONLY ?
42128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[GROUP_CLIENT_ONLY]" : "",
42138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_FORCE_FREQ ?
42148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[FORCE_FREQ]" : "",
42158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PD_FOR_JOIN ?
42168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PD_FOR_JOIN]" : "",
4217a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			  dev->flags & P2P_DEV_LAST_SEEN_AS_GROUP_CLIENT ?
4218a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			  "[LAST_SEEN_AS_GROUP_CLIENT]" : "",
42198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->status,
42208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->invitation_reqs);
42216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_snprintf_error(end - pos, res))
42228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return pos - buf;
42238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += res;
42248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->ext_listen_period) {
42268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = os_snprintf(pos, end - pos,
42278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "ext_listen_period=%u\n"
42288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "ext_listen_interval=%u\n",
42298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  dev->ext_listen_period,
42308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  dev->ext_listen_interval);
42316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (os_snprintf_error(end - pos, res))
42328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos - buf;
42338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += res;
42348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
42358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->oper_ssid_len) {
42378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = os_snprintf(pos, end - pos,
42388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "oper_ssid=%s\n",
42398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  wpa_ssid_txt(dev->oper_ssid,
42408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       dev->oper_ssid_len));
42416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (os_snprintf_error(end - pos, res))
42428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos - buf;
42438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += res;
42448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
42458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
424661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
424761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (dev->info.wfd_subelems) {
424861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		res = os_snprintf(pos, end - pos, "wfd_subelems=");
42496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (os_snprintf_error(end - pos, res))
425061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return pos - buf;
425161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += res;
425261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
425361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += wpa_snprintf_hex(pos, end - pos,
425461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					wpabuf_head(dev->info.wfd_subelems),
425561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					wpabuf_len(dev->info.wfd_subelems));
425661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
425761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		res = os_snprintf(pos, end - pos, "\n");
42586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (os_snprintf_error(end - pos, res))
425961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return pos - buf;
426061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += res;
426161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
426261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
426361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
42648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return pos - buf;
42658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
42668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_peer_known(struct p2p_data *p2p, const u8 *addr)
42691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
42701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return p2p_get_device(p2p, addr) != NULL;
42711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
42721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
42731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
42748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_client_discoverability(struct p2p_data *p2p, int enabled)
42758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
42768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (enabled) {
4277b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Client discoverability enabled");
42788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
42798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
4280b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Client discoverability disabled");
42818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab &= ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
42828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
42838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
42848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_presence_req(u32 duration1, u32 interval1,
42878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      u32 duration2, u32 interval2)
42888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
42898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
42908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_noa_desc desc1, desc2, *ptr1 = NULL, *ptr2 = NULL;
42918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
42928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req = wpabuf_alloc(100);
42948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL)
42958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
42968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (duration1 || interval1) {
42988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(&desc1, 0, sizeof(desc1));
42998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc1.count_type = 1;
43008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc1.duration = duration1;
43018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc1.interval = interval1;
43028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ptr1 = &desc1;
43038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (duration2 || interval2) {
43058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(&desc2, 0, sizeof(desc2));
43068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc2.count_type = 2;
43078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc2.duration = duration2;
43088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc2.interval = interval2;
43098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ptr2 = &desc2;
43108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
43118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
43128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_action_hdr(req, P2P_PRESENCE_REQ, 1);
43148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(req);
43158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_noa(req, 0, 0, 0, ptr1, ptr2);
43168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(req, len);
43178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return req;
43198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
43208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_presence_req(struct p2p_data *p2p, const u8 *go_interface_addr,
43238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     const u8 *own_interface_addr, unsigned int freq,
43248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     u32 duration1, u32 interval1, u32 duration2,
43258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     u32 interval2)
43268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
43278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
43288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4329b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Send Presence Request to GO " MACSTR
4330b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		" (own interface " MACSTR ") freq=%u dur1=%u int1=%u "
4331b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		"dur2=%u int2=%u",
43328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(go_interface_addr), MAC2STR(own_interface_addr),
43338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		freq, duration1, interval1, duration2, interval2);
43348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req = p2p_build_presence_req(duration1, interval1, duration2,
43368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     interval2);
43378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL)
43388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
43398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
43418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_send_action(p2p, freq, go_interface_addr, own_interface_addr,
43428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    go_interface_addr,
43438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpabuf_head(req), wpabuf_len(req), 200) < 0) {
4344b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to send Action frame");
43458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
43468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(req);
43478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
43498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
43508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_presence_resp(u8 status, const u8 *noa,
43538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       size_t noa_len, u8 dialog_token)
43548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
43558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
43568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
43578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = wpabuf_alloc(100 + noa_len);
43598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
43608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
43618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_action_hdr(resp, P2P_PRESENCE_RESP, dialog_token);
43638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(resp);
43648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_status(resp, status);
43658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (noa) {
43668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(resp, P2P_ATTR_NOTICE_OF_ABSENCE);
43678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_le16(resp, noa_len);
43688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_data(resp, noa, noa_len);
43698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
43708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_noa(resp, 0, 0, 0, NULL, NULL);
43718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(resp, len);
43728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return resp;
43748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
43758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_req(struct p2p_data *p2p, const u8 *da,
43788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const u8 *sa, const u8 *data, size_t len,
43798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     int rx_freq)
43808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
43818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
43828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 status;
43838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
43848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t g;
43858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group *group = NULL;
43868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int parsed = 0;
43878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 noa[50];
43888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int noa_len;
43898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4390b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Received P2P Action - P2P Presence Request");
43918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (g = 0; g < p2p->num_groups; g++) {
43938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(da, p2p_group_get_interface_addr(p2p->groups[g]),
43948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      ETH_ALEN) == 0) {
43958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group = p2p->groups[g];
43968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
43978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
43988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
43998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group == NULL) {
4400b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Ignore P2P Presence Request for unknown group "
44018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MACSTR, MAC2STR(da));
44028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
44038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
44048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse(data, len, &msg) < 0) {
4406b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to parse P2P Presence Request");
44078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		status = P2P_SC_FAIL_INVALID_PARAMS;
44088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
44098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
44108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	parsed = 1;
44118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.noa == NULL) {
4413b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "No NoA attribute in P2P Presence Request");
44148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		status = P2P_SC_FAIL_INVALID_PARAMS;
44158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
44168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
44178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	status = p2p_group_presence_req(group, sa, msg.noa, msg.noa_len);
44198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail:
44218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->get_noa)
44228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		noa_len = p2p->cfg->get_noa(p2p->cfg->cb_ctx, da, noa,
44238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    sizeof(noa));
44248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
44258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		noa_len = -1;
44268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = p2p_build_presence_resp(status, noa_len > 0 ? noa : NULL,
44278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       noa_len > 0 ? noa_len : 0,
44288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       msg.dialog_token);
44298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (parsed)
44308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
44318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
44328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
44338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
44358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_send_action(p2p, rx_freq, sa, da, da,
44368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
4437b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to send Action frame");
44388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
44398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(resp);
44408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
44418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_resp(struct p2p_data *p2p, const u8 *da,
44448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *sa, const u8 *data, size_t len)
44458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
44468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
44478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4448b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Received P2P Action - P2P Presence Response");
44498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse(data, len, &msg) < 0) {
4451b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to parse P2P Presence Response");
44528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
44538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
44548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.status == NULL || msg.noa == NULL) {
4456b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "No Status or NoA attribute in P2P Presence Response");
44578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
44588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
44598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
44608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4461fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (p2p->cfg->presence_resp) {
4462fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		p2p->cfg->presence_resp(p2p->cfg->cb_ctx, sa, *msg.status,
4463fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt					msg.noa, msg.noa_len);
4464fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	}
4465fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
44668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*msg.status) {
4467b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "P2P Presence Request was rejected: status %u",
44688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*msg.status);
44698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
44708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
44718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
44728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4473b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "P2P Presence Request was accepted");
44748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "P2P: P2P Presence Response - NoA",
44758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    msg.noa, msg.noa_len);
44768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: process NoA */
44778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
44788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
44798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_ext_listen_timeout(void *eloop_ctx, void *timeout_ctx)
44828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
44838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
44848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval) {
44868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Schedule next extended listen timeout */
44878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(p2p->ext_listen_interval_sec,
44888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p->ext_listen_interval_usec,
44898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p_ext_listen_timeout, p2p, NULL);
44908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
44918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44926dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt	if ((p2p->cfg->is_p2p_in_progress &&
44936dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt	     p2p->cfg->is_p2p_in_progress(p2p->cfg->cb_ctx)) ||
44946dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt	    (p2p->pending_action_state == P2P_PENDING_PD &&
44956dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt	     p2p->pd_retries > 0)) {
44965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		p2p_dbg(p2p, "Operation in progress - skip Extended Listen timeout (%s)",
44975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			p2p_state_txt(p2p->state));
44985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
44995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
45005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
45018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_LISTEN_ONLY && p2p->ext_listen_only) {
45028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
45038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * This should not really happen, but it looks like the Listen
45048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * command may fail is something else (e.g., a scan) was
45058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * running at an inconvenient time. As a workaround, allow new
45068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Extended Listen operation to be started.
45078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
4508b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Previous Extended Listen operation had not been completed - try again");
45098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_only = 0;
45108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
45118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
45128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state != P2P_IDLE) {
4514b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Skip Extended Listen timeout in active state (%s)", p2p_state_txt(p2p->state));
45158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
45168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
45178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4518b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Extended Listen timeout");
45198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_only = 1;
45208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_listen(p2p, p2p->ext_listen_period) < 0) {
4521b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to start Listen state for Extended Listen Timing");
45228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_only = 0;
45238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
45248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
45258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_ext_listen(struct p2p_data *p2p, unsigned int period,
45288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   unsigned int interval)
45298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
45308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (period > 65535 || interval > 65535 || period > interval ||
45318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (period == 0 && interval > 0) || (period > 0 && interval == 0)) {
4532b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Invalid Extended Listen Timing request: period=%u interval=%u",
4533b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			period, interval);
45348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
45358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
45368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_ext_listen_timeout, p2p, NULL);
45388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (interval == 0) {
4540b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Disabling Extended Listen Timing");
45418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_period = 0;
45428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_interval = 0;
45438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
45448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
45458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4546b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Enabling Extended Listen Timing: period %u msec, interval %u msec",
4547b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		period, interval);
45488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_period = period;
45498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_interval = interval;
45508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_interval_sec = interval / 1000;
45518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_interval_usec = (interval % 1000) * 1000;
45528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(p2p->ext_listen_interval_sec,
45548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p->ext_listen_interval_usec,
45558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p_ext_listen_timeout, p2p, NULL);
45568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
45588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
45598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_deauth_notif(struct p2p_data *p2p, const u8 *bssid, u16 reason_code,
45628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      const u8 *ie, size_t ie_len)
45638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
45648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
45658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bssid == NULL || ie == NULL)
45678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
45688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
45708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg))
45718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
45729767226d8e6a1adaa33beb9f517ef40dddfa460cDmitry Shmidt	if (msg.minor_reason_code == NULL) {
45739767226d8e6a1adaa33beb9f517ef40dddfa460cDmitry Shmidt		p2p_parse_free(&msg);
45748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
45759767226d8e6a1adaa33beb9f517ef40dddfa460cDmitry Shmidt	}
45768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4577b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Deauthentication notification BSSID " MACSTR
45788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" reason_code=%u minor_reason_code=%u",
45798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(bssid), reason_code, *msg.minor_reason_code);
45808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
45828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
45838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_disassoc_notif(struct p2p_data *p2p, const u8 *bssid, u16 reason_code,
45868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const u8 *ie, size_t ie_len)
45878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
45888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
45898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bssid == NULL || ie == NULL)
45918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
45928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
45948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg))
45958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
45969767226d8e6a1adaa33beb9f517ef40dddfa460cDmitry Shmidt	if (msg.minor_reason_code == NULL) {
45979767226d8e6a1adaa33beb9f517ef40dddfa460cDmitry Shmidt		p2p_parse_free(&msg);
45988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
45999767226d8e6a1adaa33beb9f517ef40dddfa460cDmitry Shmidt	}
46008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4601b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Disassociation notification BSSID " MACSTR
46028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" reason_code=%u minor_reason_code=%u",
46038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(bssid), reason_code, *msg.minor_reason_code);
46048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
46068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
46078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_managed_oper(struct p2p_data *p2p, int enabled)
46108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
46118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (enabled) {
4612b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Managed P2P Device operations enabled");
46138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_INFRA_MANAGED;
46148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
4615b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Managed P2P Device operations disabled");
46168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab &= ~P2P_DEV_CAPAB_INFRA_MANAGED;
46178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
46188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
46198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4621661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidtint p2p_config_get_random_social(struct p2p_config *p2p, u8 *op_class,
4622661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt				 u8 *op_channel)
4623661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt{
4624661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	return p2p_channel_random_social(&p2p->channels, op_class, op_channel);
4625661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt}
4626661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt
4627661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt
462843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidtint p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel,
462943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt			   u8 forced)
46308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
46314b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	if (p2p_channel_to_freq(reg_class, channel) < 0)
46328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
46338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
463443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	/*
463543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	 * Listen channel was set in configuration or set by control interface;
463643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	 * cannot override it.
463743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	 */
4638216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (p2p->cfg->channel_forced && forced == 0) {
4639216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p_dbg(p2p,
4640216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			"Listen channel was previously configured - do not override based on optimization");
464143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		return -1;
4642216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
4643216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
4644216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	p2p_dbg(p2p, "Set Listen channel: reg_class %u channel %u",
4645216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		reg_class, channel);
464643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt
464743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	if (p2p->state == P2P_IDLE) {
464843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		p2p->cfg->reg_class = reg_class;
464943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		p2p->cfg->channel = channel;
465043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		p2p->cfg->channel_forced = forced;
465143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	} else {
465243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		p2p_dbg(p2p, "Defer setting listen channel");
465343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		p2p->pending_reg_class = reg_class;
465443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		p2p->pending_channel = channel;
465543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		p2p->pending_channel_forced = forced;
465643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	}
46578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
46598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
46608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
466243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidtu8 p2p_get_listen_channel(struct p2p_data *p2p)
466343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt{
466443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	return p2p->cfg->channel;
466543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt}
466643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt
466743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt
46688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_ssid_postfix(struct p2p_data *p2p, const u8 *postfix, size_t len)
46698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4670b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "New SSID postfix: %s", wpa_ssid_txt(postfix, len));
46718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (postfix == NULL) {
46728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->ssid_postfix_len = 0;
46738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
46748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
46758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > sizeof(p2p->cfg->ssid_postfix))
46768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
46778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->ssid_postfix, postfix, len);
46788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->ssid_postfix_len = len;
46798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
46808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
46818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
468375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenint p2p_set_oper_channel(struct p2p_data *p2p, u8 op_reg_class, u8 op_channel,
468475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			 int cfg_op_channel)
468575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
46864b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	if (p2p_channel_to_freq(op_reg_class, op_channel) < 0)
468775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return -1;
468875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
4689b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Set Operating channel: reg_class %u channel %u",
4690b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		op_reg_class, op_channel);
469175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->cfg->op_reg_class = op_reg_class;
469275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->cfg->op_channel = op_channel;
469375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->cfg->cfg_op_channel = cfg_op_channel;
469475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	return 0;
469575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
469675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
469775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
469804949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint p2p_set_pref_chan(struct p2p_data *p2p, unsigned int num_pref_chan,
469904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		      const struct p2p_channel *pref_chan)
470004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
470104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct p2p_channel *n;
470204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
470304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (pref_chan) {
470404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		n = os_malloc(num_pref_chan * sizeof(struct p2p_channel));
470504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (n == NULL)
470604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			return -1;
470704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(n, pref_chan,
470804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			  num_pref_chan * sizeof(struct p2p_channel));
470904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	} else
471004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		n = NULL;
471104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
471204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	os_free(p2p->cfg->pref_chan);
471304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p->cfg->pref_chan = n;
471404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p->cfg->num_pref_chan = num_pref_chan;
471504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
471604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return 0;
471704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
471804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
471904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
472068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidtint p2p_set_no_go_freq(struct p2p_data *p2p,
472168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		       const struct wpa_freq_range_list *list)
472268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt{
472368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	struct wpa_freq_range *tmp;
472468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt
472568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	if (list == NULL || list->num == 0) {
472668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		os_free(p2p->no_go_freq.range);
472768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		p2p->no_go_freq.range = NULL;
472868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		p2p->no_go_freq.num = 0;
472968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		return 0;
473068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	}
473168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt
473268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	tmp = os_calloc(list->num, sizeof(struct wpa_freq_range));
473368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	if (tmp == NULL)
473468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		return -1;
473568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	os_memcpy(tmp, list->range, list->num * sizeof(struct wpa_freq_range));
473668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	os_free(p2p->no_go_freq.range);
473768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p->no_go_freq.range = tmp;
473868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p->no_go_freq.num = list->num;
473968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p_dbg(p2p, "Updated no GO chan list");
474068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt
474168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	return 0;
474268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt}
474368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt
474468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt
47458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_interface_addr(struct p2p_data *p2p, const u8 *dev_addr,
47468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   u8 *iface_addr)
47478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
47488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p_get_device(p2p, dev_addr);
47498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL || is_zero_ether_addr(dev->interface_addr))
47508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
47518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(iface_addr, dev->interface_addr, ETH_ALEN);
47528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
47538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
47548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_dev_addr(struct p2p_data *p2p, const u8 *iface_addr,
47578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   u8 *dev_addr)
47588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
47598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p_get_device_interface(p2p, iface_addr);
47608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
47618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
47628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev_addr, dev->info.p2p_device_addr, ETH_ALEN);
47638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
47648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
47658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_peer_filter(struct p2p_data *p2p, const u8 *addr)
47688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
47698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->peer_filter, addr, ETH_ALEN);
47708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (is_zero_ether_addr(p2p->peer_filter))
4771b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Disable peer filter");
47728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
4773b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Enable peer filter for " MACSTR,
4774b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			MAC2STR(p2p->peer_filter));
47758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
47768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_cross_connect(struct p2p_data *p2p, int enabled)
47798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4780b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Cross connection %s", enabled ? "enabled" : "disabled");
47818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cross_connect == enabled)
47828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
47838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cross_connect = enabled;
47848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: may need to tear down any action group where we are GO(?) */
47858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
47868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_oper_freq(struct p2p_data *p2p, const u8 *iface_addr)
47898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
47908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p_get_device_interface(p2p, iface_addr);
47918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
47928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
47938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->oper_freq <= 0)
47948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
47958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return dev->oper_freq;
47968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
47978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_intra_bss_dist(struct p2p_data *p2p, int enabled)
48008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4801b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Intra BSS distribution %s",
48028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		enabled ? "enabled" : "disabled");
48038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->p2p_intra_bss = enabled;
48048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
48058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
480768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidtvoid p2p_update_channel_list(struct p2p_data *p2p,
480868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt			     const struct p2p_channels *chan,
480968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt			     const struct p2p_channels *cli_chan)
48108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4811b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Update channel list");
48128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&p2p->cfg->channels, chan, sizeof(struct p2p_channels));
481368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p_channels_dump(p2p, "channels", &p2p->cfg->channels);
481468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	os_memcpy(&p2p->cfg->cli_channels, cli_chan,
481568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		  sizeof(struct p2p_channels));
481668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p_channels_dump(p2p, "cli_channels", &p2p->cfg->cli_channels);
48178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
48188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_send_action(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
48218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    const u8 *src, const u8 *bssid, const u8 *buf,
48228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    size_t len, unsigned int wait_time)
48238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
48248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
4825b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Delay Action frame TX until p2p_scan completes");
48268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->after_scan_tx) {
4827b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Dropped previous pending Action frame TX");
48288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(p2p->after_scan_tx);
48298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
48308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = os_malloc(sizeof(*p2p->after_scan_tx) +
48318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       len);
48328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->after_scan_tx == NULL)
48338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
48348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx->freq = freq;
48358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx->dst, dst, ETH_ALEN);
48368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx->src, src, ETH_ALEN);
48378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx->bssid, bssid, ETH_ALEN);
48388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx->len = len;
48398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx->wait_time = wait_time;
48408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx + 1, buf, len);
48418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
48428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
48438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, dst, src, bssid,
48458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     buf, len, wait_time);
48468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
48478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_best_channels(struct p2p_data *p2p, int freq_24, int freq_5,
48508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   int freq_overall)
48518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4852b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Best channel: 2.4 GHz: %d,  5 GHz: %d,  overall: %d",
4853b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		freq_24, freq_5, freq_overall);
48548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->best_freq_24 = freq_24;
48558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->best_freq_5 = freq_5;
48568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->best_freq_overall = freq_overall;
48578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
48588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4860700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidtvoid p2p_set_own_freq_preference(struct p2p_data *p2p, int freq)
4861700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt{
4862b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Own frequency preference: %d MHz", freq);
4863700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	p2p->own_freq_preference = freq;
4864700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt}
4865700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt
4866700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt
48678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * p2p_get_go_neg_peer(struct p2p_data *p2p)
48688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
48698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p == NULL || p2p->go_neg_peer == NULL)
48708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
48718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p->go_neg_peer->info.p2p_device_addr;
48728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
48738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst struct p2p_peer_info *
48768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtp2p_get_peer_found(struct p2p_data *p2p, const u8 *addr, int next)
48778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
48788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
48798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr) {
48818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, addr);
48828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!dev)
48838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
48848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!next) {
48868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev->flags & P2P_DEV_PROBE_REQ_ONLY)
48878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return NULL;
48888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return &dev->info;
48908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
48918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			do {
48928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev = dl_list_first(&dev->list,
48938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    struct p2p_device,
48948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    list);
48957832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt				if (!dev || &dev->list == &p2p->devices)
48968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					return NULL;
48978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} while (dev->flags & P2P_DEV_PROBE_REQ_ONLY);
48988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
48998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
49008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = dl_list_first(&p2p->devices, struct p2p_device, list);
49018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!dev)
49028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
49038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (dev->flags & P2P_DEV_PROBE_REQ_ONLY) {
49048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev = dl_list_first(&dev->list,
49058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    struct p2p_device,
49068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    list);
49077832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt			if (!dev || &dev->list == &p2p->devices)
49088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return NULL;
49098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
49108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
49118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return &dev->info;
49138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
49141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
49151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
49161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_in_progress(struct p2p_data *p2p)
49171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
49181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p == NULL)
49191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
4920fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (p2p->state == P2P_SEARCH)
492161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return 2;
49221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return p2p->state != P2P_IDLE && p2p->state != P2P_PROVISIONING;
49231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
492461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
492561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
492661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid p2p_set_config_timeout(struct p2p_data *p2p, u8 go_timeout,
492761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			    u8 client_timeout)
492861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
492961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p) {
493061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->go_timeout = go_timeout;
493161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->client_timeout = client_timeout;
493261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
493361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
493461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
493561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
493661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
493761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
493861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void p2p_update_wfd_ie_groups(struct p2p_data *p2p)
493961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
494061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t g;
494161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct p2p_group *group;
494261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
494361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	for (g = 0; g < p2p->num_groups; g++) {
494461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		group = p2p->groups[g];
4945b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt		p2p_group_force_beacon_update_ies(group);
494661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
494761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
494861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
494961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
495061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_beacon(struct p2p_data *p2p, struct wpabuf *ie)
495161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
495261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_beacon);
495361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_beacon = ie;
495461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_update_wfd_ie_groups(p2p);
495561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
495661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
495761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
495861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
495961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_probe_req(struct p2p_data *p2p, struct wpabuf *ie)
496061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
496161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_probe_req);
496261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_probe_req = ie;
496361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
496461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
496561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
496661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
496761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_probe_resp(struct p2p_data *p2p, struct wpabuf *ie)
496861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
496961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_probe_resp);
497061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_probe_resp = ie;
497161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_update_wfd_ie_groups(p2p);
497261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
497361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
497461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
497561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
497661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_assoc_req(struct p2p_data *p2p, struct wpabuf *ie)
497761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
497861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_assoc_req);
497961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_assoc_req = ie;
498061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
498161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
498261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
498361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
498461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_invitation(struct p2p_data *p2p, struct wpabuf *ie)
498561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
498661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_invitation);
498761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_invitation = ie;
498861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
498961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
499061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
499161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
499261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_prov_disc_req(struct p2p_data *p2p, struct wpabuf *ie)
499361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
499461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_prov_disc_req);
499561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_prov_disc_req = ie;
499661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
499761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
499861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
499961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
500061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_prov_disc_resp(struct p2p_data *p2p, struct wpabuf *ie)
500161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
500261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_prov_disc_resp);
500361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_prov_disc_resp = ie;
500461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
500561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
500661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
500761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
500861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_go_neg(struct p2p_data *p2p, struct wpabuf *ie)
500961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
501061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_go_neg);
501161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_go_neg = ie;
501261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
501361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
501461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
501561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
501661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_dev_info(struct p2p_data *p2p, const struct wpabuf *elem)
501761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
501861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_dev_info);
501961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (elem) {
502061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_dev_info = wpabuf_dup(elem);
502161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->wfd_dev_info == NULL)
502261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
502361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else
502461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_dev_info = NULL;
502561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
502661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
502761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
502861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
502961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
503061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_assoc_bssid(struct p2p_data *p2p, const struct wpabuf *elem)
503161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
503261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_assoc_bssid);
503361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (elem) {
503461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_assoc_bssid = wpabuf_dup(elem);
503561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->wfd_assoc_bssid == NULL)
503661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
503761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else
503861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_assoc_bssid = NULL;
503961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
504061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
504161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
504261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
504361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
504461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_coupled_sink_info(struct p2p_data *p2p,
504561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				  const struct wpabuf *elem)
504661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
504761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_coupled_sink_info);
504861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (elem) {
504961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_coupled_sink_info = wpabuf_dup(elem);
505061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->wfd_coupled_sink_info == NULL)
505161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
505261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else
505361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_coupled_sink_info = NULL;
505461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
505561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
505661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
505761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
505861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
5059d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
5060d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
5061d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtint p2p_set_disc_int(struct p2p_data *p2p, int min_disc_int, int max_disc_int,
5062d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		     int max_disc_tu)
5063d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt{
5064d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (min_disc_int > max_disc_int || min_disc_int < 0 || max_disc_int < 0)
5065d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return -1;
5066d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
5067d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p->min_disc_int = min_disc_int;
5068d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p->max_disc_int = max_disc_int;
5069d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p->max_disc_tu = max_disc_tu;
5070b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Set discoverable interval: min=%d max=%d max_tu=%d",
5071b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		min_disc_int, max_disc_int, max_disc_tu);
5072d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
5073d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	return 0;
5074d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt}
5075b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
5076b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
5077b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidtvoid p2p_dbg(struct p2p_data *p2p, const char *fmt, ...)
5078b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt{
5079b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_list ap;
5080b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	char buf[500];
5081b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
5082b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	if (!p2p->cfg->debug_print)
5083b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		return;
5084b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
5085b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_start(ap, fmt);
5086b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	vsnprintf(buf, sizeof(buf), fmt, ap);
5087b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	buf[sizeof(buf) - 1] = '\0';
5088b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_end(ap);
5089b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p->cfg->debug_print(p2p->cfg->cb_ctx, MSG_DEBUG, buf);
5090b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt}
5091b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
5092b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
5093b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidtvoid p2p_info(struct p2p_data *p2p, const char *fmt, ...)
5094b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt{
5095b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_list ap;
5096b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	char buf[500];
5097b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
5098b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	if (!p2p->cfg->debug_print)
5099b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		return;
5100b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
5101b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_start(ap, fmt);
5102b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	vsnprintf(buf, sizeof(buf), fmt, ap);
5103b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	buf[sizeof(buf) - 1] = '\0';
5104b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_end(ap);
5105b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p->cfg->debug_print(p2p->cfg->cb_ctx, MSG_INFO, buf);
5106b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt}
5107b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
5108b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
5109b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidtvoid p2p_err(struct p2p_data *p2p, const char *fmt, ...)
5110b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt{
5111b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_list ap;
5112b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	char buf[500];
5113b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
5114b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	if (!p2p->cfg->debug_print)
5115b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		return;
5116b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
5117b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_start(ap, fmt);
5118b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	vsnprintf(buf, sizeof(buf), fmt, ap);
5119b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	buf[sizeof(buf) - 1] = '\0';
5120b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_end(ap);
5121b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p->cfg->debug_print(p2p->cfg->cb_ctx, MSG_ERROR, buf);
5122b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt}
5123cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5124cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5125d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidtvoid p2p_loop_on_known_peers(struct p2p_data *p2p,
5126d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt			     void (*peer_callback)(struct p2p_peer_info *peer,
5127d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt						   void *user_data),
5128d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt			     void *user_data)
5129d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt{
5130d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt	struct p2p_device *dev, *n;
5131d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt
5132d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt	dl_list_for_each_safe(dev, n, &p2p->devices, struct p2p_device, list) {
5133d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt		peer_callback(&dev->info, user_data);
5134d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt	}
5135d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt}
5136d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt
5137d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt
5138cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_WPS_NFC
5139cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5140cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtstatic struct wpabuf * p2p_build_nfc_handover(struct p2p_data *p2p,
5141cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					      int client_freq,
5142cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					      const u8 *go_dev_addr,
5143cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					      const u8 *ssid, size_t ssid_len)
5144cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{
5145cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	struct wpabuf *buf;
5146cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	u8 op_class, channel;
5147cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	enum p2p_role_indication role = P2P_DEVICE_NOT_IN_GROUP;
5148cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5149cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	buf = wpabuf_alloc(1000);
5150cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (buf == NULL)
5151cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		return NULL;
5152cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5153cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	op_class = p2p->cfg->reg_class;
5154cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	channel = p2p->cfg->channel;
5155cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5156cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	p2p_buf_add_capability(buf, p2p->dev_capab &
5157cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			       ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 0);
5158cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	p2p_buf_add_device_info(buf, p2p, NULL);
5159cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5160cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (p2p->num_groups > 0) {
51617832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt		int freq = p2p_group_get_freq(p2p->groups[0]);
5162cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		role = P2P_GO_IN_A_GROUP;
51637832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt		if (p2p_freq_to_channel(freq, &op_class, &channel) < 0) {
51647832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt			p2p_dbg(p2p,
51657832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt				"Unknown GO operating frequency %d MHz for NFC handover",
51667832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt				freq);
51677832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt			wpabuf_free(buf);
51687832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt			return NULL;
51697832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt		}
5170cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	} else if (client_freq > 0) {
5171cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		role = P2P_CLIENT_IN_A_GROUP;
51727832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt		if (p2p_freq_to_channel(client_freq, &op_class, &channel) < 0) {
51737832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt			p2p_dbg(p2p,
51747832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt				"Unknown client operating frequency %d MHz for NFC handover",
51757832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt				client_freq);
51767832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt			wpabuf_free(buf);
51777832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt			return NULL;
51787832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt		}
5179cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5180cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5181cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	p2p_buf_add_oob_go_neg_channel(buf, p2p->cfg->country, op_class,
5182cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				       channel, role);
5183cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5184cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (p2p->num_groups > 0) {
5185cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		/* Limit number of clients to avoid very long message */
5186cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_buf_add_group_info(p2p->groups[0], buf, 5);
5187cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_group_buf_add_id(p2p->groups[0], buf);
5188cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	} else if (client_freq > 0 &&
5189cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		   go_dev_addr && !is_zero_ether_addr(go_dev_addr) &&
5190cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		   ssid && ssid_len > 0) {
5191cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		/*
5192cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		 * Add the optional P2P Group ID to indicate in which group this
5193cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		 * device is a P2P Client.
5194cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		 */
5195cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_buf_add_group_id(buf, go_dev_addr, ssid, ssid_len);
5196cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5197cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5198cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	return buf;
5199cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt}
5200cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5201cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5202cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtstruct wpabuf * p2p_build_nfc_handover_req(struct p2p_data *p2p,
5203cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					   int client_freq,
5204cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					   const u8 *go_dev_addr,
5205cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					   const u8 *ssid, size_t ssid_len)
5206cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{
5207cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	return p2p_build_nfc_handover(p2p, client_freq, go_dev_addr, ssid,
5208cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				      ssid_len);
5209cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt}
5210cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5211cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5212cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtstruct wpabuf * p2p_build_nfc_handover_sel(struct p2p_data *p2p,
5213cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					   int client_freq,
5214cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					   const u8 *go_dev_addr,
5215cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					   const u8 *ssid, size_t ssid_len)
5216cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{
5217cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	return p2p_build_nfc_handover(p2p, client_freq, go_dev_addr, ssid,
5218cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				      ssid_len);
5219cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt}
5220cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5221cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5222cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtint p2p_process_nfc_connection_handover(struct p2p_data *p2p,
5223cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					struct p2p_nfc_params *params)
5224cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{
5225cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	struct p2p_message msg;
5226cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	struct p2p_device *dev;
5227cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	const u8 *p2p_dev_addr;
5228cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	int freq;
5229cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	enum p2p_role_indication role;
5230cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5231cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	params->next_step = NO_ACTION;
5232cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5233cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (p2p_parse_ies_separate(params->wsc_attr, params->wsc_len,
5234cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				   params->p2p_attr, params->p2p_len, &msg)) {
5235cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dbg(p2p, "Failed to parse WSC/P2P attributes from NFC");
5236cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_parse_free(&msg);
5237cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		return -1;
5238cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5239cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5240cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (msg.p2p_device_addr)
5241cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dev_addr = msg.p2p_device_addr;
5242cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	else if (msg.device_id)
5243cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dev_addr = msg.device_id;
5244cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	else {
5245cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dbg(p2p, "Ignore scan data without P2P Device Info or P2P Device Id");
5246cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_parse_free(&msg);
5247cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		return -1;
5248cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5249cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5250cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (msg.oob_dev_password) {
5251cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		os_memcpy(params->oob_dev_pw, msg.oob_dev_password,
5252cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			  msg.oob_dev_password_len);
5253cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		params->oob_dev_pw_len = msg.oob_dev_password_len;
5254cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5255cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5256cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	dev = p2p_create_device(p2p, p2p_dev_addr);
5257cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (dev == NULL) {
5258cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_parse_free(&msg);
5259cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		return -1;
5260cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5261cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5262cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	params->peer = &dev->info;
5263cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5264cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	os_get_reltime(&dev->last_seen);
5265cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	dev->flags &= ~(P2P_DEV_PROBE_REQ_ONLY | P2P_DEV_GROUP_CLIENT_ONLY);
5266cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	p2p_copy_wps_info(p2p, dev, 0, &msg);
5267cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5268cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (!msg.oob_go_neg_channel) {
5269cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dbg(p2p, "OOB GO Negotiation Channel attribute not included");
5270a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		p2p_parse_free(&msg);
5271cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		return -1;
5272cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5273cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5274cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (msg.oob_go_neg_channel[3] == 0 &&
5275cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	    msg.oob_go_neg_channel[4] == 0)
5276cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		freq = 0;
5277cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	else
5278cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		freq = p2p_channel_to_freq(msg.oob_go_neg_channel[3],
5279cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					   msg.oob_go_neg_channel[4]);
5280cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (freq < 0) {
5281cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dbg(p2p, "Unknown peer OOB GO Neg channel");
5282a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		p2p_parse_free(&msg);
5283cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		return -1;
5284cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5285cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	role = msg.oob_go_neg_channel[5];
5286cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5287cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (role == P2P_GO_IN_A_GROUP) {
5288cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dbg(p2p, "Peer OOB GO operating channel: %u MHz", freq);
5289cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		params->go_freq = freq;
5290cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	} else if (role == P2P_CLIENT_IN_A_GROUP) {
5291cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dbg(p2p, "Peer (client) OOB GO operating channel: %u MHz",
5292cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			freq);
5293cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		params->go_freq = freq;
5294cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	} else
5295cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dbg(p2p, "Peer OOB GO Neg channel: %u MHz", freq);
5296cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	dev->oob_go_neg_freq = freq;
5297cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5298cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (!params->sel && role != P2P_GO_IN_A_GROUP) {
5299cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		freq = p2p_channel_to_freq(p2p->cfg->reg_class,
5300cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					   p2p->cfg->channel);
5301cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		if (freq < 0) {
5302cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			p2p_dbg(p2p, "Own listen channel not known");
5303a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			p2p_parse_free(&msg);
5304cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			return -1;
5305cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		}
5306cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dbg(p2p, "Use own Listen channel as OOB GO Neg channel: %u MHz", freq);
5307cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		dev->oob_go_neg_freq = freq;
5308cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5309cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5310cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (msg.group_id) {
5311cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		os_memcpy(params->go_dev_addr, msg.group_id, ETH_ALEN);
5312cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		params->go_ssid_len = msg.group_id_len - ETH_ALEN;
5313cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		os_memcpy(params->go_ssid, msg.group_id + ETH_ALEN,
5314cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			  params->go_ssid_len);
5315cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5316cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5317cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (dev->flags & P2P_DEV_USER_REJECTED) {
5318cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dbg(p2p, "Do not report rejected device");
5319717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt		p2p_parse_free(&msg);
5320cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		return 0;
5321cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5322cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5323cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (!(dev->flags & P2P_DEV_REPORTED)) {
5324cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p->cfg->dev_found(p2p->cfg->cb_ctx, p2p_dev_addr, &dev->info,
5325cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				    !(dev->flags & P2P_DEV_REPORTED_ONCE));
5326cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
5327cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5328717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt	p2p_parse_free(&msg);
5329cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5330cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (role == P2P_GO_IN_A_GROUP && p2p->num_groups > 0)
5331cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		params->next_step = BOTH_GO;
5332cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	else if (role == P2P_GO_IN_A_GROUP)
5333cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		params->next_step = JOIN_GROUP;
5334cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	else if (role == P2P_CLIENT_IN_A_GROUP) {
5335cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		dev->flags |= P2P_DEV_GROUP_CLIENT_ONLY;
5336cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		params->next_step = PEER_CLIENT;
5337cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	} else if (p2p->num_groups > 0)
5338cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		params->next_step = AUTH_JOIN;
5339cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	else if (params->sel)
5340cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		params->next_step = INIT_GO_NEG;
5341cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	else
5342cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		params->next_step = RESP_GO_NEG;
5343cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5344cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	return 0;
5345cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt}
5346cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5347cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5348cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtvoid p2p_set_authorized_oob_dev_pw_id(struct p2p_data *p2p, u16 dev_pw_id,
5349cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				      int go_intent,
5350cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				      const u8 *own_interface_addr)
5351cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{
5352cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5353cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	p2p->authorized_oob_dev_pw_id = dev_pw_id;
5354cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (dev_pw_id == 0) {
5355cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dbg(p2p, "NFC OOB Password unauthorized for static handover");
5356cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		return;
5357cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5358cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5359cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	p2p_dbg(p2p, "NFC OOB Password (id=%u) authorized for static handover",
5360cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		dev_pw_id);
5361cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5362cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	p2p->go_intent = go_intent;
5363cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
5364cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt}
5365cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5366cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_WPS_NFC */
53672271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt
53682271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt
53692271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidtint p2p_set_passphrase_len(struct p2p_data *p2p, unsigned int len)
53702271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt{
53712271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	if (len < 8 || len > 63)
53722271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		return -1;
53732271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	p2p->cfg->passphrase_len = len;
53742271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	return 0;
53752271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt}
53762e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
53772e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
53782e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidtvoid p2p_set_vendor_elems(struct p2p_data *p2p, struct wpabuf **vendor_elem)
53792e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt{
53802e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	p2p->vendor_elem = vendor_elem;
53812e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt}
53826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
53836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
53846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtvoid p2p_go_neg_wait_timeout(void *eloop_ctx, void *timeout_ctx)
53856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
53866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
53876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
53886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	p2p_dbg(p2p,
53896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		"Timeout on waiting peer to become ready for GO Negotiation");
53906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	p2p_go_neg_failed(p2p, -1);
53916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
5392