p2p.c revision 1f69aa52ea2e0a73ac502565df8c666ee49cab6a
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Wi-Fi Direct - P2P module
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2009-2010, Atheros Communications
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This program is free software; you can redistribute it and/or modify
68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * published by the Free Software Foundation.
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * license.
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See README and COPYING for more details.
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h"
201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef ANDROID_P2P
211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "common/wpa_ctrl.h"
221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_common.h"
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps/wps_i.h"
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p_i.h"
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p.h"
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_state_timeout(void *eloop_ctx, void *timeout_ctx);
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev);
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_req(struct p2p_data *p2p, const u8 *da,
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const u8 *sa, const u8 *data, size_t len,
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     int rx_freq);
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_resp(struct p2p_data *p2p, const u8 *da,
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *sa, const u8 *data,
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      size_t len);
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_ext_listen_timeout(void *eloop_ctx, void *timeout_ctx);
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_scan_timeout(void *eloop_ctx, void *timeout_ctx);
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_scan recovery timeout
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Many drivers are using 30 second timeout on scan results. Allow a bit larger
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * timeout for this to avoid hitting P2P timeout unnecessarily.
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define P2P_SCAN_TIMEOUT 35
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * P2P_PEER_EXPIRATION_AGE - Number of seconds after which inactive peer
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * entries will be removed
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define P2P_PEER_EXPIRATION_AGE 300
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define P2P_PEER_EXPIRATION_INTERVAL (P2P_PEER_EXPIRATION_AGE / 2)
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_expire_peers(struct p2p_data *p2p)
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev, *n;
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct os_time now;
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&now);
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each_safe(dev, n, &p2p->devices, struct p2p_device, list) {
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->last_seen.sec + P2P_PEER_EXPIRATION_AGE >= now.sec)
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Expiring old peer "
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"entry " MACSTR, MAC2STR(dev->info.p2p_device_addr));
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dl_list_del(&dev->list);
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_device_free(p2p, dev);
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_expiration_timeout(void *eloop_ctx, void *timeout_ctx)
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_expire_peers(p2p);
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(P2P_PEER_EXPIRATION_INTERVAL, 0,
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p_expiration_timeout, p2p, NULL);
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * p2p_state_txt(int state)
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (state) {
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_IDLE:
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "IDLE";
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SEARCH:
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "SEARCH";
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT:
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "CONNECT";
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT_LISTEN:
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "CONNECT_LISTEN";
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG:
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "GO_NEG";
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_LISTEN_ONLY:
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "LISTEN_ONLY";
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_CONNECT:
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "WAIT_PEER_CONNECT";
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_IDLE:
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "WAIT_PEER_IDLE";
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SD_DURING_FIND:
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "SD_DURING_FIND";
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROVISIONING:
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "PROVISIONING";
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PD_DURING_FIND:
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "PD_DURING_FIND";
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE:
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "INVITE";
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE_LISTEN:
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "INVITE_LISTEN";
1121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case P2P_SEARCH_WHEN_READY:
1131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return "SEARCH_WHEN_READY";
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "?";
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtu16 p2p_get_provisioning_info(struct p2p_data *p2p, const u8 *addr)
1211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
1221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_device *dev = NULL;
1231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (!addr || !p2p)
1251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
1261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	dev = p2p_get_device(p2p, addr);
1281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (dev)
1291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return dev->wps_prov_info;
1301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	else
1311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
1321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
1331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid p2p_clear_provisioning_info(struct p2p_data *p2p, const u8 *iface_addr)
1361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
1371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_device *dev = NULL;
1381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (!iface_addr || !p2p)
1401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
1411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	dev = p2p_get_device_interface(p2p, iface_addr);
1431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (dev)
1441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->wps_prov_info = 0;
1451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
1461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_state(struct p2p_data *p2p, int new_state)
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: State %s -> %s",
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state), p2p_state_txt(new_state));
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->state = new_state;
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_timeout(struct p2p_data *p2p, unsigned int sec, unsigned int usec)
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Set timeout (state=%s): %u.%06u sec",
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state), sec, usec);
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_state_timeout, p2p, NULL);
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(sec, usec, p2p_state_timeout, p2p, NULL);
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_clear_timeout(struct p2p_data *p2p)
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Clear timeout (state=%s)",
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state));
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_state_timeout, p2p, NULL);
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_go_neg_failed(struct p2p_data *p2p, struct p2p_device *peer,
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       int status)
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_go_neg_results res;
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_IDLE);
1801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p->go_neg_peer)
1811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p->go_neg_peer->wps_method = WPS_NOT_READY;
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer = NULL;
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&res, 0, sizeof(res));
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.status = status;
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (peer) {
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(res.peer_device_addr, peer->info.p2p_device_addr,
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(res.peer_interface_addr, peer->intended_addr,
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->go_neg_completed(p2p->cfg->cb_ctx, &res);
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_listen_in_find(struct p2p_data *p2p)
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int r, tu;
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *ies;
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Starting short listen state (state=%s)",
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state));
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	freq = p2p_channel_to_freq(p2p->cfg->country, p2p->cfg->reg_class,
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   p2p->cfg->channel);
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq < 0) {
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Unknown regulatory class/channel");
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_random((u8 *) &r, sizeof(r));
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tu = (r % ((p2p->max_disc_int - p2p->min_disc_int) + 1) +
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	      p2p->min_disc_int) * 100;
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_freq = freq;
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_sec = 0;
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_usec = 1024 * tu;
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ies = p2p_build_probe_resp_ies(p2p);
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ies == NULL)
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->start_listen(p2p->cfg->cb_ctx, freq, 1024 * tu / 1000,
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    ies) < 0) {
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to start listen mode");
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_freq = 0;
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(ies);
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_listen(struct p2p_data *p2p, unsigned int timeout)
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *ies;
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Going to listen(only) state");
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	freq = p2p_channel_to_freq(p2p->cfg->country, p2p->cfg->reg_class,
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   p2p->cfg->channel);
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq < 0) {
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Unknown regulatory class/channel");
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_freq = freq;
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_sec = timeout / 1000;
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_usec = (timeout % 1000) * 1000;
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
2571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (p2p->start_after_scan == P2P_AFTER_SCAN_NOTHING) {
2581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				"P2P: p2p_scan running - connect is already "
2601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				"pending - skip listen");
2611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return 0;
2621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: p2p_scan running - delay start of listen state");
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->start_after_scan = P2P_AFTER_SCAN_LISTEN;
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ies = p2p_build_probe_resp_ies(p2p);
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ies == NULL)
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->start_listen(p2p->cfg->cb_ctx, freq, timeout, ies) < 0) {
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to start listen mode");
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_freq = 0;
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(ies);
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(ies);
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_LISTEN_ONLY);
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_device_clear_reported(struct p2p_data *p2p)
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list)
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~P2P_DEV_REPORTED;
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_get_device - Fetch a peer entry
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: P2P Device Address of the peer
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the device entry or %NULL if not found
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_device * p2p_get_device(struct p2p_data *p2p, const u8 *addr)
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(dev->info.p2p_device_addr, addr, ETH_ALEN) == 0)
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return dev;
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_get_device_interface - Fetch a peer entry based on P2P Interface Address
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: P2P Interface Address of the peer
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the device entry or %NULL if not found
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_device * p2p_get_device_interface(struct p2p_data *p2p,
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     const u8 *addr)
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(dev->interface_addr, addr, ETH_ALEN) == 0)
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return dev;
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_create_device - Create a peer entry
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: P2P Device Address of the peer
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the device entry or %NULL on failure
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * If there is already an entry for the peer, it will be returned instead of
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * creating a new one.
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct p2p_device * p2p_create_device(struct p2p_data *p2p,
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     const u8 *addr)
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev, *oldest = NULL;
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t count = 0;
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev)
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return dev;
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		count++;
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (oldest == NULL ||
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_time_before(&dev->last_seen, &oldest->last_seen))
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			oldest = dev;
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (count + 1 > p2p->cfg->max_peers && oldest) {
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Remove oldest peer entry to make room for a new "
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"peer");
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dl_list_del(&oldest->list);
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_device_free(p2p, oldest);
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = os_zalloc(sizeof(*dev));
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_add(&p2p->devices, &dev->list);
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.p2p_device_addr, addr, ETH_ALEN);
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return dev;
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_copy_client_info(struct p2p_device *dev,
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 struct p2p_client_info *cli)
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.device_name, cli->dev_name, cli->dev_name_len);
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.device_name[cli->dev_name_len] = '\0';
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.dev_capab = cli->dev_capab;
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.config_methods = cli->config_methods;
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.pri_dev_type, cli->pri_dev_type, 8);
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.wps_sec_dev_type_list_len = 8 * cli->num_sec_dev_types;
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.wps_sec_dev_type_list, cli->sec_dev_types,
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  dev->info.wps_sec_dev_type_list_len);
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_add_group_clients(struct p2p_data *p2p, const u8 *go_dev_addr,
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const u8 *go_interface_addr, int freq,
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const u8 *gi, size_t gi_len)
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_info info;
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t c;
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gi == NULL)
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_group_info_parse(gi, gi_len, &info) < 0)
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Clear old data for this group; if the devices are still in the
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * group, the information will be restored in the loop following this.
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
4071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (os_memcmp(dev->member_in_go_iface, go_interface_addr,
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      ETH_ALEN) == 0) {
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(dev->member_in_go_iface, 0, ETH_ALEN);
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(dev->member_in_go_dev, 0, ETH_ALEN);
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (c = 0; c < info.num_clients; c++) {
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct p2p_client_info *cli = &info.client[c];
4161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (os_memcmp(cli->p2p_device_addr, p2p->cfg->dev_addr,
4171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      ETH_ALEN) == 0)
4181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			continue; /* ignore our own entry */
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, cli->p2p_device_addr);
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev) {
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * Update information only if we have not received this
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * directly from the client.
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev->flags & (P2P_DEV_GROUP_CLIENT_ONLY |
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  P2P_DEV_PROBE_REQ_ONLY))
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p_copy_client_info(dev, cli);
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev->flags & P2P_DEV_PROBE_REQ_ONLY) {
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev->flags &= ~P2P_DEV_PROBE_REQ_ONLY;
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev = p2p_create_device(p2p, cli->p2p_device_addr);
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev == NULL)
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				continue;
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->flags |= P2P_DEV_GROUP_CLIENT_ONLY;
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_copy_client_info(dev, cli);
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->oper_freq = freq;
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->cfg->dev_found(p2p->cfg->cb_ctx,
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    dev->info.p2p_device_addr,
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    &dev->info, 1);
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->interface_addr, cli->p2p_interface_addr,
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_get_time(&dev->last_seen);
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->member_in_go_dev, go_dev_addr, ETH_ALEN);
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->member_in_go_iface, go_interface_addr,
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_copy_wps_info(struct p2p_device *dev, int probe_req,
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      const struct p2p_message *msg)
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.device_name, msg->device_name,
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  sizeof(dev->info.device_name));
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->manufacturer &&
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->manufacturer_len < sizeof(dev->info.manufacturer)) {
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.manufacturer, 0,
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.manufacturer));
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.manufacturer, msg->manufacturer,
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->manufacturer_len);
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->model_name &&
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->model_name_len < sizeof(dev->info.model_name)) {
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.model_name, 0,
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.model_name));
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.model_name, msg->model_name,
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->model_name_len);
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->model_number &&
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->model_number_len < sizeof(dev->info.model_number)) {
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.model_number, 0,
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.model_number));
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.model_number, msg->model_number,
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->model_number_len);
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->serial_number &&
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->serial_number_len < sizeof(dev->info.serial_number)) {
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.serial_number, 0,
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.serial_number));
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.serial_number, msg->serial_number,
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->serial_number_len);
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->pri_dev_type)
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.pri_dev_type, msg->pri_dev_type,
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.pri_dev_type));
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (msg->wps_pri_dev_type)
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.pri_dev_type, msg->wps_pri_dev_type,
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.pri_dev_type));
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->wps_sec_dev_type_list) {
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.wps_sec_dev_type_list,
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->wps_sec_dev_type_list,
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->wps_sec_dev_type_list_len);
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_sec_dev_type_list_len =
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg->wps_sec_dev_type_list_len;
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->capability) {
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.dev_capab = msg->capability[0];
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.group_capab = msg->capability[1];
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->ext_listen_timing) {
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->ext_listen_period = WPA_GET_LE16(msg->ext_listen_timing);
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->ext_listen_interval =
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			WPA_GET_LE16(msg->ext_listen_timing + 2);
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!probe_req) {
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.config_methods = msg->config_methods ?
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg->config_methods : msg->wps_config_methods;
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_add_device - Add peer entries based on scan results
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: Source address of Beacon or Probe Response frame (may be either
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *	P2P Device Address or P2P Interface Address)
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @level: Signal level (signal strength of the received frame from the peer)
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @freq: Frequency on which the Beacon or Probe Response frame was received
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ies: IEs from the Beacon or Probe Response frame
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ies_len: Length of ies buffer in octets
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * If the scan result is for a GO, the clients in the group will also be added
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to the peer table. This function can also be used with some other frames
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * like Provision Discovery Request that contains P2P Capability and P2P Device
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Info attributes.
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq, int level,
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *ies, size_t ies_len)
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *p2p_dev_addr;
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ies, ies_len, &msg)) {
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to parse P2P IE for a device entry");
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.p2p_device_addr)
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_addr = msg.p2p_device_addr;
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (msg.device_id)
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_addr = msg.device_id;
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Ignore scan data without P2P Device Info or "
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P Device Id");
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!is_zero_ether_addr(p2p->peer_filter) &&
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(p2p_dev_addr, p2p->peer_filter, ETH_ALEN) != 0) {
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Do not add peer "
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"filter for " MACSTR " due to peer filter",
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(p2p_dev_addr));
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_create_device(p2p, p2p_dev_addr);
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&dev->last_seen);
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~(P2P_DEV_PROBE_REQ_ONLY | P2P_DEV_GROUP_CLIENT_ONLY);
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(addr, p2p_dev_addr, ETH_ALEN) != 0)
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->interface_addr, addr, ETH_ALEN);
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.ssid &&
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (msg.ssid[1] != P2P_WILDCARD_SSID_LEN ||
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     os_memcmp(msg.ssid + 2, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN)
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     != 0)) {
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->oper_ssid, msg.ssid + 2, msg.ssid[1]);
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->oper_ssid_len = msg.ssid[1];
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq >= 2412 && freq <= 2484 && msg.ds_params &&
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    *msg.ds_params >= 1 && *msg.ds_params <= 14) {
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int ds_freq;
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*msg.ds_params == 14)
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ds_freq = 2484;
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ds_freq = 2407 + *msg.ds_params * 5;
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freq != ds_freq) {
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Update Listen frequency based on DS "
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Parameter Set IE: %d -> %d MHz",
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				freq, ds_freq);
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq = ds_freq;
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->listen_freq && dev->listen_freq != freq) {
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Update Listen frequency based on scan "
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"results (" MACSTR " %d -> %d MHz (DS param %d)",
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr), dev->listen_freq,
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq, msg.ds_params ? *msg.ds_params : -1);
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->listen_freq = freq;
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.group_info)
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->oper_freq = freq;
62375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	dev->info.level = level;
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_copy_wps_info(dev, 0, &msg);
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(dev->info.wps_vendor_ext[i]);
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_vendor_ext[i] = NULL;
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (msg.wps_vendor_ext[i] == NULL)
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_vendor_ext[i] = wpabuf_alloc_copy(
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg.wps_vendor_ext[i], msg.wps_vendor_ext_len[i]);
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->info.wps_vendor_ext[i] == NULL)
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_add_group_clients(p2p, p2p_dev_addr, addr, freq, msg.group_info,
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      msg.group_info_len);
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_pending_sd_req(p2p, dev))
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags |= P2P_DEV_SD_SCHEDULE;
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_REPORTED)
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Peer found with Listen frequency %d MHz", freq);
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_USER_REJECTED) {
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Do not report rejected device");
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->dev_found(p2p->cfg->cb_ctx, addr, &dev->info,
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    !(dev->flags & P2P_DEV_REPORTED_ONCE));
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev)
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
672497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt	if (p2p->go_neg_peer == dev) {
6731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/*
6741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * If GO Negotiation is in progress, report that it has failed.
6751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
676497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt		p2p_go_neg_failed(p2p, dev, -1);
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->go_neg_peer = NULL;
678497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt	}
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->invite_peer == dev)
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->invite_peer = NULL;
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->sd_peer == dev)
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->sd_peer = NULL;
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->pending_client_disc_go == dev)
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_client_disc_go = NULL;
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
686c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	/* dev_lost() device, but only if it was previously dev_found() */
687c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	if (dev->flags & P2P_DEV_REPORTED_ONCE)
688c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		p2p->cfg->dev_lost(p2p->cfg->cb_ctx,
689c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt				   dev->info.p2p_device_addr);
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(dev->info.wps_vendor_ext[i]);
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_vendor_ext[i] = NULL;
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(dev);
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_get_next_prog_freq(struct p2p_data *p2p)
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_channels *c;
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_reg_class *cla;
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t cl, ch;
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int found = 0;
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 reg_class;
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 channel;
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	c = &p2p->cfg->channels;
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (cl = 0; cl < c->reg_classes; cl++) {
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cla = &c->reg_class[cl];
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (cla->reg_class != p2p->last_prog_scan_class)
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (ch = 0; ch < cla->channels; ch++) {
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (cla->channel[ch] == p2p->last_prog_scan_chan) {
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				found = 1;
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (found)
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!found) {
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Start from beginning */
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reg_class = c->reg_class[0].reg_class;
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		channel = c->reg_class[0].channel[0];
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Pick the next channel */
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ch++;
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ch == cla->channels) {
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			cl++;
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (cl == c->reg_classes)
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				cl = 0;
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ch = 0;
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reg_class = c->reg_class[cl].reg_class;
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		channel = c->reg_class[cl].channel[ch];
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	freq = p2p_channel_to_freq(p2p->cfg->country, reg_class, channel);
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Next progressive search "
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"channel: reg_class %u channel %u -> %d MHz",
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reg_class, channel, freq);
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->last_prog_scan_class = reg_class;
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->last_prog_scan_chan = channel;
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq == 2412 || freq == 2437 || freq == 2462)
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* No need to add social channels */
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return freq;
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_search(struct p2p_data *p2p)
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq = 0;
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum p2p_scan_type type;
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->drv_in_listen) {
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Driver is still "
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"in Listen state - wait for it to end before "
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"continuing");
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer) {
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Only scan the known listen frequency of the peer
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * during GO Negotiation start.
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		freq = p2p->go_neg_peer->listen_freq;
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freq <= 0)
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq = p2p->go_neg_peer->oper_freq;
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type = P2P_SCAN_SPECIFIC;
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting search "
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"for freq %u (GO Neg)", freq);
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (p2p->invite_peer) {
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Only scan the known listen frequency of the peer
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * during Invite start.
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		freq = p2p->invite_peer->listen_freq;
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freq <= 0)
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq = p2p->invite_peer->oper_freq;
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type = P2P_SCAN_SPECIFIC;
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting search "
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"for freq %u (Invite)", freq);
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (p2p->find_type == P2P_FIND_PROGRESSIVE &&
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (freq = p2p_get_next_prog_freq(p2p)) > 0) {
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type = P2P_SCAN_SOCIAL_PLUS_ONE;
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting search "
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"(+ freq %u)", freq);
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type = P2P_SCAN_SOCIAL;
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting search");
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, type, freq,
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p->num_req_dev_types, p2p->req_dev_types) < 0)
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Scan request failed");
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Running p2p_scan");
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->p2p_scan_running = 1;
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(P2P_SCAN_TIMEOUT, 0, p2p_scan_timeout,
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p, NULL);
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_find_timeout(void *eloop_ctx, void *timeout_ctx)
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Find timeout -> stop");
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_stop_find(p2p);
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_run_after_scan(struct p2p_data *p2p)
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum p2p_after_scan op;
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->after_scan_tx) {
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO: schedule p2p_run_after_scan to be called from TX
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * status callback(?) */
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send pending "
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Action frame at p2p_scan completion");
8341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p->cfg->send_action(p2p->cfg->cb_ctx,
8351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->freq,
8361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->dst,
8371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->src,
8381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->bssid,
8391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      (u8 *) (p2p->after_scan_tx + 1),
8401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->len,
8411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      p2p->after_scan_tx->wait_time);
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p2p->after_scan_tx);
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = NULL;
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	op = p2p->start_after_scan;
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (op) {
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_AFTER_SCAN_NOTHING:
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_AFTER_SCAN_LISTEN:
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Start previously "
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"requested Listen state");
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_listen(p2p, p2p->pending_listen_sec * 1000 +
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   p2p->pending_listen_usec / 1000);
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_AFTER_SCAN_CONNECT:
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Start previously "
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"requested connect with " MACSTR,
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(p2p->after_scan_peer));
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, p2p->after_scan_peer);
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev == NULL) {
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer not "
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"known anymore");
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, dev);
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_scan_timeout(void *eloop_ctx, void *timeout_ctx)
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int running;
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan timeout "
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"(running=%d)", p2p->p2p_scan_running);
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	running = p2p->p2p_scan_running;
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Make sure we recover from missed scan results callback */
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->p2p_scan_running = 0;
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (running)
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_run_after_scan(p2p);
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_free_req_dev_types(struct p2p_data *p2p)
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->num_req_dev_types = 0;
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->req_dev_types);
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->req_dev_types = NULL;
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_find(struct p2p_data *p2p, unsigned int timeout,
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     enum p2p_discovery_type type,
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     unsigned int num_req_dev_types, const u8 *req_dev_types)
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting find (type=%d)",
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type);
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan is "
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"already running");
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_req_dev_types(p2p);
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req_dev_types && num_req_dev_types) {
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->req_dev_types = os_malloc(num_req_dev_types *
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       WPS_DEV_TYPE_LEN);
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->req_dev_types == NULL)
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->req_dev_types, req_dev_types,
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  num_req_dev_types * WPS_DEV_TYPE_LEN);
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->num_req_dev_types = num_req_dev_types;
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->find_type = type;
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_device_clear_reported(p2p);
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_SEARCH);
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
9301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p->last_p2p_find_timeout = timeout;
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (timeout)
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(timeout, 0, p2p_find_timeout,
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p, NULL);
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (type) {
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_FIND_START_WITH_FULL:
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_FIND_PROGRESSIVE:
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_FULL, 0,
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 p2p->num_req_dev_types,
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 p2p->req_dev_types);
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_FIND_ONLY_SOCIAL:
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_SOCIAL, 0,
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 p2p->num_req_dev_types,
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 p2p->req_dev_types);
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res == 0) {
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Running p2p_scan");
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->p2p_scan_running = 1;
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(P2P_SCAN_TIMEOUT, 0, p2p_scan_timeout,
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p, NULL);
9561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	} else if (res == 1) {
9571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Could not start "
9581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			"p2p_scan at this point - will try again after "
9591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			"previous scan completes");
9601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		res = 0;
9611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_set_state(p2p, P2P_SEARCH_WHEN_READY);
9621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Failed to start "
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"p2p_scan");
9661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
9671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_other_scan_completed(struct p2p_data *p2p)
9751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
9761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p->state != P2P_SEARCH_WHEN_READY)
9771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
9781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting pending P2P find "
9791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		"now that previous scan was completed");
9801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p_find(p2p, p2p->last_p2p_find_timeout, p2p->find_type,
9811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		     p2p->num_req_dev_types, p2p->req_dev_types) < 0)
9821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
9831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return 1;
9841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
9851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
9861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_stop_find_for_freq(struct p2p_data *p2p, int freq)
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Stopping find");
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_IDLE);
9931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef ANDROID_P2P
9941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, P2P_EVENT_FIND_STOPPED);
9951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif
9961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_req_dev_types(p2p);
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer = NULL;
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->sd_peer = NULL;
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->invite_peer = NULL;
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq > 0 && p2p->drv_in_listen == freq && p2p->in_listen) {
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Skip stop_listen "
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"since we are on correct channel for response");
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p->drv_in_listen) {
10081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/*
10091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * The driver may not deliver callback to p2p_listen_end()
10101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * when the operation gets canceled, so clear the internal
10111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * variable that is tracking driver state.
10121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
10131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Clear "
10141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			"drv_in_listen (%d)", p2p->drv_in_listen);
10151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p->drv_in_listen = 0;
10161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_stop_find(struct p2p_data *p2p)
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_stop_find_for_freq(p2p, 0);
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_prepare_channel(struct p2p_data *p2p, unsigned int force_freq)
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (force_freq) {
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 op_reg_class, op_channel;
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p_freq_to_channel(p2p->cfg->country, force_freq,
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					&op_reg_class, &op_channel) < 0) {
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Unsupported frequency %u MHz",
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				force_freq);
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!p2p_channels_includes(&p2p->cfg->channels, op_reg_class,
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   op_channel)) {
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Frequency %u MHz (oper_class %u "
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"channel %u) not allowed for P2P",
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				force_freq, op_reg_class, op_channel);
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->op_reg_class = op_reg_class;
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->op_channel = op_channel;
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->channels.reg_classes = 1;
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->channels.reg_class[0].channels = 1;
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->channels.reg_class[0].reg_class = p2p->op_reg_class;
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->channels.reg_class[0].channel[0] = p2p->op_channel;
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 op_reg_class, op_channel;
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!p2p->cfg->cfg_op_channel && p2p->best_freq_overall > 0 &&
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    p2p_supported_freq(p2p, p2p->best_freq_overall) &&
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    p2p_freq_to_channel(p2p->cfg->country,
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					p2p->best_freq_overall,
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					&op_reg_class, &op_channel) == 0) {
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Select best overall channel as "
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"operating channel preference");
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->op_reg_class = op_reg_class;
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->op_channel = op_channel;
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (!p2p->cfg->cfg_op_channel && p2p->best_freq_5 > 0 &&
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   p2p_supported_freq(p2p, p2p->best_freq_5) &&
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   p2p_freq_to_channel(p2p->cfg->country,
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       p2p->best_freq_5,
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       &op_reg_class, &op_channel) ==
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   0) {
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Select best 5 GHz channel as "
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"operating channel preference");
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->op_reg_class = op_reg_class;
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->op_channel = op_channel;
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (!p2p->cfg->cfg_op_channel &&
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   p2p->best_freq_24 > 0 &&
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   p2p_supported_freq(p2p, p2p->best_freq_24) &&
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   p2p_freq_to_channel(p2p->cfg->country,
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       p2p->best_freq_24,
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       &op_reg_class, &op_channel) ==
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   0) {
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Select best 2.4 GHz channel as "
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"operating channel preference");
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->op_reg_class = op_reg_class;
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->op_channel = op_channel;
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->op_reg_class = p2p->cfg->op_reg_class;
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->op_channel = p2p->cfg->op_channel;
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(&p2p->channels, &p2p->cfg->channels,
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(struct p2p_channels));
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Own preference for operation channel: "
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"Operating Class %u Channel %u%s",
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->op_reg_class, p2p->op_channel,
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		force_freq ? " (forced)" : "");
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void p2p_set_dev_persistent(struct p2p_device *dev,
11071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   int persistent_group)
11081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
11091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	switch (persistent_group) {
11101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case 0:
11111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags &= ~(P2P_DEV_PREFER_PERSISTENT_GROUP |
11121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				P2P_DEV_PREFER_PERSISTENT_RECONN);
11131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
11141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case 1:
11151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP;
11161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags &= ~P2P_DEV_PREFER_PERSISTENT_RECONN;
11171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
11181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case 2:
11191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP |
11201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			P2P_DEV_PREFER_PERSISTENT_RECONN;
11211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
11221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
11231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
11241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		enum p2p_wps_method wps_method,
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int go_intent, const u8 *own_interface_addr,
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		unsigned int force_freq, int persistent_group)
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Request to start group negotiation - peer=" MACSTR
11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  GO Intent=%d  Intended Interface Address=" MACSTR
11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" wps_method=%d persistent_group=%d",
11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wps_method, persistent_group);
11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_prepare_channel(p2p, force_freq) < 0)
11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p->ssid_set = 0;
11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Cannot connect to unknown P2P Device " MACSTR,
11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(peer_addr));
11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!(dev->info.dev_capab &
11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Cannot connect to P2P Device " MACSTR
11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				" that is in a group and is not discoverable",
11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(peer_addr));
11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->oper_freq <= 0) {
11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Cannot connect to P2P Device " MACSTR
11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				" with incomplete information",
11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(peer_addr));
11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * First, try to connect directly. If the peer does not
11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * acknowledge frames, assume it is sleeping and use device
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * discoverability via the GO at that point.
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_NOT_YET_READY;
11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_USER_REJECTED;
11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE;
11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM;
11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->connect_reqs = 0;
11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_neg_req_sent = 0;
11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_state = UNKNOWN_GO;
11831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_set_dev_persistent(dev, persistent_group);
11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_intent = go_intent;
11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state != P2P_IDLE)
11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_stop_find(p2p);
11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->after_scan_tx) {
11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * We need to drop the pending frame to avoid issues with the
11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * new GO Negotiation, e.g., when the pending frame was from a
11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * previous attempt at starting a GO Negotiation.
11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Dropped "
11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"previous pending Action frame TX that was waiting "
11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"for p2p_scan completion");
11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p2p->after_scan_tx);
12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = NULL;
12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wps_method = wps_method;
12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->status = P2P_SC_SUCCESS;
12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (force_freq)
12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags |= P2P_DEV_FORCE_FREQ;
12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~P2P_DEV_FORCE_FREQ;
12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: p2p_scan running - delay connect send");
12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->start_after_scan = P2P_AFTER_SCAN_CONNECT;
12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_peer, peer_addr, ETH_ALEN);
12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_connect_send(p2p, dev);
12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  enum p2p_wps_method wps_method,
12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  int go_intent, const u8 *own_interface_addr,
12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  unsigned int force_freq, int persistent_group)
12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Request to authorize group negotiation - peer=" MACSTR
12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  GO Intent=%d  Intended Interface Address=" MACSTR
12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" wps_method=%d  persistent_group=%d",
12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wps_method, persistent_group);
12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_prepare_channel(p2p, force_freq) < 0)
12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Cannot authorize unknown P2P Device " MACSTR,
12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(peer_addr));
12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_NOT_YET_READY;
12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_USER_REJECTED;
12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_neg_req_sent = 0;
12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_state = UNKNOWN_GO;
12531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_set_dev_persistent(dev, persistent_group);
12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_intent = go_intent;
12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wps_method = wps_method;
12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->status = P2P_SC_SUCCESS;
12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (force_freq)
12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags |= P2P_DEV_FORCE_FREQ;
12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~P2P_DEV_FORCE_FREQ;
12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_add_dev_info(struct p2p_data *p2p, const u8 *addr,
12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      struct p2p_device *dev, struct p2p_message *msg)
12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&dev->last_seen);
12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_copy_wps_info(dev, 0, msg);
12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->listen_channel) {
12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int freq;
12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		freq = p2p_channel_to_freq((char *) msg->listen_channel,
12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   msg->listen_channel[3],
12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   msg->listen_channel[4]);
12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freq < 0) {
12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Unknown peer Listen channel: "
12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"country=%c%c(0x%02x) reg_class=%u channel=%u",
12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[0],
12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[1],
12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[2],
12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[3],
12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[4]);
12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Update "
12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"peer " MACSTR " Listen channel: %u -> %u MHz",
12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(dev->info.p2p_device_addr),
12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev->listen_freq, freq);
12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->listen_freq = freq;
12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_PROBE_REQ_ONLY) {
13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~P2P_DEV_PROBE_REQ_ONLY;
13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Completed device entry based on data from "
13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"GO Negotiation Request");
13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Created device entry based on GO Neg Req: "
13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MACSTR " dev_capab=0x%x group_capab=0x%x name='%s' "
13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"listen_freq=%d",
13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr),
13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->info.dev_capab, dev->info.group_capab,
13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->info.device_name, dev->listen_freq);
13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_GROUP_CLIENT_ONLY;
13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_USER_REJECTED) {
13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Do not report rejected device");
13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->dev_found(p2p->cfg->cb_ctx, addr, &dev->info,
13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    !(dev->flags & P2P_DEV_REPORTED_ONCE));
13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_build_ssid(struct p2p_data *p2p, u8 *ssid, size_t *ssid_len)
13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_random((char *) &ssid[P2P_WILDCARD_SSID_LEN], 2);
13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&ssid[P2P_WILDCARD_SSID_LEN + 2],
13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  p2p->cfg->ssid_postfix, p2p->cfg->ssid_postfix_len);
13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*ssid_len = P2P_WILDCARD_SSID_LEN + 2 + p2p->cfg->ssid_postfix_len;
13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_go_params(struct p2p_data *p2p, struct p2p_go_neg_results *params)
13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_build_ssid(p2p, params->ssid, &params->ssid_len);
13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_random(params->passphrase, 8);
13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_go_complete(struct p2p_data *p2p, struct p2p_device *peer)
13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_go_neg_results res;
13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int go = peer->go_state == LOCAL_GO;
13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_channels intersection;
13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freqs;
13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i, j;
13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: GO Negotiation with " MACSTR " completed (%s will be "
13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"GO)", MAC2STR(peer->info.p2p_device_addr),
13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		go ? "local end" : "peer");
13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&res, 0, sizeof(res));
13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.role_go = go;
13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(res.peer_device_addr, peer->info.p2p_device_addr, ETH_ALEN);
13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(res.peer_interface_addr, peer->intended_addr, ETH_ALEN);
13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.wps_method = peer->wps_method;
13641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) {
13651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN)
13661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			res.persistent_group = 2;
13671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		else
13681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			res.persistent_group = 1;
13691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (go) {
13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Setup AP mode for WPS provisioning */
13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res.freq = p2p_channel_to_freq(p2p->cfg->country,
13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       p2p->op_reg_class,
13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       p2p->op_channel);
13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(res.ssid, p2p->ssid, p2p->ssid_len);
13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res.ssid_len = p2p->ssid_len;
13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_random(res.passphrase, 8);
13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res.freq = peer->oper_freq;
13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->ssid_len) {
13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(res.ssid, p2p->ssid, p2p->ssid_len);
13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res.ssid_len = p2p->ssid_len;
13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_channels_intersect(&p2p->channels, &peer->channels,
13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       &intersection);
13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	freqs = 0;
13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < intersection.reg_classes; i++) {
13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct p2p_reg_class *c = &intersection.reg_class[i];
13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freqs + 1 == P2P_MAX_CHANNELS)
13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < c->channels; j++) {
13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			int freq;
13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (freqs + 1 == P2P_MAX_CHANNELS)
13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq = p2p_channel_to_freq(peer->country, c->reg_class,
13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   c->channel[j]);
14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (freq < 0)
14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				continue;
14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res.freq_list[freqs++] = freq;
14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.peer_config_timeout = go ? peer->client_timeout : peer->go_timeout;
14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
14091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p->ssid_set = 0;
14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer->go_neg_req_sent = 0;
14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer->wps_method = WPS_NOT_READY;
14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_PROVISIONING);
14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->go_neg_completed(p2p->cfg->cb_ctx, &res);
14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_rx_p2p_action(struct p2p_data *p2p, const u8 *sa,
14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      const u8 *data, size_t len, int rx_freq)
14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: RX P2P Public Action from " MACSTR, MAC2STR(sa));
14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "P2P: P2P Public Action contents", data, len);
14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1)
14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data[0]) {
14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG_REQ:
14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_neg_req(p2p, sa, data + 1, len - 1, rx_freq);
14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG_RESP:
14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_neg_resp(p2p, sa, data + 1, len - 1, rx_freq);
14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG_CONF:
14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_neg_conf(p2p, sa, data + 1, len - 1);
14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITATION_REQ:
14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_invitation_req(p2p, sa, data + 1, len - 1,
14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   rx_freq);
14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITATION_RESP:
14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_invitation_resp(p2p, sa, data + 1, len - 1);
14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROV_DISC_REQ:
14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_prov_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROV_DISC_RESP:
14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_prov_disc_resp(p2p, sa, data + 1, len - 1);
14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_DEV_DISC_REQ:
14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_dev_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_DEV_DISC_RESP:
14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_dev_disc_resp(p2p, sa, data + 1, len - 1);
14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Unsupported P2P Public Action frame type %d",
14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data[0]);
14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void p2p_rx_action_public(struct p2p_data *p2p, const u8 *da,
14671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				 const u8 *sa, const u8 *bssid, const u8 *data,
14681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				 size_t len, int freq)
14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1)
14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data[0]) {
14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_VENDOR_SPECIFIC:
14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data++;
14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len--;
14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 3)
14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (WPA_GET_BE24(data) != OUI_WFA)
14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data += 3;
14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len -= 3;
14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 1)
14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*data != P2P_OUI_TYPE)
14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_p2p_action(p2p, sa, data + 1, len - 1, freq);
14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_INITIAL_REQ:
14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_initial_req(p2p, sa, data + 1, len - 1, freq);
14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_INITIAL_RESP:
14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_initial_resp(p2p, sa, data + 1, len - 1, freq);
14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_COMEBACK_REQ:
14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_comeback_req(p2p, sa, data + 1, len - 1, freq);
15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_COMEBACK_RESP:
15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_comeback_resp(p2p, sa, data + 1, len - 1, freq);
15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_rx_action(struct p2p_data *p2p, const u8 *da, const u8 *sa,
15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *bssid, u8 category,
15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *data, size_t len, int freq)
15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (category == WLAN_ACTION_PUBLIC) {
15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_action_public(p2p, da, sa, bssid, data, len, freq);
15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (category != WLAN_ACTION_VENDOR_SPECIFIC)
15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 4)
15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (WPA_GET_BE24(data) != OUI_WFA)
15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data += 3;
15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len -= 3;
15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*data != P2P_OUI_TYPE)
15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data++;
15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len--;
15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P action frame */
15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: RX P2P Action from " MACSTR, MAC2STR(sa));
15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "P2P: P2P Action contents", data, len);
15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1)
15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data[0]) {
15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_NOA:
15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Received P2P Action - Notice of Absence");
15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO */
15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PRESENCE_REQ:
15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_presence_req(p2p, da, sa, data + 1, len - 1, freq);
15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PRESENCE_RESP:
15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_presence_resp(p2p, da, sa, data + 1, len - 1);
15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_DISC_REQ:
15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_disc_req(p2p, da, sa, data + 1, len - 1, freq);
15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Received P2P Action - unknown type %u", data[0]);
15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_start(void *eloop_ctx, void *timeout_ctx)
15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == NULL)
15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer->status = P2P_SC_SUCCESS;
15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_connect_send(p2p, p2p->go_neg_peer);
15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_invite_start(void *eloop_ctx, void *timeout_ctx)
15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->invite_peer == NULL)
15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_invite_send(p2p, p2p->invite_peer, p2p->invite_go_dev_addr);
15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_add_dev_from_probe_req(struct p2p_data *p2p, const u8 *addr,
15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const u8 *ie, size_t ie_len)
15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg) < 0 || msg.p2p_attributes == NULL)
15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* not a P2P probe */
15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.ssid == NULL || msg.ssid[1] != P2P_WILDCARD_SSID_LEN ||
15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(msg.ssid + 2, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN)
15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    != 0) {
16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* The Probe Request is not part of P2P Device Discovery. It is
16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * not known whether the source address of the frame is the P2P
16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Device Address or P2P Interface Address. Do not add a new
16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * peer entry based on this frames.
16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev) {
16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->country[0] == 0 && msg.listen_channel)
16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(dev->country, msg.listen_channel, 3);
16131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		os_get_time(&dev->last_seen);
16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* already known */
16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_create_device(p2p, addr);
16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&dev->last_seen);
16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_PROBE_REQ_ONLY;
16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.listen_channel) {
16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->country, msg.listen_channel, 3);
16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->listen_freq = p2p_channel_to_freq(dev->country,
16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       msg.listen_channel[3],
16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       msg.listen_channel[4]);
16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_copy_wps_info(dev, 1, &msg);
16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Created device entry based on Probe Req: " MACSTR
16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" dev_capab=0x%x group_capab=0x%x name='%s' listen_freq=%d",
16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(dev->info.p2p_device_addr), dev->info.dev_capab,
16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.group_capab, dev->info.device_name,
16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->listen_freq);
16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_device * p2p_add_dev_from_go_neg_req(struct p2p_data *p2p,
16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						const u8 *addr,
16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						struct p2p_message *msg)
16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev) {
16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_get_time(&dev->last_seen);
16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return dev; /* already known */
16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_create_device(p2p, addr);
16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_add_dev_info(p2p, addr, dev, msg);
16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return dev;
16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int dev_type_match(const u8 *dev_type, const u8 *req_dev_type)
16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(dev_type, req_dev_type, WPS_DEV_TYPE_LEN) == 0)
16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(dev_type, req_dev_type, 2) == 0 &&
16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    WPA_GET_BE32(&req_dev_type[2]) == 0 &&
16758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    WPA_GET_BE16(&req_dev_type[6]) == 0)
16768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Category match with wildcard OUI/sub-category */
16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint dev_type_list_match(const u8 *dev_type, const u8 *req_dev_type[],
16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			size_t num_req_dev_type)
16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_req_dev_type; i++) {
16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev_type_match(dev_type, req_dev_type[i]))
16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 1;
16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_match_dev_type - Match local device type with requested type
16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wps: WPS TLVs from Probe Request frame (concatenated WPS IEs)
16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 on match, 0 on mismatch
16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function can be used to match the Requested Device Type attribute in
17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPS IE with the local device types for deciding whether to reply to a Probe
17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Request frame.
17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_match_dev_type(struct p2p_data *p2p, struct wpabuf *wps)
17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wps_parse_attr attr;
17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wps_parse_msg(wps, &attr))
17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* assume no Requested Device Type attributes */
17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (attr.num_req_dev_type == 0)
17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* no Requested Device Type attributes -> match */
17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev_type_list_match(p2p->cfg->pri_dev_type, attr.req_dev_type,
17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				attr.num_req_dev_type))
17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Own Primary Device Type matches */
17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < p2p->cfg->num_sec_dev_types; i++)
17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev_type_list_match(p2p->cfg->sec_dev_type[i],
17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					attr.req_dev_type,
17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					attr.num_req_dev_type))
17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Own Secondary Device Type matches */
17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* No matching device type found */
17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * p2p_build_probe_resp_ies(struct p2p_data *p2p)
17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = wpabuf_alloc(1000);
17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_build_wps_ie(p2p, buf, DEV_PW_DEFAULT, 1);
17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P IE */
17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(buf);
17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_capability(buf, p2p->dev_capab, 0);
17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval)
17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_ext_listen_timing(buf, p2p->ext_listen_period,
17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      p2p->ext_listen_interval);
17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_device_info(buf, p2p, NULL);
17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(buf, len);
17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int is_11b(u8 rate)
17541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
17551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
17561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
17571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
17581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
17591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int supp_rates_11b_only(struct ieee802_11_elems *elems)
17601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
17611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int num_11b = 0, num_others = 0;
17621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int i;
17631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
17641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (elems->supp_rates == NULL && elems->ext_supp_rates == NULL)
17651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
17661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
17671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (i = 0; elems->supp_rates && i < elems->supp_rates_len; i++) {
17681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (is_11b(elems->supp_rates[i]))
17691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			num_11b++;
17701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		else
17711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			num_others++;
17721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
17731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
17741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (i = 0; elems->ext_supp_rates && i < elems->ext_supp_rates_len;
17751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	     i++) {
17761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (is_11b(elems->ext_supp_rates[i]))
17771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			num_11b++;
17781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		else
17791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			num_others++;
17801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
17811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
17821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return num_11b > 0 && num_others == 0;
17831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
17841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
17851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
17861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void p2p_reply_probe(struct p2p_data *p2p, const u8 *addr,
17871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			    const u8 *dst, const u8 *bssid, const u8 *ie,
17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    size_t ie_len)
17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ieee802_11_elems elems;
17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ieee80211_mgmt *resp;
17931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_message msg;
17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *ies;
17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p->in_listen || !p2p->drv_in_listen) {
17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* not in Listen state - ignore Probe Request */
17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ieee802_11_parse_elems((u8 *) ie, ie_len, &elems, 0) ==
18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ParseFailed) {
18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Ignore invalid Probe Request frames */
18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (elems.p2p == NULL) {
18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* not a P2P probe - ignore it */
18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (dst && !is_broadcast_ether_addr(dst) &&
18131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    os_memcmp(dst, p2p->cfg->dev_addr, ETH_ALEN) != 0) {
18141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Not sent to the broadcast address or our P2P Device Address
18151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
18161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
18171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
18181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
18191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (bssid && !is_broadcast_ether_addr(bssid)) {
18201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Not sent to the Wildcard BSSID */
18211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
18221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
18231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (elems.ssid == NULL || elems.ssid_len != P2P_WILDCARD_SSID_LEN ||
18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(elems.ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) !=
18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0) {
18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* not using P2P Wildcard SSID - ignore */
18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (supp_rates_11b_only(&elems)) {
18321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Indicates support for 11b rates only */
18331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
18341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
18351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
18361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
18371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg) < 0) {
18381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Could not parse P2P attributes */
18391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
18401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
18411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
18421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (msg.device_id &&
18431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    os_memcmp(msg.device_id, p2p->cfg->dev_addr, ETH_ALEN != 0)) {
18441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Device ID did not match */
18451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_parse_free(&msg);
18461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
18471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
18481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Check Requested Device Type match */
18501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (msg.wps_attributes &&
18511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    !p2p_match_dev_type(p2p, msg.wps_attributes)) {
18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* No match with Requested Device Type */
18531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_parse_free(&msg);
18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_parse_free(&msg);
18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p->cfg->send_probe_resp)
18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* Response generated elsewhere */
18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Reply to P2P Probe Request in Listen state");
18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
18658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * We do not really have a specific BSS that this frame is advertising,
18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * so build a frame that has some information in valid format. This is
18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * really only used for discovery purposes, not to learn exact BSS
18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * parameters.
18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ies = p2p_build_probe_resp_ies(p2p);
18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ies == NULL)
18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = wpabuf_alloc(200 + wpabuf_len(ies));
18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL) {
18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(ies);
18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = NULL;
18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = wpabuf_put(buf, resp->u.probe_resp.variable - (u8 *) resp);
18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   (WLAN_FC_STYPE_PROBE_RESP << 4));
18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(resp->da, addr, ETH_ALEN);
18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(resp->sa, p2p->cfg->dev_addr, ETH_ALEN);
18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(resp->bssid, p2p->cfg->dev_addr, ETH_ALEN);
18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->u.probe_resp.beacon_int = host_to_le16(100);
18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* hardware or low-level driver will setup seq_ctrl and timestamp */
18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->u.probe_resp.capab_info =
18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		host_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE |
18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     WLAN_CAPABILITY_PRIVACY |
18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     WLAN_CAPABILITY_SHORT_SLOT_TIME);
18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_SSID);
18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, P2P_WILDCARD_SSID_LEN);
18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(buf, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_SUPP_RATES);
19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 8);
19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, (60 / 5) | 0x80);
19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 90 / 5);
19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, (120 / 5) | 0x80);
19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 180 / 5);
19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, (240 / 5) | 0x80);
19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 360 / 5);
19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 480 / 5);
19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 540 / 5);
19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_DS_PARAMS);
19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 1);
19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, p2p->cfg->channel);
19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_buf(buf, ies);
19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(ies);
19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_probe_resp(p2p->cfg->cb_ctx, buf);
19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(buf);
19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
19241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		     const u8 *bssid, const u8 *ie, size_t ie_len)
19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_add_dev_from_probe_req(p2p, addr, ie, ie_len);
19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_reply_probe(p2p, addr, dst, bssid, ie, ie_len);
19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((p2p->state == P2P_CONNECT || p2p->state == P2P_CONNECT_LISTEN) &&
19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    p2p->go_neg_peer &&
19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(addr, p2p->go_neg_peer->info.p2p_device_addr, ETH_ALEN)
19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    == 0) {
19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Received a Probe Request from GO Negotiation peer */
19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Found GO Negotiation peer - try to start GO "
19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"negotiation from timeout");
19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(0, 0, p2p_go_neg_start, p2p, NULL);
19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((p2p->state == P2P_INVITE || p2p->state == P2P_INVITE_LISTEN) &&
19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    p2p->invite_peer &&
19448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(addr, p2p->invite_peer->info.p2p_device_addr, ETH_ALEN)
19458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    == 0) {
19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Received a Probe Request from Invite peer */
19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Found Invite peer - try to start Invite from "
19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"timeout");
19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(0, 0, p2p_invite_start, p2p, NULL);
19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_assoc_req_ie_wlan_ap(struct p2p_data *p2p, const u8 *bssid,
19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    u8 *buf, size_t len, struct wpabuf *p2p_ie)
19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *tmp;
19628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *lpos;
19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t tmplen;
19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 group_capab;
19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_ie == NULL)
19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* WLAN AP is not a P2P manager */
19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (Re)Association Request - P2P IE
19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Capability attribute (shall be present)
19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Interface attribute (present if concurrent device and
19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *	P2P Management is enabled)
19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp = wpabuf_alloc(200);
19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp == NULL)
19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	lpos = p2p_buf_add_ie_hdr(tmp);
19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group_capab = 0;
19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->num_groups > 0) {
19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group_capab |= P2P_GROUP_CAPAB_GROUP_OWNER;
19848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) &&
19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED) &&
19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    p2p->cross_connect)
19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_capability(tmp, p2p->dev_capab, group_capab);
19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) &&
19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED))
19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_p2p_interface(tmp, p2p);
19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(tmp, lpos);
19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmplen = wpabuf_len(tmp);
19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmplen > len)
19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = -1;
19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(buf, wpabuf_head(tmp), tmplen);
20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = tmplen;
20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(tmp);
20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_assoc_req_ie(struct p2p_data *p2p, const u8 *bssid, u8 *buf,
20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     size_t len, int p2p_group, struct wpabuf *p2p_ie)
20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *tmp;
20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *lpos;
20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *peer;
20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t tmplen;
20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p_group)
20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return p2p_assoc_req_ie_wlan_ap(p2p, bssid, buf, len, p2p_ie);
20198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (Re)Association Request - P2P IE
20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Capability attribute (shall be present)
20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Extended Listen Timing (may be present)
20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Device Info attribute (shall be present)
20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp = wpabuf_alloc(200);
20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp == NULL)
20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer = bssid ? p2p_get_device(p2p, bssid) : NULL;
20318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	lpos = p2p_buf_add_ie_hdr(tmp);
20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_capability(tmp, p2p->dev_capab, 0);
20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval)
20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_ext_listen_timing(tmp, p2p->ext_listen_period,
20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      p2p->ext_listen_interval);
20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_device_info(tmp, p2p, peer);
20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(tmp, lpos);
20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmplen = wpabuf_len(tmp);
20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmplen > len)
20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = -1;
20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(buf, wpabuf_head(tmp), tmplen);
20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = tmplen;
20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(tmp);
20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_scan_result_text(const u8 *ies, size_t ies_len, char *buf, char *end)
20548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *p2p_ie;
20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len, P2P_IE_VENDOR_TYPE);
20598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_ie == NULL)
20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = p2p_attr_text(p2p_ie, buf, end);
20638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(p2p_ie);
20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_clear_go_neg(struct p2p_data *p2p)
20698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer = NULL;
20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
20728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_IDLE);
20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_wps_success_cb(struct p2p_data *p2p, const u8 *mac_addr)
20778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == NULL) {
20798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
20808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No pending Group Formation - "
20818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"ignore WPS registration success notification");
20828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* No pending Group Formation */
20838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(mac_addr, p2p->go_neg_peer->intended_addr, ETH_ALEN) !=
20868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0) {
20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
20888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Ignore WPS registration success notification "
20898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"for " MACSTR " (GO Negotiation peer " MACSTR ")",
20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(mac_addr),
20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(p2p->go_neg_peer->intended_addr));
20928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* Ignore unexpected peer address */
20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Group Formation completed successfully with " MACSTR,
20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(mac_addr));
20988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_go_neg(p2p);
21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_group_formation_failed(struct p2p_data *p2p)
21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == NULL) {
21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No pending Group Formation - "
21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"ignore group formation failure notification");
21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* No pending Group Formation */
21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
21138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Group Formation failed with " MACSTR,
21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(p2p->go_neg_peer->intended_addr));
21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_go_neg(p2p);
21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_data * p2p_init(const struct p2p_config *cfg)
21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p;
21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->max_peers < 1)
21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p = os_zalloc(sizeof(*p2p) + sizeof(*cfg));
21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p == NULL)
21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
21308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg = (struct p2p_config *) (p2p + 1);
21318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg, cfg, sizeof(*cfg));
21328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->dev_name)
21338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->dev_name = os_strdup(cfg->dev_name);
21348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->manufacturer)
21358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->manufacturer = os_strdup(cfg->manufacturer);
21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->model_name)
21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_name = os_strdup(cfg->model_name);
21388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->model_number)
21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_number = os_strdup(cfg->model_number);
21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->serial_number)
21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->serial_number = os_strdup(cfg->serial_number);
21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->min_disc_int = 1;
21448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->max_disc_int = 3;
21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_random(&p2p->next_tie_breaker, 1);
21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->next_tie_breaker &= 0x01;
21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->sd_request)
21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_SERVICE_DISCOVERY;
21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->dev_capab |= P2P_DEV_CAPAB_INVITATION_PROCEDURE;
21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->concurrent_operations)
21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_CONCURRENT_OPER;
21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->dev_capab |= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_init(&p2p->devices);
21568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(P2P_PEER_EXPIRATION_INTERVAL, 0,
21588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p_expiration_timeout, p2p, NULL);
21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p;
21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_deinit(struct p2p_data *p2p)
21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_expiration_timeout, p2p, NULL);
21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_ext_listen_timeout, p2p, NULL);
21688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
21698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_flush(p2p);
21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_req_dev_types(p2p);
21718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->dev_name);
21728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->manufacturer);
21738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_name);
21748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_number);
21758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->serial_number);
21768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->groups);
21778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(p2p->sd_resp);
21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->after_scan_tx);
21798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_remove_wps_vendor_extensions(p2p);
21808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p);
21818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_flush(struct p2p_data *p2p)
21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev, *prev;
21878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_IDLE);
21898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
21908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer = NULL;
21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each_safe(dev, prev, &p2p->devices, struct p2p_device,
21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      list) {
21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dl_list_del(&dev->list);
21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_device_free(p2p, dev);
21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_sd_queries(p2p);
21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->after_scan_tx);
21998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->after_scan_tx = NULL;
22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_unauthorize(struct p2p_data *p2p, const u8 *addr)
22048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Unauthorizing " MACSTR,
22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(addr));
22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == dev)
22158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->go_neg_peer = NULL;
22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wps_method = WPS_NOT_READY;
22188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE;
22198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM;
22208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Check if after_scan_tx is for this peer. If so free it */
22228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->after_scan_tx &&
22238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(addr, p2p->after_scan_tx->dst, ETH_ALEN) == 0) {
22248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p2p->after_scan_tx);
22258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = NULL;
22268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
22298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_dev_name(struct p2p_data *p2p, const char *dev_name)
22338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->dev_name);
22358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev_name) {
22368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->dev_name = os_strdup(dev_name);
22378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->dev_name == NULL)
22388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
22398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
22408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->dev_name = NULL;
22418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
22428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_manufacturer(struct p2p_data *p2p, const char *manufacturer)
22468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->manufacturer);
22488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->manufacturer = NULL;
22498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (manufacturer) {
22508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->manufacturer = os_strdup(manufacturer);
22518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->manufacturer == NULL)
22528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
22568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_model_name(struct p2p_data *p2p, const char *model_name)
22608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_name);
22628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->model_name = NULL;
22638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (model_name) {
22648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_name = os_strdup(model_name);
22658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->model_name == NULL)
22668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
22678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
22708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_model_number(struct p2p_data *p2p, const char *model_number)
22748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_number);
22768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->model_number = NULL;
22778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (model_number) {
22788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_number = os_strdup(model_number);
22798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->model_number == NULL)
22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
22818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
22848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_serial_number(struct p2p_data *p2p, const char *serial_number)
22888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->serial_number);
22908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->serial_number = NULL;
22918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (serial_number) {
22928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->serial_number = os_strdup(serial_number);
22938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->serial_number == NULL)
22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_config_methods(struct p2p_data *p2p, u16 config_methods)
23028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->config_methods = config_methods;
23048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_uuid(struct p2p_data *p2p, const u8 *uuid)
23088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->uuid, uuid, 16);
23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_pri_dev_type(struct p2p_data *p2p, const u8 *pri_dev_type)
23148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->pri_dev_type, pri_dev_type, 8);
23168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
23178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_sec_dev_types(struct p2p_data *p2p, const u8 dev_types[][8],
23218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  size_t num_dev_types)
23228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (num_dev_types > P2P_SEC_DEVICE_TYPES)
23248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num_dev_types = P2P_SEC_DEVICE_TYPES;
23258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->num_sec_dev_types = num_dev_types;
23268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->sec_dev_type, dev_types, num_dev_types * 8);
23278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
23288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_remove_wps_vendor_extensions(struct p2p_data *p2p)
23328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
23348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
23368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(p2p->wps_vendor_ext[i]);
23378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->wps_vendor_ext[i] = NULL;
23388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_add_wps_vendor_extension(struct p2p_data *p2p,
23438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const struct wpabuf *vendor_ext)
23448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
23468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (vendor_ext == NULL)
23488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
23498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
23518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->wps_vendor_ext[i] == NULL)
23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (i >= P2P_MAX_WPS_VENDOR_EXT)
23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->wps_vendor_ext[i] = wpabuf_dup(vendor_ext);
23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->wps_vendor_ext[i] == NULL)
23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_country(struct p2p_data *p2p, const char *country)
23668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->country, country, 3);
23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_continue_find(struct p2p_data *p2p)
23738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
23758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_SEARCH);
23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->flags & P2P_DEV_SD_SCHEDULE) {
23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (p2p_start_sd(p2p, dev) == 0)
23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
23808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
23828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (dev->req_config_methods &&
23838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   !(dev->flags & P2P_DEV_PD_FOR_JOIN)) {
23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send "
23851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				"pending Provision Discovery Request to "
23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MACSTR " (config methods 0x%x)",
23878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(dev->info.p2p_device_addr),
23888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev->req_config_methods);
23891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (p2p_send_prov_disc_req(p2p, dev, 0, 0) == 0)
23908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
23918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
23928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_listen_in_find(p2p);
23958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_sd_cb(struct p2p_data *p2p, int success)
23998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
24018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Service Discovery Query TX callback: success=%d",
24028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
24038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
24048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!success) {
24068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->sd_peer) {
24078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE;
24088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->sd_peer = NULL;
24098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
24108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
24118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
24128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->sd_peer == NULL) {
24158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
24168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No SD peer entry known");
24178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
24188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
24198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Wait for response from the peer */
24228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_SD_DURING_FIND);
24238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_timeout(p2p, 0, 200000);
24248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
242675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
242775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen/**
242875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen * p2p_retry_pd - Retry any pending provision disc requests in IDLE state
242975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen * @p2p: P2P module context from p2p_init()
243075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen */
24311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void p2p_retry_pd(struct p2p_data *p2p)
243275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
243375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	struct p2p_device *dev;
243475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
243575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p->state != P2P_IDLE)
243675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
243775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
243875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
243975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * Retry the prov disc req attempt only for the peer that the user had
244075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * requested for and provided a join has not been initiated on it
244175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * in the meantime.
244275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
244375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
244475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
244575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (os_memcmp(p2p->pending_pd_devaddr,
244675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			      dev->info.p2p_device_addr, ETH_ALEN) != 0)
244775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			continue;
244875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (!dev->req_config_methods)
244975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			continue;
245075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (dev->flags & P2P_DEV_PD_FOR_JOIN)
245175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			continue;
245275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
245375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send "
24541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			"pending Provision Discovery Request to "
245575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			MACSTR " (config methods 0x%x)",
245675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			MAC2STR(dev->info.p2p_device_addr),
245775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			dev->req_config_methods);
24581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_send_prov_disc_req(p2p, dev, 0, 0);
245975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
246075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	}
246175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
246275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
246375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
24648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_prov_disc_cb(struct p2p_data *p2p, int success)
24658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
24678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Provision Discovery Request TX callback: success=%d",
24688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
246975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
247075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
247175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * Postpone resetting the pending action state till after we actually
247275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * time out. This allows us to take some action like notifying any
247375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * interested parties about no response to the request.
247475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 *
247575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * When the timer (below) goes off we check in IDLE, SEARCH, or
247675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * LISTEN_ONLY state, which are the only allowed states to issue a PD
247775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * requests in, if this was still pending and then raise notification.
247875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
24798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!success) {
248175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pending_action_state = P2P_NO_PENDING_ACTION;
248275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
24838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->state != P2P_IDLE)
24848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_continue_find(p2p);
248575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		else if (p2p->user_initiated_pd) {
248675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p->pending_action_state = P2P_PENDING_PD;
248775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_set_timeout(p2p, 0, 300000);
248875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		}
24898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
24908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
249275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
249375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * This postponing, of resetting pending_action_state, needs to be
249475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * done only for user initiated PD requests and not internal ones.
249575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
249675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p->user_initiated_pd)
249775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pending_action_state = P2P_PENDING_PD;
249875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	else
249975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pending_action_state = P2P_NO_PENDING_ACTION;
250075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
25018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Wait for response from the peer */
25028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_SEARCH)
25038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_PD_DURING_FIND);
25048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_timeout(p2p, 0, 200000);
25058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_scan_res_handler(struct p2p_data *p2p, const u8 *bssid, int freq,
25098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 int level, const u8 *ies, size_t ies_len)
25108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_add_device(p2p, bssid, freq, level, ies, ies_len);
25128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer && p2p->state == P2P_SEARCH &&
25148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(p2p->go_neg_peer->info.p2p_device_addr, bssid, ETH_ALEN)
25158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    == 0) {
25168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
25178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Found GO Negotiation peer - try to start GO "
25188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"negotiation");
25198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, p2p->go_neg_peer);
25208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
25218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
25248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_scan_res_handled(struct p2p_data *p2p)
25288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p->p2p_scan_running) {
25308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan was not "
25318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"running, but scan results received");
25328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->p2p_scan_running = 0;
25348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
25358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_run_after_scan(p2p))
25378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
25388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_SEARCH)
25398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
25408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies)
25448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len = p2p_buf_add_ie_hdr(ies);
25468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_capability(ies, p2p->dev_capab, 0);
25478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->reg_class && p2p->cfg->channel)
25488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_listen_channel(ies, p2p->cfg->country,
25498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   p2p->cfg->reg_class,
25508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   p2p->cfg->channel);
25518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval)
25528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_ext_listen_timing(ies, p2p->ext_listen_period,
25538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      p2p->ext_listen_interval);
25548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: p2p_buf_add_operating_channel() if GO */
25558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(ies, len);
25568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtsize_t p2p_scan_ie_buf_len(struct p2p_data *p2p)
25601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
25611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return 100;
25621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
25631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
25641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
25658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_ie_text(struct wpabuf *p2p_ie, char *buf, char *end)
25668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_attr_text(p2p_ie, buf, end);
25688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_req_cb(struct p2p_data *p2p, int success)
25728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p->go_neg_peer;
25748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
25768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: GO Negotiation Request TX callback: success=%d",
25778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
25788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
25808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
25818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No pending GO Negotiation");
25828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
25838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (success) {
25868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->go_neg_req_sent++;
25878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->flags & P2P_DEV_USER_REJECTED) {
25888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_set_state(p2p, P2P_IDLE);
25898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
25908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
25918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!success &&
25948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (dev->info.dev_capab & P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY) &&
25958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !is_zero_ether_addr(dev->member_in_go_dev)) {
25968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
25978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Peer " MACSTR " did not acknowledge request - "
25988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"try to use device discoverability through its GO",
25998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr));
26008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
26018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_send_dev_disc_req(p2p, dev);
26028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
26038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
26068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Use P2P find, if needed, to find the other device from its listen
26078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * channel.
26088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
26098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_CONNECT);
26108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_timeout(p2p, 0, 100000);
26118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_resp_cb(struct p2p_data *p2p, int success)
26158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
26178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: GO Negotiation Response TX callback: success=%d",
26188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
26198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p->go_neg_peer && p2p->state == P2P_PROVISIONING) {
26208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
26218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Ignore TX callback event - GO Negotiation is "
26228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"not running anymore");
26238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
26248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_CONNECT);
26268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_timeout(p2p, 0, 100000);
26278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_resp_failure_cb(struct p2p_data *p2p, int success)
26318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
26338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: GO Negotiation Response (failure) TX callback: "
26348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"success=%d", success);
26358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer && p2p->go_neg_peer->status != P2P_SC_SUCCESS) {
26368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_failed(p2p, p2p->go_neg_peer,
26378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  p2p->go_neg_peer->status);
26388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_conf_cb(struct p2p_data *p2p,
26438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       enum p2p_send_action_result result)
26448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
26468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
26488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: GO Negotiation Confirm TX callback: result=%d",
26498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		result);
26508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
26518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (result == P2P_SEND_ACTION_FAILED) {
26528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
26538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
26548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (result == P2P_SEND_ACTION_NO_ACK) {
26568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
26578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * It looks like the TX status for GO Negotiation Confirm is
26588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * often showing failure even when the peer has actually
26598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * received the frame. Since the peer may change channels
26608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * immediately after having received the frame, we may not see
26618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * an Ack for retries, so just dropping a single frame may
26628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * trigger this. To allow the group formation to succeed if the
26638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * peer did indeed receive the frame, continue regardless of
26648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * the TX status.
26658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
26668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
26678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Assume GO Negotiation Confirm TX was actually "
26688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"received by the peer even though Ack was not "
26698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"reported");
26708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p->go_neg_peer;
26738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
26748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
26758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_go_complete(p2p, dev);
26778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_send_action_cb(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
26818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const u8 *src, const u8 *bssid,
26828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			enum p2p_send_action_result result)
26838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum p2p_pending_action_state state;
26858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int success;
26868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
26888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Action frame TX callback (state=%d freq=%u dst=" MACSTR
26898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" src=" MACSTR " bssid=" MACSTR " result=%d",
26908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_action_state, freq, MAC2STR(dst), MAC2STR(src),
26918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(bssid), result);
26928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	success = result == P2P_SEND_ACTION_SUCCESS;
26938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	state = p2p->pending_action_state;
26948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
26958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (state) {
26968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_NO_PENDING_ACTION:
26978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
26988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_REQUEST:
26998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_req_cb(p2p, success);
27008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
27018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_RESPONSE:
27028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_resp_cb(p2p, success);
27038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
27048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_RESPONSE_FAILURE:
27058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_resp_failure_cb(p2p, success);
27068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
27078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_CONFIRM:
27088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_conf_cb(p2p, result);
27098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
27108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_SD:
27118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_sd_cb(p2p, success);
27128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
27138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_PD:
27148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_prov_disc_cb(p2p, success);
27158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
27168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_INVITATION_REQUEST:
27178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_invitation_req_cb(p2p, success);
27188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
27198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_INVITATION_RESPONSE:
27208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_invitation_resp_cb(p2p, success);
27218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
27228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_DEV_DISC_REQUEST:
27238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_disc_req_cb(p2p, success);
27248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
27258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_DEV_DISC_RESPONSE:
27268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_disc_resp_cb(p2p, success);
27278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
27288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_DISC_REQ:
27298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_disc_req_cb(p2p, success);
27308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
27318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_listen_cb(struct p2p_data *p2p, unsigned int freq,
27368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   unsigned int duration)
27378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq == p2p->pending_client_disc_freq) {
27398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
27408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Client discoverability remain-awake completed");
27418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_client_disc_freq = 0;
27428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
27438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq != p2p->pending_listen_freq) {
27468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
27478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Unexpected listen callback for freq=%u "
27488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"duration=%u (pending_listen_freq=%u)",
27498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq, duration, p2p->pending_listen_freq);
27508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
27518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
27548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Starting Listen timeout(%u,%u) on freq=%u based on "
27558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"callback",
27568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_sec, p2p->pending_listen_usec,
27578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_freq);
27588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->in_listen = 1;
27598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->drv_in_listen = freq;
27608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->pending_listen_sec || p2p->pending_listen_usec) {
27618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
27628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Add 20 msec extra wait to avoid race condition with driver
27638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * remain-on-channel end event, i.e., give driver more time to
27648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * complete the operation before our timeout expires.
27658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
27668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_timeout(p2p, p2p->pending_listen_sec,
27678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p->pending_listen_usec + 20000);
27688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_freq = 0;
27718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_listen_end(struct p2p_data *p2p, unsigned int freq)
27758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Driver ended Listen "
27778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"state (freq=%u)", freq);
27788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->drv_in_listen = 0;
27798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->in_listen)
27808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* Internal timeout will trigger the next step */
27818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_CONNECT_LISTEN && p2p->go_neg_peer) {
27838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->go_neg_peer->connect_reqs >= 120) {
27848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
27858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Timeout on sending GO Negotiation "
27868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Request without getting response");
27878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
27888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 0;
27898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
27908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_CONNECT);
27928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, p2p->go_neg_peer);
27938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
27948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (p2p->state == P2P_SEARCH) {
27958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_search(p2p);
27968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
27978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
28008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_connect(struct p2p_data *p2p)
28048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
28068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_CONNECT_LISTEN);
28078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_listen_in_find(p2p);
28088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_connect_listen(struct p2p_data *p2p)
28128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer) {
28148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->drv_in_listen) {
28158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Driver is "
28168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"still in Listen state; wait for it to "
28178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"complete");
28188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
28198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
28208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->go_neg_peer->connect_reqs >= 120) {
28228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
28238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Timeout on sending GO Negotiation "
28248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Request without getting response");
28258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
28268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
28278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
28288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_CONNECT);
28308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, p2p->go_neg_peer);
28318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
28328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
28338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_wait_peer_connect(struct p2p_data *p2p)
28378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
28398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * TODO: could remain constantly in Listen state for some time if there
28408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * are no other concurrent uses for the radio. For now, go to listen
28418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * state once per second to give other uses a chance to use the radio.
28428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
28438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_WAIT_PEER_IDLE);
28441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_set_timeout(p2p, 0, 500000);
28458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_wait_peer_idle(struct p2p_data *p2p)
28498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p->go_neg_peer;
28518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
28538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
28548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Unknown GO Neg peer - stop GO Neg wait");
28558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
28568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wait_count++;
28598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->wait_count >= 120) {
28608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
28618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Timeout on waiting peer to become ready for GO "
28628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Negotiation");
28638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_failed(p2p, dev, -1);
28648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
28658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
28688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Go to Listen state while waiting for the peer to become "
28698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"ready for GO Negotiation");
28708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_WAIT_PEER_CONNECT);
28718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_listen_in_find(p2p);
28728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_sd_during_find(struct p2p_data *p2p)
28768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
28788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Service Discovery Query timeout");
28798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->sd_peer) {
28808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
28818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE;
28828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->sd_peer = NULL;
28838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_continue_find(p2p);
28858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_prov_disc_during_find(struct p2p_data *p2p)
28898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
28918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Provision Discovery Request timeout");
28928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
28938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_continue_find(p2p);
28948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
289775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic void p2p_timeout_prov_disc_req(struct p2p_data *p2p)
289875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
289975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
290075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
290175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
290275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * For user initiated PD requests that we have not gotten any responses
290375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * for while in IDLE state, we retry them a couple of times before
290475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * giving up.
290575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
290675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (!p2p->user_initiated_pd)
290775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
290875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
290975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
291075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		"P2P: User initiated Provision Discovery Request timeout");
291175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
291275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p->pd_retries) {
291375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pd_retries--;
291475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p_retry_pd(p2p);
291575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	} else {
291675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->cfg->prov_disc_fail)
291775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx,
291875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen						 p2p->pending_pd_devaddr,
291975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen						 P2P_PROV_DISC_TIMEOUT);
292075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p_reset_pending_pd(p2p);
292175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	}
292275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
292375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
292475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
29258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_invite(struct p2p_data *p2p)
29268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
29288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_INVITE_LISTEN);
29298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->inv_role == P2P_INVITE_ROLE_ACTIVE_GO) {
29308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
29318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Better remain on operating channel instead of listen channel
29328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * when running a group.
29338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
29348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Inviting in "
29358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"active GO role - wait on operating channel");
29368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_timeout(p2p, 0, 100000);
29378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
29388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_listen_in_find(p2p);
29408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_invite_listen(struct p2p_data *p2p)
29448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->invite_peer && p2p->invite_peer->invitation_reqs < 100) {
29468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_INVITE);
29478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_invite_send(p2p, p2p->invite_peer,
29488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p->invite_go_dev_addr);
29498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
29508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->invite_peer) {
29518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
29528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Invitation Request retry limit reached");
29538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (p2p->cfg->invitation_result)
29548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p->cfg->invitation_result(
29558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					p2p->cfg->cb_ctx, -1, NULL);
29568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
29578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
29588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_state_timeout(void *eloop_ctx, void *timeout_ctx)
29638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
29658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Timeout (state=%s)",
29678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state));
29688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->in_listen = 0;
29708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (p2p->state) {
29728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_IDLE:
297375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/* Check if we timed out waiting for PD req */
297475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->pending_action_state == P2P_PENDING_PD)
297575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_timeout_prov_disc_req(p2p);
29768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
29778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SEARCH:
297875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/* Check if we timed out waiting for PD req */
297975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->pending_action_state == P2P_PENDING_PD)
298075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_timeout_prov_disc_req(p2p);
29818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_search(p2p);
29828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
29838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT:
29848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_connect(p2p);
29858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
29868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT_LISTEN:
29878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_connect_listen(p2p);
29888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
29898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG:
29908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
29918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_LISTEN_ONLY:
299275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/* Check if we timed out waiting for PD req */
299375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->pending_action_state == P2P_PENDING_PD)
299475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_timeout_prov_disc_req(p2p);
299575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
29968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->ext_listen_only) {
29978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
29988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Extended Listen Timing - Listen State "
29998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"completed");
30008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->ext_listen_only = 0;
30018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_set_state(p2p, P2P_IDLE);
30028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
30038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_CONNECT:
30058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_wait_peer_connect(p2p);
30068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_IDLE:
30088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_wait_peer_idle(p2p);
30098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SD_DURING_FIND:
30118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_sd_during_find(p2p);
30128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROVISIONING:
30148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PD_DURING_FIND:
30168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_prov_disc_during_find(p2p);
30178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE:
30198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_invite(p2p);
30208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE_LISTEN:
30228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_invite_listen(p2p);
30238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case P2P_SEARCH_WHEN_READY:
30251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
30268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_reject(struct p2p_data *p2p, const u8 *peer_addr)
30318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
30338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
30358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Local request to reject "
30368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"connection attempts by peer " MACSTR, MAC2STR(peer_addr));
30378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
30388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR
30398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			" unknown", MAC2STR(peer_addr));
30408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
30418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->status = P2P_SC_FAIL_REJECTED_BY_USER;
30438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_USER_REJECTED;
30448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
30458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtconst char * p2p_wps_method_text(enum p2p_wps_method method)
30498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (method) {
30518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_NOT_READY:
30528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "not-ready";
30538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_PIN_DISPLAY:
30548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "Display";
30558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_PIN_KEYPAD:
30568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "Keypad";
30578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_PBC:
30588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "PBC";
30598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return "??";
30628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * p2p_go_state_text(enum p2p_go_state go_state)
30668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (go_state) {
30688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case UNKNOWN_GO:
30698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "unknown";
30708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case LOCAL_GO:
30718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "local";
30728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case  REMOTE_GO:
30738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "remote";
30748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return "??";
30778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtconst struct p2p_peer_info * p2p_get_peer_info(struct p2p_data *p2p,
30811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					       const u8 *addr, int next)
30828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
30848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr)
30868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, addr);
30878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
30888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = dl_list_first(&p2p->devices, struct p2p_device, list);
30898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev && next) {
30918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = dl_list_first(&dev->list, struct p2p_device, list);
30928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (&dev->list == &p2p->devices)
30938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev = NULL;
30948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
30971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return NULL;
30981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
30991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return &dev->info;
31001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
31011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
31021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
31031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_get_peer_info_txt(const struct p2p_peer_info *info,
31041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			  char *buf, size_t buflen)
31051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
31061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_device *dev;
31071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int res;
31081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	char *pos, *end;
31091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct os_time now;
31101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
31111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (info == NULL)
31128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
31138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	dev = (struct p2p_device *) (((u8 *) info) -
31151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				     offsetof(struct p2p_device, info));
31161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
31178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf;
31188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = buf + buflen;
31198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&now);
31218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = os_snprintf(pos, end - pos,
31228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "age=%d\n"
31238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "listen_freq=%d\n"
31248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "wps_method=%s\n"
31258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "interface_addr=" MACSTR "\n"
31268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "member_in_go_dev=" MACSTR "\n"
31278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "member_in_go_iface=" MACSTR "\n"
31288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "go_neg_req_sent=%d\n"
31298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "go_state=%s\n"
31308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dialog_token=%u\n"
31318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "intended_addr=" MACSTR "\n"
31328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "country=%c%c\n"
31338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "oper_freq=%d\n"
31348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "req_config_methods=0x%x\n"
31358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "flags=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n"
31368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "status=%d\n"
31378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "wait_count=%u\n"
31388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "invitation_reqs=%u\n",
31398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  (int) (now.sec - dev->last_seen.sec),
31408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->listen_freq,
31418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  p2p_wps_method_text(dev->wps_method),
31428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->interface_addr),
31438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->member_in_go_dev),
31448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->member_in_go_iface),
31458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->go_neg_req_sent,
31468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  p2p_go_state_text(dev->go_state),
31478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->dialog_token,
31488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->intended_addr),
31498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->country[0] ? dev->country[0] : '_',
31508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->country[1] ? dev->country[1] : '_',
31518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->oper_freq,
31528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->req_config_methods,
31538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PROBE_REQ_ONLY ?
31548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PROBE_REQ_ONLY]" : "",
31558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_REPORTED ? "[REPORTED]" : "",
31568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_NOT_YET_READY ?
31578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[NOT_YET_READY]" : "",
31588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_SD_INFO ? "[SD_INFO]" : "",
31598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_SD_SCHEDULE ? "[SD_SCHEDULE]" :
31608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "",
31618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PD_PEER_DISPLAY ?
31628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PD_PEER_DISPLAY]" : "",
31638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PD_PEER_KEYPAD ?
31648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PD_PEER_KEYPAD]" : "",
31658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_USER_REJECTED ?
31668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[USER_REJECTED]" : "",
31678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PEER_WAITING_RESPONSE ?
31688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PEER_WAITING_RESPONSE]" : "",
31698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PREFER_PERSISTENT_GROUP ?
31708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PREFER_PERSISTENT_GROUP]" : "",
31718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_WAIT_GO_NEG_RESPONSE ?
31728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[WAIT_GO_NEG_RESPONSE]" : "",
31738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM ?
31748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[WAIT_GO_NEG_CONFIRM]" : "",
31758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_GROUP_CLIENT_ONLY ?
31768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[GROUP_CLIENT_ONLY]" : "",
31778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_FORCE_FREQ ?
31788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[FORCE_FREQ]" : "",
31798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PD_FOR_JOIN ?
31808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PD_FOR_JOIN]" : "",
31818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->status,
31828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->wait_count,
31838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->invitation_reqs);
31848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0 || res >= end - pos)
31858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return pos - buf;
31868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += res;
31878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->ext_listen_period) {
31898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = os_snprintf(pos, end - pos,
31908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "ext_listen_period=%u\n"
31918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "ext_listen_interval=%u\n",
31928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  dev->ext_listen_period,
31938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  dev->ext_listen_interval);
31948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res < 0 || res >= end - pos)
31958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos - buf;
31968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += res;
31978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->oper_ssid_len) {
32008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = os_snprintf(pos, end - pos,
32018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "oper_ssid=%s\n",
32028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  wpa_ssid_txt(dev->oper_ssid,
32038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       dev->oper_ssid_len));
32048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res < 0 || res >= end - pos)
32058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos - buf;
32068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += res;
32078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return pos - buf;
32108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_peer_known(struct p2p_data *p2p, const u8 *addr)
32141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
32151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return p2p_get_device(p2p, addr) != NULL;
32161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
32171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
32181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
32198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_client_discoverability(struct p2p_data *p2p, int enabled)
32208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
32218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (enabled) {
32228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Client "
32238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"discoverability enabled");
32248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
32258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
32268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Client "
32278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"discoverability disabled");
32288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab &= ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
32298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_presence_req(u32 duration1, u32 interval1,
32348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      u32 duration2, u32 interval2)
32358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
32368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
32378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_noa_desc desc1, desc2, *ptr1 = NULL, *ptr2 = NULL;
32388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
32398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req = wpabuf_alloc(100);
32418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL)
32428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
32438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (duration1 || interval1) {
32458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(&desc1, 0, sizeof(desc1));
32468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc1.count_type = 1;
32478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc1.duration = duration1;
32488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc1.interval = interval1;
32498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ptr1 = &desc1;
32508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (duration2 || interval2) {
32528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(&desc2, 0, sizeof(desc2));
32538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc2.count_type = 2;
32548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc2.duration = duration2;
32558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc2.interval = interval2;
32568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ptr2 = &desc2;
32578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
32588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_action_hdr(req, P2P_PRESENCE_REQ, 1);
32618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(req);
32628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_noa(req, 0, 0, 0, ptr1, ptr2);
32638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(req, len);
32648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return req;
32668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_presence_req(struct p2p_data *p2p, const u8 *go_interface_addr,
32708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     const u8 *own_interface_addr, unsigned int freq,
32718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     u32 duration1, u32 interval1, u32 duration2,
32728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     u32 interval2)
32738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
32748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
32758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send Presence Request to "
32778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"GO " MACSTR " (own interface " MACSTR ") freq=%u dur1=%u "
32788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"int1=%u dur2=%u int2=%u",
32798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(go_interface_addr), MAC2STR(own_interface_addr),
32808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		freq, duration1, interval1, duration2, interval2);
32818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req = p2p_build_presence_req(duration1, interval1, duration2,
32838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     interval2);
32848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL)
32858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
32868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
32888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_send_action(p2p, freq, go_interface_addr, own_interface_addr,
32898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    go_interface_addr,
32908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpabuf_head(req), wpabuf_len(req), 200) < 0) {
32918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
32928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to send Action frame");
32938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(req);
32958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
32978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_presence_resp(u8 status, const u8 *noa,
33018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       size_t noa_len, u8 dialog_token)
33028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
33048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
33058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = wpabuf_alloc(100 + noa_len);
33078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
33088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
33098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_action_hdr(resp, P2P_PRESENCE_RESP, dialog_token);
33118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(resp);
33128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_status(resp, status);
33138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (noa) {
33148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(resp, P2P_ATTR_NOTICE_OF_ABSENCE);
33158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_le16(resp, noa_len);
33168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_data(resp, noa, noa_len);
33178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
33188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_noa(resp, 0, 0, 0, NULL, NULL);
33198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(resp, len);
33208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return resp;
33228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_req(struct p2p_data *p2p, const u8 *da,
33268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const u8 *sa, const u8 *data, size_t len,
33278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     int rx_freq)
33288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
33308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 status;
33318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
33328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t g;
33338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group *group = NULL;
33348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int parsed = 0;
33358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 noa[50];
33368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int noa_len;
33378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
33398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Received P2P Action - P2P Presence Request");
33408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (g = 0; g < p2p->num_groups; g++) {
33428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(da, p2p_group_get_interface_addr(p2p->groups[g]),
33438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      ETH_ALEN) == 0) {
33448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group = p2p->groups[g];
33458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
33468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
33478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group == NULL) {
33498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
33508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Ignore P2P Presence Request for unknown group "
33518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MACSTR, MAC2STR(da));
33528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
33538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse(data, len, &msg) < 0) {
33568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
33578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to parse P2P Presence Request");
33588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		status = P2P_SC_FAIL_INVALID_PARAMS;
33598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
33608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	parsed = 1;
33628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.noa == NULL) {
33648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
33658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No NoA attribute in P2P Presence Request");
33668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		status = P2P_SC_FAIL_INVALID_PARAMS;
33678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
33688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	status = p2p_group_presence_req(group, sa, msg.noa, msg.noa_len);
33718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail:
33738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->get_noa)
33748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		noa_len = p2p->cfg->get_noa(p2p->cfg->cb_ctx, da, noa,
33758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    sizeof(noa));
33768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
33778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		noa_len = -1;
33788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = p2p_build_presence_resp(status, noa_len > 0 ? noa : NULL,
33798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       noa_len > 0 ? noa_len : 0,
33808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       msg.dialog_token);
33818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (parsed)
33828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
33838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
33848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
33858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
33878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_send_action(p2p, rx_freq, sa, da, da,
33888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
33898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
33908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to send Action frame");
33918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(resp);
33938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_resp(struct p2p_data *p2p, const u8 *da,
33978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *sa, const u8 *data, size_t len)
33988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
34008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
34028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Received P2P Action - P2P Presence Response");
34038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse(data, len, &msg) < 0) {
34058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
34068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to parse P2P Presence Response");
34078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
34088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.status == NULL || msg.noa == NULL) {
34118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
34128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No Status or NoA attribute in P2P Presence "
34138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Response");
34148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
34158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
34168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*msg.status) {
34198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
34208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: P2P Presence Request was rejected: status %u",
34218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*msg.status);
34228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
34238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
34248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
34278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: P2P Presence Request was accepted");
34288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "P2P: P2P Presence Response - NoA",
34298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    msg.noa, msg.noa_len);
34308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: process NoA */
34318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
34328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_ext_listen_timeout(void *eloop_ctx, void *timeout_ctx)
34368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
34388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval) {
34408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Schedule next extended listen timeout */
34418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(p2p->ext_listen_interval_sec,
34428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p->ext_listen_interval_usec,
34438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p_ext_listen_timeout, p2p, NULL);
34448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_LISTEN_ONLY && p2p->ext_listen_only) {
34478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
34488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * This should not really happen, but it looks like the Listen
34498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * command may fail is something else (e.g., a scan) was
34508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * running at an inconvenient time. As a workaround, allow new
34518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Extended Listen operation to be started.
34528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
34538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Previous "
34548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Extended Listen operation had not been completed - "
34558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"try again");
34568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_only = 0;
34578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
34588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state != P2P_IDLE) {
34618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Skip Extended "
34628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Listen timeout in active state (%s)",
34638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_state_txt(p2p->state));
34648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
34658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Extended Listen timeout");
34688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_only = 1;
34698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_listen(p2p, p2p->ext_listen_period) < 0) {
34708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Failed to start "
34718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Listen state for Extended Listen Timing");
34728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_only = 0;
34738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_ext_listen(struct p2p_data *p2p, unsigned int period,
34788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   unsigned int interval)
34798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (period > 65535 || interval > 65535 || period > interval ||
34818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (period == 0 && interval > 0) || (period > 0 && interval == 0)) {
34828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
34838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Invalid Extended Listen Timing request: "
34848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"period=%u interval=%u", period, interval);
34858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
34868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_ext_listen_timeout, p2p, NULL);
34898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (interval == 0) {
34918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
34928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Disabling Extended Listen Timing");
34938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_period = 0;
34948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_interval = 0;
34958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
34968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
34998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Enabling Extended Listen Timing: period %u msec, "
35008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"interval %u msec", period, interval);
35018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_period = period;
35028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_interval = interval;
35038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_interval_sec = interval / 1000;
35048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_interval_usec = (interval % 1000) * 1000;
35058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(p2p->ext_listen_interval_sec,
35078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p->ext_listen_interval_usec,
35088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p_ext_listen_timeout, p2p, NULL);
35098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
35118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
35128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_deauth_notif(struct p2p_data *p2p, const u8 *bssid, u16 reason_code,
35158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      const u8 *ie, size_t ie_len)
35168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
35178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
35188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bssid == NULL || ie == NULL)
35208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
35218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
35238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg))
35248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
35258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.minor_reason_code == NULL)
35268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
35278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_INFO,
35298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Deauthentication notification BSSID " MACSTR
35308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" reason_code=%u minor_reason_code=%u",
35318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(bssid), reason_code, *msg.minor_reason_code);
35328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
35348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
35358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_disassoc_notif(struct p2p_data *p2p, const u8 *bssid, u16 reason_code,
35388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const u8 *ie, size_t ie_len)
35398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
35408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
35418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bssid == NULL || ie == NULL)
35438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
35448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
35468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg))
35478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
35488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.minor_reason_code == NULL)
35498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
35508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_INFO,
35528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Disassociation notification BSSID " MACSTR
35538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" reason_code=%u minor_reason_code=%u",
35548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(bssid), reason_code, *msg.minor_reason_code);
35558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
35578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
35588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_managed_oper(struct p2p_data *p2p, int enabled)
35618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
35628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (enabled) {
35638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Managed P2P "
35648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Device operations enabled");
35658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_INFRA_MANAGED;
35668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
35678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Managed P2P "
35688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Device operations disabled");
35698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab &= ~P2P_DEV_CAPAB_INFRA_MANAGED;
35708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
35718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
35728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel)
35758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
35768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_channel_to_freq(p2p->cfg->country, reg_class, channel) < 0)
35778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
35788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Set Listen channel: "
35808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"reg_class %u channel %u", reg_class, channel);
35818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->reg_class = reg_class;
35828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->channel = channel;
35838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
35858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
35868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_ssid_postfix(struct p2p_data *p2p, const u8 *postfix, size_t len)
35898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
35908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "P2P: New SSID postfix", postfix, len);
35918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (postfix == NULL) {
35928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->ssid_postfix_len = 0;
35938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
35948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
35958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > sizeof(p2p->cfg->ssid_postfix))
35968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
35978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->ssid_postfix, postfix, len);
35988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->ssid_postfix_len = len;
35998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
36008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
36018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
360375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenint p2p_set_oper_channel(struct p2p_data *p2p, u8 op_reg_class, u8 op_channel,
360475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			 int cfg_op_channel)
360575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
360675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p_channel_to_freq(p2p->cfg->country, op_reg_class, op_channel)
360775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	    < 0)
360875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return -1;
360975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
361075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, "P2P: Set Operating channel: "
361175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		"reg_class %u channel %u", op_reg_class, op_channel);
361275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->cfg->op_reg_class = op_reg_class;
361375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->cfg->op_channel = op_channel;
361475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->cfg->cfg_op_channel = cfg_op_channel;
361575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	return 0;
361675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
361775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
361875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
36198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_interface_addr(struct p2p_data *p2p, const u8 *dev_addr,
36208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   u8 *iface_addr)
36218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
36228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p_get_device(p2p, dev_addr);
36238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL || is_zero_ether_addr(dev->interface_addr))
36248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
36258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(iface_addr, dev->interface_addr, ETH_ALEN);
36268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
36278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
36288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_dev_addr(struct p2p_data *p2p, const u8 *iface_addr,
36318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   u8 *dev_addr)
36328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
36338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p_get_device_interface(p2p, iface_addr);
36348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
36358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
36368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev_addr, dev->info.p2p_device_addr, ETH_ALEN);
36378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
36388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
36398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_peer_filter(struct p2p_data *p2p, const u8 *addr)
36428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
36438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->peer_filter, addr, ETH_ALEN);
36448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (is_zero_ether_addr(p2p->peer_filter))
36458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Disable peer "
36468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"filter");
36478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
36488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Enable peer "
36498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"filter for " MACSTR, MAC2STR(p2p->peer_filter));
36508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
36518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_cross_connect(struct p2p_data *p2p, int enabled)
36548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
36558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Cross connection %s",
36568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		enabled ? "enabled" : "disabled");
36578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cross_connect == enabled)
36588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
36598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cross_connect = enabled;
36608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: may need to tear down any action group where we are GO(?) */
36618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
36628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_oper_freq(struct p2p_data *p2p, const u8 *iface_addr)
36658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
36668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p_get_device_interface(p2p, iface_addr);
36678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
36688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
36698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->oper_freq <= 0)
36708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
36718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return dev->oper_freq;
36728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
36738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_intra_bss_dist(struct p2p_data *p2p, int enabled)
36768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
36778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Intra BSS distribution %s",
36788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		enabled ? "enabled" : "disabled");
36798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->p2p_intra_bss = enabled;
36808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
36818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_update_channel_list(struct p2p_data *p2p, struct p2p_channels *chan)
36848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
36858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Update channel list");
36868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&p2p->cfg->channels, chan, sizeof(struct p2p_channels));
36878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
36888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_send_action(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
36918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    const u8 *src, const u8 *bssid, const u8 *buf,
36928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    size_t len, unsigned int wait_time)
36938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
36948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
36958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Delay Action "
36968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"frame TX until p2p_scan completes");
36978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->after_scan_tx) {
36988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Dropped "
36998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"previous pending Action frame TX");
37008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(p2p->after_scan_tx);
37018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
37028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = os_malloc(sizeof(*p2p->after_scan_tx) +
37038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       len);
37048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->after_scan_tx == NULL)
37058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
37068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx->freq = freq;
37078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx->dst, dst, ETH_ALEN);
37088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx->src, src, ETH_ALEN);
37098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx->bssid, bssid, ETH_ALEN);
37108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx->len = len;
37118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx->wait_time = wait_time;
37128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx + 1, buf, len);
37138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
37148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, dst, src, bssid,
37178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     buf, len, wait_time);
37188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
37198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_best_channels(struct p2p_data *p2p, int freq_24, int freq_5,
37228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   int freq_overall)
37238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
37248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Best channel: 2.4 GHz: %d,"
37258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  5 GHz: %d,  overall: %d", freq_24, freq_5, freq_overall);
37268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->best_freq_24 = freq_24;
37278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->best_freq_5 = freq_5;
37288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->best_freq_overall = freq_overall;
37298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
37308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * p2p_get_go_neg_peer(struct p2p_data *p2p)
37338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
37348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p == NULL || p2p->go_neg_peer == NULL)
37358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
37368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p->go_neg_peer->info.p2p_device_addr;
37378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
37388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst struct p2p_peer_info *
37418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtp2p_get_peer_found(struct p2p_data *p2p, const u8 *addr, int next)
37428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
37438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
37448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr) {
37468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, addr);
37478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!dev)
37488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
37498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!next) {
37518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev->flags & P2P_DEV_PROBE_REQ_ONLY)
37528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return NULL;
37538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return &dev->info;
37558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
37568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			do {
37578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev = dl_list_first(&dev->list,
37588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    struct p2p_device,
37598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    list);
37608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				if (&dev->list == &p2p->devices)
37618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					return NULL;
37628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} while (dev->flags & P2P_DEV_PROBE_REQ_ONLY);
37638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
37648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
37658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = dl_list_first(&p2p->devices, struct p2p_device, list);
37668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!dev)
37678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
37688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (dev->flags & P2P_DEV_PROBE_REQ_ONLY) {
37698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev = dl_list_first(&dev->list,
37708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    struct p2p_device,
37718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    list);
37728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (&dev->list == &p2p->devices)
37738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return NULL;
37748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
37758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return &dev->info;
37788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
37791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
37801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef ANDROID_P2P
37811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_search_in_progress(struct p2p_data *p2p)
37821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
37831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p == NULL)
37841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
37851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
37861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return p2p->state == P2P_SEARCH;
37871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
37881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif
37891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
37901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint p2p_in_progress(struct p2p_data *p2p)
37911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
37921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p == NULL)
37931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
37941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return p2p->state != P2P_IDLE && p2p->state != P2P_PROVISIONING;
37951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
3796