p2p.c revision c55524ad84d13014e8019491c2b17e5dcf13545a
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"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_common.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps/wps_i.h"
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p_i.h"
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p.h"
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_state_timeout(void *eloop_ctx, void *timeout_ctx);
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev);
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_req(struct p2p_data *p2p, const u8 *da,
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const u8 *sa, const u8 *data, size_t len,
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     int rx_freq);
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_resp(struct p2p_data *p2p, const u8 *da,
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *sa, const u8 *data,
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      size_t len);
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_ext_listen_timeout(void *eloop_ctx, void *timeout_ctx);
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_scan_timeout(void *eloop_ctx, void *timeout_ctx);
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_scan recovery timeout
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Many drivers are using 30 second timeout on scan results. Allow a bit larger
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * timeout for this to avoid hitting P2P timeout unnecessarily.
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define P2P_SCAN_TIMEOUT 35
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * P2P_PEER_EXPIRATION_AGE - Number of seconds after which inactive peer
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * entries will be removed
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define P2P_PEER_EXPIRATION_AGE 300
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define P2P_PEER_EXPIRATION_INTERVAL (P2P_PEER_EXPIRATION_AGE / 2)
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_expire_peers(struct p2p_data *p2p)
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev, *n;
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct os_time now;
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&now);
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each_safe(dev, n, &p2p->devices, struct p2p_device, list) {
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->last_seen.sec + P2P_PEER_EXPIRATION_AGE >= now.sec)
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Expiring old peer "
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"entry " MACSTR, MAC2STR(dev->info.p2p_device_addr));
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dl_list_del(&dev->list);
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_device_free(p2p, dev);
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_expiration_timeout(void *eloop_ctx, void *timeout_ctx)
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_expire_peers(p2p);
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(P2P_PEER_EXPIRATION_INTERVAL, 0,
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p_expiration_timeout, p2p, NULL);
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * p2p_state_txt(int state)
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (state) {
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_IDLE:
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "IDLE";
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SEARCH:
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "SEARCH";
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT:
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "CONNECT";
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT_LISTEN:
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "CONNECT_LISTEN";
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG:
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "GO_NEG";
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_LISTEN_ONLY:
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "LISTEN_ONLY";
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_CONNECT:
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "WAIT_PEER_CONNECT";
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_IDLE:
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "WAIT_PEER_IDLE";
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SD_DURING_FIND:
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "SD_DURING_FIND";
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROVISIONING:
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "PROVISIONING";
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PD_DURING_FIND:
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "PD_DURING_FIND";
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE:
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "INVITE";
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE_LISTEN:
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "INVITE_LISTEN";
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "?";
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_state(struct p2p_data *p2p, int new_state)
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: State %s -> %s",
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state), p2p_state_txt(new_state));
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->state = new_state;
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_timeout(struct p2p_data *p2p, unsigned int sec, unsigned int usec)
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Set timeout (state=%s): %u.%06u sec",
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state), sec, usec);
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_state_timeout, p2p, NULL);
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(sec, usec, p2p_state_timeout, p2p, NULL);
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_clear_timeout(struct p2p_data *p2p)
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Clear timeout (state=%s)",
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state));
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_state_timeout, p2p, NULL);
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_go_neg_failed(struct p2p_data *p2p, struct p2p_device *peer,
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       int status)
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_go_neg_results res;
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_IDLE);
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer = NULL;
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&res, 0, sizeof(res));
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.status = status;
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (peer) {
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(res.peer_device_addr, peer->info.p2p_device_addr,
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(res.peer_interface_addr, peer->intended_addr,
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->go_neg_completed(p2p->cfg->cb_ctx, &res);
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_listen_in_find(struct p2p_data *p2p)
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int r, tu;
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *ies;
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Starting short listen state (state=%s)",
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state));
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	freq = p2p_channel_to_freq(p2p->cfg->country, p2p->cfg->reg_class,
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   p2p->cfg->channel);
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq < 0) {
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Unknown regulatory class/channel");
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_random((u8 *) &r, sizeof(r));
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tu = (r % ((p2p->max_disc_int - p2p->min_disc_int) + 1) +
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	      p2p->min_disc_int) * 100;
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_freq = freq;
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_sec = 0;
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_usec = 1024 * tu;
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ies = p2p_build_probe_resp_ies(p2p);
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ies == NULL)
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->start_listen(p2p->cfg->cb_ctx, freq, 1024 * tu / 1000,
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    ies) < 0) {
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to start listen mode");
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_freq = 0;
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(ies);
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_listen(struct p2p_data *p2p, unsigned int timeout)
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *ies;
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Going to listen(only) state");
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	freq = p2p_channel_to_freq(p2p->cfg->country, p2p->cfg->reg_class,
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   p2p->cfg->channel);
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq < 0) {
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Unknown regulatory class/channel");
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_freq = freq;
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_sec = timeout / 1000;
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_usec = (timeout % 1000) * 1000;
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: p2p_scan running - delay start of listen state");
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->start_after_scan = P2P_AFTER_SCAN_LISTEN;
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ies = p2p_build_probe_resp_ies(p2p);
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ies == NULL)
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->start_listen(p2p->cfg->cb_ctx, freq, timeout, ies) < 0) {
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to start listen mode");
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_freq = 0;
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(ies);
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(ies);
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_LISTEN_ONLY);
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_device_clear_reported(struct p2p_data *p2p)
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list)
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~P2P_DEV_REPORTED;
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_get_device - Fetch a peer entry
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: P2P Device Address of the peer
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the device entry or %NULL if not found
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_device * p2p_get_device(struct p2p_data *p2p, const u8 *addr)
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(dev->info.p2p_device_addr, addr, ETH_ALEN) == 0)
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return dev;
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_get_device_interface - Fetch a peer entry based on P2P Interface Address
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: P2P Interface Address of the peer
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the device entry or %NULL if not found
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_device * p2p_get_device_interface(struct p2p_data *p2p,
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     const u8 *addr)
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(dev->interface_addr, addr, ETH_ALEN) == 0)
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return dev;
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_create_device - Create a peer entry
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: P2P Device Address of the peer
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the device entry or %NULL on failure
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * If there is already an entry for the peer, it will be returned instead of
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * creating a new one.
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct p2p_device * p2p_create_device(struct p2p_data *p2p,
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     const u8 *addr)
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev, *oldest = NULL;
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t count = 0;
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev)
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return dev;
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		count++;
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (oldest == NULL ||
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_time_before(&dev->last_seen, &oldest->last_seen))
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			oldest = dev;
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (count + 1 > p2p->cfg->max_peers && oldest) {
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Remove oldest peer entry to make room for a new "
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"peer");
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dl_list_del(&oldest->list);
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_device_free(p2p, oldest);
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = os_zalloc(sizeof(*dev));
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_add(&p2p->devices, &dev->list);
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.p2p_device_addr, addr, ETH_ALEN);
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return dev;
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_copy_client_info(struct p2p_device *dev,
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 struct p2p_client_info *cli)
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.device_name, cli->dev_name, cli->dev_name_len);
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.device_name[cli->dev_name_len] = '\0';
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.dev_capab = cli->dev_capab;
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.config_methods = cli->config_methods;
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.pri_dev_type, cli->pri_dev_type, 8);
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->info.wps_sec_dev_type_list_len = 8 * cli->num_sec_dev_types;
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.wps_sec_dev_type_list, cli->sec_dev_types,
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  dev->info.wps_sec_dev_type_list_len);
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_add_group_clients(struct p2p_data *p2p, const u8 *go_dev_addr,
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const u8 *go_interface_addr, int freq,
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const u8 *gi, size_t gi_len)
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_info info;
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t c;
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gi == NULL)
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_group_info_parse(gi, gi_len, &info) < 0)
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Clear old data for this group; if the devices are still in the
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * group, the information will be restored in the loop following this.
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcpy(dev->member_in_go_iface, go_interface_addr,
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      ETH_ALEN) == 0) {
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(dev->member_in_go_iface, 0, ETH_ALEN);
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(dev->member_in_go_dev, 0, ETH_ALEN);
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (c = 0; c < info.num_clients; c++) {
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct p2p_client_info *cli = &info.client[c];
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, cli->p2p_device_addr);
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev) {
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * Update information only if we have not received this
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * directly from the client.
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev->flags & (P2P_DEV_GROUP_CLIENT_ONLY |
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  P2P_DEV_PROBE_REQ_ONLY))
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p_copy_client_info(dev, cli);
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev->flags & P2P_DEV_PROBE_REQ_ONLY) {
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev->flags &= ~P2P_DEV_PROBE_REQ_ONLY;
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev = p2p_create_device(p2p, cli->p2p_device_addr);
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev == NULL)
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				continue;
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->flags |= P2P_DEV_GROUP_CLIENT_ONLY;
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_copy_client_info(dev, cli);
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->oper_freq = freq;
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->cfg->dev_found(p2p->cfg->cb_ctx,
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    dev->info.p2p_device_addr,
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    &dev->info, 1);
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->interface_addr, cli->p2p_interface_addr,
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_get_time(&dev->last_seen);
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->member_in_go_dev, go_dev_addr, ETH_ALEN);
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->member_in_go_iface, go_interface_addr,
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_copy_wps_info(struct p2p_device *dev, int probe_req,
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      const struct p2p_message *msg)
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->info.device_name, msg->device_name,
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  sizeof(dev->info.device_name));
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->manufacturer &&
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->manufacturer_len < sizeof(dev->info.manufacturer)) {
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.manufacturer, 0,
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.manufacturer));
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.manufacturer, msg->manufacturer,
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->manufacturer_len);
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->model_name &&
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->model_name_len < sizeof(dev->info.model_name)) {
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.model_name, 0,
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.model_name));
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.model_name, msg->model_name,
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->model_name_len);
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->model_number &&
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->model_number_len < sizeof(dev->info.model_number)) {
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.model_number, 0,
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.model_number));
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.model_number, msg->model_number,
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->model_number_len);
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->serial_number &&
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg->serial_number_len < sizeof(dev->info.serial_number)) {
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(dev->info.serial_number, 0,
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.serial_number));
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.serial_number, msg->serial_number,
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->serial_number_len);
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->pri_dev_type)
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.pri_dev_type, msg->pri_dev_type,
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.pri_dev_type));
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (msg->wps_pri_dev_type)
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.pri_dev_type, msg->wps_pri_dev_type,
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(dev->info.pri_dev_type));
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->wps_sec_dev_type_list) {
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->info.wps_sec_dev_type_list,
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->wps_sec_dev_type_list,
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg->wps_sec_dev_type_list_len);
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_sec_dev_type_list_len =
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg->wps_sec_dev_type_list_len;
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->capability) {
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.dev_capab = msg->capability[0];
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.group_capab = msg->capability[1];
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->ext_listen_timing) {
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->ext_listen_period = WPA_GET_LE16(msg->ext_listen_timing);
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->ext_listen_interval =
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			WPA_GET_LE16(msg->ext_listen_timing + 2);
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!probe_req) {
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.config_methods = msg->config_methods ?
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg->config_methods : msg->wps_config_methods;
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_add_device - Add peer entries based on scan results
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: Source address of Beacon or Probe Response frame (may be either
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *	P2P Device Address or P2P Interface Address)
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @level: Signal level (signal strength of the received frame from the peer)
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @freq: Frequency on which the Beacon or Probe Response frame was received
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ies: IEs from the Beacon or Probe Response frame
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ies_len: Length of ies buffer in octets
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * If the scan result is for a GO, the clients in the group will also be added
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to the peer table. This function can also be used with some other frames
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * like Provision Discovery Request that contains P2P Capability and P2P Device
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Info attributes.
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq, int level,
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *ies, size_t ies_len)
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *p2p_dev_addr;
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ies, ies_len, &msg)) {
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to parse P2P IE for a device entry");
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.p2p_device_addr)
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_addr = msg.p2p_device_addr;
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (msg.device_id)
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_addr = msg.device_id;
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Ignore scan data without P2P Device Info or "
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P Device Id");
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!is_zero_ether_addr(p2p->peer_filter) &&
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(p2p_dev_addr, p2p->peer_filter, ETH_ALEN) != 0) {
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Do not add peer "
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"filter for " MACSTR " due to peer filter",
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(p2p_dev_addr));
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_create_device(p2p, p2p_dev_addr);
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&dev->last_seen);
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~(P2P_DEV_PROBE_REQ_ONLY | P2P_DEV_GROUP_CLIENT_ONLY);
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(addr, p2p_dev_addr, ETH_ALEN) != 0)
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->interface_addr, addr, ETH_ALEN);
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.ssid &&
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (msg.ssid[1] != P2P_WILDCARD_SSID_LEN ||
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     os_memcmp(msg.ssid + 2, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN)
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     != 0)) {
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->oper_ssid, msg.ssid + 2, msg.ssid[1]);
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->oper_ssid_len = msg.ssid[1];
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq >= 2412 && freq <= 2484 && msg.ds_params &&
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    *msg.ds_params >= 1 && *msg.ds_params <= 14) {
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int ds_freq;
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*msg.ds_params == 14)
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ds_freq = 2484;
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ds_freq = 2407 + *msg.ds_params * 5;
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freq != ds_freq) {
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Update Listen frequency based on DS "
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Parameter Set IE: %d -> %d MHz",
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				freq, ds_freq);
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq = ds_freq;
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->listen_freq && dev->listen_freq != freq) {
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Update Listen frequency based on scan "
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"results (" MACSTR " %d -> %d MHz (DS param %d)",
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr), dev->listen_freq,
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq, msg.ds_params ? *msg.ds_params : -1);
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->listen_freq = freq;
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.group_info)
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->oper_freq = freq;
57975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	dev->info.level = level;
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_copy_wps_info(dev, 0, &msg);
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(dev->info.wps_vendor_ext[i]);
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_vendor_ext[i] = NULL;
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (msg.wps_vendor_ext[i] == NULL)
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_vendor_ext[i] = wpabuf_alloc_copy(
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg.wps_vendor_ext[i], msg.wps_vendor_ext_len[i]);
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->info.wps_vendor_ext[i] == NULL)
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_add_group_clients(p2p, p2p_dev_addr, addr, freq, msg.group_info,
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      msg.group_info_len);
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_pending_sd_req(p2p, dev))
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags |= P2P_DEV_SD_SCHEDULE;
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_REPORTED)
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Peer found with Listen frequency %d MHz", freq);
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_USER_REJECTED) {
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Do not report rejected device");
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->dev_found(p2p->cfg->cb_ctx, addr, &dev->info,
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    !(dev->flags & P2P_DEV_REPORTED_ONCE));
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev)
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == dev)
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->go_neg_peer = NULL;
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->invite_peer == dev)
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->invite_peer = NULL;
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->sd_peer == dev)
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->sd_peer = NULL;
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->pending_client_disc_go == dev)
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_client_disc_go = NULL;
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
637c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	/* dev_lost() device, but only if it was previously dev_found() */
638c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	if (dev->flags & P2P_DEV_REPORTED_ONCE)
639c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		p2p->cfg->dev_lost(p2p->cfg->cb_ctx,
640c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt				   dev->info.p2p_device_addr);
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(dev->info.wps_vendor_ext[i]);
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.wps_vendor_ext[i] = NULL;
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(dev);
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_get_next_prog_freq(struct p2p_data *p2p)
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_channels *c;
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_reg_class *cla;
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t cl, ch;
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int found = 0;
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 reg_class;
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 channel;
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	c = &p2p->cfg->channels;
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (cl = 0; cl < c->reg_classes; cl++) {
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cla = &c->reg_class[cl];
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (cla->reg_class != p2p->last_prog_scan_class)
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (ch = 0; ch < cla->channels; ch++) {
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (cla->channel[ch] == p2p->last_prog_scan_chan) {
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				found = 1;
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (found)
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!found) {
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Start from beginning */
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reg_class = c->reg_class[0].reg_class;
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		channel = c->reg_class[0].channel[0];
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Pick the next channel */
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ch++;
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ch == cla->channels) {
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			cl++;
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (cl == c->reg_classes)
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				cl = 0;
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ch = 0;
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reg_class = c->reg_class[cl].reg_class;
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		channel = c->reg_class[cl].channel[ch];
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	freq = p2p_channel_to_freq(p2p->cfg->country, reg_class, channel);
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Next progressive search "
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"channel: reg_class %u channel %u -> %d MHz",
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reg_class, channel, freq);
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->last_prog_scan_class = reg_class;
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->last_prog_scan_chan = channel;
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq == 2412 || freq == 2437 || freq == 2462)
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* No need to add social channels */
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return freq;
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_search(struct p2p_data *p2p)
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq = 0;
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum p2p_scan_type type;
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->drv_in_listen) {
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Driver is still "
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"in Listen state - wait for it to end before "
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"continuing");
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer) {
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Only scan the known listen frequency of the peer
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * during GO Negotiation start.
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		freq = p2p->go_neg_peer->listen_freq;
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freq <= 0)
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq = p2p->go_neg_peer->oper_freq;
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type = P2P_SCAN_SPECIFIC;
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting search "
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"for freq %u (GO Neg)", freq);
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (p2p->invite_peer) {
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Only scan the known listen frequency of the peer
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * during Invite start.
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		freq = p2p->invite_peer->listen_freq;
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freq <= 0)
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq = p2p->invite_peer->oper_freq;
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type = P2P_SCAN_SPECIFIC;
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting search "
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"for freq %u (Invite)", freq);
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (p2p->find_type == P2P_FIND_PROGRESSIVE &&
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (freq = p2p_get_next_prog_freq(p2p)) > 0) {
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type = P2P_SCAN_SOCIAL_PLUS_ONE;
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting search "
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"(+ freq %u)", freq);
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type = P2P_SCAN_SOCIAL;
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting search");
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, type, freq,
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p->num_req_dev_types, p2p->req_dev_types) < 0)
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Scan request failed");
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Running p2p_scan");
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->p2p_scan_running = 1;
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(P2P_SCAN_TIMEOUT, 0, p2p_scan_timeout,
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p, NULL);
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_find_timeout(void *eloop_ctx, void *timeout_ctx)
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Find timeout -> stop");
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_stop_find(p2p);
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_run_after_scan(struct p2p_data *p2p)
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum p2p_after_scan op;
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->after_scan_tx) {
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int ret;
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO: schedule p2p_run_after_scan to be called from TX
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * status callback(?) */
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send pending "
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Action frame at p2p_scan completion");
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = p2p->cfg->send_action(p2p->cfg->cb_ctx,
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    p2p->after_scan_tx->freq,
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    p2p->after_scan_tx->dst,
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    p2p->after_scan_tx->src,
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    p2p->after_scan_tx->bssid,
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    (u8 *) (p2p->after_scan_tx + 1),
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    p2p->after_scan_tx->len,
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    p2p->after_scan_tx->wait_time);
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p2p->after_scan_tx);
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = NULL;
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	op = p2p->start_after_scan;
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (op) {
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_AFTER_SCAN_NOTHING:
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_AFTER_SCAN_LISTEN:
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Start previously "
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"requested Listen state");
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_listen(p2p, p2p->pending_listen_sec * 1000 +
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   p2p->pending_listen_usec / 1000);
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_AFTER_SCAN_CONNECT:
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Start previously "
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"requested connect with " MACSTR,
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(p2p->after_scan_peer));
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, p2p->after_scan_peer);
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev == NULL) {
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer not "
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"known anymore");
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, dev);
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_scan_timeout(void *eloop_ctx, void *timeout_ctx)
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int running;
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan timeout "
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"(running=%d)", p2p->p2p_scan_running);
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	running = p2p->p2p_scan_running;
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Make sure we recover from missed scan results callback */
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->p2p_scan_running = 0;
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (running)
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_run_after_scan(p2p);
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_free_req_dev_types(struct p2p_data *p2p)
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->num_req_dev_types = 0;
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->req_dev_types);
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->req_dev_types = NULL;
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_find(struct p2p_data *p2p, unsigned int timeout,
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     enum p2p_discovery_type type,
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     unsigned int num_req_dev_types, const u8 *req_dev_types)
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting find (type=%d)",
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type);
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan is "
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"already running");
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_req_dev_types(p2p);
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req_dev_types && num_req_dev_types) {
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->req_dev_types = os_malloc(num_req_dev_types *
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       WPS_DEV_TYPE_LEN);
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->req_dev_types == NULL)
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->req_dev_types, req_dev_types,
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  num_req_dev_types * WPS_DEV_TYPE_LEN);
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->num_req_dev_types = num_req_dev_types;
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->find_type = type;
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_device_clear_reported(p2p);
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_SEARCH);
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (timeout)
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(timeout, 0, p2p_find_timeout,
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p, NULL);
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (type) {
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_FIND_START_WITH_FULL:
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_FIND_PROGRESSIVE:
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_FULL, 0,
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 p2p->num_req_dev_types,
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 p2p->req_dev_types);
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_FIND_ONLY_SOCIAL:
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_SOCIAL, 0,
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 p2p->num_req_dev_types,
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 p2p->req_dev_types);
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res == 0) {
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Running p2p_scan");
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->p2p_scan_running = 1;
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(P2P_SCAN_TIMEOUT, 0, p2p_scan_timeout,
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p, NULL);
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Failed to start "
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"p2p_scan");
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_stop_find_for_freq(struct p2p_data *p2p, int freq)
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Stopping find");
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_IDLE);
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_req_dev_types(p2p);
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer = NULL;
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->sd_peer = NULL;
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->invite_peer = NULL;
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq > 0 && p2p->drv_in_listen == freq && p2p->in_listen) {
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Skip stop_listen "
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"since we are on correct channel for response");
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_stop_find(struct p2p_data *p2p)
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_stop_find_for_freq(p2p, 0);
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_prepare_channel(struct p2p_data *p2p, unsigned int force_freq)
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (force_freq) {
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 op_reg_class, op_channel;
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p_freq_to_channel(p2p->cfg->country, force_freq,
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					&op_reg_class, &op_channel) < 0) {
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Unsupported frequency %u MHz",
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				force_freq);
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!p2p_channels_includes(&p2p->cfg->channels, op_reg_class,
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   op_channel)) {
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Frequency %u MHz (oper_class %u "
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"channel %u) not allowed for P2P",
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				force_freq, op_reg_class, op_channel);
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->op_reg_class = op_reg_class;
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->op_channel = op_channel;
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->channels.reg_classes = 1;
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->channels.reg_class[0].channels = 1;
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->channels.reg_class[0].reg_class = p2p->op_reg_class;
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->channels.reg_class[0].channel[0] = p2p->op_channel;
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 op_reg_class, op_channel;
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!p2p->cfg->cfg_op_channel && p2p->best_freq_overall > 0 &&
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    p2p_supported_freq(p2p, p2p->best_freq_overall) &&
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    p2p_freq_to_channel(p2p->cfg->country,
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					p2p->best_freq_overall,
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					&op_reg_class, &op_channel) == 0) {
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Select best overall channel as "
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"operating channel preference");
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->op_reg_class = op_reg_class;
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->op_channel = op_channel;
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (!p2p->cfg->cfg_op_channel && p2p->best_freq_5 > 0 &&
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   p2p_supported_freq(p2p, p2p->best_freq_5) &&
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   p2p_freq_to_channel(p2p->cfg->country,
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       p2p->best_freq_5,
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       &op_reg_class, &op_channel) ==
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   0) {
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Select best 5 GHz channel as "
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"operating channel preference");
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->op_reg_class = op_reg_class;
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->op_channel = op_channel;
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (!p2p->cfg->cfg_op_channel &&
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   p2p->best_freq_24 > 0 &&
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   p2p_supported_freq(p2p, p2p->best_freq_24) &&
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   p2p_freq_to_channel(p2p->cfg->country,
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       p2p->best_freq_24,
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       &op_reg_class, &op_channel) ==
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   0) {
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Select best 2.4 GHz channel as "
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"operating channel preference");
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->op_reg_class = op_reg_class;
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->op_channel = op_channel;
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->op_reg_class = p2p->cfg->op_reg_class;
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->op_channel = p2p->cfg->op_channel;
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(&p2p->channels, &p2p->cfg->channels,
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(struct p2p_channels));
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Own preference for operation channel: "
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"Operating Class %u Channel %u%s",
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->op_reg_class, p2p->op_channel,
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		force_freq ? " (forced)" : "");
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		enum p2p_wps_method wps_method,
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int go_intent, const u8 *own_interface_addr,
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		unsigned int force_freq, int persistent_group)
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Request to start group negotiation - peer=" MACSTR
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  GO Intent=%d  Intended Interface Address=" MACSTR
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" wps_method=%d persistent_group=%d",
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wps_method, persistent_group);
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_prepare_channel(p2p, force_freq) < 0)
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Cannot connect to unknown P2P Device " MACSTR,
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(peer_addr));
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!(dev->info.dev_capab &
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Cannot connect to P2P Device " MACSTR
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				" that is in a group and is not discoverable",
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(peer_addr));
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->oper_freq <= 0) {
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Cannot connect to P2P Device " MACSTR
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				" with incomplete information",
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(peer_addr));
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * First, try to connect directly. If the peer does not
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * acknowledge frames, assume it is sleeping and use device
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * discoverability via the GO at that point.
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_NOT_YET_READY;
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_USER_REJECTED;
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE;
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM;
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->connect_reqs = 0;
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_neg_req_sent = 0;
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_state = UNKNOWN_GO;
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (persistent_group)
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP;
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~P2P_DEV_PREFER_PERSISTENT_GROUP;
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_intent = go_intent;
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state != P2P_IDLE)
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_stop_find(p2p);
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->after_scan_tx) {
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * We need to drop the pending frame to avoid issues with the
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * new GO Negotiation, e.g., when the pending frame was from a
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * previous attempt at starting a GO Negotiation.
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Dropped "
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"previous pending Action frame TX that was waiting "
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"for p2p_scan completion");
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p2p->after_scan_tx);
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = NULL;
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wps_method = wps_method;
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->status = P2P_SC_SUCCESS;
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (force_freq)
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags |= P2P_DEV_FORCE_FREQ;
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~P2P_DEV_FORCE_FREQ;
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: p2p_scan running - delay connect send");
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->start_after_scan = P2P_AFTER_SCAN_CONNECT;
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_peer, peer_addr, ETH_ALEN);
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_connect_send(p2p, dev);
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  enum p2p_wps_method wps_method,
11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  int go_intent, const u8 *own_interface_addr,
11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  unsigned int force_freq, int persistent_group)
11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Request to authorize group negotiation - peer=" MACSTR
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  GO Intent=%d  Intended Interface Address=" MACSTR
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" wps_method=%d  persistent_group=%d",
11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wps_method, persistent_group);
11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_prepare_channel(p2p, force_freq) < 0)
11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Cannot authorize unknown P2P Device " MACSTR,
11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(peer_addr));
11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_NOT_YET_READY;
11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_USER_REJECTED;
11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_neg_req_sent = 0;
11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->go_state = UNKNOWN_GO;
11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (persistent_group)
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP;
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~P2P_DEV_PREFER_PERSISTENT_GROUP;
11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_intent = go_intent;
11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wps_method = wps_method;
11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->status = P2P_SC_SUCCESS;
11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (force_freq)
11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags |= P2P_DEV_FORCE_FREQ;
11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~P2P_DEV_FORCE_FREQ;
11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_add_dev_info(struct p2p_data *p2p, const u8 *addr,
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      struct p2p_device *dev, struct p2p_message *msg)
11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&dev->last_seen);
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_copy_wps_info(dev, 0, msg);
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->listen_channel) {
11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int freq;
11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		freq = p2p_channel_to_freq((char *) msg->listen_channel,
11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   msg->listen_channel[3],
11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   msg->listen_channel[4]);
11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freq < 0) {
11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Unknown peer Listen channel: "
11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"country=%c%c(0x%02x) reg_class=%u channel=%u",
11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[0],
11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[1],
11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[2],
11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[3],
11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				msg->listen_channel[4]);
11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Update "
11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"peer " MACSTR " Listen channel: %u -> %u MHz",
11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(dev->info.p2p_device_addr),
11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev->listen_freq, freq);
11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->listen_freq = freq;
11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_PROBE_REQ_ONLY) {
12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~P2P_DEV_PROBE_REQ_ONLY;
12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Completed device entry based on data from "
12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"GO Negotiation Request");
12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Created device entry based on GO Neg Req: "
12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MACSTR " dev_capab=0x%x group_capab=0x%x name='%s' "
12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"listen_freq=%d",
12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr),
12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->info.dev_capab, dev->info.group_capab,
12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->info.device_name, dev->listen_freq);
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_GROUP_CLIENT_ONLY;
12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_USER_REJECTED) {
12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Do not report rejected device");
12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->dev_found(p2p->cfg->cb_ctx, addr, &dev->info,
12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    !(dev->flags & P2P_DEV_REPORTED_ONCE));
12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_build_ssid(struct p2p_data *p2p, u8 *ssid, size_t *ssid_len)
12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_random((char *) &ssid[P2P_WILDCARD_SSID_LEN], 2);
12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&ssid[P2P_WILDCARD_SSID_LEN + 2],
12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  p2p->cfg->ssid_postfix, p2p->cfg->ssid_postfix_len);
12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*ssid_len = P2P_WILDCARD_SSID_LEN + 2 + p2p->cfg->ssid_postfix_len;
12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_go_params(struct p2p_data *p2p, struct p2p_go_neg_results *params)
12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_build_ssid(p2p, params->ssid, &params->ssid_len);
12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_random(params->passphrase, 8);
12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_go_complete(struct p2p_data *p2p, struct p2p_device *peer)
12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_go_neg_results res;
12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int go = peer->go_state == LOCAL_GO;
12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_channels intersection;
12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freqs;
12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i, j;
12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: GO Negotiation with " MACSTR " completed (%s will be "
12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"GO)", MAC2STR(peer->info.p2p_device_addr),
12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		go ? "local end" : "peer");
12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&res, 0, sizeof(res));
12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.role_go = go;
12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(res.peer_device_addr, peer->info.p2p_device_addr, ETH_ALEN);
12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(res.peer_interface_addr, peer->intended_addr, ETH_ALEN);
12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.wps_method = peer->wps_method;
12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP)
12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res.persistent_group = 1;
12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (go) {
12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Setup AP mode for WPS provisioning */
12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res.freq = p2p_channel_to_freq(p2p->cfg->country,
12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       p2p->op_reg_class,
12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       p2p->op_channel);
12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(res.ssid, p2p->ssid, p2p->ssid_len);
12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res.ssid_len = p2p->ssid_len;
12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_random(res.passphrase, 8);
12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res.freq = peer->oper_freq;
12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->ssid_len) {
12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(res.ssid, p2p->ssid, p2p->ssid_len);
12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res.ssid_len = p2p->ssid_len;
12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_channels_intersect(&p2p->channels, &peer->channels,
12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       &intersection);
12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	freqs = 0;
12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < intersection.reg_classes; i++) {
12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct p2p_reg_class *c = &intersection.reg_class[i];
12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freqs + 1 == P2P_MAX_CHANNELS)
12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < c->channels; j++) {
12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			int freq;
12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (freqs + 1 == P2P_MAX_CHANNELS)
12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq = p2p_channel_to_freq(peer->country, c->reg_class,
12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   c->channel[j]);
12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (freq < 0)
12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				continue;
12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res.freq_list[freqs++] = freq;
12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.peer_config_timeout = go ? peer->client_timeout : peer->go_timeout;
13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer->go_neg_req_sent = 0;
13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer->wps_method = WPS_NOT_READY;
13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_PROVISIONING);
13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->go_neg_completed(p2p->cfg->cb_ctx, &res);
13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_rx_p2p_action(struct p2p_data *p2p, const u8 *sa,
13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      const u8 *data, size_t len, int rx_freq)
13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: RX P2P Public Action from " MACSTR, MAC2STR(sa));
13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "P2P: P2P Public Action contents", data, len);
13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1)
13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data[0]) {
13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG_REQ:
13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_neg_req(p2p, sa, data + 1, len - 1, rx_freq);
13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG_RESP:
13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_neg_resp(p2p, sa, data + 1, len - 1, rx_freq);
13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG_CONF:
13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_neg_conf(p2p, sa, data + 1, len - 1);
13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITATION_REQ:
13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_invitation_req(p2p, sa, data + 1, len - 1,
13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   rx_freq);
13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITATION_RESP:
13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_invitation_resp(p2p, sa, data + 1, len - 1);
13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROV_DISC_REQ:
13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_prov_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROV_DISC_RESP:
13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_prov_disc_resp(p2p, sa, data + 1, len - 1);
13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_DEV_DISC_REQ:
13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_dev_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_DEV_DISC_RESP:
13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_dev_disc_resp(p2p, sa, data + 1, len - 1);
13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Unsupported P2P Public Action frame type %d",
13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data[0]);
13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_rx_action_public(struct p2p_data *p2p, const u8 *da, const u8 *sa,
13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  const u8 *bssid, const u8 *data, size_t len,
13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  int freq)
13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1)
13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data[0]) {
13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_VENDOR_SPECIFIC:
13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data++;
13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len--;
13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 3)
13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (WPA_GET_BE24(data) != OUI_WFA)
13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data += 3;
13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len -= 3;
13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 1)
13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*data != P2P_OUI_TYPE)
13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_p2p_action(p2p, sa, data + 1, len - 1, freq);
13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_INITIAL_REQ:
13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_initial_req(p2p, sa, data + 1, len - 1, freq);
13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_INITIAL_RESP:
13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_initial_resp(p2p, sa, data + 1, len - 1, freq);
13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_COMEBACK_REQ:
13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_comeback_req(p2p, sa, data + 1, len - 1, freq);
13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WLAN_PA_GAS_COMEBACK_RESP:
13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_gas_comeback_resp(p2p, sa, data + 1, len - 1, freq);
13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_rx_action(struct p2p_data *p2p, const u8 *da, const u8 *sa,
14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *bssid, u8 category,
14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *data, size_t len, int freq)
14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (category == WLAN_ACTION_PUBLIC) {
14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_rx_action_public(p2p, da, sa, bssid, data, len, freq);
14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (category != WLAN_ACTION_VENDOR_SPECIFIC)
14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 4)
14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (WPA_GET_BE24(data) != OUI_WFA)
14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data += 3;
14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len -= 3;
14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*data != P2P_OUI_TYPE)
14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data++;
14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len--;
14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P action frame */
14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: RX P2P Action from " MACSTR, MAC2STR(sa));
14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "P2P: P2P Action contents", data, len);
14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1)
14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data[0]) {
14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_NOA:
14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Received P2P Action - Notice of Absence");
14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO */
14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PRESENCE_REQ:
14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_presence_req(p2p, da, sa, data + 1, len - 1, freq);
14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PRESENCE_RESP:
14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_presence_resp(p2p, da, sa, data + 1, len - 1);
14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_DISC_REQ:
14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_process_go_disc_req(p2p, da, sa, data + 1, len - 1, freq);
14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Received P2P Action - unknown type %u", data[0]);
14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_start(void *eloop_ctx, void *timeout_ctx)
14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == NULL)
14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer->status = P2P_SC_SUCCESS;
14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_connect_send(p2p, p2p->go_neg_peer);
14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_invite_start(void *eloop_ctx, void *timeout_ctx)
14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->invite_peer == NULL)
14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_invite_send(p2p, p2p->invite_peer, p2p->invite_go_dev_addr);
14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_add_dev_from_probe_req(struct p2p_data *p2p, const u8 *addr,
14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const u8 *ie, size_t ie_len)
14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg) < 0 || msg.p2p_attributes == NULL)
14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* not a P2P probe */
14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.ssid == NULL || msg.ssid[1] != P2P_WILDCARD_SSID_LEN ||
14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(msg.ssid + 2, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN)
14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    != 0) {
14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* The Probe Request is not part of P2P Device Discovery. It is
14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * not known whether the source address of the frame is the P2P
14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Device Address or P2P Interface Address. Do not add a new
14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * peer entry based on this frames.
14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev) {
15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->country[0] == 0 && msg.listen_channel)
15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(dev->country, msg.listen_channel, 3);
15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* already known */
15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_create_device(p2p, addr);
15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&dev->last_seen);
15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_PROBE_REQ_ONLY;
15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.listen_channel) {
15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev->country, msg.listen_channel, 3);
15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->listen_freq = p2p_channel_to_freq(dev->country,
15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       msg.listen_channel[3],
15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       msg.listen_channel[4]);
15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_copy_wps_info(dev, 1, &msg);
15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Created device entry based on Probe Req: " MACSTR
15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" dev_capab=0x%x group_capab=0x%x name='%s' listen_freq=%d",
15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(dev->info.p2p_device_addr), dev->info.dev_capab,
15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->info.group_capab, dev->info.device_name,
15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->listen_freq);
15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_device * p2p_add_dev_from_go_neg_req(struct p2p_data *p2p,
15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						const u8 *addr,
15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						struct p2p_message *msg)
15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev) {
15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_get_time(&dev->last_seen);
15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return dev; /* already known */
15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_create_device(p2p, addr);
15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_add_dev_info(p2p, addr, dev, msg);
15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return dev;
15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int dev_type_match(const u8 *dev_type, const u8 *req_dev_type)
15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(dev_type, req_dev_type, WPS_DEV_TYPE_LEN) == 0)
15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(dev_type, req_dev_type, 2) == 0 &&
15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    WPA_GET_BE32(&req_dev_type[2]) == 0 &&
15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    WPA_GET_BE16(&req_dev_type[6]) == 0)
15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Category match with wildcard OUI/sub-category */
15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint dev_type_list_match(const u8 *dev_type, const u8 *req_dev_type[],
15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			size_t num_req_dev_type)
15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_req_dev_type; i++) {
15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev_type_match(dev_type, req_dev_type[i]))
15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 1;
15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_match_dev_type - Match local device type with requested type
15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p: P2P module context from p2p_init()
15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wps: WPS TLVs from Probe Request frame (concatenated WPS IEs)
15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 on match, 0 on mismatch
15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function can be used to match the Requested Device Type attribute in
15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPS IE with the local device types for deciding whether to reply to a Probe
15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Request frame.
15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_match_dev_type(struct p2p_data *p2p, struct wpabuf *wps)
15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wps_parse_attr attr;
16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wps_parse_msg(wps, &attr))
16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* assume no Requested Device Type attributes */
16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (attr.num_req_dev_type == 0)
16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* no Requested Device Type attributes -> match */
16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev_type_list_match(p2p->cfg->pri_dev_type, attr.req_dev_type,
16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				attr.num_req_dev_type))
16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Own Primary Device Type matches */
16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < p2p->cfg->num_sec_dev_types; i++)
16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev_type_list_match(p2p->cfg->sec_dev_type[i],
16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					attr.req_dev_type,
16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					attr.num_req_dev_type))
16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Own Secondary Device Type matches */
16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* No matching device type found */
16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * p2p_build_probe_resp_ies(struct p2p_data *p2p)
16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = wpabuf_alloc(1000);
16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_build_wps_ie(p2p, buf, DEV_PW_DEFAULT, 1);
16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P IE */
16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(buf);
16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_capability(buf, p2p->dev_capab, 0);
16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval)
16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_ext_listen_timing(buf, p2p->ext_listen_period,
16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      p2p->ext_listen_interval);
16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_device_info(buf, p2p, NULL);
16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(buf, len);
16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_reply_probe(struct p2p_data *p2p, const u8 *addr, const u8 *ie,
16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    size_t ie_len)
16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ieee802_11_elems elems;
16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ieee80211_mgmt *resp;
16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *wps;
16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *ies;
16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p->in_listen || !p2p->drv_in_listen) {
16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* not in Listen state - ignore Probe Request */
16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ieee802_11_parse_elems((u8 *) ie, ie_len, &elems, 0) ==
16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ParseFailed) {
16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Ignore invalid Probe Request frames */
16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (elems.p2p == NULL) {
16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* not a P2P probe - ignore it */
16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (elems.ssid == NULL || elems.ssid_len != P2P_WILDCARD_SSID_LEN ||
16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(elems.ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) !=
16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0) {
16758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* not using P2P Wildcard SSID - ignore */
16768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Check Requested Device Type match */
16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wps = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA);
16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wps && !p2p_match_dev_type(p2p, wps)) {
16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(wps);
16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* No match with Requested Device Type */
16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(wps);
16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p->cfg->send_probe_resp)
16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* Response generated elsewhere */
16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Reply to P2P Probe Request in Listen state");
16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * We do not really have a specific BSS that this frame is advertising,
16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * so build a frame that has some information in valid format. This is
16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * really only used for discovery purposes, not to learn exact BSS
16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * parameters.
16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ies = p2p_build_probe_resp_ies(p2p);
17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ies == NULL)
17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = wpabuf_alloc(200 + wpabuf_len(ies));
17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL) {
17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(ies);
17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = NULL;
17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = wpabuf_put(buf, resp->u.probe_resp.variable - (u8 *) resp);
17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   (WLAN_FC_STYPE_PROBE_RESP << 4));
17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(resp->da, addr, ETH_ALEN);
17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(resp->sa, p2p->cfg->dev_addr, ETH_ALEN);
17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(resp->bssid, p2p->cfg->dev_addr, ETH_ALEN);
17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->u.probe_resp.beacon_int = host_to_le16(100);
17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* hardware or low-level driver will setup seq_ctrl and timestamp */
17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->u.probe_resp.capab_info =
17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		host_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE |
17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     WLAN_CAPABILITY_PRIVACY |
17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     WLAN_CAPABILITY_SHORT_SLOT_TIME);
17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_SSID);
17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, P2P_WILDCARD_SSID_LEN);
17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(buf, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_SUPP_RATES);
17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 8);
17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, (60 / 5) | 0x80);
17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 90 / 5);
17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, (120 / 5) | 0x80);
17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 180 / 5);
17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, (240 / 5) | 0x80);
17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 360 / 5);
17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 480 / 5);
17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 540 / 5);
17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_DS_PARAMS);
17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, 1);
17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, p2p->cfg->channel);
17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_buf(buf, ies);
17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(ies);
17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_probe_resp(p2p->cfg->cb_ctx, buf);
17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(buf);
17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *ie,
17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     size_t ie_len)
17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_add_dev_from_probe_req(p2p, addr, ie, ie_len);
17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_reply_probe(p2p, addr, ie, ie_len);
17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((p2p->state == P2P_CONNECT || p2p->state == P2P_CONNECT_LISTEN) &&
17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    p2p->go_neg_peer &&
17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(addr, p2p->go_neg_peer->info.p2p_device_addr, ETH_ALEN)
17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    == 0) {
17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Received a Probe Request from GO Negotiation peer */
17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Found GO Negotiation peer - try to start GO "
17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"negotiation from timeout");
17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(0, 0, p2p_go_neg_start, p2p, NULL);
17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((p2p->state == P2P_INVITE || p2p->state == P2P_INVITE_LISTEN) &&
17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    p2p->invite_peer &&
17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(addr, p2p->invite_peer->info.p2p_device_addr, ETH_ALEN)
17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    == 0) {
17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Received a Probe Request from Invite peer */
17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Found Invite peer - try to start Invite from "
17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"timeout");
17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(0, 0, p2p_invite_start, p2p, NULL);
17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_assoc_req_ie_wlan_ap(struct p2p_data *p2p, const u8 *bssid,
17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    u8 *buf, size_t len, struct wpabuf *p2p_ie)
17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *tmp;
17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *lpos;
17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t tmplen;
17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 group_capab;
17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_ie == NULL)
17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* WLAN AP is not a P2P manager */
17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (Re)Association Request - P2P IE
18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Capability attribute (shall be present)
18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Interface attribute (present if concurrent device and
18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *	P2P Management is enabled)
18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp = wpabuf_alloc(200);
18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp == NULL)
18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	lpos = p2p_buf_add_ie_hdr(tmp);
18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group_capab = 0;
18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->num_groups > 0) {
18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group_capab |= P2P_GROUP_CAPAB_GROUP_OWNER;
18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) &&
18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED) &&
18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    p2p->cross_connect)
18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_capability(tmp, p2p->dev_capab, group_capab);
18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) &&
18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED))
18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_p2p_interface(tmp, p2p);
18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(tmp, lpos);
18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmplen = wpabuf_len(tmp);
18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmplen > len)
18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = -1;
18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(buf, wpabuf_head(tmp), tmplen);
18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = tmplen;
18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(tmp);
18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_assoc_req_ie(struct p2p_data *p2p, const u8 *bssid, u8 *buf,
18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     size_t len, int p2p_group, struct wpabuf *p2p_ie)
18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *tmp;
18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *lpos;
18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *peer;
18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t tmplen;
18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p_group)
18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return p2p_assoc_req_ie_wlan_ap(p2p, bssid, buf, len, p2p_ie);
18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (Re)Association Request - P2P IE
18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Capability attribute (shall be present)
18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Extended Listen Timing (may be present)
18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * P2P Device Info attribute (shall be present)
18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp = wpabuf_alloc(200);
18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp == NULL)
18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer = bssid ? p2p_get_device(p2p, bssid) : NULL;
18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	lpos = p2p_buf_add_ie_hdr(tmp);
18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_capability(tmp, p2p->dev_capab, 0);
18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval)
18658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_ext_listen_timing(tmp, p2p->ext_listen_period,
18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      p2p->ext_listen_interval);
18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_device_info(tmp, p2p, peer);
18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(tmp, lpos);
18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmplen = wpabuf_len(tmp);
18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmplen > len)
18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = -1;
18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(buf, wpabuf_head(tmp), tmplen);
18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = tmplen;
18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(tmp);
18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_scan_result_text(const u8 *ies, size_t ies_len, char *buf, char *end)
18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *p2p_ie;
18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len, P2P_IE_VENDOR_TYPE);
18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_ie == NULL)
18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = p2p_attr_text(p2p_ie, buf, end);
18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(p2p_ie);
18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_clear_go_neg(struct p2p_data *p2p)
18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer = NULL;
19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_IDLE);
19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_wps_success_cb(struct p2p_data *p2p, const u8 *mac_addr)
19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == NULL) {
19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No pending Group Formation - "
19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"ignore WPS registration success notification");
19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* No pending Group Formation */
19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(mac_addr, p2p->go_neg_peer->intended_addr, ETH_ALEN) !=
19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0) {
19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Ignore WPS registration success notification "
19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"for " MACSTR " (GO Negotiation peer " MACSTR ")",
19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(mac_addr),
19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(p2p->go_neg_peer->intended_addr));
19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* Ignore unexpected peer address */
19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Group Formation completed successfully with " MACSTR,
19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(mac_addr));
19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_go_neg(p2p);
19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_group_formation_failed(struct p2p_data *p2p)
19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == NULL) {
19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No pending Group Formation - "
19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"ignore group formation failure notification");
19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* No pending Group Formation */
19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Group Formation failed with " MACSTR,
19448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(p2p->go_neg_peer->intended_addr));
19458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_go_neg(p2p);
19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_data * p2p_init(const struct p2p_config *cfg)
19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p;
19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->max_peers < 1)
19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p = os_zalloc(sizeof(*p2p) + sizeof(*cfg));
19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p == NULL)
19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg = (struct p2p_config *) (p2p + 1);
19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg, cfg, sizeof(*cfg));
19628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->dev_name)
19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->dev_name = os_strdup(cfg->dev_name);
19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->manufacturer)
19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->manufacturer = os_strdup(cfg->manufacturer);
19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->model_name)
19678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_name = os_strdup(cfg->model_name);
19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->model_number)
19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_number = os_strdup(cfg->model_number);
19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->serial_number)
19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->serial_number = os_strdup(cfg->serial_number);
19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->min_disc_int = 1;
19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->max_disc_int = 3;
19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_random(&p2p->next_tie_breaker, 1);
19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->next_tie_breaker &= 0x01;
19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->sd_request)
19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_SERVICE_DISCOVERY;
19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->dev_capab |= P2P_DEV_CAPAB_INVITATION_PROCEDURE;
19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg->concurrent_operations)
19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_CONCURRENT_OPER;
19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->dev_capab |= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
19848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_init(&p2p->devices);
19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(P2P_PEER_EXPIRATION_INTERVAL, 0,
19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p_expiration_timeout, p2p, NULL);
19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p;
19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_deinit(struct p2p_data *p2p)
19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_expiration_timeout, p2p, NULL);
19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_ext_listen_timeout, p2p, NULL);
19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_flush(p2p);
20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_req_dev_types(p2p);
20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->dev_name);
20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->manufacturer);
20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_name);
20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_number);
20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->serial_number);
20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->groups);
20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(p2p->sd_resp);
20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->after_scan_tx);
20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_remove_wps_vendor_extensions(p2p);
20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p);
20118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_flush(struct p2p_data *p2p)
20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev, *prev;
20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_clear_timeout(p2p);
20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_IDLE);
20198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->go_neg_peer = NULL;
20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each_safe(dev, prev, &p2p->devices, struct p2p_device,
20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      list) {
20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dl_list_del(&dev->list);
20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_device_free(p2p, dev);
20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_free_sd_queries(p2p);
20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->after_scan_tx);
20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->after_scan_tx = NULL;
20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_unauthorize(struct p2p_data *p2p, const u8 *addr)
20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, addr);
20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Unauthorizing " MACSTR,
20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(addr));
20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer == dev)
20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->go_neg_peer = NULL;
20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wps_method = WPS_NOT_READY;
20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE;
20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM;
20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Check if after_scan_tx is for this peer. If so free it */
20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->after_scan_tx &&
20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(addr, p2p->after_scan_tx->dst, ETH_ALEN) == 0) {
20548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p2p->after_scan_tx);
20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = NULL;
20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
20598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_dev_name(struct p2p_data *p2p, const char *dev_name)
20638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->dev_name);
20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev_name) {
20668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->dev_name = os_strdup(dev_name);
20678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->dev_name == NULL)
20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
20698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
20708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->dev_name = NULL;
20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
20728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_manufacturer(struct p2p_data *p2p, const char *manufacturer)
20768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->manufacturer);
20788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->manufacturer = NULL;
20798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (manufacturer) {
20808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->manufacturer = os_strdup(manufacturer);
20818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->manufacturer == NULL)
20828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
20838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
20868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_model_name(struct p2p_data *p2p, const char *model_name)
20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_name);
20928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->model_name = NULL;
20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (model_name) {
20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_name = os_strdup(model_name);
20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->model_name == NULL)
20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_model_number(struct p2p_data *p2p, const char *model_number)
21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->model_number);
21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->model_number = NULL;
21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (model_number) {
21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->model_number = os_strdup(model_number);
21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->model_number == NULL)
21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_serial_number(struct p2p_data *p2p, const char *serial_number)
21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p2p->cfg->serial_number);
21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->serial_number = NULL;
21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (serial_number) {
21228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->serial_number = os_strdup(serial_number);
21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->cfg->serial_number == NULL)
21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_config_methods(struct p2p_data *p2p, u16 config_methods)
21328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->config_methods = config_methods;
21348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_uuid(struct p2p_data *p2p, const u8 *uuid)
21388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->uuid, uuid, 16);
21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_pri_dev_type(struct p2p_data *p2p, const u8 *pri_dev_type)
21448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->pri_dev_type, pri_dev_type, 8);
21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_sec_dev_types(struct p2p_data *p2p, const u8 dev_types[][8],
21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  size_t num_dev_types)
21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (num_dev_types > P2P_SEC_DEVICE_TYPES)
21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num_dev_types = P2P_SEC_DEVICE_TYPES;
21558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->num_sec_dev_types = num_dev_types;
21568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->sec_dev_type, dev_types, num_dev_types * 8);
21578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
21588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_remove_wps_vendor_extensions(struct p2p_data *p2p)
21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(p2p->wps_vendor_ext[i]);
21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->wps_vendor_ext[i] = NULL;
21688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_add_wps_vendor_extension(struct p2p_data *p2p,
21738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const struct wpabuf *vendor_ext)
21748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
21768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (vendor_ext == NULL)
21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
21798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
21818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->wps_vendor_ext[i] == NULL)
21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
21838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (i >= P2P_MAX_WPS_VENDOR_EXT)
21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->wps_vendor_ext[i] = wpabuf_dup(vendor_ext);
21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->wps_vendor_ext[i] == NULL)
21898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
21908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_country(struct p2p_data *p2p, const char *country)
21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->country, country, 3);
21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
21998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_continue_find(struct p2p_data *p2p)
22038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_SEARCH);
22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->flags & P2P_DEV_SD_SCHEDULE) {
22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (p2p_start_sd(p2p, dev) == 0)
22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (dev->req_config_methods &&
22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   !(dev->flags & P2P_DEV_PD_FOR_JOIN)) {
22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send "
22158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"pending Provisioning Discovery Request to "
22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MACSTR " (config methods 0x%x)",
22178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(dev->info.p2p_device_addr),
22188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev->req_config_methods);
22198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (p2p_send_prov_disc_req(p2p, dev, 0) == 0)
22208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
22218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
22228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_listen_in_find(p2p);
22258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_sd_cb(struct p2p_data *p2p, int success)
22298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
22318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Service Discovery Query TX callback: success=%d",
22328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
22338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
22348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!success) {
22368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->sd_peer) {
22378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE;
22388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->sd_peer = NULL;
22398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
22408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
22418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
22428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->sd_peer == NULL) {
22458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
22468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No SD peer entry known");
22478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
22488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
22498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Wait for response from the peer */
22528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_SD_DURING_FIND);
22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_timeout(p2p, 0, 200000);
22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
225675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
225775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen/**
225875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen * p2p_retry_pd - Retry any pending provision disc requests in IDLE state
225975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen * @p2p: P2P module context from p2p_init()
226075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen */
226175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenvoid p2p_retry_pd(struct p2p_data *p2p)
226275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
226375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	struct p2p_device *dev;
226475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
226575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p->state != P2P_IDLE)
226675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
226775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
226875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
226975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * Retry the prov disc req attempt only for the peer that the user had
227075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * requested for and provided a join has not been initiated on it
227175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * in the meantime.
227275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
227375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
227475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
227575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (os_memcmp(p2p->pending_pd_devaddr,
227675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			      dev->info.p2p_device_addr, ETH_ALEN) != 0)
227775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			continue;
227875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (!dev->req_config_methods)
227975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			continue;
228075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (dev->flags & P2P_DEV_PD_FOR_JOIN)
228175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			continue;
228275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
228375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send "
228475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			"pending Provisioning Discovery Request to "
228575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			MACSTR " (config methods 0x%x)",
228675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			MAC2STR(dev->info.p2p_device_addr),
228775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			dev->req_config_methods);
228875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p_send_prov_disc_req(p2p, dev, 0);
228975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
229075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	}
229175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
229275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
229375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_prov_disc_cb(struct p2p_data *p2p, int success)
22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Provision Discovery Request TX callback: success=%d",
22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
229975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
230075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
230175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * Postpone resetting the pending action state till after we actually
230275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * time out. This allows us to take some action like notifying any
230375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * interested parties about no response to the request.
230475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 *
230575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * When the timer (below) goes off we check in IDLE, SEARCH, or
230675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * LISTEN_ONLY state, which are the only allowed states to issue a PD
230775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * requests in, if this was still pending and then raise notification.
230875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
23098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!success) {
231175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pending_action_state = P2P_NO_PENDING_ACTION;
231275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
23138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->state != P2P_IDLE)
23148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_continue_find(p2p);
231575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		else if (p2p->user_initiated_pd) {
231675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p->pending_action_state = P2P_PENDING_PD;
231775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_set_timeout(p2p, 0, 300000);
231875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		}
23198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
23208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
232275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
232375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * This postponing, of resetting pending_action_state, needs to be
232475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * done only for user initiated PD requests and not internal ones.
232575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
232675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p->user_initiated_pd)
232775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pending_action_state = P2P_PENDING_PD;
232875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	else
232975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pending_action_state = P2P_NO_PENDING_ACTION;
233075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
23318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Wait for response from the peer */
23328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_SEARCH)
23338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_PD_DURING_FIND);
23348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_timeout(p2p, 0, 200000);
23358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_scan_res_handler(struct p2p_data *p2p, const u8 *bssid, int freq,
23398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 int level, const u8 *ies, size_t ies_len)
23408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_add_device(p2p, bssid, freq, level, ies, ies_len);
23428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer && p2p->state == P2P_SEARCH &&
23448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(p2p->go_neg_peer->info.p2p_device_addr, bssid, ETH_ALEN)
23458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    == 0) {
23468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
23478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Found GO Negotiation peer - try to start GO "
23488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"negotiation");
23498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, p2p->go_neg_peer);
23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
23518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_scan_res_handled(struct p2p_data *p2p)
23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p->p2p_scan_running) {
23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan was not "
23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"running, but scan results received");
23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->p2p_scan_running = 0;
23648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_run_after_scan(p2p))
23678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_SEARCH)
23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_continue_find(p2p);
23708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies)
23748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len = p2p_buf_add_ie_hdr(ies);
23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_capability(ies, p2p->dev_capab, 0);
23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->reg_class && p2p->cfg->channel)
23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_listen_channel(ies, p2p->cfg->country,
23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   p2p->cfg->reg_class,
23808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   p2p->cfg->channel);
23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval)
23828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_ext_listen_timing(ies, p2p->ext_listen_period,
23838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      p2p->ext_listen_interval);
23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: p2p_buf_add_operating_channel() if GO */
23858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(ies, len);
23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_ie_text(struct wpabuf *p2p_ie, char *buf, char *end)
23908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_attr_text(p2p_ie, buf, end);
23928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_req_cb(struct p2p_data *p2p, int success)
23968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p->go_neg_peer;
23988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
24008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: GO Negotiation Request TX callback: success=%d",
24018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
24028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
24048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
24058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No pending GO Negotiation");
24068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
24078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (success) {
24108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->go_neg_req_sent++;
24118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->flags & P2P_DEV_USER_REJECTED) {
24128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_set_state(p2p, P2P_IDLE);
24138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
24148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
24158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!success &&
24188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (dev->info.dev_capab & P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY) &&
24198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !is_zero_ether_addr(dev->member_in_go_dev)) {
24208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
24218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Peer " MACSTR " did not acknowledge request - "
24228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"try to use device discoverability through its GO",
24238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr));
24248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
24258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_send_dev_disc_req(p2p, dev);
24268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
24278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
24308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Use P2P find, if needed, to find the other device from its listen
24318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * channel.
24328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
24338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_CONNECT);
24348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_timeout(p2p, 0, 100000);
24358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_resp_cb(struct p2p_data *p2p, int success)
24398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
24418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: GO Negotiation Response TX callback: success=%d",
24428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		success);
24438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!p2p->go_neg_peer && p2p->state == P2P_PROVISIONING) {
24448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
24458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Ignore TX callback event - GO Negotiation is "
24468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"not running anymore");
24478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
24488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_CONNECT);
24508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_timeout(p2p, 0, 100000);
24518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_resp_failure_cb(struct p2p_data *p2p, int success)
24558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
24578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: GO Negotiation Response (failure) TX callback: "
24588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"success=%d", success);
24598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer && p2p->go_neg_peer->status != P2P_SC_SUCCESS) {
24608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_failed(p2p, p2p->go_neg_peer,
24618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  p2p->go_neg_peer->status);
24628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_neg_conf_cb(struct p2p_data *p2p,
24678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       enum p2p_send_action_result result)
24688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
24708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
24728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: GO Negotiation Confirm TX callback: result=%d",
24738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		result);
24748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
24758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (result == P2P_SEND_ACTION_FAILED) {
24768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
24778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
24788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (result == P2P_SEND_ACTION_NO_ACK) {
24808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
24818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * It looks like the TX status for GO Negotiation Confirm is
24828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * often showing failure even when the peer has actually
24838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * received the frame. Since the peer may change channels
24848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * immediately after having received the frame, we may not see
24858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * an Ack for retries, so just dropping a single frame may
24868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * trigger this. To allow the group formation to succeed if the
24878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * peer did indeed receive the frame, continue regardless of
24888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * the TX status.
24898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
24908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
24918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Assume GO Negotiation Confirm TX was actually "
24928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"received by the peer even though Ack was not "
24938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"reported");
24948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p->go_neg_peer;
24978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
24988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
24998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_go_complete(p2p, dev);
25018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_send_action_cb(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
25058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const u8 *src, const u8 *bssid,
25068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			enum p2p_send_action_result result)
25078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum p2p_pending_action_state state;
25098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int success;
25108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
25128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Action frame TX callback (state=%d freq=%u dst=" MACSTR
25138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" src=" MACSTR " bssid=" MACSTR " result=%d",
25148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_action_state, freq, MAC2STR(dst), MAC2STR(src),
25158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(bssid), result);
25168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	success = result == P2P_SEND_ACTION_SUCCESS;
25178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	state = p2p->pending_action_state;
25188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
25198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (state) {
25208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_NO_PENDING_ACTION:
25218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
25228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_REQUEST:
25238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_req_cb(p2p, success);
25248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
25258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_RESPONSE:
25268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_resp_cb(p2p, success);
25278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
25288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_RESPONSE_FAILURE:
25298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_resp_failure_cb(p2p, success);
25308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
25318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_NEG_CONFIRM:
25328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_conf_cb(p2p, result);
25338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
25348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_SD:
25358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_sd_cb(p2p, success);
25368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
25378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_PD:
25388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_prov_disc_cb(p2p, success);
25398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
25408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_INVITATION_REQUEST:
25418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_invitation_req_cb(p2p, success);
25428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
25438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_INVITATION_RESPONSE:
25448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_invitation_resp_cb(p2p, success);
25458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
25468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_DEV_DISC_REQUEST:
25478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_disc_req_cb(p2p, success);
25488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
25498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_DEV_DISC_RESPONSE:
25508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_dev_disc_resp_cb(p2p, success);
25518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
25528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PENDING_GO_DISC_REQ:
25538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_disc_req_cb(p2p, success);
25548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
25558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_listen_cb(struct p2p_data *p2p, unsigned int freq,
25608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   unsigned int duration)
25618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq == p2p->pending_client_disc_freq) {
25638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
25648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Client discoverability remain-awake completed");
25658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_client_disc_freq = 0;
25668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
25678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq != p2p->pending_listen_freq) {
25708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
25718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Unexpected listen callback for freq=%u "
25728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"duration=%u (pending_listen_freq=%u)",
25738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			freq, duration, p2p->pending_listen_freq);
25748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
25758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
25788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Starting Listen timeout(%u,%u) on freq=%u based on "
25798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"callback",
25808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_sec, p2p->pending_listen_usec,
25818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->pending_listen_freq);
25828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->in_listen = 1;
25838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->drv_in_listen = freq;
25848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->pending_listen_sec || p2p->pending_listen_usec) {
25858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
25868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Add 20 msec extra wait to avoid race condition with driver
25878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * remain-on-channel end event, i.e., give driver more time to
25888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * complete the operation before our timeout expires.
25898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
25908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_timeout(p2p, p2p->pending_listen_sec,
25918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p->pending_listen_usec + 20000);
25928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_listen_freq = 0;
25958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_listen_end(struct p2p_data *p2p, unsigned int freq)
25998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Driver ended Listen "
26018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"state (freq=%u)", freq);
26028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->drv_in_listen = 0;
26038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->in_listen)
26048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* Internal timeout will trigger the next step */
26058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_CONNECT_LISTEN && p2p->go_neg_peer) {
26078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->go_neg_peer->connect_reqs >= 120) {
26088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
26098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Timeout on sending GO Negotiation "
26108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Request without getting response");
26118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
26128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 0;
26138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
26148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_CONNECT);
26168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, p2p->go_neg_peer);
26178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
26188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (p2p->state == P2P_SEARCH) {
26198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_search(p2p);
26208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
26218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_connect(struct p2p_data *p2p)
26288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
26308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_CONNECT_LISTEN);
26318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_listen_in_find(p2p);
26328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_connect_listen(struct p2p_data *p2p)
26368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->go_neg_peer) {
26388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->drv_in_listen) {
26398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Driver is "
26408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"still in Listen state; wait for it to "
26418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"complete");
26428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
26438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
26448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->go_neg_peer->connect_reqs >= 120) {
26468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
26478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Timeout on sending GO Negotiation "
26488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Request without getting response");
26498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1);
26508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
26518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
26528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_CONNECT);
26548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_connect_send(p2p, p2p->go_neg_peer);
26558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
26568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
26578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_wait_peer_connect(struct p2p_data *p2p)
26618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
26638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * TODO: could remain constantly in Listen state for some time if there
26648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * are no other concurrent uses for the radio. For now, go to listen
26658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * state once per second to give other uses a chance to use the radio.
26668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
26678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_WAIT_PEER_IDLE);
26688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_timeout(p2p, 1, 0);
26698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_wait_peer_idle(struct p2p_data *p2p)
26738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p->go_neg_peer;
26758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
26778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
26788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Unknown GO Neg peer - stop GO Neg wait");
26798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
26808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->wait_count++;
26838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->wait_count >= 120) {
26848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
26858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Timeout on waiting peer to become ready for GO "
26868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Negotiation");
26878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_go_neg_failed(p2p, dev, -1);
26888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
26898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
26928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Go to Listen state while waiting for the peer to become "
26938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"ready for GO Negotiation");
26948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_WAIT_PEER_CONNECT);
26958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_listen_in_find(p2p);
26968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_sd_during_find(struct p2p_data *p2p)
27008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
27028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Service Discovery Query timeout");
27038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->sd_peer) {
27048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
27058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE;
27068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->sd_peer = NULL;
27078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_continue_find(p2p);
27098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_prov_disc_during_find(struct p2p_data *p2p)
27138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
27158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Provision Discovery Request timeout");
27168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
27178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_continue_find(p2p);
27188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
272175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic void p2p_timeout_prov_disc_req(struct p2p_data *p2p)
272275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
272375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
272475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
272575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
272675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * For user initiated PD requests that we have not gotten any responses
272775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * for while in IDLE state, we retry them a couple of times before
272875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * giving up.
272975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
273075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (!p2p->user_initiated_pd)
273175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
273275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
273375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
273475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		"P2P: User initiated Provision Discovery Request timeout");
273575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
273675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p->pd_retries) {
273775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pd_retries--;
273875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p_retry_pd(p2p);
273975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	} else {
274075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->cfg->prov_disc_fail)
274175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx,
274275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen						 p2p->pending_pd_devaddr,
274375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen						 P2P_PROV_DISC_TIMEOUT);
274475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p_reset_pending_pd(p2p);
274575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	}
274675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
274775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
274875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
27498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_invite(struct p2p_data *p2p)
27508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
27528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_state(p2p, P2P_INVITE_LISTEN);
27538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->inv_role == P2P_INVITE_ROLE_ACTIVE_GO) {
27548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
27558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Better remain on operating channel instead of listen channel
27568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * when running a group.
27578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
27588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Inviting in "
27598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"active GO role - wait on operating channel");
27608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_timeout(p2p, 0, 100000);
27618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
27628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_listen_in_find(p2p);
27648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_timeout_invite_listen(struct p2p_data *p2p)
27688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->invite_peer && p2p->invite_peer->invitation_reqs < 100) {
27708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_INVITE);
27718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_invite_send(p2p, p2p->invite_peer,
27728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p->invite_go_dev_addr);
27738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
27748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->invite_peer) {
27758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
27768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Invitation Request retry limit reached");
27778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (p2p->cfg->invitation_result)
27788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p->cfg->invitation_result(
27798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					p2p->cfg->cb_ctx, -1, NULL);
27808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
27818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
27828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_state_timeout(void *eloop_ctx, void *timeout_ctx)
27878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
27898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Timeout (state=%s)",
27918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_state_txt(p2p->state));
27928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->in_listen = 0;
27948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (p2p->state) {
27968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_IDLE:
279775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/* Check if we timed out waiting for PD req */
279875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->pending_action_state == P2P_PENDING_PD)
279975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_timeout_prov_disc_req(p2p);
28008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
28018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SEARCH:
280275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/* Check if we timed out waiting for PD req */
280375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->pending_action_state == P2P_PENDING_PD)
280475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_timeout_prov_disc_req(p2p);
28058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_search(p2p);
28068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
28078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT:
28088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_connect(p2p);
28098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
28108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_CONNECT_LISTEN:
28118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_connect_listen(p2p);
28128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
28138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GO_NEG:
28148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
28158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_LISTEN_ONLY:
281675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/* Check if we timed out waiting for PD req */
281775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->pending_action_state == P2P_PENDING_PD)
281875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p_timeout_prov_disc_req(p2p);
281975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
28208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->ext_listen_only) {
28218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
28228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Extended Listen Timing - Listen State "
28238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"completed");
28248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->ext_listen_only = 0;
28258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_set_state(p2p, P2P_IDLE);
28268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
28278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
28288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_CONNECT:
28298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_wait_peer_connect(p2p);
28308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
28318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_WAIT_PEER_IDLE:
28328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_wait_peer_idle(p2p);
28338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
28348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SD_DURING_FIND:
28358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_sd_during_find(p2p);
28368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
28378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PROVISIONING:
28388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
28398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_PD_DURING_FIND:
28408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_prov_disc_during_find(p2p);
28418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
28428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE:
28438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_invite(p2p);
28448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
28458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_INVITE_LISTEN:
28468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_timeout_invite_listen(p2p);
28478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
28488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_reject(struct p2p_data *p2p, const u8 *peer_addr)
28538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
28558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
28578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Local request to reject "
28588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"connection attempts by peer " MACSTR, MAC2STR(peer_addr));
28598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL) {
28608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR
28618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			" unknown", MAC2STR(peer_addr));
28628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
28638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->status = P2P_SC_FAIL_REJECTED_BY_USER;
28658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags |= P2P_DEV_USER_REJECTED;
28668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
28678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * p2p_wps_method_text(enum p2p_wps_method method)
28718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (method) {
28738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_NOT_READY:
28748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "not-ready";
28758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_PIN_LABEL:
28768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "Label";
28778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_PIN_DISPLAY:
28788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "Display";
28798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_PIN_KEYPAD:
28808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "Keypad";
28818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_PBC:
28828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "PBC";
28838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return "??";
28868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * p2p_go_state_text(enum p2p_go_state go_state)
28908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (go_state) {
28928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case UNKNOWN_GO:
28938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "unknown";
28948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case LOCAL_GO:
28958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "local";
28968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case  REMOTE_GO:
28978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "remote";
28988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return "??";
29018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_peer_info(struct p2p_data *p2p, const u8 *addr, int next,
29058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      char *buf, size_t buflen)
29068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
29088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
29098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *pos, *end;
29108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct os_time now;
29118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char devtype[WPS_DEV_TYPE_BUFSIZE];
29128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr)
29148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, addr);
29158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
29168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = dl_list_first(&p2p->devices, struct p2p_device, list);
29178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev && next) {
29198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = dl_list_first(&dev->list, struct p2p_device, list);
29208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (&dev->list == &p2p->devices)
29218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev = NULL;
29228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
29258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
29268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf;
29288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = buf + buflen;
29298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = os_snprintf(pos, end - pos, MACSTR "\n",
29318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->info.p2p_device_addr));
29328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0 || res >= end - pos)
29338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return pos - buf;
29348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += res;
29358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&now);
29378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = os_snprintf(pos, end - pos,
29388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "age=%d\n"
29398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "listen_freq=%d\n"
29408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "level=%d\n"
29418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "wps_method=%s\n"
29428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "interface_addr=" MACSTR "\n"
29438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "member_in_go_dev=" MACSTR "\n"
29448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "member_in_go_iface=" MACSTR "\n"
29458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "pri_dev_type=%s\n"
29468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "device_name=%s\n"
29478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "manufacturer=%s\n"
29488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "model_name=%s\n"
29498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "model_number=%s\n"
29508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "serial_number=%s\n"
29518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "config_methods=0x%x\n"
29528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dev_capab=0x%x\n"
29538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "group_capab=0x%x\n"
29548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "go_neg_req_sent=%d\n"
29558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "go_state=%s\n"
29568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dialog_token=%u\n"
29578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "intended_addr=" MACSTR "\n"
29588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "country=%c%c\n"
29598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "oper_freq=%d\n"
29608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "req_config_methods=0x%x\n"
29618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "flags=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n"
29628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "status=%d\n"
29638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "wait_count=%u\n"
29648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "invitation_reqs=%u\n",
29658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  (int) (now.sec - dev->last_seen.sec),
29668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->listen_freq,
296775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			  dev->info.level,
29688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  p2p_wps_method_text(dev->wps_method),
29698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->interface_addr),
29708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->member_in_go_dev),
29718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->member_in_go_iface),
29728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  wps_dev_type_bin2str(dev->info.pri_dev_type,
29738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       devtype, sizeof(devtype)),
29748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->info.device_name,
29758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->info.manufacturer,
29768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->info.model_name,
29778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->info.model_number,
29788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->info.serial_number,
29798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->info.config_methods,
29808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->info.dev_capab,
29818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->info.group_capab,
29828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->go_neg_req_sent,
29838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  p2p_go_state_text(dev->go_state),
29848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->dialog_token,
29858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  MAC2STR(dev->intended_addr),
29868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->country[0] ? dev->country[0] : '_',
29878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->country[1] ? dev->country[1] : '_',
29888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->oper_freq,
29898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->req_config_methods,
29908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PROBE_REQ_ONLY ?
29918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PROBE_REQ_ONLY]" : "",
29928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_REPORTED ? "[REPORTED]" : "",
29938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_NOT_YET_READY ?
29948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[NOT_YET_READY]" : "",
29958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_SD_INFO ? "[SD_INFO]" : "",
29968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_SD_SCHEDULE ? "[SD_SCHEDULE]" :
29978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "",
29988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PD_PEER_DISPLAY ?
29998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PD_PEER_DISPLAY]" : "",
30008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PD_PEER_KEYPAD ?
30018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PD_PEER_KEYPAD]" : "",
30028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_USER_REJECTED ?
30038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[USER_REJECTED]" : "",
30048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PEER_WAITING_RESPONSE ?
30058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PEER_WAITING_RESPONSE]" : "",
30068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PREFER_PERSISTENT_GROUP ?
30078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PREFER_PERSISTENT_GROUP]" : "",
30088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_WAIT_GO_NEG_RESPONSE ?
30098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[WAIT_GO_NEG_RESPONSE]" : "",
30108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM ?
30118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[WAIT_GO_NEG_CONFIRM]" : "",
30128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_GROUP_CLIENT_ONLY ?
30138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[GROUP_CLIENT_ONLY]" : "",
30148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_FORCE_FREQ ?
30158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[FORCE_FREQ]" : "",
30168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->flags & P2P_DEV_PD_FOR_JOIN ?
30178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "[PD_FOR_JOIN]" : "",
30188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->status,
30198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->wait_count,
30208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  dev->invitation_reqs);
30218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0 || res >= end - pos)
30228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return pos - buf;
30238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += res;
30248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->ext_listen_period) {
30268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = os_snprintf(pos, end - pos,
30278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "ext_listen_period=%u\n"
30288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "ext_listen_interval=%u\n",
30298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  dev->ext_listen_period,
30308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  dev->ext_listen_interval);
30318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res < 0 || res >= end - pos)
30328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos - buf;
30338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += res;
30348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->oper_ssid_len) {
30378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = os_snprintf(pos, end - pos,
30388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "oper_ssid=%s\n",
30398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  wpa_ssid_txt(dev->oper_ssid,
30408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       dev->oper_ssid_len));
30418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res < 0 || res >= end - pos)
30428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos - buf;
30438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += res;
30448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return pos - buf;
30478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_client_discoverability(struct p2p_data *p2p, int enabled)
30518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (enabled) {
30538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Client "
30548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"discoverability enabled");
30558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
30568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
30578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Client "
30588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"discoverability disabled");
30598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab &= ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
30608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_presence_req(u32 duration1, u32 interval1,
30658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      u32 duration2, u32 interval2)
30668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
30688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_noa_desc desc1, desc2, *ptr1 = NULL, *ptr2 = NULL;
30698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
30708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req = wpabuf_alloc(100);
30728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL)
30738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
30748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (duration1 || interval1) {
30768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(&desc1, 0, sizeof(desc1));
30778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc1.count_type = 1;
30788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc1.duration = duration1;
30798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc1.interval = interval1;
30808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ptr1 = &desc1;
30818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (duration2 || interval2) {
30838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(&desc2, 0, sizeof(desc2));
30848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc2.count_type = 2;
30858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc2.duration = duration2;
30868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc2.interval = interval2;
30878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ptr2 = &desc2;
30888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
30898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_action_hdr(req, P2P_PRESENCE_REQ, 1);
30928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(req);
30938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_noa(req, 0, 0, 0, ptr1, ptr2);
30948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(req, len);
30958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return req;
30978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_presence_req(struct p2p_data *p2p, const u8 *go_interface_addr,
31018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     const u8 *own_interface_addr, unsigned int freq,
31028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     u32 duration1, u32 interval1, u32 duration2,
31038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     u32 interval2)
31048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
31068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send Presence Request to "
31088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"GO " MACSTR " (own interface " MACSTR ") freq=%u dur1=%u "
31098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"int1=%u dur2=%u int2=%u",
31108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(go_interface_addr), MAC2STR(own_interface_addr),
31118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		freq, duration1, interval1, duration2, interval2);
31128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req = p2p_build_presence_req(duration1, interval1, duration2,
31148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     interval2);
31158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL)
31168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
31178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
31198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_send_action(p2p, freq, go_interface_addr, own_interface_addr,
31208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    go_interface_addr,
31218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpabuf_head(req), wpabuf_len(req), 200) < 0) {
31228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
31238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to send Action frame");
31248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(req);
31268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
31288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_presence_resp(u8 status, const u8 *noa,
31328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       size_t noa_len, u8 dialog_token)
31338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
31358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
31368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = wpabuf_alloc(100 + noa_len);
31388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
31398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
31408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_action_hdr(resp, P2P_PRESENCE_RESP, dialog_token);
31428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(resp);
31438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_status(resp, status);
31448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (noa) {
31458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(resp, P2P_ATTR_NOTICE_OF_ABSENCE);
31468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_le16(resp, noa_len);
31478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_data(resp, noa, noa_len);
31488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
31498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_noa(resp, 0, 0, 0, NULL, NULL);
31508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(resp, len);
31518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return resp;
31538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_req(struct p2p_data *p2p, const u8 *da,
31578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const u8 *sa, const u8 *data, size_t len,
31588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     int rx_freq)
31598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
31618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 status;
31628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
31638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t g;
31648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group *group = NULL;
31658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int parsed = 0;
31668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 noa[50];
31678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int noa_len;
31688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
31708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Received P2P Action - P2P Presence Request");
31718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (g = 0; g < p2p->num_groups; g++) {
31738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(da, p2p_group_get_interface_addr(p2p->groups[g]),
31748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      ETH_ALEN) == 0) {
31758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group = p2p->groups[g];
31768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
31778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group == NULL) {
31808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
31818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Ignore P2P Presence Request for unknown group "
31828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MACSTR, MAC2STR(da));
31838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
31848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse(data, len, &msg) < 0) {
31878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
31888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to parse P2P Presence Request");
31898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		status = P2P_SC_FAIL_INVALID_PARAMS;
31908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
31918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	parsed = 1;
31938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.noa == NULL) {
31958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
31968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No NoA attribute in P2P Presence Request");
31978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		status = P2P_SC_FAIL_INVALID_PARAMS;
31988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
31998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	status = p2p_group_presence_req(group, sa, msg.noa, msg.noa_len);
32028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail:
32048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->get_noa)
32058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		noa_len = p2p->cfg->get_noa(p2p->cfg->cb_ctx, da, noa,
32068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    sizeof(noa));
32078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
32088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		noa_len = -1;
32098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = p2p_build_presence_resp(status, noa_len > 0 ? noa : NULL,
32108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       noa_len > 0 ? noa_len : 0,
32118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       msg.dialog_token);
32128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (parsed)
32138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
32148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
32158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
32168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
32188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_send_action(p2p, rx_freq, sa, da, da,
32198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
32208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
32218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to send Action frame");
32228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(resp);
32248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_process_presence_resp(struct p2p_data *p2p, const u8 *da,
32288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *sa, const u8 *data, size_t len)
32298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
32308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
32318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
32338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Received P2P Action - P2P Presence Response");
32348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse(data, len, &msg) < 0) {
32368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
32378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to parse P2P Presence Response");
32388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
32398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.status == NULL || msg.noa == NULL) {
32428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
32438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No Status or NoA attribute in P2P Presence "
32448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Response");
32458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
32468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
32478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*msg.status) {
32508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
32518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: P2P Presence Request was rejected: status %u",
32528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*msg.status);
32538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
32548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
32558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
32588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: P2P Presence Request was accepted");
32598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "P2P: P2P Presence Response - NoA",
32608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    msg.noa, msg.noa_len);
32618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: process NoA */
32628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
32638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_ext_listen_timeout(void *eloop_ctx, void *timeout_ctx)
32678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
32688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = eloop_ctx;
32698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->ext_listen_interval) {
32718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Schedule next extended listen timeout */
32728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(p2p->ext_listen_interval_sec,
32738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p->ext_listen_interval_usec,
32748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       p2p_ext_listen_timeout, p2p, NULL);
32758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state == P2P_LISTEN_ONLY && p2p->ext_listen_only) {
32788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
32798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * This should not really happen, but it looks like the Listen
32808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * command may fail is something else (e.g., a scan) was
32818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * running at an inconvenient time. As a workaround, allow new
32828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Extended Listen operation to be started.
32838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
32848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Previous "
32858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Extended Listen operation had not been completed - "
32868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"try again");
32878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_only = 0;
32888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_state(p2p, P2P_IDLE);
32898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->state != P2P_IDLE) {
32928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Skip Extended "
32938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Listen timeout in active state (%s)",
32948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_state_txt(p2p->state));
32958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
32968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Extended Listen timeout");
32998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_only = 1;
33008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_listen(p2p, p2p->ext_listen_period) < 0) {
33018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Failed to start "
33028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Listen state for Extended Listen Timing");
33038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_only = 0;
33048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_ext_listen(struct p2p_data *p2p, unsigned int period,
33098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   unsigned int interval)
33108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (period > 65535 || interval > 65535 || period > interval ||
33128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (period == 0 && interval > 0) || (period > 0 && interval == 0)) {
33138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
33148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Invalid Extended Listen Timing request: "
33158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"period=%u interval=%u", period, interval);
33168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
33178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(p2p_ext_listen_timeout, p2p, NULL);
33208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (interval == 0) {
33228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
33238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Disabling Extended Listen Timing");
33248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_period = 0;
33258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->ext_listen_interval = 0;
33268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
33278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
33308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Enabling Extended Listen Timing: period %u msec, "
33318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"interval %u msec", period, interval);
33328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_period = period;
33338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_interval = interval;
33348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_interval_sec = interval / 1000;
33358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->ext_listen_interval_usec = (interval % 1000) * 1000;
33368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(p2p->ext_listen_interval_sec,
33388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p->ext_listen_interval_usec,
33398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p_ext_listen_timeout, p2p, NULL);
33408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
33428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_deauth_notif(struct p2p_data *p2p, const u8 *bssid, u16 reason_code,
33468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      const u8 *ie, size_t ie_len)
33478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
33498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bssid == NULL || ie == NULL)
33518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
33528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
33548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg))
33558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
33568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.minor_reason_code == NULL)
33578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
33588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_INFO,
33608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Deauthentication notification BSSID " MACSTR
33618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" reason_code=%u minor_reason_code=%u",
33628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(bssid), reason_code, *msg.minor_reason_code);
33638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
33658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_disassoc_notif(struct p2p_data *p2p, const u8 *bssid, u16 reason_code,
33698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const u8 *ie, size_t ie_len)
33708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
33728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bssid == NULL || ie == NULL)
33748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
33758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
33778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_ies(ie, ie_len, &msg))
33788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
33798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.minor_reason_code == NULL)
33808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
33818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_INFO,
33838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Disassociation notification BSSID " MACSTR
33848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" reason_code=%u minor_reason_code=%u",
33858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(bssid), reason_code, *msg.minor_reason_code);
33868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
33888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_managed_oper(struct p2p_data *p2p, int enabled)
33928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (enabled) {
33948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Managed P2P "
33958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Device operations enabled");
33968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab |= P2P_DEV_CAPAB_INFRA_MANAGED;
33978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
33988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Managed P2P "
33998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Device operations disabled");
34008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->dev_capab &= ~P2P_DEV_CAPAB_INFRA_MANAGED;
34018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel)
34068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_channel_to_freq(p2p->cfg->country, reg_class, channel) < 0)
34088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
34098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Set Listen channel: "
34118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"reg_class %u channel %u", reg_class, channel);
34128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->reg_class = reg_class;
34138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->channel = channel;
34148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
34168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_set_ssid_postfix(struct p2p_data *p2p, const u8 *postfix, size_t len)
34208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "P2P: New SSID postfix", postfix, len);
34228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (postfix == NULL) {
34238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->ssid_postfix_len = 0;
34248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
34258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > sizeof(p2p->cfg->ssid_postfix))
34278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
34288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->cfg->ssid_postfix, postfix, len);
34298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->ssid_postfix_len = len;
34308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
34318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
343475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenint p2p_set_oper_channel(struct p2p_data *p2p, u8 op_reg_class, u8 op_channel,
343575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			 int cfg_op_channel)
343675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
343775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p_channel_to_freq(p2p->cfg->country, op_reg_class, op_channel)
343875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	    < 0)
343975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return -1;
344075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
344175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, "P2P: Set Operating channel: "
344275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		"reg_class %u channel %u", op_reg_class, op_channel);
344375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->cfg->op_reg_class = op_reg_class;
344475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->cfg->op_channel = op_channel;
344575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->cfg->cfg_op_channel = cfg_op_channel;
344675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	return 0;
344775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
344875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
344975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
34508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_interface_addr(struct p2p_data *p2p, const u8 *dev_addr,
34518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   u8 *iface_addr)
34528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p_get_device(p2p, dev_addr);
34548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL || is_zero_ether_addr(dev->interface_addr))
34558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
34568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(iface_addr, dev->interface_addr, ETH_ALEN);
34578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
34588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_dev_addr(struct p2p_data *p2p, const u8 *iface_addr,
34628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   u8 *dev_addr)
34638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p_get_device_interface(p2p, iface_addr);
34658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
34668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
34678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev_addr, dev->info.p2p_device_addr, ETH_ALEN);
34688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
34698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_peer_filter(struct p2p_data *p2p, const u8 *addr)
34738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p->peer_filter, addr, ETH_ALEN);
34758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (is_zero_ether_addr(p2p->peer_filter))
34768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Disable peer "
34778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"filter");
34788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
34798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Enable peer "
34808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"filter for " MACSTR, MAC2STR(p2p->peer_filter));
34818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_cross_connect(struct p2p_data *p2p, int enabled)
34858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Cross connection %s",
34878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		enabled ? "enabled" : "disabled");
34888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cross_connect == enabled)
34898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
34908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cross_connect = enabled;
34918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: may need to tear down any action group where we are GO(?) */
34928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_oper_freq(struct p2p_data *p2p, const u8 *iface_addr)
34968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev = p2p_get_device_interface(p2p, iface_addr);
34988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
34998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
35008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->oper_freq <= 0)
35018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
35028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return dev->oper_freq;
35038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
35048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_intra_bss_dist(struct p2p_data *p2p, int enabled)
35078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
35088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Intra BSS distribution %s",
35098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		enabled ? "enabled" : "disabled");
35108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->p2p_intra_bss = enabled;
35118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
35128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_update_channel_list(struct p2p_data *p2p, struct p2p_channels *chan)
35158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
35168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Update channel list");
35178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&p2p->cfg->channels, chan, sizeof(struct p2p_channels));
35188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
35198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_send_action(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
35228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    const u8 *src, const u8 *bssid, const u8 *buf,
35238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    size_t len, unsigned int wait_time)
35248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
35258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->p2p_scan_running) {
35268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Delay Action "
35278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"frame TX until p2p_scan completes");
35288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->after_scan_tx) {
35298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Dropped "
35308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"previous pending Action frame TX");
35318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(p2p->after_scan_tx);
35328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
35338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx = os_malloc(sizeof(*p2p->after_scan_tx) +
35348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       len);
35358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->after_scan_tx == NULL)
35368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
35378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx->freq = freq;
35388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx->dst, dst, ETH_ALEN);
35398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx->src, src, ETH_ALEN);
35408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx->bssid, bssid, ETH_ALEN);
35418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx->len = len;
35428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->after_scan_tx->wait_time = wait_time;
35438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p->after_scan_tx + 1, buf, len);
35448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
35458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
35468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, dst, src, bssid,
35488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     buf, len, wait_time);
35498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
35508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_set_best_channels(struct p2p_data *p2p, int freq_24, int freq_5,
35538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   int freq_overall)
35548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
35558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Best channel: 2.4 GHz: %d,"
35568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  5 GHz: %d,  overall: %d", freq_24, freq_5, freq_overall);
35578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->best_freq_24 = freq_24;
35588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->best_freq_5 = freq_5;
35598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->best_freq_overall = freq_overall;
35608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
35618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * p2p_get_go_neg_peer(struct p2p_data *p2p)
35648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
35658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p == NULL || p2p->go_neg_peer == NULL)
35668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
35678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p->go_neg_peer->info.p2p_device_addr;
35688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
35698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst struct p2p_peer_info *
35728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtp2p_get_peer_found(struct p2p_data *p2p, const u8 *addr, int next)
35738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
35748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
35758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr) {
35778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device(p2p, addr);
35788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!dev)
35798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
35808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!next) {
35828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dev->flags & P2P_DEV_PROBE_REQ_ONLY)
35838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return NULL;
35848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return &dev->info;
35868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
35878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			do {
35888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				dev = dl_list_first(&dev->list,
35898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    struct p2p_device,
35908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    list);
35918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				if (&dev->list == &p2p->devices)
35928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					return NULL;
35938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} while (dev->flags & P2P_DEV_PROBE_REQ_ONLY);
35948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
35958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
35968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = dl_list_first(&p2p->devices, struct p2p_device, list);
35978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!dev)
35988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
35998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (dev->flags & P2P_DEV_PROBE_REQ_ONLY) {
36008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev = dl_list_first(&dev->list,
36018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    struct p2p_device,
36028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    list);
36038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (&dev->list == &p2p->devices)
36048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return NULL;
36058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
36068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
36078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return &dev->info;
36098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3610