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"
139c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt#include "common/defs.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_common.h"
162e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt#include "common/wpa_ctrl.h"
17216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt#include "crypto/sha256.h"
18216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt#include "crypto/crypto.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps/wps_i.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p_i.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p.h"
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_state_timeout(void *eloop_ctx, void *timeout_ctx);
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev);
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_req(struct p2p_data *p2p, const u8 *da,
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const u8 *sa, const u8 *data, size_t len,
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     int rx_freq);
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_resp(struct p2p_data *p2p, const u8 *da,
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *sa, const u8 *data,
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      size_t len);
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_ext_listen_timeout(void *eloop_ctx, void *timeout_ctx);
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_scan_timeout(void *eloop_ctx, void *timeout_ctx);
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_scan recovery timeout
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Many drivers are using 30 second timeout on scan results. Allow a bit larger
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * timeout for this to avoid hitting P2P timeout unnecessarily.
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define P2P_SCAN_TIMEOUT 35
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * P2P_PEER_EXPIRATION_AGE - Number of seconds after which inactive peer
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * entries will be removed
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
482093d0658d2f0f8b5a98df7accc97fff3b2bb7d5Dmitry Shmidt#ifndef P2P_PEER_EXPIRATION_AGE
492093d0658d2f0f8b5a98df7accc97fff3b2bb7d5Dmitry Shmidt#define P2P_PEER_EXPIRATION_AGE 60
501846323989242844f0e857458a8939fa5836429cDmitry Shmidt#endif /* P2P_PEER_EXPIRATION_AGE */
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
53d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtvoid 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 const char * p2p_state_txt(int state)
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (state) {
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_IDLE:
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "IDLE";
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SEARCH:
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "SEARCH";
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT:
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "CONNECT";
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT_LISTEN:
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "CONNECT_LISTEN";
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG:
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "GO_NEG";
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_LISTEN_ONLY:
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "LISTEN_ONLY";
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_CONNECT:
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "WAIT_PEER_CONNECT";
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_IDLE:
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "WAIT_PEER_IDLE";
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SD_DURING_FIND:
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "SD_DURING_FIND";
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROVISIONING:
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "PROVISIONING";
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PD_DURING_FIND:
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "PD_DURING_FIND";
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE:
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "INVITE";
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE_LISTEN:
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "INVITE_LISTEN";
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "?";
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
141b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtconst char * p2p_get_state_txt(struct p2p_data *p2p)
142b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt{
143b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	return p2p_state_txt(p2p->state);
144b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt}
145b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt
146b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt
147216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtstruct p2ps_advertisement * p2p_get_p2ps_adv_list(struct p2p_data *p2p)
148216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt{
149216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	return p2p ? p2p->p2ps_adv_list : NULL;
150216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt}
151216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
152216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
153216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtvoid p2p_set_intended_addr(struct p2p_data *p2p, const u8 *intended_addr)
154216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt{
155216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (p2p && intended_addr)
156216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		os_memcpy(p2p->intended_addr, intended_addr, ETH_ALEN);
157216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt}
158216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
159216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
1601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtu16 p2p_get_provisioning_info(struct p2p_data *p2p, const u8 *addr)
1611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
1621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_device *dev = NULL;
1631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (!addr || !p2p)
1651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
1661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	dev = p2p_get_device(p2p, addr);
1681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (dev)
1691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return dev->wps_prov_info;
1701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	else
1711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
1721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
1731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
17504949598a23f501be6eec21697465fd46a28840aDmitry Shmidtvoid p2p_clear_provisioning_info(struct p2p_data *p2p, const u8 *addr)
1761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
1771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_device *dev = NULL;
1781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
17904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (!addr || !p2p)
1801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
1811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
18204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	dev = p2p_get_device(p2p, addr);
1831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (dev)
1841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->wps_prov_info = 0;
1851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
1861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_state(struct p2p_data *p2p, int new_state)
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
190b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "State %s -> %s",
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state), p2p_state_txt(new_state));
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->state = new_state;
19343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt
19443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	if (new_state == P2P_IDLE && p2p->pending_channel) {
19543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		p2p_dbg(p2p, "Apply change in listen channel");
19643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		p2p->cfg->reg_class = p2p->pending_reg_class;
19743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		p2p->cfg->channel = p2p->pending_channel;
19843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		p2p->pending_reg_class = 0;
19943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		p2p->pending_channel = 0;
20043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	}
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_timeout(struct p2p_data *p2p, unsigned int sec, unsigned int usec)
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
206b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Set timeout (state=%s): %u.%06u sec",
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state), sec, usec);
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_state_timeout, p2p, NULL);
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(sec, usec, p2p_state_timeout, p2p, NULL);
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_clear_timeout(struct p2p_data *p2p)
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
215b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Clear timeout (state=%s)", p2p_state_txt(p2p->state));
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_state_timeout, p2p, NULL);
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtvoid p2p_go_neg_failed(struct p2p_data *p2p, int status)
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_go_neg_results res;
2236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	struct p2p_device *peer = p2p->go_neg_peer;
2246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
2256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (!peer)
2266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return;
2276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
2286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	eloop_cancel_timeout(p2p_go_neg_wait_timeout, p2p, NULL);
2296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (p2p->state != P2P_SEARCH) {
2306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		/*
2316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 * Clear timeouts related to GO Negotiation if no new p2p_find
2326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 * has been started.
2336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 */
2346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_clear_timeout(p2p);
2356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
2368c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	}
2376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
2386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	peer->flags &= ~P2P_DEV_PEER_WAITING_RESPONSE;
2396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	peer->wps_method = WPS_NOT_READY;
2406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	peer->oob_pw_id = 0;
2416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpabuf_free(peer->go_neg_conf);
2426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	peer->go_neg_conf = NULL;
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer = NULL;
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&res, 0, sizeof(res));
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.status = status;
2476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	os_memcpy(res.peer_device_addr, peer->info.p2p_device_addr, ETH_ALEN);
2486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	os_memcpy(res.peer_interface_addr, peer->intended_addr, ETH_ALEN);
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->go_neg_completed(p2p->cfg->cb_ctx, &res);
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
253d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic void p2p_listen_in_find(struct p2p_data *p2p, int dev_disc)
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int r, tu;
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *ies;
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
259b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Starting short listen state (state=%s)",
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state));
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2623c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt	if (p2p->pending_listen_freq) {
2633c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt		/* We have a pending p2p_listen request */
2643c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt		p2p_dbg(p2p, "p2p_listen command pending already");
2653c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt		return;
2663c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt	}
2673c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt
2684b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	freq = p2p_channel_to_freq(p2p->cfg->reg_class, p2p->cfg->channel);
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq < 0) {
270b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Unknown regulatory class/channel");
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
274661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	if (os_get_random((u8 *) &r, sizeof(r)) < 0)
275661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		r = 0;
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tu = (r % ((p2p->max_disc_int - p2p->min_disc_int) + 1) +
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	      p2p->min_disc_int) * 100;
278d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (p2p->max_disc_tu >= 0 && tu > (unsigned int) p2p->max_disc_tu)
279d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		tu = p2p->max_disc_tu;
280d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (!dev_disc && tu < 100)
281d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		tu = 100; /* Need to wait in non-device discovery use cases */
282d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (p2p->cfg->max_listen && 1024 * tu / 1000 > p2p->cfg->max_listen)
283d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		tu = p2p->cfg->max_listen * 1000 / 1024;
284d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
285d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (tu == 0) {
286b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Skip listen state since duration was 0 TU");
287d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		p2p_set_timeout(p2p, 0, 0);
288d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return;
289d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
291a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	ies = p2p_build_probe_resp_ies(p2p, NULL, 0);
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ies == NULL)
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2953c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt	p2p->pending_listen_freq = freq;
2963c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt	p2p->pending_listen_sec = 0;
2973c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt	p2p->pending_listen_usec = 1024 * tu;
2983c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->start_listen(p2p->cfg->cb_ctx, freq, 1024 * tu / 1000,
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    ies) < 0) {
301b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to start listen mode");
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_freq = 0;
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(ies);
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_listen(struct p2p_data *p2p, unsigned int timeout)
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *ies;
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
313b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Going to listen(only) state");
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3153c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt	if (p2p->pending_listen_freq) {
3163c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt		/* We have a pending p2p_listen request */
3173c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt		p2p_dbg(p2p, "p2p_listen command pending already");
3183c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt		return -1;
3193c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt	}
3203c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt
3214b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	freq = p2p_channel_to_freq(p2p->cfg->reg_class, p2p->cfg->channel);
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq < 0) {
323b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Unknown regulatory class/channel");
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_sec = timeout / 1000;
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_usec = (timeout % 1000) * 1000;
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
33104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (p2p->start_after_scan == P2P_AFTER_SCAN_CONNECT) {
332b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "p2p_scan running - connect is already pending - skip listen");
3331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return 0;
3341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
335b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "p2p_scan running - delay start of listen state");
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->start_after_scan = P2P_AFTER_SCAN_LISTEN;
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
340a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	ies = p2p_build_probe_resp_ies(p2p, NULL, 0);
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ies == NULL)
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3443c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt	p2p->pending_listen_freq = freq;
3453c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->start_listen(p2p->cfg->cb_ctx, freq, timeout, ies) < 0) {
347b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to start listen mode");
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_freq = 0;
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(ies);
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(ies);
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_LISTEN_ONLY);
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_device_clear_reported(struct p2p_data *p2p)
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
3636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~P2P_DEV_REPORTED;
3656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		dev->sd_reqs = 0;
3666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_get_device - Fetch a peer entry
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: P2P Device Address of the peer
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the device entry or %NULL if not found
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_device * p2p_get_device(struct p2p_data *p2p, const u8 *addr)
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(dev->info.p2p_device_addr, addr, ETH_ALEN) == 0)
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return dev;
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_get_device_interface - Fetch a peer entry based on P2P Interface Address
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: P2P Interface Address of the peer
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the device entry or %NULL if not found
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_device * p2p_get_device_interface(struct p2p_data *p2p,
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     const u8 *addr)
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(dev->interface_addr, addr, ETH_ALEN) == 0)
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return dev;
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_create_device - Create a peer entry
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: P2P Device Address of the peer
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the device entry or %NULL on failure
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * If there is already an entry for the peer, it will be returned instead of
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * creating a new one.
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct p2p_device * p2p_create_device(struct p2p_data *p2p,
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     const u8 *addr)
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev, *oldest = NULL;
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t count = 0;
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev)
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return dev;
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		count++;
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (oldest == NULL ||
427fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		    os_reltime_before(&dev->last_seen, &oldest->last_seen))
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			oldest = dev;
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (count + 1 > p2p->cfg->max_peers && oldest) {
431b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Remove oldest peer entry to make room for a new peer");
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dl_list_del(&oldest->list);
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_device_free(p2p, oldest);
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = os_zalloc(sizeof(*dev));
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_add(&p2p->devices, &dev->list);
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.p2p_device_addr, addr, ETH_ALEN);
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return dev;
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_copy_client_info(struct p2p_device *dev,
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 struct p2p_client_info *cli)
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
449d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	p2p_copy_filter_devname(dev->info.device_name,
450d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				sizeof(dev->info.device_name),
451d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				cli->dev_name, cli->dev_name_len);
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.dev_capab = cli->dev_capab;
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.config_methods = cli->config_methods;
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.pri_dev_type, cli->pri_dev_type, 8);
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.wps_sec_dev_type_list_len = 8 * cli->num_sec_dev_types;
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.wps_sec_dev_type_list, cli->sec_dev_types,
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  dev->info.wps_sec_dev_type_list_len);
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_add_group_clients(struct p2p_data *p2p, const u8 *go_dev_addr,
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const u8 *go_interface_addr, int freq,
463a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt				 const u8 *gi, size_t gi_len,
464a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt				 struct os_reltime *rx_time)
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_info info;
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t c;
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gi == NULL)
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_group_info_parse(gi, gi_len, &info) < 0)
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Clear old data for this group; if the devices are still in the
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * group, the information will be restored in the loop following this.
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
4811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (os_memcmp(dev->member_in_go_iface, go_interface_addr,
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      ETH_ALEN) == 0) {
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(dev->member_in_go_iface, 0, ETH_ALEN);
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(dev->member_in_go_dev, 0, ETH_ALEN);
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (c = 0; c < info.num_clients; c++) {
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct p2p_client_info *cli = &info.client[c];
4901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (os_memcmp(cli->p2p_device_addr, p2p->cfg->dev_addr,
4911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      ETH_ALEN) == 0)
4921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			continue; /* ignore our own entry */
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, cli->p2p_device_addr);
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev) {
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev->flags & (P2P_DEV_GROUP_CLIENT_ONLY |
49604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					  P2P_DEV_PROBE_REQ_ONLY)) {
49704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				/*
49804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 * Update information since we have not
49904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 * received this directly from the client.
50004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 */
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p_copy_client_info(dev, cli);
50204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			} else {
50304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				/*
50404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 * Need to update P2P Client Discoverability
50504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 * flag since it is valid only in P2P Group
50604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 * Info attribute.
50704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 */
50804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				dev->info.dev_capab &=
50904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
51004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				dev->info.dev_capab |=
51104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					cli->dev_capab &
51204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
51304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			}
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev->flags & P2P_DEV_PROBE_REQ_ONLY) {
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev->flags &= ~P2P_DEV_PROBE_REQ_ONLY;
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev = p2p_create_device(p2p, cli->p2p_device_addr);
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev == NULL)
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				continue;
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->flags |= P2P_DEV_GROUP_CLIENT_ONLY;
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_copy_client_info(dev, cli);
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->oper_freq = freq;
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->cfg->dev_found(p2p->cfg->cb_ctx,
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    dev->info.p2p_device_addr,
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    &dev->info, 1);
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->interface_addr, cli->p2p_interface_addr,
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
532a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		os_memcpy(&dev->last_seen, rx_time, sizeof(struct os_reltime));
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->member_in_go_dev, go_dev_addr, ETH_ALEN);
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->member_in_go_iface, go_interface_addr,
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
536a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		dev->flags |= P2P_DEV_LAST_SEEN_AS_GROUP_CLIENT;
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
543b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidtstatic void p2p_copy_wps_info(struct p2p_data *p2p, struct p2p_device *dev,
544b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			      int probe_req, const struct p2p_message *msg)
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.device_name, msg->device_name,
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  sizeof(dev->info.device_name));
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->manufacturer &&
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->manufacturer_len < sizeof(dev->info.manufacturer)) {
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.manufacturer, 0,
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.manufacturer));
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.manufacturer, msg->manufacturer,
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->manufacturer_len);
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->model_name &&
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->model_name_len < sizeof(dev->info.model_name)) {
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.model_name, 0,
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.model_name));
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.model_name, msg->model_name,
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->model_name_len);
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->model_number &&
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->model_number_len < sizeof(dev->info.model_number)) {
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.model_number, 0,
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.model_number));
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.model_number, msg->model_number,
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->model_number_len);
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->serial_number &&
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->serial_number_len < sizeof(dev->info.serial_number)) {
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.serial_number, 0,
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.serial_number));
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.serial_number, msg->serial_number,
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->serial_number_len);
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->pri_dev_type)
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.pri_dev_type, msg->pri_dev_type,
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.pri_dev_type));
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (msg->wps_pri_dev_type)
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.pri_dev_type, msg->wps_pri_dev_type,
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.pri_dev_type));
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->wps_sec_dev_type_list) {
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.wps_sec_dev_type_list,
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->wps_sec_dev_type_list,
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->wps_sec_dev_type_list_len);
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_sec_dev_type_list_len =
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg->wps_sec_dev_type_list_len;
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->capability) {
59704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/*
59804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * P2P Client Discoverability bit is reserved in all frames
59904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * that use this function, so do not change its value here.
60004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 */
60104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->info.dev_capab &= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
60204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->info.dev_capab |= msg->capability[0] &
60304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.group_capab = msg->capability[1];
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->ext_listen_timing) {
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->ext_listen_period = WPA_GET_LE16(msg->ext_listen_timing);
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->ext_listen_interval =
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			WPA_GET_LE16(msg->ext_listen_timing + 2);
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
61204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!probe_req) {
614f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		u16 new_config_methods;
615f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		new_config_methods = msg->config_methods ?
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg->config_methods : msg->wps_config_methods;
617f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		if (new_config_methods &&
618f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		    dev->info.config_methods != new_config_methods) {
619b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Update peer " MACSTR
620b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				" config_methods 0x%x -> 0x%x",
621b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				MAC2STR(dev->info.p2p_device_addr),
622b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				dev->info.config_methods,
623b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				new_config_methods);
624f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			dev->info.config_methods = new_config_methods;
625f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		}
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6302e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidtstatic void p2p_update_peer_vendor_elems(struct p2p_device *dev, const u8 *ies,
6312e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt					 size_t ies_len)
6322e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt{
6332e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	const u8 *pos, *end;
6342e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	u8 id, len;
6352e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
6362e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	wpabuf_free(dev->info.vendor_elems);
6372e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	dev->info.vendor_elems = NULL;
6382e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
6392e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	end = ies + ies_len;
6402e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
641d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	for (pos = ies; end - pos > 1; pos += len) {
6422e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		id = *pos++;
6432e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		len = *pos++;
6442e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
645d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (len > end - pos)
6462e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			break;
6472e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
6482e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		if (id != WLAN_EID_VENDOR_SPECIFIC || len < 3)
6492e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			continue;
6502e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
6512e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		if (len >= 4) {
6522e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			u32 type = WPA_GET_BE32(pos);
6532e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
6542e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			if (type == WPA_IE_VENDOR_TYPE ||
6552e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			    type == WMM_IE_VENDOR_TYPE ||
6562e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			    type == WPS_IE_VENDOR_TYPE ||
6572e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			    type == P2P_IE_VENDOR_TYPE ||
6582e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			    type == WFD_IE_VENDOR_TYPE)
6592e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt				continue;
6602e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		}
6612e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
6622e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		/* Unknown vendor element - make raw IE data available */
6632e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		if (wpabuf_resize(&dev->info.vendor_elems, 2 + len) < 0)
6642e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			break;
6652e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		wpabuf_put_data(dev->info.vendor_elems, pos - 2, 2 + len);
6662e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	}
6672e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt}
6682e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
6692e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
6706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int p2p_compare_wfd_info(struct p2p_device *dev,
6716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			      const struct p2p_message *msg)
6726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
6736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (dev->info.wfd_subelems && msg->wfd_subelems) {
6746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (dev->info.wfd_subelems->used != msg->wfd_subelems->used)
6756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return 1;
6766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
6776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return os_memcmp(dev->info.wfd_subelems->buf,
6786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				 msg->wfd_subelems->buf,
6796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				 dev->info.wfd_subelems->used);
6806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
6816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (dev->info.wfd_subelems || msg->wfd_subelems)
6826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 1;
6836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
6846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return 0;
6856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
6866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
6876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
68904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * p2p_add_device - Add peer entries based on scan results or P2P frames
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: Source address of Beacon or Probe Response frame (may be either
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *	P2P Device Address or P2P Interface Address)
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @level: Signal level (signal strength of the received frame from the peer)
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @freq: Frequency on which the Beacon or Probe Response frame was received
695f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * @rx_time: Time when the result was received
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ies: IEs from the Beacon or Probe Response frame
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ies_len: Length of ies buffer in octets
69804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * @scan_res: Whether this was based on scan results
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * If the scan result is for a GO, the clients in the group will also be added
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to the peer table. This function can also be used with some other frames
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * like Provision Discovery Request that contains P2P Capability and P2P Device
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Info attributes.
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
706a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtint p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq,
707fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		   struct os_reltime *rx_time, int level, const u8 *ies,
708a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		   size_t ies_len, int scan_res)
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *p2p_dev_addr;
7136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	int wfd_changed;
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
715fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	struct os_reltime time_now;
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ies, ies_len, &msg)) {
719b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to parse P2P IE for a device entry");
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.p2p_device_addr)
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_addr = msg.p2p_device_addr;
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (msg.device_id)
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_addr = msg.device_id;
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
729b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Ignore scan data without P2P Device Info or P2P Device Id");
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!is_zero_ether_addr(p2p->peer_filter) &&
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(p2p_dev_addr, p2p->peer_filter, ETH_ALEN) != 0) {
736b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Do not add peer filter for " MACSTR
737b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			" due to peer filter", MAC2STR(p2p_dev_addr));
738a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p_parse_free(&msg);
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_create_device(p2p, p2p_dev_addr);
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
747a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
748f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	if (rx_time == NULL) {
749fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		os_get_reltime(&time_now);
750f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		rx_time = &time_now;
751f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	}
752a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
753a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	/*
754a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	 * Update the device entry only if the new peer
755a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	 * entry is newer than the one previously stored, or if
756a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	 * the device was previously seen as a P2P Client in a group
757a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	 * and the new entry isn't older than a threshold.
758a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	 */
759f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	if (dev->last_seen.sec > 0 &&
760a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	    os_reltime_before(rx_time, &dev->last_seen) &&
761a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	    (!(dev->flags & P2P_DEV_LAST_SEEN_AS_GROUP_CLIENT) ||
762a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	     os_reltime_expired(&dev->last_seen, rx_time,
763a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt				P2P_DEV_GROUP_CLIENT_RESP_THRESHOLD))) {
764a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		p2p_dbg(p2p,
765a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			"Do not update peer entry based on old frame (rx_time=%u.%06u last_seen=%u.%06u flags=0x%x)",
766f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			(unsigned int) rx_time->sec,
767f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			(unsigned int) rx_time->usec,
768f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			(unsigned int) dev->last_seen.sec,
769a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			(unsigned int) dev->last_seen.usec,
770a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			dev->flags);
771a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p_parse_free(&msg);
772a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
773a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
774a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
775fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	os_memcpy(&dev->last_seen, rx_time, sizeof(struct os_reltime));
776a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
777a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	dev->flags &= ~(P2P_DEV_PROBE_REQ_ONLY | P2P_DEV_GROUP_CLIENT_ONLY |
778a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			P2P_DEV_LAST_SEEN_AS_GROUP_CLIENT);
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(addr, p2p_dev_addr, ETH_ALEN) != 0)
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->interface_addr, addr, ETH_ALEN);
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.ssid &&
783fdb708a37d8f7f1483e3cd4e8ded974f53fedaceJouni Malinen	    msg.ssid[1] <= sizeof(dev->oper_ssid) &&
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (msg.ssid[1] != P2P_WILDCARD_SSID_LEN ||
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     os_memcmp(msg.ssid + 2, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN)
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     != 0)) {
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->oper_ssid, msg.ssid + 2, msg.ssid[1]);
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->oper_ssid_len = msg.ssid[1];
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
791216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (msg.adv_service_instance && msg.adv_service_instance_len) {
792216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		wpabuf_free(dev->info.p2ps_instance);
793216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		dev->info.p2ps_instance = wpabuf_alloc_copy(
794216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			msg.adv_service_instance, msg.adv_service_instance_len);
795216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
796216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq >= 2412 && freq <= 2484 && msg.ds_params &&
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    *msg.ds_params >= 1 && *msg.ds_params <= 14) {
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int ds_freq;
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*msg.ds_params == 14)
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ds_freq = 2484;
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ds_freq = 2407 + *msg.ds_params * 5;
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freq != ds_freq) {
805b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Update Listen frequency based on DS Parameter Set IE: %d -> %d MHz",
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				freq, ds_freq);
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq = ds_freq;
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
81104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (dev->listen_freq && dev->listen_freq != freq && scan_res) {
812b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Update Listen frequency based on scan results ("
813b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			MACSTR " %d -> %d MHz (DS param %d)",
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr), dev->listen_freq,
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq, msg.ds_params ? *msg.ds_params : -1);
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
81704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (scan_res) {
81804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->listen_freq = freq;
81904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (msg.group_info)
82004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			dev->oper_freq = freq;
82104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
82275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	dev->info.level = level;
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
824b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_copy_wps_info(p2p, dev, 0, &msg);
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(dev->info.wps_vendor_ext[i]);
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_vendor_ext[i] = NULL;
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (msg.wps_vendor_ext[i] == NULL)
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_vendor_ext[i] = wpabuf_alloc_copy(
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg.wps_vendor_ext[i], msg.wps_vendor_ext_len[i]);
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->info.wps_vendor_ext[i] == NULL)
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wfd_changed = p2p_compare_wfd_info(dev, &msg);
8416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
84261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (msg.wfd_subelems) {
84361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_free(dev->info.wfd_subelems);
84461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
84561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
84661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
84704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (scan_res) {
84804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p_add_group_clients(p2p, p2p_dev_addr, addr, freq,
849a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt				      msg.group_info, msg.group_info_len,
850a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt				      rx_time);
85104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8552e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	p2p_update_peer_vendor_elems(dev, ies, ies_len);
8562e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
857216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (dev->flags & P2P_DEV_REPORTED && !wfd_changed &&
858216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	    (!msg.adv_service_instance ||
859216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	     (dev->flags & P2P_DEV_P2PS_REPORTED)))
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
862b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Peer found with Listen frequency %d MHz (rx_time=%u.%06u)",
863b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		freq, (unsigned int) rx_time->sec,
864f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		(unsigned int) rx_time->usec);
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_USER_REJECTED) {
866b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Do not report rejected device");
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
870f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	if (dev->info.config_methods == 0 &&
871f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	    (freq == 2412 || freq == 2437 || freq == 2462)) {
872f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		/*
873f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * If we have only seen a Beacon frame from a GO, we do not yet
874f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * know what WPS config methods it supports. Since some
875f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * applications use config_methods value from P2P-DEVICE-FOUND
876f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * events, postpone reporting this peer until we've fully
877f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * discovered its capabilities.
878f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 *
879f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * At least for now, do this only if the peer was detected on
880f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * one of the social channels since that peer can be easily be
881f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * found again and there are no limitations of having to use
882f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * passive scan on this channels, so this can be done through
883f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * Probe Response frame that includes the config_methods
884f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * information.
885f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 */
886b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Do not report peer " MACSTR
887b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			" with unknown config methods", MAC2STR(addr));
888f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		return 0;
889f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	}
890f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->dev_found(p2p->cfg->cb_ctx, addr, &dev->info,
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    !(dev->flags & P2P_DEV_REPORTED_ONCE));
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
895216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (msg.adv_service_instance)
896216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		dev->flags |= P2P_DEV_P2PS_REPORTED;
897216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev)
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
906497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt	if (p2p->go_neg_peer == dev) {
9071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/*
9081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * If GO Negotiation is in progress, report that it has failed.
9091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
9106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_go_neg_failed(p2p, -1);
911497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt	}
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->invite_peer == dev)
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->invite_peer = NULL;
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->sd_peer == dev)
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->sd_peer = NULL;
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->pending_client_disc_go == dev)
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_client_disc_go = NULL;
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
919c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	/* dev_lost() device, but only if it was previously dev_found() */
920c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	if (dev->flags & P2P_DEV_REPORTED_ONCE)
921c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		p2p->cfg->dev_lost(p2p->cfg->cb_ctx,
922c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt				   dev->info.p2p_device_addr);
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(dev->info.wps_vendor_ext[i]);
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_vendor_ext[i] = NULL;
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
92961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(dev->info.wfd_subelems);
9302e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	wpabuf_free(dev->info.vendor_elems);
931413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt	wpabuf_free(dev->go_neg_conf);
932216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	wpabuf_free(dev->info.p2ps_instance);
93361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(dev);
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_get_next_prog_freq(struct p2p_data *p2p)
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_channels *c;
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_reg_class *cla;
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t cl, ch;
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int found = 0;
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 reg_class;
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 channel;
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	c = &p2p->cfg->channels;
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (cl = 0; cl < c->reg_classes; cl++) {
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cla = &c->reg_class[cl];
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (cla->reg_class != p2p->last_prog_scan_class)
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (ch = 0; ch < cla->channels; ch++) {
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (cla->channel[ch] == p2p->last_prog_scan_chan) {
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				found = 1;
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (found)
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!found) {
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Start from beginning */
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reg_class = c->reg_class[0].reg_class;
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		channel = c->reg_class[0].channel[0];
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Pick the next channel */
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ch++;
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ch == cla->channels) {
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			cl++;
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (cl == c->reg_classes)
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				cl = 0;
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ch = 0;
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reg_class = c->reg_class[cl].reg_class;
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		channel = c->reg_class[cl].channel[ch];
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9804b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	freq = p2p_channel_to_freq(reg_class, channel);
981b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Next progressive search channel: reg_class %u channel %u -> %d MHz",
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reg_class, channel, freq);
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->last_prog_scan_class = reg_class;
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->last_prog_scan_chan = channel;
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq == 2412 || freq == 2437 || freq == 2462)
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* No need to add social channels */
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return freq;
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_search(struct p2p_data *p2p)
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq = 0;
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum p2p_scan_type type;
99604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	u16 pw_id = DEV_PW_DEFAULT;
99761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	int res;
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->drv_in_listen) {
1000b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Driver is still in Listen state - wait for it to end before continuing");
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
100504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p->find_type == P2P_FIND_PROGRESSIVE &&
100604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    (freq = p2p_get_next_prog_freq(p2p)) > 0) {
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type = P2P_SCAN_SOCIAL_PLUS_ONE;
1008b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Starting search (+ freq %u)", freq);
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type = P2P_SCAN_SOCIAL;
1011b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Starting search");
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
101461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, type, freq,
101561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				 p2p->num_req_dev_types, p2p->req_dev_types,
101661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				 p2p->find_dev_id, pw_id);
101761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (res < 0) {
10186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_dbg(p2p, "Scan request schedule failed");
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_find_timeout(void *eloop_ctx, void *timeout_ctx)
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
1027b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Find timeout -> stop");
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_stop_find(p2p);
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtvoid p2p_notify_scan_trigger_status(struct p2p_data *p2p, int status)
10336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
10346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (status != 0) {
10356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_dbg(p2p, "Scan request failed");
10366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		/* Do continue find even for the first p2p_find_scan */
10376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_continue_find(p2p);
10386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	} else {
10396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_dbg(p2p, "Running p2p_scan");
10406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p->p2p_scan_running = 1;
10416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
10426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		eloop_register_timeout(P2P_SCAN_TIMEOUT, 0, p2p_scan_timeout,
10436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				       p2p, NULL);
10446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
10456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
10466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
10476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_run_after_scan(struct p2p_data *p2p)
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum p2p_after_scan op;
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->after_scan_tx) {
10548da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt		p2p->after_scan_tx_in_progress = 1;
1055b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Send pending Action frame at p2p_scan completion");
10561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p->cfg->send_action(p2p->cfg->cb_ctx,
10571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->freq,
10581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->dst,
10591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->src,
10601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->bssid,
10611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      (u8 *) (p2p->after_scan_tx + 1),
10621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->len,
10631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->wait_time);
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p2p->after_scan_tx);
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = NULL;
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	op = p2p->start_after_scan;
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (op) {
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_AFTER_SCAN_NOTHING:
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_AFTER_SCAN_LISTEN:
1075b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Start previously requested Listen state");
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_listen(p2p, p2p->pending_listen_sec * 1000 +
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   p2p->pending_listen_usec / 1000);
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_AFTER_SCAN_CONNECT:
1080b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Start previously requested connect with " MACSTR,
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(p2p->after_scan_peer));
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, p2p->after_scan_peer);
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev == NULL) {
1084b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Peer not known anymore");
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, dev);
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_scan_timeout(void *eloop_ctx, void *timeout_ctx)
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int running;
1099b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "p2p_scan timeout (running=%d)", p2p->p2p_scan_running);
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	running = p2p->p2p_scan_running;
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Make sure we recover from missed scan results callback */
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->p2p_scan_running = 0;
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (running)
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_run_after_scan(p2p);
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_free_req_dev_types(struct p2p_data *p2p)
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->num_req_dev_types = 0;
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->req_dev_types);
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->req_dev_types = NULL;
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1117216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtstatic int p2ps_gen_hash(struct p2p_data *p2p, const char *str, u8 *hash)
1118216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt{
1119216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	u8 buf[SHA256_MAC_LEN];
1120216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	char str_buf[256];
1121216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	const u8 *adv_array;
1122216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	size_t i, adv_len;
1123216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
1124216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (!str || !hash)
1125216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		return 0;
1126216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
1127216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (!str[0]) {
1128216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		os_memcpy(hash, p2p->wild_card_hash, P2PS_HASH_LEN);
1129216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		return 1;
1130216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
1131216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
1132216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_array = (u8 *) str_buf;
1133216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_len = os_strlen(str);
1134a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	if (adv_len >= sizeof(str_buf))
1135a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		return 0;
1136216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
1137d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	for (i = 0; i < adv_len; i++) {
1138216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (str[i] >= 'A' && str[i] <= 'Z')
1139216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			str_buf[i] = str[i] - 'A' + 'a';
1140216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		else
1141216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			str_buf[i] = str[i];
1142216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
1143216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
1144216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (sha256_vector(1, &adv_array, &adv_len, buf))
1145216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		return 0;
1146216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
1147216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	os_memcpy(hash, buf, P2PS_HASH_LEN);
1148216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	return 1;
1149216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt}
1150216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
1151216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_find(struct p2p_data *p2p, unsigned int timeout,
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     enum p2p_discovery_type type,
1154c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	     unsigned int num_req_dev_types, const u8 *req_dev_types,
1155216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	     const u8 *dev_id, unsigned int search_delay,
1156203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt	     u8 seek_count, const char **seek, int freq)
11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1160b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Starting find (type=%d)", type);
1161fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	os_get_reltime(&p2p->find_start);
11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
1163b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "p2p_scan is already running");
11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_req_dev_types(p2p);
11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req_dev_types && num_req_dev_types) {
11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->req_dev_types = os_malloc(num_req_dev_types *
11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       WPS_DEV_TYPE_LEN);
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->req_dev_types == NULL)
11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->req_dev_types, req_dev_types,
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  num_req_dev_types * WPS_DEV_TYPE_LEN);
11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->num_req_dev_types = num_req_dev_types;
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1177c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (dev_id) {
1178c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		os_memcpy(p2p->find_dev_id_buf, dev_id, ETH_ALEN);
1179c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		p2p->find_dev_id = p2p->find_dev_id_buf;
1180c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	} else
1181c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		p2p->find_dev_id = NULL;
1182c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1183216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (seek_count == 0 || !seek) {
1184216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		/* Not an ASP search */
1185216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p->p2ps_seek = 0;
1186216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	} else if (seek_count == 1 && seek && (!seek[0] || !seek[0][0])) {
1187216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		/*
1188216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		 * An empty seek string means no hash values, but still an ASP
1189216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		 * search.
1190216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		 */
1191a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		p2p_dbg(p2p, "ASP search");
1192216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p->p2ps_seek_count = 0;
1193216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p->p2ps_seek = 1;
1194216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	} else if (seek && seek_count <= P2P_MAX_QUERY_HASH) {
1195216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		u8 buf[P2PS_HASH_LEN];
1196a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		int i, count = 0;
1197216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
1198216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		for (i = 0; i < seek_count; i++) {
1199216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			if (!p2ps_gen_hash(p2p, seek[i], buf))
1200216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				continue;
1201216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
1202a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			p2p_dbg(p2p, "Seek service %s hash " MACSTR,
1203a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt				seek[i], MAC2STR(buf));
1204a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			os_memcpy(&p2p->p2ps_seek_hash[count * P2PS_HASH_LEN],
1205a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt				  buf, P2PS_HASH_LEN);
1206a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			count++;
1207216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		}
1208a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt
1209a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		p2p->p2ps_seek_count = count;
1210216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p->p2ps_seek = 1;
1211216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	} else {
1212216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p->p2ps_seek_count = 0;
1213216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p->p2ps_seek = 1;
1214216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
1215216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
1216216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	/* Special case to perform wildcard search */
1217216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (p2p->p2ps_seek_count == 0 && p2p->p2ps_seek) {
1218216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p->p2ps_seek_count = 1;
1219a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		os_memcpy(&p2p->p2ps_seek_hash, p2p->wild_card_hash,
1220a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			  P2PS_HASH_LEN);
1221216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
1222216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
1225de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	if (p2p->pending_listen_freq) {
1226de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt		p2p_dbg(p2p, "Clear pending_listen_freq for p2p_find");
1227de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt		p2p->pending_listen_freq = 0;
1228de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	}
12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->find_type = type;
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_device_clear_reported(p2p);
1232de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	os_memset(p2p->sd_query_no_ack, 0, ETH_ALEN);
12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_SEARCH);
123461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->search_delay = search_delay;
123561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->in_search_delay = 0;
12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
12371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p->last_p2p_find_timeout = timeout;
12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (timeout)
12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(timeout, 0, p2p_find_timeout,
12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p, NULL);
12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (type) {
12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_FIND_START_WITH_FULL:
1243203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt		if (freq > 0) {
1244203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt			/*
1245203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt			 * Start with the specified channel and then move to
1246203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt			 * social channels only scans.
1247203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt			 */
1248203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt			res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx,
1249203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt						 P2P_SCAN_SPECIFIC, freq,
1250203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt						 p2p->num_req_dev_types,
1251203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt						 p2p->req_dev_types, dev_id,
1252203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt						 DEV_PW_DEFAULT);
1253203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt			break;
1254203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt		}
1255203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt		/* fall through */
12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_FIND_PROGRESSIVE:
12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_FULL, 0,
12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 p2p->num_req_dev_types,
125904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 p2p->req_dev_types, dev_id,
126004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 DEV_PW_DEFAULT);
12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_FIND_ONLY_SOCIAL:
12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_SOCIAL, 0,
12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 p2p->num_req_dev_types,
126504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 p2p->req_dev_types, dev_id,
126604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 DEV_PW_DEFAULT);
12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (res != 0 && p2p->p2p_scan_running) {
1273fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		p2p_dbg(p2p, "Failed to start p2p_scan - another p2p_scan was already running");
1274fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		/* wait for the previous p2p_scan to complete */
127596be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt		res = 0; /* do not report failure */
12766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	} else if (res != 0) {
1277b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to start p2p_scan");
12781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
12791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_stop_find_for_freq(struct p2p_data *p2p, int freq)
12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1288b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Stopping find");
12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
1291216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (p2p->state == P2P_SEARCH || p2p->state == P2P_SD_DURING_FIND)
1292b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p->cfg->find_stopped(p2p->cfg->cb_ctx);
1293216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
1294216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	p2p->p2ps_seek_count = 0;
1295216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_IDLE);
12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_req_dev_types(p2p);
12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
12998c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	if (p2p->go_neg_peer)
13008c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		p2p->go_neg_peer->flags &= ~P2P_DEV_PEER_WAITING_RESPONSE;
13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer = NULL;
13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->sd_peer = NULL;
13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->invite_peer = NULL;
130404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_stop_listen_for_freq(p2p, freq);
13057f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt	p2p->send_action_in_progress = 0;
130604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
130704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
130804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
130904949598a23f501be6eec21697465fd46a28840aDmitry Shmidtvoid p2p_stop_listen_for_freq(struct p2p_data *p2p, int freq)
131004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq > 0 && p2p->drv_in_listen == freq && p2p->in_listen) {
1312b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Skip stop_listen since we are on correct channel for response");
13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
131504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p->in_listen) {
131604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->in_listen = 0;
131704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p_clear_timeout(p2p);
131804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
13191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p->drv_in_listen) {
13201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/*
13211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * The driver may not deliver callback to p2p_listen_end()
13221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * when the operation gets canceled, so clear the internal
13231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * variable that is tracking driver state.
13241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
1325b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Clear drv_in_listen (%d)", p2p->drv_in_listen);
13261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p->drv_in_listen = 0;
13271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1332391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtvoid p2p_stop_listen(struct p2p_data *p2p)
1333391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{
1334391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (p2p->state != P2P_LISTEN_ONLY) {
1335391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		p2p_dbg(p2p, "Skip stop_listen since not in listen_only state.");
1336391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		return;
1337391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	}
1338391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
1339391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	p2p_stop_listen_for_freq(p2p, 0);
1340391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	p2p_set_state(p2p, P2P_IDLE);
1341391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt}
1342391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
1343391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_stop_find(struct p2p_data *p2p)
13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13463c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt	p2p->pending_listen_freq = 0;
13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_stop_find_for_freq(p2p, 0);
13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1351a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtstatic int p2p_prepare_channel_pref(struct p2p_data *p2p,
1352a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt				    unsigned int force_freq,
135368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt				    unsigned int pref_freq, int go)
13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1355a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	u8 op_class, op_channel;
1356a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	unsigned int freq = force_freq ? force_freq : pref_freq;
13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
135868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p_dbg(p2p, "Prepare channel pref - force_freq=%u pref_freq=%u go=%d",
135968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		force_freq, pref_freq, go);
13604b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	if (p2p_freq_to_channel(freq, &op_class, &op_channel) < 0) {
1361b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Unsupported frequency %u MHz", freq);
1362a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
1363a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
1364a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
136568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	if (!p2p_channels_includes(&p2p->cfg->channels, op_class, op_channel) &&
136668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	    (go || !p2p_channels_includes(&p2p->cfg->cli_channels, op_class,
136768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt					  op_channel))) {
1368b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Frequency %u MHz (oper_class %u channel %u) not allowed for P2P",
1369b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			freq, op_class, op_channel);
1370a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
1371a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
1372a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1373a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	p2p->op_reg_class = op_class;
1374a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	p2p->op_channel = op_channel;
13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1376a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (force_freq) {
1377a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->channels.reg_classes = 1;
1378a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->channels.reg_class[0].channels = 1;
1379a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->channels.reg_class[0].reg_class = p2p->op_reg_class;
1380a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->channels.reg_class[0].channel[0] = p2p->op_channel;
1381a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	} else {
13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(&p2p->channels, &p2p->cfg->channels,
13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(struct p2p_channels));
13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1385a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1386a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	return 0;
1387a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt}
1388a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1389a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1390a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtstatic void p2p_prepare_channel_best(struct p2p_data *p2p)
1391a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{
1392a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	u8 op_class, op_channel;
1393a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	const int op_classes_5ghz[] = { 124, 125, 115, 0 };
1394a0d265f81180f341d22511538fa18166e1bbce9fDmitry Shmidt	const int op_classes_ht40[] = { 126, 127, 116, 117, 0 };
1395e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	const int op_classes_vht[] = { 128, 0 };
1396a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1397b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	p2p_dbg(p2p, "Prepare channel best");
1398b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt
1399a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (!p2p->cfg->cfg_op_channel && p2p->best_freq_overall > 0 &&
1400a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	    p2p_supported_freq(p2p, p2p->best_freq_overall) &&
14014b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	    p2p_freq_to_channel(p2p->best_freq_overall, &op_class, &op_channel)
14024b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	    == 0) {
1403b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Select best overall channel as operating channel preference");
1404a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_reg_class = op_class;
1405a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_channel = op_channel;
1406a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	} else if (!p2p->cfg->cfg_op_channel && p2p->best_freq_5 > 0 &&
1407a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		   p2p_supported_freq(p2p, p2p->best_freq_5) &&
14084b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		   p2p_freq_to_channel(p2p->best_freq_5, &op_class, &op_channel)
14094b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		   == 0) {
1410b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Select best 5 GHz channel as operating channel preference");
1411a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_reg_class = op_class;
1412a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_channel = op_channel;
1413a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	} else if (!p2p->cfg->cfg_op_channel && p2p->best_freq_24 > 0 &&
1414a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		   p2p_supported_freq(p2p, p2p->best_freq_24) &&
14154b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		   p2p_freq_to_channel(p2p->best_freq_24, &op_class,
14164b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt				       &op_channel) == 0) {
1417b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Select best 2.4 GHz channel as operating channel preference");
1418a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_reg_class = op_class;
1419a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_channel = op_channel;
1420b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	} else if (p2p->cfg->num_pref_chan > 0 &&
1421b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		   p2p_channels_includes(&p2p->cfg->channels,
1422b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt					 p2p->cfg->pref_chan[0].op_class,
1423b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt					 p2p->cfg->pref_chan[0].chan)) {
1424b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		p2p_dbg(p2p, "Select first pref_chan entry as operating channel preference");
1425b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		p2p->op_reg_class = p2p->cfg->pref_chan[0].op_class;
1426b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		p2p->op_channel = p2p->cfg->pref_chan[0].chan;
1427e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	} else if (p2p_channel_select(&p2p->cfg->channels, op_classes_vht,
1428e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt				      &p2p->op_reg_class, &p2p->op_channel) ==
1429e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		   0) {
1430e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		p2p_dbg(p2p, "Select possible VHT channel (op_class %u channel %u) as operating channel preference",
1431e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt			p2p->op_reg_class, p2p->op_channel);
1432e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	} else if (p2p_channel_select(&p2p->cfg->channels, op_classes_ht40,
1433e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt				      &p2p->op_reg_class, &p2p->op_channel) ==
1434e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		   0) {
1435e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		p2p_dbg(p2p, "Select possible HT40 channel (op_class %u channel %u) as operating channel preference",
1436e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt			p2p->op_reg_class, p2p->op_channel);
1437e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	} else if (p2p_channel_select(&p2p->cfg->channels, op_classes_5ghz,
1438e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt				      &p2p->op_reg_class, &p2p->op_channel) ==
1439e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		   0) {
1440e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		p2p_dbg(p2p, "Select possible 5 GHz channel (op_class %u channel %u) as operating channel preference",
1441e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt			p2p->op_reg_class, p2p->op_channel);
1442d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt	} else if (p2p_channels_includes(&p2p->cfg->channels,
1443d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt					 p2p->cfg->op_reg_class,
1444d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt					 p2p->cfg->op_channel)) {
1445b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		p2p_dbg(p2p, "Select pre-configured channel as operating channel preference");
1446a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_reg_class = p2p->cfg->op_reg_class;
1447a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p->op_channel = p2p->cfg->op_channel;
1448d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt	} else if (p2p_channel_random_social(&p2p->cfg->channels,
1449d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt					     &p2p->op_reg_class,
1450d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt					     &p2p->op_channel) == 0) {
1451661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		p2p_dbg(p2p, "Select random available social channel (op_class %u channel %u) as operating channel preference",
1452661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt			p2p->op_reg_class, p2p->op_channel);
1453d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt	} else {
1454d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt		/* Select any random available channel from the first available
1455d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt		 * operating class */
1456d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt		p2p_channel_select(&p2p->cfg->channels, NULL,
1457d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt				   &p2p->op_reg_class,
1458d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt				   &p2p->op_channel);
1459d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt		p2p_dbg(p2p, "Select random available channel %d from operating class %d as operating channel preference",
1460d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt			p2p->op_channel, p2p->op_reg_class);
1461a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
1462a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1463a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	os_memcpy(&p2p->channels, &p2p->cfg->channels,
1464a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		  sizeof(struct p2p_channels));
1465a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt}
1466a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1467a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
1468a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt/**
1469d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * p2p_prepare_channel - Select operating channel for GO Negotiation or P2PS PD
1470a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @p2p: P2P module context from p2p_init()
1471a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @dev: Selected peer device
1472a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @force_freq: Forced frequency in MHz or 0 if not forced
1473a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @pref_freq: Preferred frequency in MHz or 0 if no preference
147468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt * @go: Whether the local end will be forced to be GO
1475a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Returns: 0 on success, -1 on failure (channel not supported for P2P)
1476a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *
1477a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * This function is used to do initial operating channel selection for GO
1478d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * Negotiation prior to having received peer information or for P2PS PD
1479d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * signalling. The selected channel may be further optimized in
1480d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * p2p_reselect_channel() once the peer information is available.
1481a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt */
14827a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidtint p2p_prepare_channel(struct p2p_data *p2p, struct p2p_device *dev,
148368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt			unsigned int force_freq, unsigned int pref_freq, int go)
1484a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{
148568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p_dbg(p2p, "Prepare channel - force_freq=%u pref_freq=%u go=%d",
148668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		force_freq, pref_freq, go);
1487a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (force_freq || pref_freq) {
148868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		if (p2p_prepare_channel_pref(p2p, force_freq, pref_freq, go) <
148968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		    0)
1490a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			return -1;
1491a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	} else {
1492a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		p2p_prepare_channel_best(p2p);
1493a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
149468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p_channels_dump(p2p, "prepared channels", &p2p->channels);
149568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	if (go)
149668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		p2p_channels_remove_freqs(&p2p->channels, &p2p->no_go_freq);
149768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	else if (!force_freq)
14986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_channels_union_inplace(&p2p->channels,
14996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt					   &p2p->cfg->cli_channels);
150068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p_channels_dump(p2p, "after go/cli filter/add", &p2p->channels);
150168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt
1502b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Own preference for operation channel: Operating Class %u Channel %u%s",
15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->op_reg_class, p2p->op_channel,
15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		force_freq ? " (forced)" : "");
15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1506a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (force_freq)
1507a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		dev->flags |= P2P_DEV_FORCE_FREQ;
1508a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	else
1509a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		dev->flags &= ~P2P_DEV_FORCE_FREQ;
1510a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void p2p_set_dev_persistent(struct p2p_device *dev,
15161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   int persistent_group)
15171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
15181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	switch (persistent_group) {
15191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case 0:
15201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags &= ~(P2P_DEV_PREFER_PERSISTENT_GROUP |
15211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				P2P_DEV_PREFER_PERSISTENT_RECONN);
15221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
15231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case 1:
15241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP;
15251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags &= ~P2P_DEV_PREFER_PERSISTENT_RECONN;
15261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
15271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case 2:
15281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP |
15291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			P2P_DEV_PREFER_PERSISTENT_RECONN;
15301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
15311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
15321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
15331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
15341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		enum p2p_wps_method wps_method,
15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int go_intent, const u8 *own_interface_addr,
153804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		unsigned int force_freq, int persistent_group,
153904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		const u8 *force_ssid, size_t force_ssid_len,
1540cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		int pd_before_go_neg, unsigned int pref_freq, u16 oob_pw_id)
15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1544b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Request to start group negotiation - peer=" MACSTR
15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  GO Intent=%d  Intended Interface Address=" MACSTR
1546cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		" wps_method=%d persistent_group=%d pd_before_go_neg=%d "
1547cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		"oob_pw_id=%u",
15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
1549cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		wps_method, persistent_group, pd_before_go_neg, oob_pw_id);
15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
1553b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Cannot connect to unknown P2P Device " MACSTR,
15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(peer_addr));
15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
155868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	if (p2p_prepare_channel(p2p, dev, force_freq, pref_freq,
155968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt				go_intent == 15) < 0)
1560a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
1561a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!(dev->info.dev_capab &
15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
1565b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Cannot connect to P2P Device " MACSTR
15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				" that is in a group and is not discoverable",
15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(peer_addr));
15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->oper_freq <= 0) {
1571b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Cannot connect to P2P Device " MACSTR
15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				" with incomplete information",
15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(peer_addr));
15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * First, try to connect directly. If the peer does not
15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * acknowledge frames, assume it is sleeping and use device
15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * discoverability via the GO at that point.
15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
158404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p->ssid_set = 0;
158504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (force_ssid) {
158604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "P2P: Forced SSID",
158704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  force_ssid, force_ssid_len);
158804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(p2p->ssid, force_ssid, force_ssid_len);
158904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->ssid_len = force_ssid_len;
159004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->ssid_set = 1;
159104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
159204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_NOT_YET_READY;
15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_USER_REJECTED;
15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE;
15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM;
159704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (pd_before_go_neg)
159804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->flags |= P2P_DEV_PD_BEFORE_GO_NEG;
1599a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	else {
160004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->flags &= ~P2P_DEV_PD_BEFORE_GO_NEG;
1601a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		/*
16029cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt		 * Assign dialog token and tie breaker here to use the same
16039cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt		 * values in each retry within the same GO Negotiation exchange.
1604a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		 */
1605a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		dev->dialog_token++;
1606a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		if (dev->dialog_token == 0)
1607a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			dev->dialog_token = 1;
16089cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt		dev->tie_breaker = p2p->next_tie_breaker;
16099cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt		p2p->next_tie_breaker = !p2p->next_tie_breaker;
1610a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->connect_reqs = 0;
16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_neg_req_sent = 0;
16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_state = UNKNOWN_GO;
16141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_set_dev_persistent(dev, persistent_group);
16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_intent = go_intent;
16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state != P2P_IDLE)
16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_stop_find(p2p);
16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->after_scan_tx) {
16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * We need to drop the pending frame to avoid issues with the
16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * new GO Negotiation, e.g., when the pending frame was from a
16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * previous attempt at starting a GO Negotiation.
16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
1627b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Dropped previous pending Action frame TX that was waiting for p2p_scan completion");
16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p2p->after_scan_tx);
16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = NULL;
16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wps_method = wps_method;
1633cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	dev->oob_pw_id = oob_pw_id;
16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->status = P2P_SC_SUCCESS;
16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
1637b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "p2p_scan running - delay connect send");
16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->start_after_scan = P2P_AFTER_SCAN_CONNECT;
16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_peer, peer_addr, ETH_ALEN);
16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_connect_send(p2p, dev);
16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  enum p2p_wps_method wps_method,
16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  int go_intent, const u8 *own_interface_addr,
165104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		  unsigned int force_freq, int persistent_group,
1652d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		  const u8 *force_ssid, size_t force_ssid_len,
1653cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		  unsigned int pref_freq, u16 oob_pw_id)
16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1657b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Request to authorize group negotiation - peer=" MACSTR
16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  GO Intent=%d  Intended Interface Address=" MACSTR
1659cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		" wps_method=%d  persistent_group=%d oob_pw_id=%u",
16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
1661cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		wps_method, persistent_group, oob_pw_id);
16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
1665b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Cannot authorize unknown P2P Device " MACSTR,
16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(peer_addr));
16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
167068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	if (p2p_prepare_channel(p2p, dev, force_freq, pref_freq, go_intent ==
167168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt				15) < 0)
1672a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
1673a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
167404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p->ssid_set = 0;
167504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (force_ssid) {
167604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "P2P: Forced SSID",
167704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  force_ssid, force_ssid_len);
167804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(p2p->ssid, force_ssid, force_ssid_len);
167904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->ssid_len = force_ssid_len;
168004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->ssid_set = 1;
168104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
168204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_NOT_YET_READY;
16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_USER_REJECTED;
16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_neg_req_sent = 0;
16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_state = UNKNOWN_GO;
16871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_set_dev_persistent(dev, persistent_group);
16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_intent = go_intent;
16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wps_method = wps_method;
1692cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	dev->oob_pw_id = oob_pw_id;
16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->status = P2P_SC_SUCCESS;
16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_add_dev_info(struct p2p_data *p2p, const u8 *addr,
17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      struct p2p_device *dev, struct p2p_message *msg)
17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1702fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	os_get_reltime(&dev->last_seen);
17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1704b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_copy_wps_info(p2p, dev, 0, msg);
17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->listen_channel) {
17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int freq;
17084b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		freq = p2p_channel_to_freq(msg->listen_channel[3],
17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   msg->listen_channel[4]);
17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freq < 0) {
1711b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Unknown peer Listen channel: "
17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"country=%c%c(0x%02x) reg_class=%u channel=%u",
17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[0],
17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[1],
17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[2],
17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[3],
17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[4]);
17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
1719b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Update peer " MACSTR
1720b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				" Listen channel: %u -> %u MHz",
17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(dev->info.p2p_device_addr),
17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev->listen_freq, freq);
17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->listen_freq = freq;
17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
172761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (msg->wfd_subelems) {
172861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_free(dev->info.wfd_subelems);
172961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		dev->info.wfd_subelems = wpabuf_dup(msg->wfd_subelems);
173061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
173161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_PROBE_REQ_ONLY) {
17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~P2P_DEV_PROBE_REQ_ONLY;
1734b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Completed device entry based on data from GO Negotiation Request");
17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
1736b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Created device entry based on GO Neg Req: "
17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MACSTR " dev_capab=0x%x group_capab=0x%x name='%s' "
17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"listen_freq=%d",
17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr),
17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->info.dev_capab, dev->info.group_capab,
17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->info.device_name, dev->listen_freq);
17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_GROUP_CLIENT_ONLY;
17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_USER_REJECTED) {
1747b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Do not report rejected device");
17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->dev_found(p2p->cfg->cb_ctx, addr, &dev->info,
17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    !(dev->flags & P2P_DEV_REPORTED_ONCE));
17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_build_ssid(struct p2p_data *p2p, u8 *ssid, size_t *ssid_len)
17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_random((char *) &ssid[P2P_WILDCARD_SSID_LEN], 2);
17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&ssid[P2P_WILDCARD_SSID_LEN + 2],
17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  p2p->cfg->ssid_postfix, p2p->cfg->ssid_postfix_len);
17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*ssid_len = P2P_WILDCARD_SSID_LEN + 2 + p2p->cfg->ssid_postfix_len;
17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_go_params(struct p2p_data *p2p, struct p2p_go_neg_results *params)
17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1769216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (p2p->ssid_set) {
1770216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		os_memcpy(params->ssid, p2p->ssid, p2p->ssid_len);
1771216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		params->ssid_len = p2p->ssid_len;
1772216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	} else {
1773216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p_build_ssid(p2p, params->ssid, &params->ssid_len);
1774216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
1775216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	p2p->ssid_set = 0;
1776216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
17772271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	p2p_random(params->passphrase, p2p->cfg->passphrase_len);
17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_go_complete(struct p2p_data *p2p, struct p2p_device *peer)
17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_go_neg_results res;
17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int go = peer->go_state == LOCAL_GO;
17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_channels intersection;
17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1788b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "GO Negotiation with " MACSTR " completed (%s will be GO)",
1789b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		MAC2STR(peer->info.p2p_device_addr), go ? "local end" : "peer");
17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&res, 0, sizeof(res));
17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.role_go = go;
17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(res.peer_device_addr, peer->info.p2p_device_addr, ETH_ALEN);
17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(res.peer_interface_addr, peer->intended_addr, ETH_ALEN);
17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.wps_method = peer->wps_method;
17961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) {
17971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN)
17981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			res.persistent_group = 2;
17991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		else
18001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			res.persistent_group = 1;
18011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (go) {
18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Setup AP mode for WPS provisioning */
18054b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		res.freq = p2p_channel_to_freq(p2p->op_reg_class,
18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       p2p->op_channel);
18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(res.ssid, p2p->ssid, p2p->ssid_len);
18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res.ssid_len = p2p->ssid_len;
18092271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		p2p_random(res.passphrase, p2p->cfg->passphrase_len);
18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res.freq = peer->oper_freq;
18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->ssid_len) {
18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(res.ssid, p2p->ssid, p2p->ssid_len);
18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res.ssid_len = p2p->ssid_len;
18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
181868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p_channels_dump(p2p, "own channels", &p2p->channels);
181968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p_channels_dump(p2p, "peer channels", &peer->channels);
18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_channels_intersect(&p2p->channels, &peer->channels,
18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       &intersection);
182268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	if (go) {
182368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		p2p_channels_remove_freqs(&intersection, &p2p->no_go_freq);
182468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		p2p_channels_dump(p2p, "intersection after no-GO removal",
182568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt				  &intersection);
182668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	}
18276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
18286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	p2p_channels_to_freqs(&intersection, res.freq_list,
18296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			      P2P_MAX_CHANNELS);
18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.peer_config_timeout = go ? peer->client_timeout : peer->go_timeout;
18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
18341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p->ssid_set = 0;
18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer->go_neg_req_sent = 0;
18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer->wps_method = WPS_NOT_READY;
1837cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	peer->oob_pw_id = 0;
1838413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt	wpabuf_free(peer->go_neg_conf);
1839413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt	peer->go_neg_conf = NULL;
18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_PROVISIONING);
18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->go_neg_completed(p2p->cfg->cb_ctx, &res);
18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_rx_p2p_action(struct p2p_data *p2p, const u8 *sa,
18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      const u8 *data, size_t len, int rx_freq)
18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1849b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "RX P2P Public Action from " MACSTR, MAC2STR(sa));
18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "P2P: P2P Public Action contents", data, len);
18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1)
18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data[0]) {
18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG_REQ:
18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_neg_req(p2p, sa, data + 1, len - 1, rx_freq);
18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG_RESP:
18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_neg_resp(p2p, sa, data + 1, len - 1, rx_freq);
18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG_CONF:
18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_neg_conf(p2p, sa, data + 1, len - 1);
18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITATION_REQ:
18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_invitation_req(p2p, sa, data + 1, len - 1,
18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   rx_freq);
18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITATION_RESP:
18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_invitation_resp(p2p, sa, data + 1, len - 1);
18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROV_DISC_REQ:
18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_prov_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROV_DISC_RESP:
18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_prov_disc_resp(p2p, sa, data + 1, len - 1);
18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_DEV_DISC_REQ:
18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_dev_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_DEV_DISC_RESP:
18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_dev_disc_resp(p2p, sa, data + 1, len - 1);
18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
1885b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Unsupported P2P Public Action frame type %d",
18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data[0]);
18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void p2p_rx_action_public(struct p2p_data *p2p, const u8 *da,
18931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				 const u8 *sa, const u8 *bssid, const u8 *data,
18941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				 size_t len, int freq)
18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1)
18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data[0]) {
19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_VENDOR_SPECIFIC:
19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data++;
19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len--;
1903a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt		if (len < 4)
19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
1905a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt		if (WPA_GET_BE32(data) != P2P_IE_VENDOR_TYPE)
19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1908a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt		data += 4;
1909a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt		len -= 4;
19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1911a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt		p2p_rx_p2p_action(p2p, sa, data, len, freq);
19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_INITIAL_REQ:
19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_initial_req(p2p, sa, data + 1, len - 1, freq);
19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_INITIAL_RESP:
19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_initial_resp(p2p, sa, data + 1, len - 1, freq);
19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_COMEBACK_REQ:
19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_comeback_req(p2p, sa, data + 1, len - 1, freq);
19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_COMEBACK_RESP:
19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_comeback_resp(p2p, sa, data + 1, len - 1, freq);
19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_rx_action(struct p2p_data *p2p, const u8 *da, const u8 *sa,
19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *bssid, u8 category,
19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *data, size_t len, int freq)
19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (category == WLAN_ACTION_PUBLIC) {
19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_action_public(p2p, da, sa, bssid, data, len, freq);
19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (category != WLAN_ACTION_VENDOR_SPECIFIC)
19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 4)
19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1944a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt	if (WPA_GET_BE32(data) != P2P_IE_VENDOR_TYPE)
19458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1946a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt	data += 4;
1947a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt	len -= 4;
19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P action frame */
1950b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "RX P2P Action from " MACSTR, MAC2STR(sa));
19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "P2P: P2P Action contents", data, len);
19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1)
19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data[0]) {
19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_NOA:
1957b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Received P2P Action - Notice of Absence");
19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO */
19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PRESENCE_REQ:
19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_presence_req(p2p, da, sa, data + 1, len - 1, freq);
19628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PRESENCE_RESP:
19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_presence_resp(p2p, da, sa, data + 1, len - 1);
19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_DISC_REQ:
19678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_disc_req(p2p, da, sa, data + 1, len - 1, freq);
19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
1970b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Received P2P Action - unknown type %u", data[0]);
19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_start(void *eloop_ctx, void *timeout_ctx)
19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == NULL)
19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1981661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	if (p2p->pending_listen_freq) {
1982661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		p2p_dbg(p2p, "Clear pending_listen_freq for p2p_go_neg_start");
1983661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		p2p->pending_listen_freq = 0;
1984661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	}
19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer->status = P2P_SC_SUCCESS;
1987661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	/*
1988661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	 * Set new timeout to make sure a previously set one does not expire
1989661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	 * too quickly while waiting for the GO Negotiation to complete.
1990661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	 */
1991661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	p2p_set_timeout(p2p, 0, 500000);
19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_connect_send(p2p, p2p->go_neg_peer);
19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_invite_start(void *eloop_ctx, void *timeout_ctx)
19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->invite_peer == NULL)
20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2001661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	if (p2p->pending_listen_freq) {
2002661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		p2p_dbg(p2p, "Clear pending_listen_freq for p2p_invite_start");
2003661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		p2p->pending_listen_freq = 0;
2004661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	}
20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
2006cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	p2p_invite_send(p2p, p2p->invite_peer, p2p->invite_go_dev_addr,
2007cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			p2p->invite_dev_pw_id);
20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_add_dev_from_probe_req(struct p2p_data *p2p, const u8 *addr,
20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const u8 *ie, size_t ie_len)
20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg) < 0 || msg.p2p_attributes == NULL)
20198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* not a P2P probe */
20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.ssid == NULL || msg.ssid[1] != P2P_WILDCARD_SSID_LEN ||
20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(msg.ssid + 2, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN)
20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    != 0) {
20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* The Probe Request is not part of P2P Device Discovery. It is
20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * not known whether the source address of the frame is the P2P
20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Device Address or P2P Interface Address. Do not add a new
20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * peer entry based on this frames.
20318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev) {
20389c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt		if (msg.listen_channel) {
20399c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt			int freq;
20409c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt
20419c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt			if (dev->country[0] == 0)
20429c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt				os_memcpy(dev->country, msg.listen_channel, 3);
20439c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt
20449c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt			freq = p2p_channel_to_freq(msg.listen_channel[3],
20459c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt						   msg.listen_channel[4]);
20469c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt
20479c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt			if (freq > 0 && dev->listen_freq != freq) {
20489c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt				p2p_dbg(p2p,
20499c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt					"Updated peer " MACSTR " Listen channel (Probe Request): %d -> %d MHz",
20509c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt					MAC2STR(addr), dev->listen_freq, freq);
20519c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt				dev->listen_freq = freq;
20529c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt			}
20539c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt		}
20549c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt
2055fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		os_get_reltime(&dev->last_seen);
20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* already known */
20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_create_device(p2p, addr);
20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
20638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2066fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	os_get_reltime(&dev->last_seen);
20678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_PROBE_REQ_ONLY;
20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.listen_channel) {
20708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->country, msg.listen_channel, 3);
20714b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		dev->listen_freq = p2p_channel_to_freq(msg.listen_channel[3],
20728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       msg.listen_channel[4]);
20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2075b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_copy_wps_info(p2p, dev, 1, &msg);
20768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
207761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (msg.wfd_subelems) {
207861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_free(dev->info.wfd_subelems);
207961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
208061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
208161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
20828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
20838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2084b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Created device entry based on Probe Req: " MACSTR
20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" dev_capab=0x%x group_capab=0x%x name='%s' listen_freq=%d",
20868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(dev->info.p2p_device_addr), dev->info.dev_capab,
20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.group_capab, dev->info.device_name,
20888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->listen_freq);
20898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_device * p2p_add_dev_from_go_neg_req(struct p2p_data *p2p,
20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						const u8 *addr,
20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						struct p2p_message *msg)
20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev) {
2100fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		os_get_reltime(&dev->last_seen);
21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return dev; /* already known */
21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_create_device(p2p, addr);
21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_add_dev_info(p2p, addr, dev, msg);
21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return dev;
21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int dev_type_match(const u8 *dev_type, const u8 *req_dev_type)
21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(dev_type, req_dev_type, WPS_DEV_TYPE_LEN) == 0)
21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(dev_type, req_dev_type, 2) == 0 &&
21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    WPA_GET_BE32(&req_dev_type[2]) == 0 &&
21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    WPA_GET_BE16(&req_dev_type[6]) == 0)
21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Category match with wildcard OUI/sub-category */
21228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint dev_type_list_match(const u8 *dev_type, const u8 *req_dev_type[],
21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			size_t num_req_dev_type)
21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
21308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_req_dev_type; i++) {
21318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev_type_match(dev_type, req_dev_type[i]))
21328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 1;
21338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
21358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_match_dev_type - Match local device type with requested type
21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wps: WPS TLVs from Probe Request frame (concatenated WPS IEs)
21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 on match, 0 on mismatch
21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
21448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function can be used to match the Requested Device Type attribute in
21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPS IE with the local device types for deciding whether to reply to a Probe
21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Request frame.
21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_match_dev_type(struct p2p_data *p2p, struct wpabuf *wps)
21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wps_parse_attr attr;
21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wps_parse_msg(wps, &attr))
21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* assume no Requested Device Type attributes */
21558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (attr.num_req_dev_type == 0)
21578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* no Requested Device Type attributes -> match */
21588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev_type_list_match(p2p->cfg->pri_dev_type, attr.req_dev_type,
21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				attr.num_req_dev_type))
21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Own Primary Device Type matches */
21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	for (i = 0; i < p2p->cfg->num_sec_dev_types; i++) {
21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev_type_list_match(p2p->cfg->sec_dev_type[i],
21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					attr.req_dev_type,
21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					attr.num_req_dev_type))
21676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return 1; /* Own Secondary Device Type matches */
21686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
21698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* No matching device type found */
21718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
21728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2175a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidtstruct wpabuf * p2p_build_probe_resp_ies(struct p2p_data *p2p,
2176a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt					 const u8 *query_hash,
2177a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt					 u8 query_count)
21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
21808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
218104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	int pw_id = -1;
218261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t extra = 0;
218361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
218461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
218561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_probe_resp)
218661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		extra = wpabuf_len(p2p->wfd_ie_probe_resp);
218761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21892e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_PROBE_RESP_P2P])
21902e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_PROBE_RESP_P2P]);
21912e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
2192a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	if (query_count)
2193216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		extra += MAX_SVC_ADV_IE_LEN;
2194216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
219561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	buf = wpabuf_alloc(1000 + extra);
21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
219904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p->go_neg_peer) {
220004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/* Advertise immediate availability of WPS credential */
220104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		pw_id = p2p_wps_method_pw_id(p2p->go_neg_peer->wps_method);
220204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
220304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
220468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	if (p2p_build_wps_ie(p2p, buf, pw_id, 1) < 0) {
220568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		p2p_dbg(p2p, "Failed to build WPS IE for Probe Response");
220668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		wpabuf_free(buf);
220768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		return NULL;
220868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	}
22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
221061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
221161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_probe_resp)
221261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(buf, p2p->wfd_ie_probe_resp);
221361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
221461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
22152e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_PROBE_RESP_P2P])
22162e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		wpabuf_put_buf(buf,
22172e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			       p2p->vendor_elem[VENDOR_ELEM_PROBE_RESP_P2P]);
22182e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
22198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P IE */
22208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(buf);
222104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_buf_add_capability(buf, p2p->dev_capab &
222204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			       ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 0);
22238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval)
22248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_ext_listen_timing(buf, p2p->ext_listen_period,
22258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      p2p->ext_listen_interval);
22268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_device_info(buf, p2p, NULL);
22278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(buf, len);
22288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2229a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	if (query_count) {
2230a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		p2p_buf_add_service_instance(buf, p2p, query_count, query_hash,
2231216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt					     p2p->p2ps_adv_list);
2232216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
2233216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
22348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
22358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2238216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtstatic int p2p_service_find_asp(struct p2p_data *p2p, const u8 *hash)
2239216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt{
2240216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	struct p2ps_advertisement *adv_data;
2241a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	int any_wfa;
2242216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2243216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	p2p_dbg(p2p, "ASP find - ASP list: %p", p2p->p2ps_adv_list);
2244216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2245a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	/* Wildcard org.wi-fi.wfds matches any WFA spec defined service */
2246a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	any_wfa = os_memcmp(hash, p2p->wild_card_hash, P2PS_HASH_LEN) == 0;
2247216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2248216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_data = p2p->p2ps_adv_list;
2249216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	while (adv_data) {
2250216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (os_memcmp(hash, adv_data->hash, P2PS_HASH_LEN) == 0)
2251a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			return 1; /* exact hash match */
2252a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		if (any_wfa &&
2253a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		    os_strncmp(adv_data->svc_name, P2PS_WILD_HASH_STR,
2254a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			       os_strlen(P2PS_WILD_HASH_STR)) == 0)
2255a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			return 1; /* WFA service match */
2256216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		adv_data = adv_data->next;
2257216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
2258216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2259216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	return 0;
2260216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt}
2261216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2262216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
226304949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic enum p2p_probe_req_status
226404949598a23f501be6eec21697465fd46a28840aDmitry Shmidtp2p_reply_probe(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
2265a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		const u8 *bssid, const u8 *ie, size_t ie_len,
2266a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		unsigned int rx_freq)
22678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ieee802_11_elems elems;
22698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
22708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ieee80211_mgmt *resp;
22711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_message msg;
22728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *ies;
2273a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	u8 channel, op_class;
22748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ieee802_11_parse_elems((u8 *) ie, ie_len, &elems, 0) ==
22768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ParseFailed) {
22778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Ignore invalid Probe Request frames */
2278ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt		p2p_dbg(p2p, "Could not parse Probe Request frame - ignore it");
227904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_MALFORMED;
22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (elems.p2p == NULL) {
22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* not a P2P probe - ignore it */
2284ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt		p2p_dbg(p2p, "Not a P2P probe - ignore it");
228504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_P2P;
22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (dst && !is_broadcast_ether_addr(dst) &&
22891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    os_memcmp(dst, p2p->cfg->dev_addr, ETH_ALEN) != 0) {
22901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Not sent to the broadcast address or our P2P Device Address
22911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
2292ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt		p2p_dbg(p2p, "Probe Req DA " MACSTR " not ours - ignore it",
2293ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt			MAC2STR(dst));
229404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
22951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
22961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
22971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (bssid && !is_broadcast_ether_addr(bssid)) {
22981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Not sent to the Wildcard BSSID */
2299ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt		p2p_dbg(p2p, "Probe Req BSSID " MACSTR " not wildcard - ignore it",
2300ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt			MAC2STR(bssid));
230104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
23021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
23031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
23048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (elems.ssid == NULL || elems.ssid_len != P2P_WILDCARD_SSID_LEN ||
23058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(elems.ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) !=
23068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0) {
23078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* not using P2P Wildcard SSID - ignore */
2308ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt		p2p_dbg(p2p, "Probe Req not using P2P Wildcard SSID - ignore it");
230904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (supp_rates_11b_only(&elems)) {
23131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Indicates support for 11b rates only */
2314ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt		p2p_dbg(p2p, "Probe Req with 11b rates only supported - ignore it");
231504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_P2P;
23161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
23171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
23181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
23191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg) < 0) {
23201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Could not parse P2P attributes */
2321ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt		p2p_dbg(p2p, "Could not parse P2P attributes in Probe Req - ignore it");
232204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_P2P;
23231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
23241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2325216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (msg.service_hash && msg.service_hash_count) {
2326216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		const u8 *hash = msg.service_hash;
2327216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		u8 i;
2328a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		int p2ps_svc_found = 0;
2329216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
23304171258d30a612645aa061cede62233b5c58ca2aDmitry 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",
23314171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt			p2p->in_listen, p2p->drv_in_listen, rx_freq,
23324171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt			p2p->cfg->channel, p2p->pending_listen_freq);
23334171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt
23344171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt		if (!p2p->in_listen && !p2p->drv_in_listen &&
23354171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt		    p2p->pending_listen_freq && rx_freq &&
23364171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt		    rx_freq != p2p->pending_listen_freq) {
23374171258d30a612645aa061cede62233b5c58ca2aDmitry 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",
23384171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt				rx_freq, p2p->pending_listen_freq);
23394171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt			p2p_parse_free(&msg);
23404171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt			return P2P_PREQ_NOT_LISTEN;
23414171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt		}
23424171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt
2343216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		for (i = 0; i < msg.service_hash_count; i++) {
2344216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			if (p2p_service_find_asp(p2p, hash)) {
2345a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt				p2p_dbg(p2p, "Service Hash match found: "
2346a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt					MACSTR, MAC2STR(hash));
2347a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt				p2ps_svc_found = 1;
2348a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt				break;
2349216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			}
2350216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			hash += P2PS_HASH_LEN;
2351216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		}
2352216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2353216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		/* Probed hash unknown */
2354a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		if (!p2ps_svc_found) {
2355a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			p2p_dbg(p2p, "No Service Hash match found");
2356216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			p2p_parse_free(&msg);
2357216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			return P2P_PREQ_NOT_PROCESSED;
2358216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		}
2359216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	} else {
2360216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		/* This is not a P2PS Probe Request */
2361216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p_dbg(p2p, "No P2PS Hash in Probe Request");
2362216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2363216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (!p2p->in_listen || !p2p->drv_in_listen) {
2364216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			/* not in Listen state - ignore Probe Request */
2365216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			p2p_dbg(p2p, "Not in Listen state (in_listen=%d drv_in_listen=%d) - ignore Probe Request",
2366216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				p2p->in_listen, p2p->drv_in_listen);
2367216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			p2p_parse_free(&msg);
2368216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			return P2P_PREQ_NOT_LISTEN;
2369216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		}
2370216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
2371216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
23721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (msg.device_id &&
237304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    os_memcmp(msg.device_id, p2p->cfg->dev_addr, ETH_ALEN) != 0) {
23741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Device ID did not match */
2375ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt		p2p_dbg(p2p, "Probe Req requested Device ID " MACSTR " did not match - ignore it",
2376ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt			MAC2STR(msg.device_id));
23771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_parse_free(&msg);
237804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
23791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
23801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Check Requested Device Type match */
23821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (msg.wps_attributes &&
23831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    !p2p_match_dev_type(p2p, msg.wps_attributes)) {
23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* No match with Requested Device Type */
2385ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt		p2p_dbg(p2p, "Probe Req requestred Device Type did not match - ignore it");
23861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_parse_free(&msg);
238704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
23888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
239004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (!p2p->cfg->send_probe_resp) {
239104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/* Response generated elsewhere */
2392ec58b164a608cbc1d99e71bb3d86ef4b263377dcDmitry Shmidt		p2p_dbg(p2p, "Probe Resp generated elsewhere - do not generate additional response");
2393a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		p2p_parse_free(&msg);
239404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
239504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
23968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2397b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Reply to P2P Probe Request in Listen state");
23988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
24008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * We do not really have a specific BSS that this frame is advertising,
24018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * so build a frame that has some information in valid format. This is
24028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * really only used for discovery purposes, not to learn exact BSS
24038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * parameters.
24048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
2405a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	ies = p2p_build_probe_resp_ies(p2p, msg.service_hash,
2406a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt				       msg.service_hash_count);
2407a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	p2p_parse_free(&msg);
24088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ies == NULL)
240904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
24108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = wpabuf_alloc(200 + wpabuf_len(ies));
24128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL) {
24138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(ies);
241404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
24158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24174171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt	resp = wpabuf_put(buf, offsetof(struct ieee80211_mgmt,
24184171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt					u.probe_resp.variable));
24198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
24218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   (WLAN_FC_STYPE_PROBE_RESP << 4));
24228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(resp->da, addr, ETH_ALEN);
24238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(resp->sa, p2p->cfg->dev_addr, ETH_ALEN);
24248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(resp->bssid, p2p->cfg->dev_addr, ETH_ALEN);
24258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->u.probe_resp.beacon_int = host_to_le16(100);
24268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* hardware or low-level driver will setup seq_ctrl and timestamp */
24278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->u.probe_resp.capab_info =
24288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		host_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE |
24298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     WLAN_CAPABILITY_PRIVACY |
24308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     WLAN_CAPABILITY_SHORT_SLOT_TIME);
24318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_SSID);
24338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, P2P_WILDCARD_SSID_LEN);
24348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(buf, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
24358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_SUPP_RATES);
24378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 8);
24388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, (60 / 5) | 0x80);
24398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 90 / 5);
24408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, (120 / 5) | 0x80);
24418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 180 / 5);
24428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, (240 / 5) | 0x80);
24438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 360 / 5);
24448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 480 / 5);
24458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 540 / 5);
24468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2447a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	if (!rx_freq) {
2448a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		channel = p2p->cfg->channel;
2449a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	} else if (p2p_freq_to_channel(rx_freq, &op_class, &channel)) {
2450a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		wpabuf_free(ies);
2451a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		wpabuf_free(buf);
2452a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		return P2P_PREQ_NOT_PROCESSED;
2453a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	}
2454a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt
24558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_DS_PARAMS);
24568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 1);
2457a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	wpabuf_put_u8(buf, channel);
24588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_buf(buf, ies);
24608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(ies);
24618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2462a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	p2p->cfg->send_probe_resp(p2p->cfg->cb_ctx, buf, rx_freq);
24638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(buf);
246504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
2466a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	return P2P_PREQ_PROCESSED;
24678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
247004949598a23f501be6eec21697465fd46a28840aDmitry Shmidtenum p2p_probe_req_status
247104949598a23f501be6eec21697465fd46a28840aDmitry Shmidtp2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
2472a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		 const u8 *bssid, const u8 *ie, size_t ie_len,
2473a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		 unsigned int rx_freq)
24748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
247504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	enum p2p_probe_req_status res;
247604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
24778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_add_dev_from_probe_req(p2p, addr, ie, ie_len);
24788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2479a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	res = p2p_reply_probe(p2p, addr, dst, bssid, ie, ie_len, rx_freq);
2480a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	if (res != P2P_PREQ_PROCESSED && res != P2P_PREQ_NOT_PROCESSED)
2481a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		return res;
24828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2483a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	/*
2484a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	 * Activate a pending GO Negotiation/Invite flow if a received Probe
2485a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	 * Request frame is from an expected peer. Some devices may share the
2486a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	 * same address for P2P and non-P2P STA running simultaneously. The
2487a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	 * P2P_PREQ_PROCESSED and P2P_PREQ_NOT_PROCESSED p2p_reply_probe()
2488a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	 * return values verified above ensure we are handling a Probe Request
2489a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	 * frame from a P2P peer.
2490a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	 */
24918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((p2p->state == P2P_CONNECT || p2p->state == P2P_CONNECT_LISTEN) &&
24928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    p2p->go_neg_peer &&
24938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(addr, p2p->go_neg_peer->info.p2p_device_addr, ETH_ALEN)
24949cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt	    == 0 &&
24959cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt	    !(p2p->go_neg_peer->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM)) {
24968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Received a Probe Request from GO Negotiation peer */
2497b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Found GO Negotiation peer - try to start GO negotiation from timeout");
24989cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt		eloop_cancel_timeout(p2p_go_neg_start, p2p, NULL);
24998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(0, 0, p2p_go_neg_start, p2p, NULL);
2500a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		return res;
25018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((p2p->state == P2P_INVITE || p2p->state == P2P_INVITE_LISTEN) &&
25048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    p2p->invite_peer &&
25053c4793790bf06f1fe08a2ddf604c9caa855151f1Dmitry Shmidt	    (p2p->invite_peer->flags & P2P_DEV_WAIT_INV_REQ_ACK) &&
25068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(addr, p2p->invite_peer->info.p2p_device_addr, ETH_ALEN)
25078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    == 0) {
25088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Received a Probe Request from Invite peer */
2509b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Found Invite peer - try to start Invite from timeout");
25107f93d6fa14a343127754c33a03cf2f641b6ff6e4Dmitry Shmidt		eloop_cancel_timeout(p2p_invite_start, p2p, NULL);
25118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(0, 0, p2p_invite_start, p2p, NULL);
2512a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		return res;
25138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
251504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return res;
25168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_assoc_req_ie_wlan_ap(struct p2p_data *p2p, const u8 *bssid,
25208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    u8 *buf, size_t len, struct wpabuf *p2p_ie)
25218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *tmp;
25238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *lpos;
25248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t tmplen;
25258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
25268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 group_capab;
252705df46a3aef489a33f92efb91b091c1aa6d16f95Dmitry Shmidt	struct p2p_message msg;
25288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_ie == NULL)
25308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* WLAN AP is not a P2P manager */
25318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
253205df46a3aef489a33f92efb91b091c1aa6d16f95Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
253305df46a3aef489a33f92efb91b091c1aa6d16f95Dmitry Shmidt	if (p2p_parse_p2p_ie(p2p_ie, &msg) < 0)
253405df46a3aef489a33f92efb91b091c1aa6d16f95Dmitry Shmidt		return 0;
253505df46a3aef489a33f92efb91b091c1aa6d16f95Dmitry Shmidt
253605df46a3aef489a33f92efb91b091c1aa6d16f95Dmitry Shmidt	p2p_dbg(p2p, "BSS P2P manageability %s",
253705df46a3aef489a33f92efb91b091c1aa6d16f95Dmitry Shmidt		msg.manageability ? "enabled" : "disabled");
253805df46a3aef489a33f92efb91b091c1aa6d16f95Dmitry Shmidt
253905df46a3aef489a33f92efb91b091c1aa6d16f95Dmitry Shmidt	if (!msg.manageability)
254005df46a3aef489a33f92efb91b091c1aa6d16f95Dmitry Shmidt		return 0;
254105df46a3aef489a33f92efb91b091c1aa6d16f95Dmitry Shmidt
25428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
25438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (Re)Association Request - P2P IE
25448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Capability attribute (shall be present)
25458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Interface attribute (present if concurrent device and
25468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *	P2P Management is enabled)
25478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
25488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp = wpabuf_alloc(200);
25498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp == NULL)
25508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
25518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	lpos = p2p_buf_add_ie_hdr(tmp);
25538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group_capab = 0;
25548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->num_groups > 0) {
25558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group_capab |= P2P_GROUP_CAPAB_GROUP_OWNER;
25568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) &&
25578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED) &&
25588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    p2p->cross_connect)
25598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
25608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_capability(tmp, p2p->dev_capab, group_capab);
25628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) &&
25638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED))
25648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_p2p_interface(tmp, p2p);
25658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(tmp, lpos);
25668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmplen = wpabuf_len(tmp);
25688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmplen > len)
25698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = -1;
25708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
25718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(buf, wpabuf_head(tmp), tmplen);
25728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = tmplen;
25738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(tmp);
25758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
25778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_assoc_req_ie(struct p2p_data *p2p, const u8 *bssid, u8 *buf,
25818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     size_t len, int p2p_group, struct wpabuf *p2p_ie)
25828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *tmp;
25848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *lpos;
25858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *peer;
25868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t tmplen;
25878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
258861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t extra = 0;
25898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p_group)
25918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return p2p_assoc_req_ie_wlan_ap(p2p, bssid, buf, len, p2p_ie);
25928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
259361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
259461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_assoc_req)
259561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		extra = wpabuf_len(p2p->wfd_ie_assoc_req);
259661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
259761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
25982e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_REQ])
25992e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_REQ]);
26002e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
26018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
26028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (Re)Association Request - P2P IE
26038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Capability attribute (shall be present)
26048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Extended Listen Timing (may be present)
26058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Device Info attribute (shall be present)
26068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
260761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	tmp = wpabuf_alloc(200 + extra);
26088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp == NULL)
26098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
26108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
261161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
261261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_assoc_req)
261361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(tmp, p2p->wfd_ie_assoc_req);
261461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
261561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
26162e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_REQ])
26172e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		wpabuf_put_buf(tmp,
26182e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			       p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_REQ]);
26192e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
26208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer = bssid ? p2p_get_device(p2p, bssid) : NULL;
26218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	lpos = p2p_buf_add_ie_hdr(tmp);
26238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_capability(tmp, p2p->dev_capab, 0);
26248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval)
26258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_ext_listen_timing(tmp, p2p->ext_listen_period,
26268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      p2p->ext_listen_interval);
26278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_device_info(tmp, p2p, peer);
26288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(tmp, lpos);
26298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmplen = wpabuf_len(tmp);
26318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmplen > len)
26328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = -1;
26338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
26348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(buf, wpabuf_head(tmp), tmplen);
26358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = tmplen;
26368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(tmp);
26388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
26408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_scan_result_text(const u8 *ies, size_t ies_len, char *buf, char *end)
26448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *p2p_ie;
26468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
26478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len, P2P_IE_VENDOR_TYPE);
26498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_ie == NULL)
26508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
26518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = p2p_attr_text(p2p_ie, buf, end);
26538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(p2p_ie);
26548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
26558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2658216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtstruct p2ps_advertisement *
2659216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtp2p_service_p2ps_id(struct p2p_data *p2p, u32 adv_id)
2660216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt{
2661216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	struct p2ps_advertisement *adv_data;
2662216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2663216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (!p2p)
2664216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		return NULL;
2665216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2666216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_data = p2p->p2ps_adv_list;
2667216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	while (adv_data) {
2668216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (adv_data->id == adv_id)
2669216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			return adv_data;
2670216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		adv_data = adv_data->next;
2671216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
2672216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2673216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	return NULL;
2674216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt}
2675216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2676216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2677216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtint p2p_service_del_asp(struct p2p_data *p2p, u32 adv_id)
2678216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt{
2679216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	struct p2ps_advertisement *adv_data;
2680216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	struct p2ps_advertisement **prior;
2681216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2682216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (!p2p)
2683216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		return -1;
2684216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2685216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_data = p2p->p2ps_adv_list;
2686216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	prior = &p2p->p2ps_adv_list;
2687216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	while (adv_data) {
2688216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (adv_data->id == adv_id) {
2689216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			p2p_dbg(p2p, "Delete ASP adv_id=0x%x", adv_id);
2690216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			*prior = adv_data->next;
2691216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			os_free(adv_data);
2692216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			return 0;
2693216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		}
2694216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		prior = &adv_data->next;
2695216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		adv_data = adv_data->next;
2696216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
2697216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2698216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	return -1;
2699216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt}
2700216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2701216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2702216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtint p2p_service_add_asp(struct p2p_data *p2p, int auto_accept, u32 adv_id,
2703216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			const char *adv_str, u8 svc_state, u16 config_methods,
2704d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			const char *svc_info, const u8 *cpt_priority)
2705216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt{
2706216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	struct p2ps_advertisement *adv_data, *tmp, **prev;
2707216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	u8 buf[P2PS_HASH_LEN];
2708216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	size_t adv_data_len, adv_len, info_len = 0;
2709d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	int i;
2710216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2711d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!p2p || !adv_str || !adv_str[0] || !cpt_priority)
2712216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		return -1;
2713216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2714216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (!(config_methods & p2p->cfg->config_methods)) {
2715216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p_dbg(p2p, "Config methods not supported svc: 0x%x dev: 0x%x",
2716216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			config_methods, p2p->cfg->config_methods);
2717216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		return -1;
2718216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
2719216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2720216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (!p2ps_gen_hash(p2p, adv_str, buf))
2721216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		return -1;
2722216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2723216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (svc_info)
2724216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		info_len = os_strlen(svc_info);
2725216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_len = os_strlen(adv_str);
2726216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_data_len = sizeof(struct p2ps_advertisement) + adv_len + 1 +
2727216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		info_len + 1;
2728216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2729216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_data = os_zalloc(adv_data_len);
2730216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (!adv_data)
2731216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		return -1;
2732216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2733216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	os_memcpy(adv_data->hash, buf, P2PS_HASH_LEN);
2734216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_data->id = adv_id;
2735216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_data->state = svc_state;
2736216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_data->config_methods = config_methods & p2p->cfg->config_methods;
2737216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_data->auto_accept = (u8) auto_accept;
2738216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	os_memcpy(adv_data->svc_name, adv_str, adv_len);
2739216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2740d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	for (i = 0; cpt_priority[i] && i < P2PS_FEATURE_CAPAB_CPT_MAX; i++) {
2741d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		adv_data->cpt_priority[i] = cpt_priority[i];
2742d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		adv_data->cpt_mask |= cpt_priority[i];
2743d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
2744d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
2745216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (svc_info && info_len) {
2746216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		adv_data->svc_info = &adv_data->svc_name[adv_len + 1];
2747216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		os_memcpy(adv_data->svc_info, svc_info, info_len);
2748216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
2749216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2750216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	/*
2751216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	 * Group Advertisements by service string. They do not need to be
2752216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	 * sorted, but groups allow easier Probe Response instance grouping
2753216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	 */
2754216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	tmp = p2p->p2ps_adv_list;
2755216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	prev = &p2p->p2ps_adv_list;
2756216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	while (tmp) {
2757216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (tmp->id == adv_data->id) {
2758216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			if (os_strcmp(tmp->svc_name, adv_data->svc_name) != 0) {
2759216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				os_free(adv_data);
2760216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				return -1;
2761216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			}
2762216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			adv_data->next = tmp->next;
2763216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			*prev = adv_data;
2764216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			os_free(tmp);
2765216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			goto inserted;
2766216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		} else {
2767216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			if (os_strcmp(tmp->svc_name, adv_data->svc_name) == 0) {
2768216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				adv_data->next = tmp->next;
2769216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				tmp->next = adv_data;
2770216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				goto inserted;
2771216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			}
2772216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		}
2773216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		prev = &tmp->next;
2774216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		tmp = tmp->next;
2775216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
2776216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2777216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	/* No svc_name match found */
2778216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	adv_data->next = p2p->p2ps_adv_list;
2779216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	p2p->p2ps_adv_list = adv_data;
2780216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2781216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtinserted:
2782216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	p2p_dbg(p2p,
2783d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		"Added ASP advertisement adv_id=0x%x config_methods=0x%x svc_state=0x%x adv_str='%s' cpt_mask=0x%x",
2784d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		adv_id, adv_data->config_methods, svc_state, adv_str,
2785d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		adv_data->cpt_mask);
2786216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2787216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	return 0;
2788216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt}
2789216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2790216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
2791dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidtvoid p2p_service_flush_asp(struct p2p_data *p2p)
2792dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt{
2793dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt	struct p2ps_advertisement *adv, *prev;
2794dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt
2795dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt	if (!p2p)
2796dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt		return;
2797dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt
2798dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt	adv = p2p->p2ps_adv_list;
2799dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt	while (adv) {
2800dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt		prev = adv;
2801dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt		adv = adv->next;
2802dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt		os_free(prev);
2803dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt	}
2804dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt
2805dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt	p2p->p2ps_adv_list = NULL;
2806dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt	p2p_dbg(p2p, "All ASP advertisements flushed");
2807dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt}
2808dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt
2809dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt
281004949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint p2p_parse_dev_addr_in_p2p_ie(struct wpabuf *p2p_ie, u8 *dev_addr)
2811c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{
2812c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	struct p2p_message msg;
2813c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
2814c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
281504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p_parse_p2p_ie(p2p_ie, &msg))
2816c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return -1;
2817c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
281804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (msg.p2p_device_addr) {
281904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(dev_addr, msg.p2p_device_addr, ETH_ALEN);
282004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 0;
282104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	} else if (msg.device_id) {
282204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(dev_addr, msg.device_id, ETH_ALEN);
282304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 0;
2824c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
282504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return -1;
282604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
2827c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
282804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
282904949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint p2p_parse_dev_addr(const u8 *ies, size_t ies_len, u8 *dev_addr)
283004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
283104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct wpabuf *p2p_ie;
283204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	int ret;
283304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
283404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
283504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					     P2P_IE_VENDOR_TYPE);
283604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p_ie == NULL)
283704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return -1;
283804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	ret = p2p_parse_dev_addr_in_p2p_ie(p2p_ie, dev_addr);
2839c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	wpabuf_free(p2p_ie);
284004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return ret;
2841c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt}
2842c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
2843c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
28448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_clear_go_neg(struct p2p_data *p2p)
28458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer = NULL;
28478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
28488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_IDLE);
28498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_wps_success_cb(struct p2p_data *p2p, const u8 *mac_addr)
28538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == NULL) {
2855b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "No pending Group Formation - ignore WPS registration success notification");
28568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* No pending Group Formation */
28578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(mac_addr, p2p->go_neg_peer->intended_addr, ETH_ALEN) !=
28608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0) {
2861b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Ignore WPS registration success notification for "
2862b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			MACSTR " (GO Negotiation peer " MACSTR ")",
28638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(mac_addr),
28648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(p2p->go_neg_peer->intended_addr));
28658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* Ignore unexpected peer address */
28668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2868b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Group Formation completed successfully with " MACSTR,
28698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(mac_addr));
28708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_go_neg(p2p);
28728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_group_formation_failed(struct p2p_data *p2p)
28768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == NULL) {
2878b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "No pending Group Formation - ignore group formation failure notification");
28798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* No pending Group Formation */
28808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2882b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Group Formation failed with " MACSTR,
28838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(p2p->go_neg_peer->intended_addr));
28848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_go_neg(p2p);
28868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_data * p2p_init(const struct p2p_config *cfg)
28908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p;
28928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28932271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	if (cfg->max_peers < 1 ||
28942271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	    cfg->passphrase_len < 8 || cfg->passphrase_len > 63)
28958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
28968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p = os_zalloc(sizeof(*p2p) + sizeof(*cfg));
28988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p == NULL)
28998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
29008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg = (struct p2p_config *) (p2p + 1);
29018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg, cfg, sizeof(*cfg));
29028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->dev_name)
29038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->dev_name = os_strdup(cfg->dev_name);
29048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->manufacturer)
29058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->manufacturer = os_strdup(cfg->manufacturer);
29068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->model_name)
29078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_name = os_strdup(cfg->model_name);
29088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->model_number)
29098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_number = os_strdup(cfg->model_number);
29108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->serial_number)
29118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->serial_number = os_strdup(cfg->serial_number);
291204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (cfg->pref_chan) {
291304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p->cfg->pref_chan = os_malloc(cfg->num_pref_chan *
291404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt						sizeof(struct p2p_channel));
291504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (p2p->cfg->pref_chan) {
291604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			os_memcpy(p2p->cfg->pref_chan, cfg->pref_chan,
291704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  cfg->num_pref_chan *
291804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  sizeof(struct p2p_channel));
291904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		} else
292004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			p2p->cfg->num_pref_chan = 0;
292104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
292204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
2923216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	p2ps_gen_hash(p2p, P2PS_WILD_HASH_STR, p2p->wild_card_hash);
2924216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
29258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->min_disc_int = 1;
29268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->max_disc_int = 3;
2927d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p->max_disc_tu = -1;
29288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2929661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	if (os_get_random(&p2p->next_tie_breaker, 1) < 0)
2930661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		p2p->next_tie_breaker = 0;
29318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->next_tie_breaker &= 0x01;
29328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->sd_request)
29338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_SERVICE_DISCOVERY;
29348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->dev_capab |= P2P_DEV_CAPAB_INVITATION_PROCEDURE;
29358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->concurrent_operations)
29368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_CONCURRENT_OPER;
29378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->dev_capab |= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
29388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_init(&p2p->devices);
29408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
294161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->go_timeout = 100;
294261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->client_timeout = 20;
294313ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt	p2p->num_p2p_sd_queries = 0;
294461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
294568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p_dbg(p2p, "initialized");
294668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p_channels_dump(p2p, "channels", &p2p->cfg->channels);
294768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p_channels_dump(p2p, "cli_channels", &p2p->cfg->cli_channels);
294868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt
29498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p;
29508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_deinit(struct p2p_data *p2p)
29548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
295561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
295661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_beacon);
295761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_probe_req);
295861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_probe_resp);
295961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_assoc_req);
296061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_invitation);
296161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_prov_disc_req);
296261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_prov_disc_resp);
296361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_go_neg);
296461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_dev_info);
296561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_assoc_bssid);
296661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_coupled_sink_info);
296761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
296861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
29698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
29709cdf1b905fae57dea42506a1af67f6ece544b261Dmitry Shmidt	eloop_cancel_timeout(p2p_go_neg_start, p2p, NULL);
29716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	eloop_cancel_timeout(p2p_go_neg_wait_timeout, p2p, NULL);
29728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_flush(p2p);
29738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_req_dev_types(p2p);
29748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->dev_name);
29758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->manufacturer);
29768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_name);
29778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_number);
29788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->serial_number);
297904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	os_free(p2p->cfg->pref_chan);
29808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->groups);
2981a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	p2ps_prov_free(p2p);
29828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(p2p->sd_resp);
29838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->after_scan_tx);
29848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_remove_wps_vendor_extensions(p2p);
298568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	os_free(p2p->no_go_freq.range);
2986dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt	p2p_service_flush_asp(p2p);
2987216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
29888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p);
29898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_flush(struct p2p_data *p2p)
29938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev, *prev;
2995d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
2996d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	p2p_ext_listen(p2p, 0, 0);
299704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_stop_find(p2p);
29988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each_safe(dev, prev, &p2p->devices, struct p2p_device,
29998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      list) {
30008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dl_list_del(&dev->list);
30018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_device_free(p2p, dev);
30028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_sd_queries(p2p);
30048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->after_scan_tx);
30058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->after_scan_tx = NULL;
3006d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	p2p->ssid_set = 0;
30078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_unauthorize(struct p2p_data *p2p, const u8 *addr)
30118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
30138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
30158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
30168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
30178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3018b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Unauthorizing " MACSTR, MAC2STR(addr));
30198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (p2p->go_neg_peer == dev) {
30216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		eloop_cancel_timeout(p2p_go_neg_wait_timeout, p2p, NULL);
30228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->go_neg_peer = NULL;
30236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
30248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wps_method = WPS_NOT_READY;
3026cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	dev->oob_pw_id = 0;
30278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE;
30288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM;
30298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Check if after_scan_tx is for this peer. If so free it */
30318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->after_scan_tx &&
30328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(addr, p2p->after_scan_tx->dst, ETH_ALEN) == 0) {
30338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p2p->after_scan_tx);
30348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = NULL;
30358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
30388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_dev_name(struct p2p_data *p2p, const char *dev_name)
30428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->dev_name);
30448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev_name) {
30458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->dev_name = os_strdup(dev_name);
30468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->dev_name == NULL)
30478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
30488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
30498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->dev_name = NULL;
30508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
30518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_manufacturer(struct p2p_data *p2p, const char *manufacturer)
30558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->manufacturer);
30578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->manufacturer = NULL;
30588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (manufacturer) {
30598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->manufacturer = os_strdup(manufacturer);
30608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->manufacturer == NULL)
30618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
30628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
30658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_model_name(struct p2p_data *p2p, const char *model_name)
30698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_name);
30718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->model_name = NULL;
30728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (model_name) {
30738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_name = os_strdup(model_name);
30748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->model_name == NULL)
30758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
30768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
30798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_model_number(struct p2p_data *p2p, const char *model_number)
30838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_number);
30858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->model_number = NULL;
30868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (model_number) {
30878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_number = os_strdup(model_number);
30888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->model_number == NULL)
30898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
30908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
30938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_serial_number(struct p2p_data *p2p, const char *serial_number)
30978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->serial_number);
30998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->serial_number = NULL;
31008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (serial_number) {
31018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->serial_number = os_strdup(serial_number);
31028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->serial_number == NULL)
31038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
31048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
31078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_config_methods(struct p2p_data *p2p, u16 config_methods)
31118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->config_methods = config_methods;
31138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_uuid(struct p2p_data *p2p, const u8 *uuid)
31178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->uuid, uuid, 16);
31198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_pri_dev_type(struct p2p_data *p2p, const u8 *pri_dev_type)
31238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->pri_dev_type, pri_dev_type, 8);
31258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
31268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_sec_dev_types(struct p2p_data *p2p, const u8 dev_types[][8],
31308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  size_t num_dev_types)
31318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (num_dev_types > P2P_SEC_DEVICE_TYPES)
31338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num_dev_types = P2P_SEC_DEVICE_TYPES;
31348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->num_sec_dev_types = num_dev_types;
31358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->sec_dev_type, dev_types, num_dev_types * 8);
31368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
31378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_remove_wps_vendor_extensions(struct p2p_data *p2p)
31418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
31438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
31458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(p2p->wps_vendor_ext[i]);
31468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->wps_vendor_ext[i] = NULL;
31478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_add_wps_vendor_extension(struct p2p_data *p2p,
31528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const struct wpabuf *vendor_ext)
31538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
31558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (vendor_ext == NULL)
31578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
31588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
31608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->wps_vendor_ext[i] == NULL)
31618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
31628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (i >= P2P_MAX_WPS_VENDOR_EXT)
31648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
31658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->wps_vendor_ext[i] = wpabuf_dup(vendor_ext);
31678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->wps_vendor_ext[i] == NULL)
31688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
31698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
31718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_country(struct p2p_data *p2p, const char *country)
31758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->country, country, 3);
31778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
31788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int p2p_pre_find_operation(struct p2p_data *p2p, struct p2p_device *dev)
31826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
3183de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	int res;
3184de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt
31856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (dev->sd_pending_bcast_queries == 0) {
31866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		/* Initialize with total number of registered broadcast
31876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 * SD queries. */
31886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		dev->sd_pending_bcast_queries = p2p->num_p2p_sd_queries;
31896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
31906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
3191de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	res = p2p_start_sd(p2p, dev);
3192de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	if (res == -2)
3193de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt		return -2;
3194de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	if (res == 0)
31956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 1;
31966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
31976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (dev->req_config_methods &&
31986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	    !(dev->flags & P2P_DEV_PD_FOR_JOIN)) {
31996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_dbg(p2p, "Send pending Provision Discovery Request to "
32006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			MACSTR " (config methods 0x%x)",
32016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			MAC2STR(dev->info.p2p_device_addr),
32026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			dev->req_config_methods);
32036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (p2p_send_prov_disc_req(p2p, dev, 0, 0) == 0)
32046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return 1;
32056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
32066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
32076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return 0;
32086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
32096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
32106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
32118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_continue_find(struct p2p_data *p2p)
32128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
32138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
3214de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	int found, res;
32156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
32168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_SEARCH);
32176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
32186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	/* Continue from the device following the last iteration */
32196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	found = 0;
32208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
32216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (dev == p2p->last_p2p_find_oper) {
32226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			found = 1;
32236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			continue;
32246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		}
32256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (!found)
32266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			continue;
3227de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt		res = p2p_pre_find_operation(p2p, dev);
3228de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt		if (res > 0) {
32296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			p2p->last_p2p_find_oper = dev;
32306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return;
323113ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt		}
3232de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt		if (res == -2)
3233de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt			goto skip_sd;
32346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
323513ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt
32366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	/*
32376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * Wrap around to the beginning of the list and continue until the last
32386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * iteration device.
32396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 */
32406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
3241de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt		res = p2p_pre_find_operation(p2p, dev);
3242de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt		if (res > 0) {
32436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			p2p->last_p2p_find_oper = dev;
324413ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt			return;
32458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3246de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt		if (res == -2)
3247de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt			goto skip_sd;
32486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (dev == p2p->last_p2p_find_oper)
32496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			break;
32508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3252de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidtskip_sd:
3253de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt	os_memset(p2p->sd_query_no_ack, 0, ETH_ALEN);
3254d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p_listen_in_find(p2p, 1);
32558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_sd_cb(struct p2p_data *p2p, int success)
32598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3260b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Service Discovery Query TX callback: success=%d",
32618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
32628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
32638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!success) {
3265de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt		if (p2p->sd_peer) {
3266de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt			if (is_zero_ether_addr(p2p->sd_query_no_ack)) {
3267de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt				os_memcpy(p2p->sd_query_no_ack,
3268de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt					  p2p->sd_peer->info.p2p_device_addr,
3269de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt					  ETH_ALEN);
3270de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt				p2p_dbg(p2p,
3271de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt					"First SD Query no-ACK in this search iteration: "
3272de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt					MACSTR, MAC2STR(p2p->sd_query_no_ack));
3273de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt			}
32746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
3275de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt		}
327613ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt		p2p->sd_peer = NULL;
3277216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (p2p->state != P2P_IDLE)
3278216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			p2p_continue_find(p2p);
32798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
32808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->sd_peer == NULL) {
3283b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "No SD peer entry known");
3284216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (p2p->state != P2P_IDLE)
3285216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			p2p_continue_find(p2p);
32868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
32878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3289807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	if (p2p->sd_query && p2p->sd_query->for_all_peers) {
3290661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		/* Update the pending broadcast SD query count for this device
3291661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		 */
3292661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		p2p->sd_peer->sd_pending_bcast_queries--;
3293661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt
3294661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		/*
3295661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		 * If there are no pending broadcast queries for this device,
3296661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		 * mark it as done (-1).
3297661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		 */
3298661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		if (p2p->sd_peer->sd_pending_bcast_queries == 0)
3299661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt			p2p->sd_peer->sd_pending_bcast_queries = -1;
3300661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	}
3301661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt
33028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Wait for response from the peer */
33038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_SD_DURING_FIND);
33048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_timeout(p2p, 0, 200000);
33058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
330775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
330875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen/**
330975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen * p2p_retry_pd - Retry any pending provision disc requests in IDLE state
331075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen * @p2p: P2P module context from p2p_init()
331175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen */
33121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void p2p_retry_pd(struct p2p_data *p2p)
331375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
331475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	struct p2p_device *dev;
331575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
331675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
331775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * Retry the prov disc req attempt only for the peer that the user had
3318d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	 * requested.
331975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
332075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
332175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
332275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (os_memcmp(p2p->pending_pd_devaddr,
332375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			      dev->info.p2p_device_addr, ETH_ALEN) != 0)
332475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			continue;
332575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (!dev->req_config_methods)
332675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			continue;
332775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
3328b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Send pending Provision Discovery Request to "
332975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			MACSTR " (config methods 0x%x)",
333075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			MAC2STR(dev->info.p2p_device_addr),
333175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			dev->req_config_methods);
3332d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		p2p_send_prov_disc_req(p2p, dev,
3333051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt				       dev->flags & P2P_DEV_PD_FOR_JOIN,
3334051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt				       p2p->pd_force_freq);
333575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
333675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	}
333775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
333875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
333975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
33408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_prov_disc_cb(struct p2p_data *p2p, int success)
33418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3342b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Provision Discovery Request TX callback: success=%d",
33438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
334475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
334575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
334675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * Postpone resetting the pending action state till after we actually
334775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * time out. This allows us to take some action like notifying any
334875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * interested parties about no response to the request.
334975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 *
335075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * When the timer (below) goes off we check in IDLE, SEARCH, or
335175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * LISTEN_ONLY state, which are the only allowed states to issue a PD
335275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * requests in, if this was still pending and then raise notification.
335375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
33548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!success) {
335675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pending_action_state = P2P_NO_PENDING_ACTION;
335775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
335861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->user_initiated_pd &&
335961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		    (p2p->state == P2P_SEARCH || p2p->state == P2P_LISTEN_ONLY))
336061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		{
336161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			/* Retry request from timeout to avoid busy loops */
336261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p->pending_action_state = P2P_PENDING_PD;
336361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p_set_timeout(p2p, 0, 50000);
336461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		} else if (p2p->state != P2P_IDLE)
33658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_continue_find(p2p);
336675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		else if (p2p->user_initiated_pd) {
336775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p->pending_action_state = P2P_PENDING_PD;
336875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_set_timeout(p2p, 0, 300000);
336975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		}
33708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
33718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
337375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
3374d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	 * If after PD Request the peer doesn't expect to receive PD Response
3375d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	 * the PD Request ACK indicates a completion of the current PD. This
3376d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	 * happens only on the advertiser side sending the follow-on PD Request
3377d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	 * with the status different than 12 (Success: accepted by user).
3378d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	 */
3379d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (p2p->p2ps_prov && !p2p->p2ps_prov->pd_seeker &&
3380d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	    p2p->p2ps_prov->status != P2P_SC_SUCCESS_DEFERRED) {
3381d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		p2p_dbg(p2p, "P2PS PD completion on Follow-on PD Request ACK");
3382d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
3383d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (p2p->send_action_in_progress) {
3384d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			p2p->send_action_in_progress = 0;
3385d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
3386d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		}
3387d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
3388d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		p2p->pending_action_state = P2P_NO_PENDING_ACTION;
3389d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
3390d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (p2p->cfg->p2ps_prov_complete) {
3391d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			p2p->cfg->p2ps_prov_complete(
3392d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				p2p->cfg->cb_ctx,
3393d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				p2p->p2ps_prov->status,
3394d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				p2p->p2ps_prov->adv_mac,
3395d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				p2p->p2ps_prov->adv_mac,
3396d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				p2p->p2ps_prov->session_mac,
3397d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				NULL, p2p->p2ps_prov->adv_id,
3398d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				p2p->p2ps_prov->session_id,
3399d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				0, 0, NULL, 0, 0, 0,
3400de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt				NULL, NULL, 0, 0, NULL, 0);
3401d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		}
3402d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
3403d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (p2p->user_initiated_pd)
3404d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			p2p_reset_pending_pd(p2p);
3405d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
3406d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		p2ps_prov_free(p2p);
3407d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return;
3408d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
3409d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
3410d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	/*
341175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * This postponing, of resetting pending_action_state, needs to be
341275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * done only for user initiated PD requests and not internal ones.
341375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
341475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p->user_initiated_pd)
341575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pending_action_state = P2P_PENDING_PD;
341675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	else
341775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pending_action_state = P2P_NO_PENDING_ACTION;
341875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
34198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Wait for response from the peer */
34208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_SEARCH)
34218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_PD_DURING_FIND);
34228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_timeout(p2p, 0, 200000);
34238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3426216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtstatic int p2p_check_after_scan_tx_continuation(struct p2p_data *p2p)
3427216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt{
3428216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (p2p->after_scan_tx_in_progress) {
3429216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p->after_scan_tx_in_progress = 0;
3430216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (p2p->start_after_scan != P2P_AFTER_SCAN_NOTHING &&
3431216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		    p2p_run_after_scan(p2p))
3432216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			return 1;
3433216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (p2p->state == P2P_SEARCH) {
3434216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			p2p_dbg(p2p, "Continue find after after_scan_tx completion");
3435216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			p2p_continue_find(p2p);
3436216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		}
3437216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
3438216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3439216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	return 0;
3440216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt}
3441216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3442216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3443216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtstatic void p2p_prov_disc_resp_cb(struct p2p_data *p2p, int success)
3444216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt{
3445216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	p2p_dbg(p2p, "Provision Discovery Response TX callback: success=%d",
3446216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		success);
3447216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3448216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (p2p->send_action_in_progress) {
3449216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p->send_action_in_progress = 0;
3450216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
3451216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
3452216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3453216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
3454216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3455216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (!success)
3456216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		goto continue_search;
3457216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3458216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (!p2p->cfg->prov_disc_resp_cb ||
3459216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	    p2p->cfg->prov_disc_resp_cb(p2p->cfg->cb_ctx) < 1)
3460216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		goto continue_search;
3461216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3462216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	p2p_dbg(p2p,
3463216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		"Post-Provision Discovery operations started - do not try to continue other P2P operations");
3464216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	return;
3465216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3466216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtcontinue_search:
3467216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	p2p_check_after_scan_tx_continuation(p2p);
3468216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt}
3469216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3470216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
34718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_scan_res_handler(struct p2p_data *p2p, const u8 *bssid, int freq,
3472fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			 struct os_reltime *rx_time, int level, const u8 *ies,
3473a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			 size_t ies_len)
34748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3475fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (os_reltime_before(rx_time, &p2p->find_start)) {
3476f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		/*
3477f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * The driver may have cached (e.g., in cfg80211 BSS table) the
3478f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * scan results for relatively long time. To avoid reporting
3479f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * stale information, update P2P peers only based on results
3480f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * that have based on frames received after the last p2p_find
3481f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * operation was started.
3482f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 */
3483b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Ignore old scan result for " MACSTR
3484de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt			" (rx_time=%u.%06u find_start=%u.%06u)",
3485f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			MAC2STR(bssid), (unsigned int) rx_time->sec,
3486de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt			(unsigned int) rx_time->usec,
3487de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt			(unsigned int) p2p->find_start.sec,
3488de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt			(unsigned int) p2p->find_start.usec);
3489f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		return 0;
3490f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	}
3491f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
3492f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	p2p_add_device(p2p, bssid, freq, rx_time, level, ies, ies_len, 1);
34938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
34958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_scan_res_handled(struct p2p_data *p2p)
34998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
35008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p->p2p_scan_running) {
3501b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "p2p_scan was not running, but scan results received");
35028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
35038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->p2p_scan_running = 0;
35048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
35058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_run_after_scan(p2p))
35078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
35088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_SEARCH)
35098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
35108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
35118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35139c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidtvoid p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id,
35149c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt		 unsigned int bands)
35158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3516216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	u8 dev_capab;
351761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 *len;
351861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
351961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
352061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_probe_req)
352161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(ies, p2p->wfd_ie_probe_req);
352261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
352361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
35242e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_PROBE_REQ_P2P])
35252e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		wpabuf_put_buf(ies,
35262e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			       p2p->vendor_elem[VENDOR_ELEM_PROBE_REQ_P2P]);
35272e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
352861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	len = p2p_buf_add_ie_hdr(ies);
3529216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3530216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	dev_capab = p2p->dev_capab & ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
3531216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3532216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	/* P2PS requires Probe Request frames to include SD bit */
3533216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (p2p->p2ps_seek && p2p->p2ps_seek_count)
3534216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		dev_capab |= P2P_DEV_CAPAB_SERVICE_DISCOVERY;
3535216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3536216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	p2p_buf_add_capability(ies, dev_capab, 0);
3537216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
3538c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (dev_id)
3539c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		p2p_buf_add_device_id(ies, dev_id);
35408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->reg_class && p2p->cfg->channel)
35418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_listen_channel(ies, p2p->cfg->country,
35428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   p2p->cfg->reg_class,
35438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   p2p->cfg->channel);
35448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval)
35458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_ext_listen_timing(ies, p2p->ext_listen_period,
35468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      p2p->ext_listen_interval);
3547216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
35489c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt	if (bands & BAND_60_GHZ)
35499c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt		p2p_buf_add_device_info(ies, p2p, NULL);
35509c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt
3551216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (p2p->p2ps_seek && p2p->p2ps_seek_count)
3552216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p_buf_add_service_hash(ies, p2p);
3553216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
35548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: p2p_buf_add_operating_channel() if GO */
35558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(ies, len);
35568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
35578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtsize_t p2p_scan_ie_buf_len(struct p2p_data *p2p)
35601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
356161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t len = 100;
356261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
356361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
356461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p && p2p->wfd_ie_probe_req)
356561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		len += wpabuf_len(p2p->wfd_ie_probe_req);
356661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
356761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
35682e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	if (p2p && p2p->vendor_elem &&
35692e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	    p2p->vendor_elem[VENDOR_ELEM_PROBE_REQ_P2P])
35702e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		len += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_PROBE_REQ_P2P]);
35712e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
357261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return len;
35731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
35741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
35751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
35768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_ie_text(struct wpabuf *p2p_ie, char *buf, char *end)
35778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
35788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_attr_text(p2p_ie, buf, end);
35798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
35808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_req_cb(struct p2p_data *p2p, int success)
35838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
35848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p->go_neg_peer;
35858c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	int timeout;
35868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3587b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "GO Negotiation Request TX callback: success=%d", success);
35888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
3590b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "No pending GO Negotiation");
35918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
35928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
35938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (success) {
35958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->flags & P2P_DEV_USER_REJECTED) {
35968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_set_state(p2p, P2P_IDLE);
35978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
35988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
359904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	} else if (dev->go_neg_req_sent) {
360004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/* Cancel the increment from p2p_connect_send() on failure */
360198f9e76624da6bb96edc1982c423e4a119c5170aDmitry Shmidt		dev->go_neg_req_sent--;
360298f9e76624da6bb96edc1982c423e4a119c5170aDmitry Shmidt	}
36038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!success &&
36058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (dev->info.dev_capab & P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY) &&
36068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !is_zero_ether_addr(dev->member_in_go_dev)) {
3607b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Peer " MACSTR " did not acknowledge request - try to use device discoverability through its GO",
36088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr));
36098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
36108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_send_dev_disc_req(p2p, dev);
36118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
36128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
36138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
36158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Use P2P find, if needed, to find the other device from its listen
36168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * channel.
36178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
36188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_CONNECT);
36198c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	timeout = success ? 500000 : 100000;
36208c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	if (!success && p2p->go_neg_peer &&
36218c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	    (p2p->go_neg_peer->flags & P2P_DEV_PEER_WAITING_RESPONSE)) {
36228c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		unsigned int r;
36238c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		/*
36248c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		 * Peer is expected to wait our response and we will skip the
36258c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		 * listen phase. Add some randomness to the wait time here to
36268c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		 * make it less likely to hit cases where we could end up in
36278c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		 * sync with peer not listening.
36288c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		 */
3629661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		if (os_get_random((u8 *) &r, sizeof(r)) < 0)
3630661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt			r = 0;
36318c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		timeout += r % 100000;
36328c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	}
36338c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	p2p_set_timeout(p2p, 0, timeout);
36348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
36358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_resp_cb(struct p2p_data *p2p, int success)
36388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3639b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "GO Negotiation Response TX callback: success=%d",
36408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
36418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p->go_neg_peer && p2p->state == P2P_PROVISIONING) {
3642b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Ignore TX callback event - GO Negotiation is not running anymore");
36438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
36448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
36458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_CONNECT);
36468c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	p2p_set_timeout(p2p, 0, 500000);
36478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
36488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36504b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidtstatic void p2p_go_neg_resp_failure_cb(struct p2p_data *p2p, int success,
36514b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt				       const u8 *addr)
36528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3653b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "GO Negotiation Response (failure) TX callback: success=%d", success);
36548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer && p2p->go_neg_peer->status != P2P_SC_SUCCESS) {
36556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_go_neg_failed(p2p, p2p->go_neg_peer->status);
3656203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt		return;
3657203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt	}
3658203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt
3659203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt	if (success) {
36604b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		struct p2p_device *dev;
36614b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		dev = p2p_get_device(p2p, addr);
36624b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		if (dev &&
366334c1202b3e71c63661a850aad81f663e40e48ca1Dmitry Shmidt		    dev->status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE)
36644b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt			dev->flags |= P2P_DEV_PEER_WAITING_RESPONSE;
36658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3666203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt
3667203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt	if (p2p->state == P2P_SEARCH || p2p->state == P2P_SD_DURING_FIND)
3668203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt		p2p_continue_find(p2p);
36698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
36708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_conf_cb(struct p2p_data *p2p,
36738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       enum p2p_send_action_result result)
36748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
36758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
36768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3677b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "GO Negotiation Confirm TX callback: result=%d", result);
36788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (result == P2P_SEND_ACTION_FAILED) {
3679413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
36806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_go_neg_failed(p2p, -1);
36818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
36828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3683413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt
3684413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt	dev = p2p->go_neg_peer;
3685413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt
36868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (result == P2P_SEND_ACTION_NO_ACK) {
36878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
3688413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt		 * Retry GO Negotiation Confirmation
3689413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt		 * P2P_GO_NEG_CNF_MAX_RETRY_COUNT times if we did not receive
3690413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt		 * ACK for confirmation.
3691413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt		 */
3692413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt		if (dev && dev->go_neg_conf &&
3693413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt		    dev->go_neg_conf_sent <= P2P_GO_NEG_CNF_MAX_RETRY_COUNT) {
3694413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt			p2p_dbg(p2p, "GO Negotiation Confirm retry %d",
3695413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt				dev->go_neg_conf_sent);
3696413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt			p2p->pending_action_state = P2P_PENDING_GO_NEG_CONFIRM;
3697413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt			if (p2p_send_action(p2p, dev->go_neg_conf_freq,
3698413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt					    dev->info.p2p_device_addr,
3699413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt					    p2p->cfg->dev_addr,
3700413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt					    dev->info.p2p_device_addr,
3701413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt					    wpabuf_head(dev->go_neg_conf),
3702413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt					    wpabuf_len(dev->go_neg_conf), 0) >=
3703413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt			    0) {
3704413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt				dev->go_neg_conf_sent++;
3705413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt				return;
3706413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt			}
3707413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt			p2p_dbg(p2p, "Failed to re-send Action frame");
3708413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt
3709413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt			/*
3710413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt			 * Continue with the assumption that the first attempt
3711413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt			 * went through and just the ACK frame was lost.
3712413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt			 */
3713413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt		}
3714413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt
3715413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt		/*
37168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * It looks like the TX status for GO Negotiation Confirm is
37178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * often showing failure even when the peer has actually
37188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * received the frame. Since the peer may change channels
37198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * immediately after having received the frame, we may not see
37208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * an Ack for retries, so just dropping a single frame may
37218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * trigger this. To allow the group formation to succeed if the
37228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * peer did indeed receive the frame, continue regardless of
37238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * the TX status.
37248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
3725b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Assume GO Negotiation Confirm TX was actually received by the peer even though Ack was not reported");
37268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3728413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
3729413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt
37308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
37318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
37328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_go_complete(p2p, dev);
37348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
37358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_send_action_cb(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
37388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const u8 *src, const u8 *bssid,
37398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			enum p2p_send_action_result result)
37408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
37418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum p2p_pending_action_state state;
37428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int success;
37438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3744b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Action frame TX callback (state=%d freq=%u dst=" MACSTR
3745216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		" src=" MACSTR " bssid=" MACSTR " result=%d p2p_state=%s)",
37468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_action_state, freq, MAC2STR(dst), MAC2STR(src),
3747216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		MAC2STR(bssid), result, p2p_state_txt(p2p->state));
37488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	success = result == P2P_SEND_ACTION_SUCCESS;
37498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	state = p2p->pending_action_state;
37508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
37518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (state) {
37528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_NO_PENDING_ACTION:
37534582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt		if (p2p->send_action_in_progress) {
37544582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt			p2p->send_action_in_progress = 0;
37554582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt			p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
37564582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt		}
3757216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p_check_after_scan_tx_continuation(p2p);
37588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
37598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_REQUEST:
37608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_req_cb(p2p, success);
37618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
37628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_RESPONSE:
37638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_resp_cb(p2p, success);
37648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
37658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_RESPONSE_FAILURE:
37664b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		p2p_go_neg_resp_failure_cb(p2p, success, dst);
37678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
37688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_CONFIRM:
37698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_conf_cb(p2p, result);
37708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
37718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_SD:
37728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_sd_cb(p2p, success);
37738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
37748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_PD:
37758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_prov_disc_cb(p2p, success);
37768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3777216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	case P2P_PENDING_PD_RESPONSE:
3778216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p_prov_disc_resp_cb(p2p, success);
3779216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		break;
37808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_INVITATION_REQUEST:
37818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_invitation_req_cb(p2p, success);
37828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
37838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_INVITATION_RESPONSE:
37848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_invitation_resp_cb(p2p, success);
37858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
37868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_DEV_DISC_REQUEST:
37878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_disc_req_cb(p2p, success);
37888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
37898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_DEV_DISC_RESPONSE:
37908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_disc_resp_cb(p2p, success);
37918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
37928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_DISC_REQ:
37938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_disc_req_cb(p2p, success);
37948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
37958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37968da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt
37978da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt	p2p->after_scan_tx_in_progress = 0;
37988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
37998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_listen_cb(struct p2p_data *p2p, unsigned int freq,
38028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   unsigned int duration)
38038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
38048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq == p2p->pending_client_disc_freq) {
3805b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Client discoverability remain-awake completed");
38068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_client_disc_freq = 0;
38078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
38088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq != p2p->pending_listen_freq) {
3811b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Unexpected listen callback for freq=%u duration=%u (pending_listen_freq=%u)",
38128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq, duration, p2p->pending_listen_freq);
38138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
38148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3816b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Starting Listen timeout(%u,%u) on freq=%u based on callback",
38178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_sec, p2p->pending_listen_usec,
38188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_freq);
38198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->in_listen = 1;
38208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->drv_in_listen = freq;
38218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->pending_listen_sec || p2p->pending_listen_usec) {
38228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
38238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Add 20 msec extra wait to avoid race condition with driver
38248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * remain-on-channel end event, i.e., give driver more time to
38258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * complete the operation before our timeout expires.
38268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
38278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_timeout(p2p, p2p->pending_listen_sec,
38288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p->pending_listen_usec + 20000);
38298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_freq = 0;
38328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
38338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_listen_end(struct p2p_data *p2p, unsigned int freq)
38368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3837b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Driver ended Listen state (freq=%u)", freq);
38388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->drv_in_listen = 0;
38398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->in_listen)
38408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* Internal timeout will trigger the next step */
38418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_CONNECT_LISTEN && p2p->go_neg_peer) {
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 0;
38478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
38488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_CONNECT);
38508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, p2p->go_neg_peer);
38518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
38528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (p2p->state == P2P_SEARCH) {
3853c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (p2p->p2p_scan_running) {
3854c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 /*
3855c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * Search is already in progress. This can happen if
3856c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * an Action frame RX is reported immediately after
3857c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * the end of a remain-on-channel operation and the
3858c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * response frame to that is sent using an offchannel
3859c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * operation while in p2p_find. Avoid an attempt to
3860c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  * restart a scan here.
3861c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			  */
3862b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "p2p_scan already in progress - do not try to start a new one");
3863c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			return 1;
3864c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		}
386504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (p2p->pending_listen_freq) {
386604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			/*
386704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 * Better wait a bit if the driver is unable to start
386804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 * offchannel operation for some reason. p2p_search()
386904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 * will be started from internal timeout.
387004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 */
3871b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Listen operation did not seem to start - delay search phase to avoid busy loop");
387204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			p2p_set_timeout(p2p, 0, 100000);
387304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			return 1;
387404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
387561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->search_delay) {
3876b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Delay search operation by %u ms",
387761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				p2p->search_delay);
387861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p_set_timeout(p2p, p2p->search_delay / 1000,
387961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					(p2p->search_delay % 1000) * 1000);
388061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return 1;
388161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
38828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_search(p2p);
38838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
38848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
38878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
38888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_connect(struct p2p_data *p2p)
38918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
38928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
389304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p->go_neg_peer &&
389404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    (p2p->go_neg_peer->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM)) {
3895b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Wait for GO Negotiation Confirm timed out - assume GO Negotiation failed");
38966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_go_neg_failed(p2p, -1);
389704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return;
389804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
38998c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	if (p2p->go_neg_peer &&
39008c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	    (p2p->go_neg_peer->flags & P2P_DEV_PEER_WAITING_RESPONSE) &&
39018c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	    p2p->go_neg_peer->connect_reqs < 120) {
3902b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Peer expected to wait our response - skip listen");
39038c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		p2p_connect_send(p2p, p2p->go_neg_peer);
39048c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt		return;
39058c65289885e84727226d81b3d32856f79c31ee5fDmitry Shmidt	}
3906cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (p2p->go_neg_peer && p2p->go_neg_peer->oob_go_neg_freq > 0) {
3907cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dbg(p2p, "Skip connect-listen since GO Neg channel known (OOB)");
3908cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_set_state(p2p, P2P_CONNECT_LISTEN);
3909cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_set_timeout(p2p, 0, 30000);
3910cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		return;
3911cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
39128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_CONNECT_LISTEN);
3913d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p_listen_in_find(p2p, 0);
39148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_connect_listen(struct p2p_data *p2p)
39188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
39198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer) {
39208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->drv_in_listen) {
3921b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Driver is still in Listen state; wait for it to complete");
39228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
39238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
39248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->go_neg_peer->connect_reqs >= 120) {
3926b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Timeout on sending GO Negotiation Request without getting response");
39276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			p2p_go_neg_failed(p2p, -1);
39288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
39298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
39308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_CONNECT);
39328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, p2p->go_neg_peer);
39338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
39348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
39358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_wait_peer_connect(struct p2p_data *p2p)
39398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
39408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_WAIT_PEER_IDLE);
39411846323989242844f0e857458a8939fa5836429cDmitry Shmidt
39421846323989242844f0e857458a8939fa5836429cDmitry Shmidt	if (p2p->cfg->is_concurrent_session_active &&
39431846323989242844f0e857458a8939fa5836429cDmitry Shmidt	    p2p->cfg->is_concurrent_session_active(p2p->cfg->cb_ctx))
39441846323989242844f0e857458a8939fa5836429cDmitry Shmidt		p2p_set_timeout(p2p, 0, 500000);
39451846323989242844f0e857458a8939fa5836429cDmitry Shmidt	else
39461846323989242844f0e857458a8939fa5836429cDmitry Shmidt		p2p_set_timeout(p2p, 0, 200000);
39478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_wait_peer_idle(struct p2p_data *p2p)
39518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
39528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p->go_neg_peer;
39538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
3955b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Unknown GO Neg peer - stop GO Neg wait");
39568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
39578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3959b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Go to Listen state while waiting for the peer to become ready for GO Negotiation");
39608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_WAIT_PEER_CONNECT);
3961d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p_listen_in_find(p2p, 0);
39628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_sd_during_find(struct p2p_data *p2p)
39668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3967b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Service Discovery Query timeout");
39688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->sd_peer) {
39698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
39708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->sd_peer = NULL;
39718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_continue_find(p2p);
39738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_prov_disc_during_find(struct p2p_data *p2p)
39778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3978b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Provision Discovery Request timeout");
39798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
39808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_continue_find(p2p);
39818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
398475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic void p2p_timeout_prov_disc_req(struct p2p_data *p2p)
398575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
3986216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	u32 adv_id = 0;
3987216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	u8 *adv_mac = NULL;
3988216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
398975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
399075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
399175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
399275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * For user initiated PD requests that we have not gotten any responses
399375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * for while in IDLE state, we retry them a couple of times before
399475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * giving up.
399575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
399675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (!p2p->user_initiated_pd)
399775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
399875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
3999b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "User initiated Provision Discovery Request timeout");
400075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
400175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p->pd_retries) {
400275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pd_retries--;
400375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p_retry_pd(p2p);
400475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	} else {
4005d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		struct p2p_device *dev;
4006d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		int for_join = 0;
4007d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
4008d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
4009d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			if (os_memcmp(p2p->pending_pd_devaddr,
4010d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				      dev->info.p2p_device_addr, ETH_ALEN) != 0)
4011d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				continue;
4012d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			if (dev->req_config_methods &&
4013d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			    (dev->flags & P2P_DEV_PD_FOR_JOIN))
4014d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				for_join = 1;
4015d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		}
4016d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
4017216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (p2p->p2ps_prov) {
4018216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			adv_id = p2p->p2ps_prov->adv_id;
4019216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			adv_mac = p2p->p2ps_prov->adv_mac;
4020216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		}
4021216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
402275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->cfg->prov_disc_fail)
402375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx,
402475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen						 p2p->pending_pd_devaddr,
4025d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt						 for_join ?
4026d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt						 P2P_PROV_DISC_TIMEOUT_JOIN :
4027216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt						 P2P_PROV_DISC_TIMEOUT,
4028216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt						 adv_id, adv_mac, NULL);
402975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p_reset_pending_pd(p2p);
403075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	}
403175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
403275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
403375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
40348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_invite(struct p2p_data *p2p)
40358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
40368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
40378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_INVITE_LISTEN);
40388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->inv_role == P2P_INVITE_ROLE_ACTIVE_GO) {
40398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
40408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Better remain on operating channel instead of listen channel
40418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * when running a group.
40428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
4043b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Inviting in active GO role - wait on operating channel");
40448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_timeout(p2p, 0, 100000);
40458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
40468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4047d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p_listen_in_find(p2p, 0);
40488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
40498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_invite_listen(struct p2p_data *p2p)
40528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
40538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->invite_peer && p2p->invite_peer->invitation_reqs < 100) {
40548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_INVITE);
40558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_invite_send(p2p, p2p->invite_peer,
4056cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				p2p->invite_go_dev_addr, p2p->invite_dev_pw_id);
40578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
40588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->invite_peer) {
4059b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Invitation Request retry limit reached");
40608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (p2p->cfg->invitation_result)
40618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p->cfg->invitation_result(
4062700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt					p2p->cfg->cb_ctx, -1, NULL, NULL,
4063e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt					p2p->invite_peer->info.p2p_device_addr,
406415907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt					0, 0);
40658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
40668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
40678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
40688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
40698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_state_timeout(void *eloop_ctx, void *timeout_ctx)
40728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
40738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
40748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4075b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Timeout (state=%s)", p2p_state_txt(p2p->state));
40768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->in_listen = 0;
40786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (p2p->drv_in_listen) {
40796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p_dbg(p2p, "Driver is still in listen state - stop it");
40806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
40816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
40828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (p2p->state) {
40848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_IDLE:
408575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/* Check if we timed out waiting for PD req */
408675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->pending_action_state == P2P_PENDING_PD)
408775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_timeout_prov_disc_req(p2p);
40888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
40898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SEARCH:
409075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/* Check if we timed out waiting for PD req */
409175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->pending_action_state == P2P_PENDING_PD)
409275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_timeout_prov_disc_req(p2p);
409361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->search_delay && !p2p->in_search_delay) {
4094b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Delay search operation by %u ms",
409561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				p2p->search_delay);
409661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p->in_search_delay = 1;
409761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p2p_set_timeout(p2p, p2p->search_delay / 1000,
409861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					(p2p->search_delay % 1000) * 1000);
409961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			break;
410061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
410161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->in_search_delay = 0;
41028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_search(p2p);
41038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
41048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT:
41058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_connect(p2p);
41068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
41078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT_LISTEN:
41088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_connect_listen(p2p);
41098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
41108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG:
41118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
41128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_LISTEN_ONLY:
411375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/* Check if we timed out waiting for PD req */
411475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->pending_action_state == P2P_PENDING_PD)
411575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_timeout_prov_disc_req(p2p);
411675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
41178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->ext_listen_only) {
4118b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Extended Listen Timing - Listen State completed");
41198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->ext_listen_only = 0;
41208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_set_state(p2p, P2P_IDLE);
41218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
41228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
41238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_CONNECT:
41248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_wait_peer_connect(p2p);
41258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
41268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_IDLE:
41278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_wait_peer_idle(p2p);
41288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
41298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SD_DURING_FIND:
41308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_sd_during_find(p2p);
41318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
41328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROVISIONING:
41338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
41348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PD_DURING_FIND:
41358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_prov_disc_during_find(p2p);
41368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
41378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE:
41388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_invite(p2p);
41398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
41408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE_LISTEN:
41418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_invite_listen(p2p);
41428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
41438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
41448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_reject(struct p2p_data *p2p, const u8 *peer_addr)
41488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
41498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
41508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
4152b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Local request to reject connection attempts by peer "
4153b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		MACSTR, MAC2STR(peer_addr));
41548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
4155b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Peer " MACSTR " unknown", MAC2STR(peer_addr));
41568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
41578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
41588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->status = P2P_SC_FAIL_REJECTED_BY_USER;
41598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_USER_REJECTED;
41608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
41618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtconst char * p2p_wps_method_text(enum p2p_wps_method method)
41658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
41668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (method) {
41678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_NOT_READY:
41688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "not-ready";
41698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_PIN_DISPLAY:
41708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "Display";
41718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_PIN_KEYPAD:
41728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "Keypad";
41738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_PBC:
41748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "PBC";
4175cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	case WPS_NFC:
4176cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		return "NFC";
4177216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	case WPS_P2PS:
4178216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		return "P2PS";
41798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
41808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return "??";
41828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * p2p_go_state_text(enum p2p_go_state go_state)
41868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
41878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (go_state) {
41888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case UNKNOWN_GO:
41898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "unknown";
41908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case LOCAL_GO:
41918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "local";
41928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case  REMOTE_GO:
41938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "remote";
41948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
41958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return "??";
41978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
41988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtconst struct p2p_peer_info * p2p_get_peer_info(struct p2p_data *p2p,
42011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					       const u8 *addr, int next)
42028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
42038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
42048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr)
42068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, addr);
42078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
42088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = dl_list_first(&p2p->devices, struct p2p_device, list);
42098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev && next) {
42118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = dl_list_first(&dev->list, struct p2p_device, list);
42128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (&dev->list == &p2p->devices)
42138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev = NULL;
42148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
42158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
42171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return NULL;
42181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
42191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return &dev->info;
42201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
42211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
42221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
42231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_get_peer_info_txt(const struct p2p_peer_info *info,
42241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			  char *buf, size_t buflen)
42251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
42261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_device *dev;
42271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int res;
42281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	char *pos, *end;
4229fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	struct os_reltime now;
42301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
42311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (info == NULL)
42328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
42338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	dev = (struct p2p_device *) (((u8 *) info) -
42351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				     offsetof(struct p2p_device, info));
42361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
42378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf;
42388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = buf + buflen;
42398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4240fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	os_get_reltime(&now);
42418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = os_snprintf(pos, end - pos,
42428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "age=%d\n"
42438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "listen_freq=%d\n"
42448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "wps_method=%s\n"
42458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "interface_addr=" MACSTR "\n"
42468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "member_in_go_dev=" MACSTR "\n"
42478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "member_in_go_iface=" MACSTR "\n"
42488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "go_neg_req_sent=%d\n"
42498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "go_state=%s\n"
42508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dialog_token=%u\n"
42518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "intended_addr=" MACSTR "\n"
42528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "country=%c%c\n"
42538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "oper_freq=%d\n"
42548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "req_config_methods=0x%x\n"
4255a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			  "flags=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n"
42568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "status=%d\n"
42578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "invitation_reqs=%u\n",
42588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  (int) (now.sec - dev->last_seen.sec),
42598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->listen_freq,
42608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  p2p_wps_method_text(dev->wps_method),
42618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->interface_addr),
42628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->member_in_go_dev),
42638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->member_in_go_iface),
42648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->go_neg_req_sent,
42658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  p2p_go_state_text(dev->go_state),
42668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->dialog_token,
42678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->intended_addr),
42688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->country[0] ? dev->country[0] : '_',
42698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->country[1] ? dev->country[1] : '_',
42708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->oper_freq,
42718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->req_config_methods,
42728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PROBE_REQ_ONLY ?
42738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PROBE_REQ_ONLY]" : "",
42748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_REPORTED ? "[REPORTED]" : "",
42758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_NOT_YET_READY ?
42768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[NOT_YET_READY]" : "",
42778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PD_PEER_DISPLAY ?
42788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PD_PEER_DISPLAY]" : "",
42798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PD_PEER_KEYPAD ?
42808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PD_PEER_KEYPAD]" : "",
4281216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			  dev->flags & P2P_DEV_PD_PEER_P2PS ?
4282216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			  "[PD_PEER_P2PS]" : "",
42838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_USER_REJECTED ?
42848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[USER_REJECTED]" : "",
42858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PEER_WAITING_RESPONSE ?
42868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PEER_WAITING_RESPONSE]" : "",
42878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PREFER_PERSISTENT_GROUP ?
42888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PREFER_PERSISTENT_GROUP]" : "",
42898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_WAIT_GO_NEG_RESPONSE ?
42908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[WAIT_GO_NEG_RESPONSE]" : "",
42918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM ?
42928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[WAIT_GO_NEG_CONFIRM]" : "",
42938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_GROUP_CLIENT_ONLY ?
42948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[GROUP_CLIENT_ONLY]" : "",
42958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_FORCE_FREQ ?
42968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[FORCE_FREQ]" : "",
42978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PD_FOR_JOIN ?
42988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PD_FOR_JOIN]" : "",
4299a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			  dev->flags & P2P_DEV_LAST_SEEN_AS_GROUP_CLIENT ?
4300a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			  "[LAST_SEEN_AS_GROUP_CLIENT]" : "",
43018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->status,
43028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->invitation_reqs);
43036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_snprintf_error(end - pos, res))
43048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return pos - buf;
43058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += res;
43068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->ext_listen_period) {
43088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = os_snprintf(pos, end - pos,
43098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "ext_listen_period=%u\n"
43108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "ext_listen_interval=%u\n",
43118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  dev->ext_listen_period,
43128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  dev->ext_listen_interval);
43136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (os_snprintf_error(end - pos, res))
43148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos - buf;
43158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += res;
43168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
43178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->oper_ssid_len) {
43198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = os_snprintf(pos, end - pos,
43208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "oper_ssid=%s\n",
43218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  wpa_ssid_txt(dev->oper_ssid,
43228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       dev->oper_ssid_len));
43236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (os_snprintf_error(end - pos, res))
43248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos - buf;
43258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += res;
43268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
43278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
432861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
432961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (dev->info.wfd_subelems) {
433061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		res = os_snprintf(pos, end - pos, "wfd_subelems=");
43316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (os_snprintf_error(end - pos, res))
433261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return pos - buf;
433361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += res;
433461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
433561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += wpa_snprintf_hex(pos, end - pos,
433661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					wpabuf_head(dev->info.wfd_subelems),
433761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					wpabuf_len(dev->info.wfd_subelems));
433861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
433961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		res = os_snprintf(pos, end - pos, "\n");
43406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (os_snprintf_error(end - pos, res))
434161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return pos - buf;
434261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += res;
434361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
434461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
434561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
43468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return pos - buf;
43478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
43488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_peer_known(struct p2p_data *p2p, const u8 *addr)
43511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
43521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return p2p_get_device(p2p, addr) != NULL;
43531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
43541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
43551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
43568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_client_discoverability(struct p2p_data *p2p, int enabled)
43578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
43588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (enabled) {
4359b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Client discoverability enabled");
43608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
43618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
4362b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Client discoverability disabled");
43638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab &= ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
43648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
43658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
43668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_presence_req(u32 duration1, u32 interval1,
43698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      u32 duration2, u32 interval2)
43708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
43718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
43728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_noa_desc desc1, desc2, *ptr1 = NULL, *ptr2 = NULL;
43738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
43748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req = wpabuf_alloc(100);
43768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL)
43778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
43788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (duration1 || interval1) {
43808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(&desc1, 0, sizeof(desc1));
43818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc1.count_type = 1;
43828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc1.duration = duration1;
43838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc1.interval = interval1;
43848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ptr1 = &desc1;
43858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (duration2 || interval2) {
43878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(&desc2, 0, sizeof(desc2));
43888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc2.count_type = 2;
43898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc2.duration = duration2;
43908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc2.interval = interval2;
43918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ptr2 = &desc2;
43928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
43938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
43948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_action_hdr(req, P2P_PRESENCE_REQ, 1);
43968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(req);
43978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_noa(req, 0, 0, 0, ptr1, ptr2);
43988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(req, len);
43998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return req;
44018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
44028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_presence_req(struct p2p_data *p2p, const u8 *go_interface_addr,
44058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     const u8 *own_interface_addr, unsigned int freq,
44068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     u32 duration1, u32 interval1, u32 duration2,
44078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     u32 interval2)
44088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
44098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
44108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4411b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Send Presence Request to GO " MACSTR
4412b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		" (own interface " MACSTR ") freq=%u dur1=%u int1=%u "
4413b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		"dur2=%u int2=%u",
44148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(go_interface_addr), MAC2STR(own_interface_addr),
44158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		freq, duration1, interval1, duration2, interval2);
44168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req = p2p_build_presence_req(duration1, interval1, duration2,
44188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     interval2);
44198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL)
44208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
44218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
44238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_send_action(p2p, freq, go_interface_addr, own_interface_addr,
44248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    go_interface_addr,
44258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpabuf_head(req), wpabuf_len(req), 200) < 0) {
4426b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to send Action frame");
44278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
44288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(req);
44298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
44318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
44328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_presence_resp(u8 status, const u8 *noa,
44358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       size_t noa_len, u8 dialog_token)
44368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
44378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
44388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
44398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = wpabuf_alloc(100 + noa_len);
44418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
44428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
44438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_action_hdr(resp, P2P_PRESENCE_RESP, dialog_token);
44458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(resp);
44468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_status(resp, status);
44478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (noa) {
44488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(resp, P2P_ATTR_NOTICE_OF_ABSENCE);
44498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_le16(resp, noa_len);
44508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_data(resp, noa, noa_len);
44518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
44528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_noa(resp, 0, 0, 0, NULL, NULL);
44538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(resp, len);
44548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return resp;
44568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
44578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_req(struct p2p_data *p2p, const u8 *da,
44608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const u8 *sa, const u8 *data, size_t len,
44618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     int rx_freq)
44628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
44638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
44648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 status;
44658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
44668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t g;
44678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group *group = NULL;
44688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int parsed = 0;
44698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 noa[50];
44708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int noa_len;
44718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4472b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Received P2P Action - P2P Presence Request");
44738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (g = 0; g < p2p->num_groups; g++) {
44758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(da, p2p_group_get_interface_addr(p2p->groups[g]),
44768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      ETH_ALEN) == 0) {
44778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group = p2p->groups[g];
44788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
44798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
44808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
44818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group == NULL) {
4482b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Ignore P2P Presence Request for unknown group "
44838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MACSTR, MAC2STR(da));
44848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
44858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
44868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse(data, len, &msg) < 0) {
4488b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to parse P2P Presence Request");
44898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		status = P2P_SC_FAIL_INVALID_PARAMS;
44908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
44918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
44928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	parsed = 1;
44938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.noa == NULL) {
4495b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "No NoA attribute in P2P Presence Request");
44968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		status = P2P_SC_FAIL_INVALID_PARAMS;
44978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
44988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
44998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	status = p2p_group_presence_req(group, sa, msg.noa, msg.noa_len);
45018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail:
45038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->get_noa)
45048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		noa_len = p2p->cfg->get_noa(p2p->cfg->cb_ctx, da, noa,
45058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    sizeof(noa));
45068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
45078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		noa_len = -1;
45088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = p2p_build_presence_resp(status, noa_len > 0 ? noa : NULL,
45098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       noa_len > 0 ? noa_len : 0,
45108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       msg.dialog_token);
45118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (parsed)
45128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
45138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
45148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
45158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
45178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_send_action(p2p, rx_freq, sa, da, da,
45188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
4519b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to send Action frame");
45208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
45218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(resp);
45228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
45238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_resp(struct p2p_data *p2p, const u8 *da,
45268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *sa, const u8 *data, size_t len)
45278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
45288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
45298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4530b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Received P2P Action - P2P Presence Response");
45318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse(data, len, &msg) < 0) {
4533b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to parse P2P Presence Response");
45348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
45358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
45368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.status == NULL || msg.noa == NULL) {
4538b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "No Status or NoA attribute in P2P Presence Response");
45398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
45408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
45418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
45428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4543fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (p2p->cfg->presence_resp) {
4544fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		p2p->cfg->presence_resp(p2p->cfg->cb_ctx, sa, *msg.status,
4545fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt					msg.noa, msg.noa_len);
4546fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	}
4547fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
45488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*msg.status) {
4549b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "P2P Presence Request was rejected: status %u",
45508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*msg.status);
45518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
45528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
45538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
45548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4555b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "P2P Presence Request was accepted");
45568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "P2P: P2P Presence Response - NoA",
45578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    msg.noa, msg.noa_len);
45588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: process NoA */
45598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
45608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
45618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_ext_listen_timeout(void *eloop_ctx, void *timeout_ctx)
45648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
45658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
45668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval) {
45688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Schedule next extended listen timeout */
45698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(p2p->ext_listen_interval_sec,
45708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p->ext_listen_interval_usec,
45718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p_ext_listen_timeout, p2p, NULL);
45728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
45738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45746dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt	if ((p2p->cfg->is_p2p_in_progress &&
45756dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt	     p2p->cfg->is_p2p_in_progress(p2p->cfg->cb_ctx)) ||
45766dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt	    (p2p->pending_action_state == P2P_PENDING_PD &&
45776dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt	     p2p->pd_retries > 0)) {
45785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		p2p_dbg(p2p, "Operation in progress - skip Extended Listen timeout (%s)",
45795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			p2p_state_txt(p2p->state));
45805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
45815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
45825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
45838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_LISTEN_ONLY && p2p->ext_listen_only) {
45848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
45858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * This should not really happen, but it looks like the Listen
45868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * command may fail is something else (e.g., a scan) was
45878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * running at an inconvenient time. As a workaround, allow new
45888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Extended Listen operation to be started.
45898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
4590b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Previous Extended Listen operation had not been completed - try again");
45918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_only = 0;
45928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
45938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
45948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state != P2P_IDLE) {
4596b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Skip Extended Listen timeout in active state (%s)", p2p_state_txt(p2p->state));
45978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
45988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
45998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4600b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Extended Listen timeout");
46018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_only = 1;
46028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_listen(p2p, p2p->ext_listen_period) < 0) {
4603b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to start Listen state for Extended Listen Timing");
46048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_only = 0;
46058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
46068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
46078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_ext_listen(struct p2p_data *p2p, unsigned int period,
46108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   unsigned int interval)
46118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
46128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (period > 65535 || interval > 65535 || period > interval ||
46138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (period == 0 && interval > 0) || (period > 0 && interval == 0)) {
4614b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Invalid Extended Listen Timing request: period=%u interval=%u",
4615b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			period, interval);
46168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
46178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
46188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_ext_listen_timeout, p2p, NULL);
46208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (interval == 0) {
4622b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Disabling Extended Listen Timing");
46238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_period = 0;
46248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_interval = 0;
46258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
46268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
46278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4628b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Enabling Extended Listen Timing: period %u msec, interval %u msec",
4629b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		period, interval);
46308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_period = period;
46318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_interval = interval;
46328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_interval_sec = interval / 1000;
46338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_interval_usec = (interval % 1000) * 1000;
46348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(p2p->ext_listen_interval_sec,
46368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p->ext_listen_interval_usec,
46378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p_ext_listen_timeout, p2p, NULL);
46388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
46408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
46418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_deauth_notif(struct p2p_data *p2p, const u8 *bssid, u16 reason_code,
46448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      const u8 *ie, size_t ie_len)
46458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
46468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
46478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bssid == NULL || ie == NULL)
46498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
46508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
46528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg))
46538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
46549767226d8e6a1adaa33beb9f517ef40dddfa460cDmitry Shmidt	if (msg.minor_reason_code == NULL) {
46559767226d8e6a1adaa33beb9f517ef40dddfa460cDmitry Shmidt		p2p_parse_free(&msg);
46568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
46579767226d8e6a1adaa33beb9f517ef40dddfa460cDmitry Shmidt	}
46588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4659b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Deauthentication notification BSSID " MACSTR
46608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" reason_code=%u minor_reason_code=%u",
46618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(bssid), reason_code, *msg.minor_reason_code);
46628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
46648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
46658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_disassoc_notif(struct p2p_data *p2p, const u8 *bssid, u16 reason_code,
46688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const u8 *ie, size_t ie_len)
46698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
46708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
46718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bssid == NULL || ie == NULL)
46738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
46748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
46768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg))
46778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
46789767226d8e6a1adaa33beb9f517ef40dddfa460cDmitry Shmidt	if (msg.minor_reason_code == NULL) {
46799767226d8e6a1adaa33beb9f517ef40dddfa460cDmitry Shmidt		p2p_parse_free(&msg);
46808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
46819767226d8e6a1adaa33beb9f517ef40dddfa460cDmitry Shmidt	}
46828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4683b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Disassociation notification BSSID " MACSTR
46848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" reason_code=%u minor_reason_code=%u",
46858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(bssid), reason_code, *msg.minor_reason_code);
46868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
46888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
46898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_managed_oper(struct p2p_data *p2p, int enabled)
46928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
46938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (enabled) {
4694b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Managed P2P Device operations enabled");
46958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_INFRA_MANAGED;
46968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
4697b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Managed P2P Device operations disabled");
46988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab &= ~P2P_DEV_CAPAB_INFRA_MANAGED;
46998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
47008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
47018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4703661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidtint p2p_config_get_random_social(struct p2p_config *p2p, u8 *op_class,
4704661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt				 u8 *op_channel)
4705661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt{
4706661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	return p2p_channel_random_social(&p2p->channels, op_class, op_channel);
4707661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt}
4708661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt
4709661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt
471043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidtint p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel,
471143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt			   u8 forced)
47128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
47134b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	if (p2p_channel_to_freq(reg_class, channel) < 0)
47148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
47158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
471643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	/*
471743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	 * Listen channel was set in configuration or set by control interface;
471843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	 * cannot override it.
471943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	 */
4720216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	if (p2p->cfg->channel_forced && forced == 0) {
4721216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		p2p_dbg(p2p,
4722216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			"Listen channel was previously configured - do not override based on optimization");
472343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		return -1;
4724216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
4725216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
4726216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	p2p_dbg(p2p, "Set Listen channel: reg_class %u channel %u",
4727216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		reg_class, channel);
472843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt
472943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	if (p2p->state == P2P_IDLE) {
473043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		p2p->cfg->reg_class = reg_class;
473143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		p2p->cfg->channel = channel;
473243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		p2p->cfg->channel_forced = forced;
473343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	} else {
473443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		p2p_dbg(p2p, "Defer setting listen channel");
473543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		p2p->pending_reg_class = reg_class;
473643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		p2p->pending_channel = channel;
473743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		p2p->pending_channel_forced = forced;
473843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	}
47398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
47418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
47428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
474443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidtu8 p2p_get_listen_channel(struct p2p_data *p2p)
474543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt{
474643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	return p2p->cfg->channel;
474743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt}
474843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt
474943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt
47508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_ssid_postfix(struct p2p_data *p2p, const u8 *postfix, size_t len)
47518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4752b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "New SSID postfix: %s", wpa_ssid_txt(postfix, len));
47538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (postfix == NULL) {
47548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->ssid_postfix_len = 0;
47558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
47568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
47578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > sizeof(p2p->cfg->ssid_postfix))
47588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
47598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->ssid_postfix, postfix, len);
47608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->ssid_postfix_len = len;
47618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
47628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
47638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
476575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenint p2p_set_oper_channel(struct p2p_data *p2p, u8 op_reg_class, u8 op_channel,
476675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			 int cfg_op_channel)
476775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
47684b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	if (p2p_channel_to_freq(op_reg_class, op_channel) < 0)
476975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return -1;
477075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
4771b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Set Operating channel: reg_class %u channel %u",
4772b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		op_reg_class, op_channel);
477375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->cfg->op_reg_class = op_reg_class;
477475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->cfg->op_channel = op_channel;
477575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->cfg->cfg_op_channel = cfg_op_channel;
477675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	return 0;
477775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
477875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
477975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
478004949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint p2p_set_pref_chan(struct p2p_data *p2p, unsigned int num_pref_chan,
478104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		      const struct p2p_channel *pref_chan)
478204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
478304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct p2p_channel *n;
478404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
478504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (pref_chan) {
478604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		n = os_malloc(num_pref_chan * sizeof(struct p2p_channel));
478704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (n == NULL)
478804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			return -1;
478904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(n, pref_chan,
479004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			  num_pref_chan * sizeof(struct p2p_channel));
479104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	} else
479204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		n = NULL;
479304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
479404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	os_free(p2p->cfg->pref_chan);
479504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p->cfg->pref_chan = n;
479604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p->cfg->num_pref_chan = num_pref_chan;
479704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
479804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return 0;
479904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
480004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
480104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
480268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidtint p2p_set_no_go_freq(struct p2p_data *p2p,
480368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		       const struct wpa_freq_range_list *list)
480468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt{
480568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	struct wpa_freq_range *tmp;
480668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt
480768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	if (list == NULL || list->num == 0) {
480868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		os_free(p2p->no_go_freq.range);
480968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		p2p->no_go_freq.range = NULL;
481068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		p2p->no_go_freq.num = 0;
481168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		return 0;
481268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	}
481368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt
481468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	tmp = os_calloc(list->num, sizeof(struct wpa_freq_range));
481568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	if (tmp == NULL)
481668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		return -1;
481768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	os_memcpy(tmp, list->range, list->num * sizeof(struct wpa_freq_range));
481868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	os_free(p2p->no_go_freq.range);
481968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p->no_go_freq.range = tmp;
482068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p->no_go_freq.num = list->num;
482168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p_dbg(p2p, "Updated no GO chan list");
482268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt
482368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	return 0;
482468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt}
482568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt
482668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt
48278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_interface_addr(struct p2p_data *p2p, const u8 *dev_addr,
48288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   u8 *iface_addr)
48298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
48308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p_get_device(p2p, dev_addr);
48318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL || is_zero_ether_addr(dev->interface_addr))
48328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
48338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(iface_addr, dev->interface_addr, ETH_ALEN);
48348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
48358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
48368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_dev_addr(struct p2p_data *p2p, const u8 *iface_addr,
48398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   u8 *dev_addr)
48408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
48418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p_get_device_interface(p2p, iface_addr);
48428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
48438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
48448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev_addr, dev->info.p2p_device_addr, ETH_ALEN);
48458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
48468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
48478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_peer_filter(struct p2p_data *p2p, const u8 *addr)
48508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
48518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->peer_filter, addr, ETH_ALEN);
48528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (is_zero_ether_addr(p2p->peer_filter))
4853b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Disable peer filter");
48548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
4855b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Enable peer filter for " MACSTR,
4856b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			MAC2STR(p2p->peer_filter));
48578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
48588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_cross_connect(struct p2p_data *p2p, int enabled)
48618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4862b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Cross connection %s", enabled ? "enabled" : "disabled");
48638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cross_connect == enabled)
48648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
48658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cross_connect = enabled;
48668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: may need to tear down any action group where we are GO(?) */
48678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
48688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_oper_freq(struct p2p_data *p2p, const u8 *iface_addr)
48718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
48728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p_get_device_interface(p2p, iface_addr);
48738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
48748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
48758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->oper_freq <= 0)
48768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
48778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return dev->oper_freq;
48788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
48798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_intra_bss_dist(struct p2p_data *p2p, int enabled)
48828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4883b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Intra BSS distribution %s",
48848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		enabled ? "enabled" : "disabled");
48858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->p2p_intra_bss = enabled;
48868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
48878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
488968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidtvoid p2p_update_channel_list(struct p2p_data *p2p,
489068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt			     const struct p2p_channels *chan,
489168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt			     const struct p2p_channels *cli_chan)
48928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4893b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Update channel list");
48948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&p2p->cfg->channels, chan, sizeof(struct p2p_channels));
489568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p_channels_dump(p2p, "channels", &p2p->cfg->channels);
489668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	os_memcpy(&p2p->cfg->cli_channels, cli_chan,
489768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt		  sizeof(struct p2p_channels));
489868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	p2p_channels_dump(p2p, "cli_channels", &p2p->cfg->cli_channels);
48998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
49008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_send_action(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
49038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    const u8 *src, const u8 *bssid, const u8 *buf,
49048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    size_t len, unsigned int wait_time)
49058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
49068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
4907b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Delay Action frame TX until p2p_scan completes");
49088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->after_scan_tx) {
4909b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Dropped previous pending Action frame TX");
49108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(p2p->after_scan_tx);
49118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
49128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = os_malloc(sizeof(*p2p->after_scan_tx) +
49138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       len);
49148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->after_scan_tx == NULL)
49158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
49168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx->freq = freq;
49178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx->dst, dst, ETH_ALEN);
49188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx->src, src, ETH_ALEN);
49198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx->bssid, bssid, ETH_ALEN);
49208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx->len = len;
49218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx->wait_time = wait_time;
49228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx + 1, buf, len);
49238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
49248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
49258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, dst, src, bssid,
49278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     buf, len, wait_time);
49288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
49298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_best_channels(struct p2p_data *p2p, int freq_24, int freq_5,
49328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   int freq_overall)
49338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4934b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Best channel: 2.4 GHz: %d,  5 GHz: %d,  overall: %d",
4935b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		freq_24, freq_5, freq_overall);
49368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->best_freq_24 = freq_24;
49378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->best_freq_5 = freq_5;
49388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->best_freq_overall = freq_overall;
49398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
49408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4942700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidtvoid p2p_set_own_freq_preference(struct p2p_data *p2p, int freq)
4943700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt{
4944b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Own frequency preference: %d MHz", freq);
4945700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	p2p->own_freq_preference = freq;
4946700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt}
4947700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt
4948700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt
49498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * p2p_get_go_neg_peer(struct p2p_data *p2p)
49508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
49518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p == NULL || p2p->go_neg_peer == NULL)
49528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
49538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p->go_neg_peer->info.p2p_device_addr;
49548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
49558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst struct p2p_peer_info *
49588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtp2p_get_peer_found(struct p2p_data *p2p, const u8 *addr, int next)
49598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
49608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
49618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr) {
49638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, addr);
49648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!dev)
49658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
49668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!next) {
49688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev->flags & P2P_DEV_PROBE_REQ_ONLY)
49698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return NULL;
49708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return &dev->info;
49728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
49738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			do {
49748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev = dl_list_first(&dev->list,
49758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    struct p2p_device,
49768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    list);
49777832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt				if (!dev || &dev->list == &p2p->devices)
49788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					return NULL;
49798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} while (dev->flags & P2P_DEV_PROBE_REQ_ONLY);
49808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
49818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
49828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = dl_list_first(&p2p->devices, struct p2p_device, list);
49838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!dev)
49848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
49858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (dev->flags & P2P_DEV_PROBE_REQ_ONLY) {
49868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev = dl_list_first(&dev->list,
49878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    struct p2p_device,
49888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    list);
49897832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt			if (!dev || &dev->list == &p2p->devices)
49908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return NULL;
49918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
49928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
49938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return &dev->info;
49958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
49961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
49971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
49981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_in_progress(struct p2p_data *p2p)
49991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
50001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p == NULL)
50011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
5002fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (p2p->state == P2P_SEARCH)
500361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return 2;
50041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return p2p->state != P2P_IDLE && p2p->state != P2P_PROVISIONING;
50051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
500661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
500761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
500861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid p2p_set_config_timeout(struct p2p_data *p2p, u8 go_timeout,
500961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			    u8 client_timeout)
501061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
501161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p) {
501261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->go_timeout = go_timeout;
501361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->client_timeout = client_timeout;
501461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
501561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
501661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
501761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
501861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
501961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
502061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void p2p_update_wfd_ie_groups(struct p2p_data *p2p)
502161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
502261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t g;
502361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct p2p_group *group;
502461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
502561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	for (g = 0; g < p2p->num_groups; g++) {
502661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		group = p2p->groups[g];
5027b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt		p2p_group_force_beacon_update_ies(group);
502861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
502961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
503061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
503161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
503261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_beacon(struct p2p_data *p2p, struct wpabuf *ie)
503361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
503461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_beacon);
503561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_beacon = ie;
503661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_update_wfd_ie_groups(p2p);
503761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
503861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
503961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
504061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
504161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_probe_req(struct p2p_data *p2p, struct wpabuf *ie)
504261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
504361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_probe_req);
504461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_probe_req = ie;
504561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
504661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
504761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
504861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
504961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_probe_resp(struct p2p_data *p2p, struct wpabuf *ie)
505061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
505161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_probe_resp);
505261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_probe_resp = ie;
505361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_update_wfd_ie_groups(p2p);
505461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
505561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
505661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
505761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
505861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_assoc_req(struct p2p_data *p2p, struct wpabuf *ie)
505961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
506061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_assoc_req);
506161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_assoc_req = ie;
506261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
506361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
506461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
506561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
506661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_invitation(struct p2p_data *p2p, struct wpabuf *ie)
506761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
506861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_invitation);
506961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_invitation = ie;
507061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
507161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
507261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
507361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
507461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_prov_disc_req(struct p2p_data *p2p, struct wpabuf *ie)
507561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
507661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_prov_disc_req);
507761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_prov_disc_req = ie;
507861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
507961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
508061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
508161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
508261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_prov_disc_resp(struct p2p_data *p2p, struct wpabuf *ie)
508361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
508461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_prov_disc_resp);
508561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_prov_disc_resp = ie;
508661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
508761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
508861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
508961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
509061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_ie_go_neg(struct p2p_data *p2p, struct wpabuf *ie)
509161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
509261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_ie_go_neg);
509361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p->wfd_ie_go_neg = ie;
509461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
509561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
509661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
509761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
509861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_dev_info(struct p2p_data *p2p, const struct wpabuf *elem)
509961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
510061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_dev_info);
510161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (elem) {
510261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_dev_info = wpabuf_dup(elem);
510361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->wfd_dev_info == NULL)
510461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
510561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else
510661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_dev_info = NULL;
510761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
510861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
510961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
511061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
511161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
511261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_assoc_bssid(struct p2p_data *p2p, const struct wpabuf *elem)
511361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
511461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_assoc_bssid);
511561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (elem) {
511661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_assoc_bssid = wpabuf_dup(elem);
511761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->wfd_assoc_bssid == NULL)
511861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
511961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else
512061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_assoc_bssid = NULL;
512161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
512261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
512361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
512461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
512561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
512661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint p2p_set_wfd_coupled_sink_info(struct p2p_data *p2p,
512761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				  const struct wpabuf *elem)
512861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
512961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(p2p->wfd_coupled_sink_info);
513061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (elem) {
513161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_coupled_sink_info = wpabuf_dup(elem);
513261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (p2p->wfd_coupled_sink_info == NULL)
513361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
513461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else
513561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p->wfd_coupled_sink_info = NULL;
513661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
513761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
513861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
513961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
514061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
5141d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
5142d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
5143d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtint p2p_set_disc_int(struct p2p_data *p2p, int min_disc_int, int max_disc_int,
5144d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		     int max_disc_tu)
5145d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt{
5146d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (min_disc_int > max_disc_int || min_disc_int < 0 || max_disc_int < 0)
5147d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return -1;
5148d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
5149d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p->min_disc_int = min_disc_int;
5150d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p->max_disc_int = max_disc_int;
5151d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p->max_disc_tu = max_disc_tu;
5152b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Set discoverable interval: min=%d max=%d max_tu=%d",
5153b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		min_disc_int, max_disc_int, max_disc_tu);
5154d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
5155d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	return 0;
5156d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt}
5157b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
5158b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
5159b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidtvoid p2p_dbg(struct p2p_data *p2p, const char *fmt, ...)
5160b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt{
5161b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_list ap;
5162b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	char buf[500];
5163b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
5164b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	if (!p2p->cfg->debug_print)
5165b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		return;
5166b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
5167b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_start(ap, fmt);
5168b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	vsnprintf(buf, sizeof(buf), fmt, ap);
5169b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	buf[sizeof(buf) - 1] = '\0';
5170b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_end(ap);
5171b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p->cfg->debug_print(p2p->cfg->cb_ctx, MSG_DEBUG, buf);
5172b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt}
5173b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
5174b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
5175b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidtvoid p2p_info(struct p2p_data *p2p, const char *fmt, ...)
5176b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt{
5177b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_list ap;
5178b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	char buf[500];
5179b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
5180b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	if (!p2p->cfg->debug_print)
5181b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		return;
5182b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
5183b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_start(ap, fmt);
5184b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	vsnprintf(buf, sizeof(buf), fmt, ap);
5185b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	buf[sizeof(buf) - 1] = '\0';
5186b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_end(ap);
5187b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p->cfg->debug_print(p2p->cfg->cb_ctx, MSG_INFO, buf);
5188b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt}
5189b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
5190b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
5191b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidtvoid p2p_err(struct p2p_data *p2p, const char *fmt, ...)
5192b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt{
5193b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_list ap;
5194b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	char buf[500];
5195b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
5196b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	if (!p2p->cfg->debug_print)
5197b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		return;
5198b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
5199b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_start(ap, fmt);
5200b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	vsnprintf(buf, sizeof(buf), fmt, ap);
5201b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	buf[sizeof(buf) - 1] = '\0';
5202b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	va_end(ap);
5203b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p->cfg->debug_print(p2p->cfg->cb_ctx, MSG_ERROR, buf);
5204b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt}
5205cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5206cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5207d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidtvoid p2p_loop_on_known_peers(struct p2p_data *p2p,
5208d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt			     void (*peer_callback)(struct p2p_peer_info *peer,
5209d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt						   void *user_data),
5210d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt			     void *user_data)
5211d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt{
5212d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt	struct p2p_device *dev, *n;
5213d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt
5214d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt	dl_list_for_each_safe(dev, n, &p2p->devices, struct p2p_device, list) {
5215d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt		peer_callback(&dev->info, user_data);
5216d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt	}
5217d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt}
5218d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt
5219d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt
5220cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_WPS_NFC
5221cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5222cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtstatic struct wpabuf * p2p_build_nfc_handover(struct p2p_data *p2p,
5223cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					      int client_freq,
5224cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					      const u8 *go_dev_addr,
5225cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					      const u8 *ssid, size_t ssid_len)
5226cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{
5227cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	struct wpabuf *buf;
5228cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	u8 op_class, channel;
5229cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	enum p2p_role_indication role = P2P_DEVICE_NOT_IN_GROUP;
5230cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5231cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	buf = wpabuf_alloc(1000);
5232cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (buf == NULL)
5233cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		return NULL;
5234cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5235cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	op_class = p2p->cfg->reg_class;
5236cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	channel = p2p->cfg->channel;
5237cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5238cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	p2p_buf_add_capability(buf, p2p->dev_capab &
5239cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			       ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 0);
5240cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	p2p_buf_add_device_info(buf, p2p, NULL);
5241cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5242cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (p2p->num_groups > 0) {
52437832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt		int freq = p2p_group_get_freq(p2p->groups[0]);
5244cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		role = P2P_GO_IN_A_GROUP;
52457832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt		if (p2p_freq_to_channel(freq, &op_class, &channel) < 0) {
52467832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt			p2p_dbg(p2p,
52477832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt				"Unknown GO operating frequency %d MHz for NFC handover",
52487832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt				freq);
52497832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt			wpabuf_free(buf);
52507832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt			return NULL;
52517832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt		}
5252cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	} else if (client_freq > 0) {
5253cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		role = P2P_CLIENT_IN_A_GROUP;
52547832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt		if (p2p_freq_to_channel(client_freq, &op_class, &channel) < 0) {
52557832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt			p2p_dbg(p2p,
52567832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt				"Unknown client operating frequency %d MHz for NFC handover",
52577832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt				client_freq);
52587832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt			wpabuf_free(buf);
52597832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt			return NULL;
52607832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt		}
5261cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5262cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5263cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	p2p_buf_add_oob_go_neg_channel(buf, p2p->cfg->country, op_class,
5264cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				       channel, role);
5265cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5266cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (p2p->num_groups > 0) {
5267cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		/* Limit number of clients to avoid very long message */
5268cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_buf_add_group_info(p2p->groups[0], buf, 5);
5269cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_group_buf_add_id(p2p->groups[0], buf);
5270cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	} else if (client_freq > 0 &&
5271cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		   go_dev_addr && !is_zero_ether_addr(go_dev_addr) &&
5272cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		   ssid && ssid_len > 0) {
5273cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		/*
5274cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		 * Add the optional P2P Group ID to indicate in which group this
5275cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		 * device is a P2P Client.
5276cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		 */
5277cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_buf_add_group_id(buf, go_dev_addr, ssid, ssid_len);
5278cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5279cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5280cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	return buf;
5281cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt}
5282cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5283cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5284cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtstruct wpabuf * p2p_build_nfc_handover_req(struct p2p_data *p2p,
5285cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					   int client_freq,
5286cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					   const u8 *go_dev_addr,
5287cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					   const u8 *ssid, size_t ssid_len)
5288cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{
5289cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	return p2p_build_nfc_handover(p2p, client_freq, go_dev_addr, ssid,
5290cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				      ssid_len);
5291cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt}
5292cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5293cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5294cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtstruct wpabuf * p2p_build_nfc_handover_sel(struct p2p_data *p2p,
5295cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					   int client_freq,
5296cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					   const u8 *go_dev_addr,
5297cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					   const u8 *ssid, size_t ssid_len)
5298cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{
5299cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	return p2p_build_nfc_handover(p2p, client_freq, go_dev_addr, ssid,
5300cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				      ssid_len);
5301cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt}
5302cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5303cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5304cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtint p2p_process_nfc_connection_handover(struct p2p_data *p2p,
5305cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					struct p2p_nfc_params *params)
5306cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{
5307cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	struct p2p_message msg;
5308cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	struct p2p_device *dev;
5309cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	const u8 *p2p_dev_addr;
5310cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	int freq;
5311cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	enum p2p_role_indication role;
5312cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5313cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	params->next_step = NO_ACTION;
5314cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5315cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (p2p_parse_ies_separate(params->wsc_attr, params->wsc_len,
5316cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				   params->p2p_attr, params->p2p_len, &msg)) {
5317cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dbg(p2p, "Failed to parse WSC/P2P attributes from NFC");
5318cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_parse_free(&msg);
5319cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		return -1;
5320cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5321cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5322cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (msg.p2p_device_addr)
5323cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dev_addr = msg.p2p_device_addr;
5324cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	else if (msg.device_id)
5325cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dev_addr = msg.device_id;
5326cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	else {
5327cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dbg(p2p, "Ignore scan data without P2P Device Info or P2P Device Id");
5328cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_parse_free(&msg);
5329cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		return -1;
5330cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5331cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5332cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (msg.oob_dev_password) {
5333cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		os_memcpy(params->oob_dev_pw, msg.oob_dev_password,
5334cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			  msg.oob_dev_password_len);
5335cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		params->oob_dev_pw_len = msg.oob_dev_password_len;
5336cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5337cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5338cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	dev = p2p_create_device(p2p, p2p_dev_addr);
5339cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (dev == NULL) {
5340cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_parse_free(&msg);
5341cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		return -1;
5342cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5343cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5344cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	params->peer = &dev->info;
5345cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5346cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	os_get_reltime(&dev->last_seen);
5347cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	dev->flags &= ~(P2P_DEV_PROBE_REQ_ONLY | P2P_DEV_GROUP_CLIENT_ONLY);
5348cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	p2p_copy_wps_info(p2p, dev, 0, &msg);
5349cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5350cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (!msg.oob_go_neg_channel) {
5351cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dbg(p2p, "OOB GO Negotiation Channel attribute not included");
5352a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		p2p_parse_free(&msg);
5353cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		return -1;
5354cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5355cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5356cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (msg.oob_go_neg_channel[3] == 0 &&
5357cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	    msg.oob_go_neg_channel[4] == 0)
5358cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		freq = 0;
5359cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	else
5360cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		freq = p2p_channel_to_freq(msg.oob_go_neg_channel[3],
5361cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					   msg.oob_go_neg_channel[4]);
5362cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (freq < 0) {
5363cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dbg(p2p, "Unknown peer OOB GO Neg channel");
5364a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		p2p_parse_free(&msg);
5365cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		return -1;
5366cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5367cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	role = msg.oob_go_neg_channel[5];
5368cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5369cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (role == P2P_GO_IN_A_GROUP) {
5370cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dbg(p2p, "Peer OOB GO operating channel: %u MHz", freq);
5371cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		params->go_freq = freq;
5372cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	} else if (role == P2P_CLIENT_IN_A_GROUP) {
5373cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dbg(p2p, "Peer (client) OOB GO operating channel: %u MHz",
5374cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			freq);
5375cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		params->go_freq = freq;
5376cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	} else
5377cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dbg(p2p, "Peer OOB GO Neg channel: %u MHz", freq);
5378cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	dev->oob_go_neg_freq = freq;
5379cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5380cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (!params->sel && role != P2P_GO_IN_A_GROUP) {
5381cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		freq = p2p_channel_to_freq(p2p->cfg->reg_class,
5382cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					   p2p->cfg->channel);
5383cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		if (freq < 0) {
5384cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			p2p_dbg(p2p, "Own listen channel not known");
5385a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			p2p_parse_free(&msg);
5386cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			return -1;
5387cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		}
5388cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dbg(p2p, "Use own Listen channel as OOB GO Neg channel: %u MHz", freq);
5389cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		dev->oob_go_neg_freq = freq;
5390cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5391cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5392cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (msg.group_id) {
5393cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		os_memcpy(params->go_dev_addr, msg.group_id, ETH_ALEN);
5394cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		params->go_ssid_len = msg.group_id_len - ETH_ALEN;
5395cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		os_memcpy(params->go_ssid, msg.group_id + ETH_ALEN,
5396cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			  params->go_ssid_len);
5397cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5398cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5399cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (dev->flags & P2P_DEV_USER_REJECTED) {
5400cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dbg(p2p, "Do not report rejected device");
5401717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt		p2p_parse_free(&msg);
5402cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		return 0;
5403cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5404cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5405cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (!(dev->flags & P2P_DEV_REPORTED)) {
5406cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p->cfg->dev_found(p2p->cfg->cb_ctx, p2p_dev_addr, &dev->info,
5407cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				    !(dev->flags & P2P_DEV_REPORTED_ONCE));
5408cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
5409cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5410717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt	p2p_parse_free(&msg);
5411cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5412cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (role == P2P_GO_IN_A_GROUP && p2p->num_groups > 0)
5413cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		params->next_step = BOTH_GO;
5414cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	else if (role == P2P_GO_IN_A_GROUP)
5415cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		params->next_step = JOIN_GROUP;
5416cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	else if (role == P2P_CLIENT_IN_A_GROUP) {
5417cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		dev->flags |= P2P_DEV_GROUP_CLIENT_ONLY;
5418cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		params->next_step = PEER_CLIENT;
5419cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	} else if (p2p->num_groups > 0)
5420cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		params->next_step = AUTH_JOIN;
5421cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	else if (params->sel)
5422cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		params->next_step = INIT_GO_NEG;
5423cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	else
5424cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		params->next_step = RESP_GO_NEG;
5425cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5426cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	return 0;
5427cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt}
5428cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5429cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5430cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtvoid p2p_set_authorized_oob_dev_pw_id(struct p2p_data *p2p, u16 dev_pw_id,
5431cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				      int go_intent,
5432cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				      const u8 *own_interface_addr)
5433cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{
5434cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5435cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	p2p->authorized_oob_dev_pw_id = dev_pw_id;
5436cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (dev_pw_id == 0) {
5437cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_dbg(p2p, "NFC OOB Password unauthorized for static handover");
5438cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		return;
5439cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
5440cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5441cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	p2p_dbg(p2p, "NFC OOB Password (id=%u) authorized for static handover",
5442cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		dev_pw_id);
5443cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5444cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	p2p->go_intent = go_intent;
5445cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
5446cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt}
5447cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5448cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_WPS_NFC */
54492271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt
54502271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt
54512271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidtint p2p_set_passphrase_len(struct p2p_data *p2p, unsigned int len)
54522271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt{
54532271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	if (len < 8 || len > 63)
54542271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		return -1;
54552271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	p2p->cfg->passphrase_len = len;
54562271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	return 0;
54572271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt}
54582e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
54592e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
54602e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidtvoid p2p_set_vendor_elems(struct p2p_data *p2p, struct wpabuf **vendor_elem)
54612e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt{
54622e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	p2p->vendor_elem = vendor_elem;
54632e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt}
54646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
54656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
54666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtvoid p2p_go_neg_wait_timeout(void *eloop_ctx, void *timeout_ctx)
54676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
54686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
54696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
54706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	p2p_dbg(p2p,
54716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		"Timeout on waiting peer to become ready for GO Negotiation");
54726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	p2p_go_neg_failed(p2p, -1);
54736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
5474d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
5475d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
5476d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtvoid p2p_set_own_pref_freq_list(struct p2p_data *p2p,
5477d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				const unsigned int *pref_freq_list,
5478d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				unsigned int size)
5479d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
5480d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	unsigned int i;
5481d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
5482d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (size > P2P_MAX_PREF_CHANNELS)
5483d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		size = P2P_MAX_PREF_CHANNELS;
5484d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	p2p->num_pref_freq = size;
5485d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	for (i = 0; i < size; i++) {
5486d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		p2p->pref_freq_list[i] = pref_freq_list[i];
5487d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		p2p_dbg(p2p, "Own preferred frequency list[%u]=%u MHz",
5488d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			i, p2p->pref_freq_list[i]);
5489d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
5490d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
5491