18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant - P2P
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2009-2010, Atheros Communications
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_common.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/wpa_ctrl.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps/wps_i.h"
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p/p2p.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap/hostapd.h"
191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "ap/ap_config.h"
20391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#include "ap/sta_info.h"
21391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#include "ap/ap_drv_ops.h"
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap/p2p_hostapd.h"
2375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen#include "eapol_supp/eapol_supp_sm.h"
2475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen#include "rsn_supp/wpa.h"
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_supplicant_i.h"
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "driver_i.h"
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap.h"
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "config_ssid.h"
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "config.h"
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "notify.h"
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "scan.h"
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "bss.h"
331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "offchannel.h"
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps_supplicant.h"
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p_supplicant.h"
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * How many times to try to scan to find the GO before giving up on join
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * request.
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define P2P_MAX_JOIN_SCAN_ATTEMPTS 10
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#define P2P_AUTO_PD_SCAN_ATTEMPTS 5
4504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifndef P2P_MAX_CLIENT_IDLE
471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt/*
481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * How many seconds to try to reconnect to the GO when connection in P2P client
491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * role has been lost.
501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */
5198f9e76624da6bb96edc1982c423e4a119c5170aDmitry Shmidt#ifdef ANDROID_P2P
5298f9e76624da6bb96edc1982c423e4a119c5170aDmitry Shmidt#define P2P_MAX_CLIENT_IDLE 20
5398f9e76624da6bb96edc1982c423e4a119c5170aDmitry Shmidt#else
541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#define P2P_MAX_CLIENT_IDLE 10
5598f9e76624da6bb96edc1982c423e4a119c5170aDmitry Shmidt#endif /* ANDROID_P2P */
561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* P2P_MAX_CLIENT_IDLE */
571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
5804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifndef P2P_MAX_INITIAL_CONN_WAIT
5904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt/*
6004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * How many seconds to wait for initial 4-way handshake to get completed after
6104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * WPS provisioning step.
6204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt */
6304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#define P2P_MAX_INITIAL_CONN_WAIT 10
6404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* P2P_MAX_INITIAL_CONN_WAIT */
6504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
6692c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt#ifndef P2P_MAX_INITIAL_CONN_WAIT_GO
6792c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt/*
6892c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt * How many seconds to wait for initial 4-way handshake to get completed after
6992c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt * WPS provisioning step on the GO. This controls the extra time the P2P
7092c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt * operation is considered to be in progress (e.g., to delay other scans) after
7192c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt * WPS provisioning has been completed on the GO during group formation.
7292c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt */
7392c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt#define P2P_MAX_INITIAL_CONN_WAIT_GO 10
7492c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt#endif /* P2P_MAX_INITIAL_CONN_WAIT_GO */
7592c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt
7661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifndef P2P_CONCURRENT_SEARCH_DELAY
7761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#define P2P_CONCURRENT_SEARCH_DELAY 500
7861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* P2P_CONCURRENT_SEARCH_DELAY */
7961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
8034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#define P2P_MGMT_DEVICE_PREFIX		"p2p-dev-"
8134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
8261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtenum p2p_group_removal_reason {
8361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	P2P_GROUP_REMOVAL_UNKNOWN,
8461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	P2P_GROUP_REMOVAL_SILENT,
8561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	P2P_GROUP_REMOVAL_FORMATION_FAILED,
8661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	P2P_GROUP_REMOVAL_REQUESTED,
8761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	P2P_GROUP_REMOVAL_IDLE_TIMEOUT,
8861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	P2P_GROUP_REMOVAL_UNAVAILABLE,
8961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	P2P_GROUP_REMOVAL_GO_ENDING_SESSION,
90391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	P2P_GROUP_REMOVAL_PSK_FAILURE,
9161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef ANDROID_P2P
9261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	P2P_GROUP_REMOVAL_FREQ_CONFLICT
9361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif
9461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt};
9561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
96dc7b71324df9788e194745e8ab9386a4619a623aJouni Malinen
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_p2p_long_listen_timeout(void *eloop_ctx, void *timeout_ctx);
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_supplicant *
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 int go);
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpas_p2p_join_start(struct wpa_supplicant *wpa_s);
10204949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq);
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx);
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr,
10504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 const u8 *dev_addr, enum p2p_wps_method wps_method,
10604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 int auto_join);
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s);
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_p2p_cross_connect_setup(struct wpa_supplicant *wpa_s);
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_p2p_group_idle_timeout(void *eloop_ctx, void *timeout_ctx);
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_p2p_set_group_idle_timeout(struct wpa_supplicant *wpa_s);
111f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtstatic void wpas_p2p_group_formation_timeout(void *eloop_ctx,
112f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt					     void *timeout_ctx);
1131cf4573e05a4e7ce02e0ccc46771a1da5f303411Dmitry Shmidt#ifdef ANDROID_P2P
1141cf4573e05a4e7ce02e0ccc46771a1da5f303411Dmitry Shmidtstatic void wpas_p2p_group_freq_conflict(void *eloop_ctx, void *timeout_ctx);
1151cf4573e05a4e7ce02e0ccc46771a1da5f303411Dmitry Shmidt#endif
11604949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
11704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					int group_added);
118d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic int wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s);
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
121c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt/*
122c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt * Get the number of concurrent channels that the HW can operate, but that are
123c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt * currently not in use by any of the wpa_supplicant interfaces.
124c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt */
125c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidtstatic int wpas_p2p_num_unused_channels(struct wpa_supplicant *wpa_s)
126c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt{
127c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	int *freqs;
128c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	int num;
129c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
130c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	freqs = os_calloc(wpa_s->num_multichan_concurrent, sizeof(int));
131c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	if (!freqs)
132c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		return -1;
133c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
134c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	num = get_shared_radio_freqs(wpa_s, freqs,
135c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				     wpa_s->num_multichan_concurrent);
136c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	os_free(freqs);
137c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
138c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	return wpa_s->num_multichan_concurrent - num;
139c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt}
140c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
141c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
142c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt/*
143c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt * Get the frequencies that are currently in use by one or more of the virtual
144c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt * interfaces, and that are also valid for P2P operation.
145c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt */
146c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidtstatic int wpas_p2p_valid_oper_freqs(struct wpa_supplicant *wpa_s,
147c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				     int *p2p_freqs, unsigned int len)
148c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt{
149c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	int *freqs;
150c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	unsigned int num, i, j;
151c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
152c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	freqs = os_calloc(wpa_s->num_multichan_concurrent, sizeof(int));
153c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	if (!freqs)
154c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		return -1;
155c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
156c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	num = get_shared_radio_freqs(wpa_s, freqs,
157c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				     wpa_s->num_multichan_concurrent);
158c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
159c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	os_memset(p2p_freqs, 0, sizeof(int) * len);
160c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
161c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	for (i = 0, j = 0; i < num && j < len; i++) {
162c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		if (p2p_supported_freq(wpa_s->global->p2p, freqs[i]))
163c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			p2p_freqs[j++] = freqs[i];
164c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	}
165c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
166c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	os_free(freqs);
167c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
168c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	return j;
169c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt}
170c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
171c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
172700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidtstatic void wpas_p2p_set_own_freq_preference(struct wpa_supplicant *wpa_s,
173700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt					     int freq)
174700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt{
175700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
176700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt		return;
177c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	if (freq > 0 && wpa_s->num_multichan_concurrent > 1 &&
178c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	    wpas_p2p_num_unused_channels(wpa_s) > 0 &&
179700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	    wpa_s->parent->conf->p2p_ignore_shared_freq)
180700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt		freq = 0;
181700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	p2p_set_own_freq_preference(wpa_s->global->p2p, freq);
182700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt}
183700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt
184700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s,
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      struct wpa_scan_results *scan_res)
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Scan results received (%d BSS)",
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) scan_res->num);
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < scan_res->num; i++) {
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct wpa_scan_res *bss = scan_res->res[i];
198f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		struct os_time time_tmp_age, entry_ts;
199f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		time_tmp_age.sec = bss->age / 1000;
200f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		time_tmp_age.usec = (bss->age % 1000) * 1000;
201f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		os_time_sub(&scan_res->fetch_time, &time_tmp_age, &entry_ts);
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p_scan_res_handler(wpa_s->global->p2p, bss->bssid,
203f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt					 bss->freq, &entry_ts, bss->level,
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 (const u8 *) (bss + 1),
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 bss->ie_len) > 0)
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_scan_res_handled(wpa_s->global->p2p);
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 unsigned int num_req_dev_types,
21504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 const u8 *req_dev_types, const u8 *dev_id, u16 pw_id)
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
21861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct wpa_supplicant *ifs;
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_scan_params params;
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *wps_ie, *ies;
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int social_channels[] = { 2412, 2437, 2462, 0, 0 };
2231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	size_t ielen;
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
22961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (ifs->sta_scan_pending &&
23037d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt		    (wpas_scan_scheduled(ifs) || ifs->scanning) &&
23161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		    wpas_p2p_in_progress(wpa_s) == 2) {
23261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Delaying P2P scan to allow "
23361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   "pending station mode scan to be "
23461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   "completed on interface %s", ifs->ifname);
235dc7b71324df9788e194745e8ab9386a4619a623aJouni Malinen			wpa_s->global->p2p_cb_on_scan_complete = 1;
23661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_supplicant_req_scan(ifs, 0, 0);
23761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return 1;
23861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
23961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
24061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&params, 0, sizeof(params));
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P Wildcard SSID */
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.num_ssids = 1;
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.ssids[0].ssid = (u8 *) P2P_WILDCARD_SSID;
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->wps->dev.p2p = 1;
24904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wps_ie = wps_build_probe_req_ie(pw_id, &wpa_s->wps->dev,
25004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					wpa_s->wps->uuid, WPS_REQ_ENROLLEE,
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					num_req_dev_types, req_dev_types);
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wps_ie == NULL)
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
2561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen);
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ies == NULL) {
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(wps_ie);
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_buf(ies, wps_ie);
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(wps_ie);
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
264c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	p2p_scan_ie(wpa_s->global->p2p, ies, dev_id);
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	params.p2p_probe = 1;
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.extra_ies = wpabuf_head(ies);
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.extra_ies_len = wpabuf_len(ies);
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (type) {
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SCAN_SOCIAL:
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		params.freqs = social_channels;
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SCAN_FULL:
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_SCAN_SOCIAL_PLUS_ONE:
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		social_channels[3] = freq;
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		params.freqs = social_channels;
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ret = wpa_drv_scan(wpa_s, &params);
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(ies);
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (ret) {
287043a5a9d2586bf379a3f3e811c8c64d92050e131Jouni Malinen		for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
288043a5a9d2586bf379a3f3e811c8c64d92050e131Jouni Malinen			if (ifs->scanning ||
289043a5a9d2586bf379a3f3e811c8c64d92050e131Jouni Malinen			    ifs->scan_res_handler == wpas_p2p_scan_res_handler) {
290043a5a9d2586bf379a3f3e811c8c64d92050e131Jouni Malinen				wpa_s->global->p2p_cb_on_scan_complete = 1;
291043a5a9d2586bf379a3f3e811c8c64d92050e131Jouni Malinen				ret = 1;
292043a5a9d2586bf379a3f3e811c8c64d92050e131Jouni Malinen				break;
293043a5a9d2586bf379a3f3e811c8c64d92050e131Jouni Malinen			}
2941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
295444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt	} else {
296444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt		os_get_time(&wpa_s->scan_trigger_time);
29704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_s->scan_res_handler = wpas_p2p_scan_res_handler;
298444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt	}
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return ret;
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum wpa_driver_if_type wpas_p2p_if_type(int p2p_group_interface)
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (p2p_group_interface) {
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GROUP_INTERFACE_PENDING:
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return WPA_IF_P2P_GROUP;
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GROUP_INTERFACE_GO:
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return WPA_IF_P2P_GO;
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GROUP_INTERFACE_CLIENT:
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return WPA_IF_P2P_CLIENT;
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return WPA_IF_P2P_GROUP;
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_supplicant * wpas_get_p2p_group(struct wpa_supplicant *wpa_s,
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						  const u8 *ssid,
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						  size_t ssid_len, int *go)
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *s;
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (s = wpa_s->conf->ssid; s; s = s->next) {
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (s->disabled != 0 || !s->p2p_group ||
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    s->ssid_len != ssid_len ||
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    os_memcmp(ssid, s->ssid, ssid_len) != 0)
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				continue;
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (s->mode == WPAS_MODE_P2P_GO &&
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    s != wpa_s->current_ssid)
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				continue;
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (go)
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				*go = s->mode == WPAS_MODE_P2P_GO;
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return wpa_s;
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s,
34561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				 enum p2p_group_removal_reason removal_reason)
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid;
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *gtype;
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *reason;
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid = wpa_s->current_ssid;
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid == NULL) {
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * The current SSID was not known, but there may still be a
355aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt		 * pending P2P group interface waiting for provisioning or a
356aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt		 * P2P group that is trying to reconnect.
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid = wpa_s->conf->ssid;
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (ssid) {
3609d71283328fbad680cc74d9b287580e373eb4d6cJouni Malinen			if (ssid->p2p_group && ssid->disabled != 2)
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ssid = ssid->next;
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3645c44edb00c9384534a1b50981071874436aaecd5Jouni Malinen		if (ssid == NULL &&
3655c44edb00c9384534a1b50981071874436aaecd5Jouni Malinen			wpa_s->p2p_group_interface == NOT_P2P_GROUP_INTERFACE)
3665c44edb00c9384534a1b50981071874436aaecd5Jouni Malinen		{
36761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_printf(MSG_ERROR, "P2P: P2P group interface "
36861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   "not found");
36961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
37061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_GO)
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gtype = "GO";
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT ||
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 (ssid && ssid->mode == WPAS_MODE_INFRA)) {
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->reassociate = 0;
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->disconnected = 1;
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_deauthenticate(wpa_s,
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      WLAN_REASON_DEAUTH_LEAVING);
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gtype = "client";
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gtype = "GO";
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->cross_connect_in_use) {
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->cross_connect_in_use = 0;
385b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		wpa_msg_global(wpa_s->parent, MSG_INFO,
386b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
387b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       wpa_s->ifname, wpa_s->cross_connect_uplink);
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	switch (removal_reason) {
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GROUP_REMOVAL_REQUESTED:
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reason = " reason=REQUESTED";
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
39361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	case P2P_GROUP_REMOVAL_FORMATION_FAILED:
39461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		reason = " reason=FORMATION_FAILED";
39561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		break;
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GROUP_REMOVAL_IDLE_TIMEOUT:
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reason = " reason=IDLE";
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_GROUP_REMOVAL_UNAVAILABLE:
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reason = " reason=UNAVAILABLE";
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
40204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case P2P_GROUP_REMOVAL_GO_ENDING_SESSION:
40304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		reason = " reason=GO_ENDING_SESSION";
40404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
405391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	case P2P_GROUP_REMOVAL_PSK_FAILURE:
406391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		reason = " reason=PSK_FAILURE";
407391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		break;
408687922c7347bdc3b4f8c921efe1d1388cb3baac0Dmitry Shmidt#ifdef ANDROID_P2P
409687922c7347bdc3b4f8c921efe1d1388cb3baac0Dmitry Shmidt	case P2P_GROUP_REMOVAL_FREQ_CONFLICT:
410687922c7347bdc3b4f8c921efe1d1388cb3baac0Dmitry Shmidt		reason = " reason=FREQ_CONFLICT";
411687922c7347bdc3b4f8c921efe1d1388cb3baac0Dmitry Shmidt		break;
412687922c7347bdc3b4f8c921efe1d1388cb3baac0Dmitry Shmidt#endif
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reason = "";
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
41761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (removal_reason != P2P_GROUP_REMOVAL_SILENT) {
418b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		wpa_msg_global(wpa_s->parent, MSG_INFO,
419b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       P2P_EVENT_GROUP_REMOVED "%s %s%s",
420b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       wpa_s->ifname, gtype, reason);
42104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4231cf4573e05a4e7ce02e0ccc46771a1da5f303411Dmitry Shmidt#ifdef ANDROID_P2P
4241cf4573e05a4e7ce02e0ccc46771a1da5f303411Dmitry Shmidt	eloop_cancel_timeout(wpas_p2p_group_freq_conflict, wpa_s, NULL);
4251cf4573e05a4e7ce02e0ccc46771a1da5f303411Dmitry Shmidt#endif
42604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL) > 0)
42704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group idle timeout");
428f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	if (eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
4292f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt				 wpa_s->parent, NULL) > 0) {
430f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group formation "
431f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			   "timeout");
4322f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt		wpa_s->p2p_in_provisioning = 0;
4332f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt	}
43404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
43561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (removal_reason != P2P_GROUP_REMOVAL_SILENT && ssid)
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_notify_p2p_group_removed(wpa_s, ssid, gtype);
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE) {
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct wpa_global *global;
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char *ifname;
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		enum wpa_driver_if_type type;
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Remove group interface %s",
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_s->ifname);
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		global = wpa_s->global;
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ifname = os_strdup(wpa_s->ifname);
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type = wpas_p2p_if_type(wpa_s->p2p_group_interface);
447e15c7b57cc7a214d5adaa0fc1d7204378eaf62a5Dmitry Shmidt		wpa_supplicant_remove_iface(wpa_s->global, wpa_s, 0);
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s = global->ifaces;
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_s && ifname)
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_drv_if_remove(wpa_s, type, ifname);
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(ifname);
4522b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen		return 1;
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Remove temporary group network");
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid && (ssid->p2p_group ||
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION ||
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     (ssid->key_mgmt & WPA_KEY_MGMT_WPS))) {
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int id = ssid->id;
46075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (ssid == wpa_s->current_ssid) {
46175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			wpa_sm_set_config(wpa_s->wpa, NULL);
46275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_s->current_ssid = NULL;
46475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		}
46575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/*
46675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		 * Networks objects created during any P2P activities are not
46775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		 * exposed out as they might/will confuse certain non-P2P aware
46875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		 * applications since these network objects won't behave like
46975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		 * regular ones.
47075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		 *
47175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		 * Likewise, we don't send out network removed signals for such
47275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		 * network objects.
47375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		 */
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_config_remove_network(wpa_s->conf, id);
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_clear_status(wpa_s);
476c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpa_supplicant_cancel_sched_scan(wpa_s);
47791c40cdce17424d9a4718876becf0b7811cf68f2Dmitry Shmidt		wpa_s->sta_scan_pending = 0;
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Temporary group network not "
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "found");
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
48204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (wpa_s->ap_iface)
48304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_supplicant_ap_deinit(wpa_s);
48404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	else
48504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_drv_deinit_p2p_cli(wpa_s);
48661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
48761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpas_p2p_persistent_group(struct wpa_supplicant *wpa_s,
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     u8 *go_dev_addr,
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const u8 *ssid, size_t ssid_len)
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_bss *bss;
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *bssid;
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *p2p;
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 group_capab;
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *addr;
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->go_params)
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		bssid = wpa_s->go_params->peer_interface_addr;
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		bssid = wpa_s->bssid;
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bss = wpa_bss_get(wpa_s, bssid, ssid, ssid_len);
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bss == NULL) {
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 iface_addr[ETH_ALEN];
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p_get_interface_addr(wpa_s->global->p2p, bssid,
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   iface_addr) == 0)
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			bss = wpa_bss_get(wpa_s, iface_addr, ssid, ssid_len);
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bss == NULL) {
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Could not figure out whether "
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "group is persistent - BSS " MACSTR " not found",
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   MAC2STR(bssid));
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p == NULL) {
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Could not figure out whether "
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "group is persistent - BSS " MACSTR
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " did not include P2P IE", MAC2STR(bssid));
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "P2P: Probe Response IEs",
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    (u8 *) (bss + 1), bss->ie_len);
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "P2P: Beacon IEs",
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    ((u8 *) bss + 1) + bss->ie_len,
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    bss->beacon_ie_len);
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group_capab = p2p_get_group_capab(p2p);
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr = p2p_get_go_dev_addr(p2p);
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Checking whether group is persistent: "
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "group_capab=0x%x", group_capab);
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr) {
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(go_dev_addr, addr, ETH_ALEN);
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: GO Device Address " MACSTR,
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   MAC2STR(addr));
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(go_dev_addr, 0, ETH_ALEN);
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(p2p);
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: BSS " MACSTR " group_capab=0x%x "
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "go_dev_addr=" MACSTR,
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   MAC2STR(bssid), group_capab, MAC2STR(go_dev_addr));
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return group_capab & P2P_GROUP_CAPAB_PERSISTENT_GROUP;
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
55375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic int wpas_p2p_store_persistent_group(struct wpa_supplicant *wpa_s,
55475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen					   struct wpa_ssid *ssid,
55575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen					   const u8 *go_dev_addr)
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *s;
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int changed = 0;
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Storing credentials for a persistent "
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "group (GO Dev Addr " MACSTR ")", MAC2STR(go_dev_addr));
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (s = wpa_s->conf->ssid; s; s = s->next) {
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (s->disabled == 2 &&
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_memcmp(go_dev_addr, s->bssid, ETH_ALEN) == 0 &&
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    s->ssid_len == ssid->ssid_len &&
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_memcmp(ssid->ssid, s->ssid, ssid->ssid_len) == 0)
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (s) {
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Update existing persistent group "
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "entry");
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ssid->passphrase && !s->passphrase)
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			changed = 1;
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (ssid->passphrase && s->passphrase &&
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 os_strcmp(ssid->passphrase, s->passphrase) != 0)
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			changed = 1;
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Create a new persistent group "
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "entry");
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		changed = 1;
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		s = wpa_config_add_network(wpa_s->conf);
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (s == NULL)
58475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			return -1;
58575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
58675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		/*
58775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		 * Instead of network_added we emit persistent_group_added
58875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		 * notification. Also to keep the defense checks in
58975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		 * persistent_group obj registration method, we set the
59075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		 * relevant flags in s to designate it as a persistent group.
59175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		 */
59275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		s->p2p_group = 1;
59375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		s->p2p_persistent_group = 1;
59475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		wpas_notify_persistent_group_added(wpa_s, s);
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_config_set_network_defaults(s);
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	s->p2p_group = 1;
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	s->p2p_persistent_group = 1;
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	s->disabled = 2;
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	s->bssid_set = 1;
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(s->bssid, go_dev_addr, ETH_ALEN);
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	s->mode = ssid->mode;
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	s->auth_alg = WPA_AUTH_ALG_OPEN;
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	s->key_mgmt = WPA_KEY_MGMT_PSK;
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	s->proto = WPA_PROTO_RSN;
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	s->pairwise_cipher = WPA_CIPHER_CCMP;
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	s->export_keys = 1;
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->passphrase) {
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(s->passphrase);
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		s->passphrase = os_strdup(ssid->passphrase);
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->psk_set) {
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		s->psk_set = 1;
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(s->psk, ssid->psk, 32);
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (s->passphrase && !s->psk_set)
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_config_update_psk(s);
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (s->ssid == NULL || s->ssid_len < ssid->ssid_len) {
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(s->ssid);
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		s->ssid = os_malloc(ssid->ssid_len);
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (s->ssid) {
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		s->ssid_len = ssid->ssid_len;
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(s->ssid, ssid->ssid, s->ssid_len);
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
627391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (ssid->mode == WPAS_MODE_P2P_GO && wpa_s->global->add_psk) {
628391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		dl_list_add(&s->psk_list, &wpa_s->global->add_psk->list);
629391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		wpa_s->global->add_psk = NULL;
630391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		changed = 1;
631391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	}
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_CONFIG_WRITE
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (changed && wpa_s->conf->update_config &&
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_config_write(wpa_s->confname, wpa_s->conf)) {
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_CONFIG_WRITE */
63975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
64075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	return s->id;
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void wpas_p2p_add_persistent_group_client(struct wpa_supplicant *wpa_s,
6451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt						 const u8 *addr)
6461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
6471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct wpa_ssid *ssid, *s;
6481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	u8 *n;
6491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	size_t i;
65061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	int found = 0;
6511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ssid = wpa_s->current_ssid;
6531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
6541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    !ssid->p2p_persistent_group)
6551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
6561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (s = wpa_s->parent->conf->ssid; s; s = s->next) {
6581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (s->disabled != 2 || s->mode != WPAS_MODE_P2P_GO)
6591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			continue;
6601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (s->ssid_len == ssid->ssid_len &&
6621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    os_memcmp(s->ssid, ssid->ssid, s->ssid_len) == 0)
6631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			break;
6641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
6651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (s == NULL)
6671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
6681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (i = 0; s->p2p_client_list && i < s->num_p2p_clients; i++) {
6701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (os_memcmp(s->p2p_client_list + i * ETH_ALEN, addr,
67161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			      ETH_ALEN) != 0)
67261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			continue;
67361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
67461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (i == s->num_p2p_clients - 1)
67561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return; /* already the most recent entry */
67661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
67761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		/* move the entry to mark it most recent */
67861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		os_memmove(s->p2p_client_list + i * ETH_ALEN,
67961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			   s->p2p_client_list + (i + 1) * ETH_ALEN,
68061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			   (s->num_p2p_clients - i - 1) * ETH_ALEN);
68161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		os_memcpy(s->p2p_client_list +
68261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			  (s->num_p2p_clients - 1) * ETH_ALEN, addr, ETH_ALEN);
68361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		found = 1;
68461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		break;
6851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
6861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
68761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (!found && s->num_p2p_clients < P2P_MAX_STORED_CLIENTS) {
68861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		n = os_realloc_array(s->p2p_client_list,
68961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				     s->num_p2p_clients + 1, ETH_ALEN);
69061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (n == NULL)
69161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return;
69261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		os_memcpy(n + s->num_p2p_clients * ETH_ALEN, addr, ETH_ALEN);
69361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		s->p2p_client_list = n;
69461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		s->num_p2p_clients++;
69561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else if (!found) {
69661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		/* Not enough room for an additional entry - drop the oldest
69761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		 * entry */
69861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		os_memmove(s->p2p_client_list,
69961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			   s->p2p_client_list + ETH_ALEN,
70061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			   (s->num_p2p_clients - 1) * ETH_ALEN);
70161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		os_memcpy(s->p2p_client_list +
70261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			  (s->num_p2p_clients - 1) * ETH_ALEN,
70361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			  addr, ETH_ALEN);
70461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
7051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
7061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifndef CONFIG_NO_CONFIG_WRITE
7071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_s->parent->conf->update_config &&
7081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    wpa_config_write(wpa_s->parent->confname, wpa_s->parent->conf))
7091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
7101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_NO_CONFIG_WRITE */
7111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
7121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
7131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_group_formation_completed(struct wpa_supplicant *wpa_s,
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   int success)
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid;
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *ssid_txt;
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int client;
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int persistent;
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 go_dev_addr[ETH_ALEN];
72275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	int network_id = -1;
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * This callback is likely called for the main interface. Update wpa_s
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * to use the group interface if a new interface was created for the
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * group.
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_group_formation)
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s = wpa_s->global->p2p_group_formation;
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->global->p2p_group_formation = NULL;
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->p2p_in_provisioning = 0;
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!success) {
735b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		wpa_msg_global(wpa_s->parent, MSG_INFO,
736b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       P2P_EVENT_GROUP_FORMATION_FAILURE);
73761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpas_p2p_group_delete(wpa_s,
73861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				      P2P_GROUP_REMOVAL_FORMATION_FAILED);
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
742b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	wpa_msg_global(wpa_s->parent, MSG_INFO,
743b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		       P2P_EVENT_GROUP_FORMATION_SUCCESS);
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid = wpa_s->current_ssid;
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid && ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid->mode = WPAS_MODE_P2P_GO;
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_group_notif_formation_done(wpa_s->p2p_group);
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_ap_mac_addr_filter(wpa_s, NULL);
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	persistent = 0;
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid) {
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid_txt = wpa_ssid_txt(ssid->ssid, ssid->ssid_len);
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		client = ssid->mode == WPAS_MODE_INFRA;
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ssid->mode == WPAS_MODE_P2P_GO) {
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			persistent = ssid->p2p_persistent_group;
758497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt			os_memcpy(go_dev_addr, wpa_s->global->p2p_dev_addr,
759497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt				  ETH_ALEN);
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			persistent = wpas_p2p_persistent_group(wpa_s,
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							       go_dev_addr,
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							       ssid->ssid,
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							       ssid->ssid_len);
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid_txt = "";
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		client = wpa_s->p2p_group_interface ==
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			P2P_GROUP_INTERFACE_CLIENT;
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(go_dev_addr, 0, ETH_ALEN);
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->show_group_started = 0;
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (client) {
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Indicate event only after successfully completed 4-way
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * handshake, i.e., when the interface is ready for data
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * packets.
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->show_group_started = 1;
7804b86ea55603eded752b5773179884a35e74e1a89Dmitry Shmidt#ifdef ANDROID_P2P
7814b86ea55603eded752b5773179884a35e74e1a89Dmitry Shmidt		/* For client Second phase of Group formation (4-way handshake) can be still pending
7824b86ea55603eded752b5773179884a35e74e1a89Dmitry Shmidt		 * So we need to restore wpa_s->global->p2p_group_formation */
783a2854abb63b41c123e4c78e5653a55d902f00be6Dmitry Shmidt		wpa_printf(MSG_INFO, "Restoring back wpa_s->global->p2p_group_formation to wpa_s %p\n", wpa_s);
7844b86ea55603eded752b5773179884a35e74e1a89Dmitry Shmidt		wpa_s->global->p2p_group_formation = wpa_s;
7854b86ea55603eded752b5773179884a35e74e1a89Dmitry Shmidt#endif
7864b86ea55603eded752b5773179884a35e74e1a89Dmitry Shmidt
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (ssid && ssid->passphrase == NULL && ssid->psk_set) {
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char psk[65];
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_snprintf_hex(psk, sizeof(psk), ssid->psk, 32);
790b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		wpa_msg_global(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
791b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       "%s GO ssid=\"%s\" freq=%d psk=%s go_dev_addr="
792b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       MACSTR "%s",
793b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       wpa_s->ifname, ssid_txt, ssid->frequency, psk,
794b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       MAC2STR(go_dev_addr),
795b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       persistent ? " [PERSISTENT]" : "");
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_p2p_cross_connect_setup(wpa_s);
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_p2p_set_group_idle_timeout(wpa_s);
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
799b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		wpa_msg_global(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
800b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       "%s GO ssid=\"%s\" freq=%d passphrase=\"%s\" "
801b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       "go_dev_addr=" MACSTR "%s",
802b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       wpa_s->ifname, ssid_txt,
803b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       ssid ? ssid->frequency : 0,
804b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       ssid && ssid->passphrase ? ssid->passphrase : "",
805b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       MAC2STR(go_dev_addr),
806b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       persistent ? " [PERSISTENT]" : "");
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_p2p_cross_connect_setup(wpa_s);
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_p2p_set_group_idle_timeout(wpa_s);
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (persistent)
81275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		network_id = wpas_p2p_store_persistent_group(wpa_s->parent,
81375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen							     ssid, go_dev_addr);
814391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	else {
815391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		os_free(wpa_s->global->add_psk);
816391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		wpa_s->global->add_psk = NULL;
817391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	}
8181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (network_id < 0 && ssid)
81975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		network_id = ssid->id;
82092c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt	if (!client) {
82175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		wpas_notify_p2p_group_started(wpa_s, ssid, network_id, 0);
82292c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt		os_get_time(&wpa_s->global->p2p_go_wait_client);
82392c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt	}
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void wpas_p2p_send_action_tx_status(struct wpa_supplicant *wpa_s,
8281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   unsigned int freq,
8291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   const u8 *dst, const u8 *src,
8301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   const u8 *bssid,
8311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   const u8 *data, size_t data_len,
8321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   enum offchannel_send_action_result
8331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   result)
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	enum p2p_send_action_result res = P2P_SEND_ACTION_SUCCESS;
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled)
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	switch (result) {
8431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case OFFCHANNEL_SEND_ACTION_SUCCESS:
8441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		res = P2P_SEND_ACTION_SUCCESS;
8451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
8461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case OFFCHANNEL_SEND_ACTION_NO_ACK:
8471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		res = P2P_SEND_ACTION_NO_ACK;
8481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
8491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case OFFCHANNEL_SEND_ACTION_FAILED:
8501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		res = P2P_SEND_ACTION_FAILED;
8511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_send_action_cb(wpa_s->global->p2p, freq, dst, src, bssid, res);
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
856c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (result != OFFCHANNEL_SEND_ACTION_SUCCESS &&
857c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	    wpa_s->pending_pd_before_join &&
8581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    (os_memcmp(dst, wpa_s->pending_join_dev_addr, ETH_ALEN) == 0 ||
859d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	     os_memcmp(dst, wpa_s->pending_join_iface_addr, ETH_ALEN) == 0) &&
860d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	    wpa_s->p2p_fallback_to_go_neg) {
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->pending_pd_before_join = 0;
862d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: No ACK for PD Req "
863d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			"during p2p_connect-auto");
864d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wpas_p2p_fallback_to_go_neg(wpa_s, 0);
865d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return;
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpas_send_action(void *ctx, unsigned int freq, const u8 *dst,
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    const u8 *src, const u8 *bssid, const u8 *buf,
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    size_t len, unsigned int wait_time)
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
8751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return offchannel_send_action(wpa_s, freq, dst, src, bssid, buf, len,
8761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      wait_time,
8771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      wpas_p2p_send_action_tx_status, 1);
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_send_action_done(void *ctx)
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
8841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	offchannel_send_action_done(wpa_s);
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpas_copy_go_neg_results(struct wpa_supplicant *wpa_s,
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    struct p2p_go_neg_results *params)
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->go_params == NULL) {
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->go_params = os_malloc(sizeof(*params));
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_s->go_params == NULL)
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(wpa_s->go_params, params, sizeof(*params));
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_start_wps_enrollee(struct wpa_supplicant *wpa_s,
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    struct p2p_go_neg_results *res)
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Start WPS Enrollee for peer " MACSTR,
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   MAC2STR(res->peer_interface_addr));
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "P2P: Start WPS Enrollee for SSID",
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  res->ssid, res->ssid_len);
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_ap_deinit(wpa_s);
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_copy_go_neg_results(wpa_s, res);
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res->wps_method == WPS_PBC)
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_wps_start_pbc(wpa_s, res->peer_interface_addr, 1);
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u16 dev_pw_id = DEV_PW_DEFAULT;
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_s->p2p_wps_method == WPS_PIN_KEYPAD)
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev_pw_id = DEV_PW_REGISTRAR_SPECIFIED;
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_wps_start_pin(wpa_s, res->peer_interface_addr,
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   wpa_s->p2p_pin, 1, dev_pw_id);
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
922391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic void wpas_p2p_add_psk_list(struct wpa_supplicant *wpa_s,
923391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt				  struct wpa_ssid *ssid)
924391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{
925391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	struct wpa_ssid *persistent;
926391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	struct psk_list_entry *psk;
927391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	struct hostapd_data *hapd;
928391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
929391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (!wpa_s->ap_iface)
930391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		return;
931391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
932391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	persistent = wpas_p2p_get_persistent(wpa_s->parent, NULL, ssid->ssid,
933391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt					     ssid->ssid_len);
934391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (persistent == NULL)
935391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		return;
936391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
937391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	hapd = wpa_s->ap_iface->bss[0];
938391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
939391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	dl_list_for_each(psk, &persistent->psk_list, struct psk_list_entry,
940391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			 list) {
941391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		struct hostapd_wpa_psk *hpsk;
942391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
943391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Add persistent group PSK entry for "
944391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			MACSTR " psk=%d",
945391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			MAC2STR(psk->addr), psk->p2p);
946391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		hpsk = os_zalloc(sizeof(*hpsk));
947391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		if (hpsk == NULL)
948391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			break;
949391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		os_memcpy(hpsk->psk, psk->psk, PMK_LEN);
950391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		if (psk->p2p)
951391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			os_memcpy(hpsk->p2p_dev_addr, psk->addr, ETH_ALEN);
952391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		else
953391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			os_memcpy(hpsk->addr, psk->addr, ETH_ALEN);
954391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		hpsk->next = hapd->conf->ssid.wpa_psk;
955391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		hapd->conf->ssid.wpa_psk = hpsk;
956391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	}
957391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt}
958391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
959391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_go_configured(void *ctx, void *data)
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_go_neg_results *params = data;
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid;
96575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	int network_id = -1;
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid = wpa_s->current_ssid;
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid && ssid->mode == WPAS_MODE_P2P_GO) {
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Group setup without provisioning");
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_s->global->p2p_group_formation == wpa_s)
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_s->global->p2p_group_formation = NULL;
972a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		if (os_strlen(params->passphrase) > 0) {
973b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			wpa_msg_global(wpa_s->parent, MSG_INFO,
974b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       P2P_EVENT_GROUP_STARTED
975b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       "%s GO ssid=\"%s\" freq=%d "
976b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       "passphrase=\"%s\" go_dev_addr=" MACSTR
977b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       "%s", wpa_s->ifname,
978b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
979b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       ssid->frequency, params->passphrase,
980b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       MAC2STR(wpa_s->global->p2p_dev_addr),
981b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       params->persistent_group ?
982b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       " [PERSISTENT]" : "");
983a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		} else {
984a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			char psk[65];
985a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			wpa_snprintf_hex(psk, sizeof(psk), params->psk,
986a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt					 sizeof(params->psk));
987b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			wpa_msg_global(wpa_s->parent, MSG_INFO,
988b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       P2P_EVENT_GROUP_STARTED
989b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       "%s GO ssid=\"%s\" freq=%d psk=%s "
990b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       "go_dev_addr=" MACSTR "%s",
991b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       wpa_s->ifname,
992b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
993b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       ssid->frequency, psk,
994b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       MAC2STR(wpa_s->global->p2p_dev_addr),
995b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       params->persistent_group ?
996b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       " [PERSISTENT]" : "");
997a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		}
9981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
999391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		if (params->persistent_group) {
100075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			network_id = wpas_p2p_store_persistent_group(
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_s->parent, ssid,
1002497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt				wpa_s->global->p2p_dev_addr);
1003391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			wpas_p2p_add_psk_list(wpa_s, ssid);
1004391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		}
100575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (network_id < 0)
100675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			network_id = ssid->id;
100775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		wpas_notify_p2p_group_started(wpa_s, ssid, network_id, 0);
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_p2p_cross_connect_setup(wpa_s);
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_p2p_set_group_idle_timeout(wpa_s);
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Setting up WPS for GO provisioning");
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_supplicant_ap_mac_addr_filter(wpa_s,
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      params->peer_interface_addr)) {
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Failed to setup MAC address "
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "filtering");
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (params->wps_method == WPS_PBC)
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_ap_wps_pbc(wpa_s, params->peer_interface_addr,
10221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					  params->peer_device_addr);
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (wpa_s->p2p_pin[0])
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_ap_wps_pin(wpa_s, params->peer_interface_addr,
1025d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt					  wpa_s->p2p_pin, NULL, 0, 0);
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(wpa_s->go_params);
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->go_params = NULL;
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_start_wps_go(struct wpa_supplicant *wpa_s,
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      struct p2p_go_neg_results *params,
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      int group_formation)
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid;
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1037aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Starting GO");
1038aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt	if (wpas_copy_go_neg_results(wpa_s, params) < 0) {
1039aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Could not copy GO Negotiation "
1040aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt			"results");
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1042aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt	}
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid = wpa_config_add_network(wpa_s->conf);
1045aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt	if (ssid == NULL) {
1046aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Could not add network for GO");
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1048aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt	}
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_s->show_group_started = 0;
10511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_set_network_defaults(ssid);
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->temporary = 1;
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->p2p_group = 1;
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->p2p_persistent_group = params->persistent_group;
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->mode = group_formation ? WPAS_MODE_P2P_GROUP_FORMATION :
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPAS_MODE_P2P_GO;
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->frequency = params->freq;
105961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	ssid->ht40 = params->ht40;
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->ssid = os_zalloc(params->ssid_len + 1);
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->ssid) {
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(ssid->ssid, params->ssid, params->ssid_len);
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid->ssid_len = params->ssid_len;
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->auth_alg = WPA_AUTH_ALG_OPEN;
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->key_mgmt = WPA_KEY_MGMT_PSK;
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->proto = WPA_PROTO_RSN;
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->pairwise_cipher = WPA_CIPHER_CCMP;
1069a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (os_strlen(params->passphrase) > 0) {
1070a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		ssid->passphrase = os_strdup(params->passphrase);
1071a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		if (ssid->passphrase == NULL) {
1072b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			wpa_msg_global(wpa_s, MSG_ERROR,
1073b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       "P2P: Failed to copy passphrase for GO");
1074a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			wpa_config_remove_network(wpa_s->conf, ssid->id);
1075a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			return;
1076a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		}
1077a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	} else
1078a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		ssid->passphrase = NULL;
1079d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	ssid->psk_set = params->psk_set;
1080d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (ssid->psk_set)
1081d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		os_memcpy(ssid->psk, params->psk, sizeof(ssid->psk));
1082a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	else if (ssid->passphrase)
1083d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wpa_config_update_psk(ssid);
108461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	ssid->ap_max_inactivity = wpa_s->parent->conf->p2p_go_max_inactivity;
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->ap_configured_cb = p2p_go_configured;
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->ap_configured_cb_ctx = wpa_s;
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->ap_configured_cb_data = wpa_s->go_params;
108975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	wpa_s->connect_without_scan = ssid;
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->reassociate = 1;
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->disconnected = 0;
1092aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Request scan (that will be skipped) to "
1093aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt		"start GO)");
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_req_scan(wpa_s, 0, 0);
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_p2p_clone_config(struct wpa_supplicant *dst,
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  const struct wpa_supplicant *src)
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_config *d;
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct wpa_config *s;
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	d = dst->conf;
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	s = src->conf;
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define C(n) if (s->n) d->n = os_strdup(s->n)
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	C(device_name);
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	C(manufacturer);
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	C(model_name);
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	C(model_number);
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	C(serial_number);
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	C(config_methods);
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef C
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(d->device_type, s->device_type, WPS_DEV_TYPE_LEN);
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(d->sec_device_type, s->sec_device_type,
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  sizeof(d->sec_device_type));
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	d->num_sec_device_types = s->num_sec_device_types;
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	d->p2p_group_idle = s->p2p_group_idle;
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	d->p2p_intra_bss = s->p2p_intra_bss;
11231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	d->persistent_reconnect = s->persistent_reconnect;
112404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	d->max_num_sta = s->max_num_sta;
112504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	d->pbc_in_m1 = s->pbc_in_m1;
1126444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt	d->ignore_old_scan_res = s->ignore_old_scan_res;
112751b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt	d->beacon_int = s->beacon_int;
1128b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	d->disassoc_low_ack = s->disassoc_low_ack;
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
113234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void wpas_p2p_get_group_ifname(struct wpa_supplicant *wpa_s,
113334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt				      char *ifname, size_t len)
113434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
113534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	char *ifname_ptr = wpa_s->ifname;
113634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
113734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (os_strncmp(wpa_s->ifname, P2P_MGMT_DEVICE_PREFIX,
113834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		       os_strlen(P2P_MGMT_DEVICE_PREFIX)) == 0) {
113934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		ifname_ptr = os_strrchr(wpa_s->ifname, '-') + 1;
114034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
114134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
114234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	os_snprintf(ifname, len, "p2p-%s-%d", ifname_ptr, wpa_s->p2p_group_idx);
114334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (os_strlen(ifname) >= IFNAMSIZ &&
114434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	    os_strlen(wpa_s->ifname) < IFNAMSIZ) {
114534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		/* Try to avoid going over the IFNAMSIZ length limit */
114634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		os_snprintf(ifname, sizeof(ifname), "p2p-%d",
114734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			    wpa_s->p2p_group_idx);
114834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
114934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
115034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
115134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpas_p2p_add_group_interface(struct wpa_supplicant *wpa_s,
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					enum wpa_driver_if_type type)
11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char ifname[120], force_ifname[120];
11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->pending_interface_name[0]) {
11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Pending virtual interface exists "
11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "- skip creation of a new one");
11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (is_zero_ether_addr(wpa_s->pending_interface_addr)) {
11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Pending virtual address "
11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "unknown?! ifname='%s'",
11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   wpa_s->pending_interface_name);
11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
116934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpas_p2p_get_group_ifname(wpa_s, ifname, sizeof(ifname));
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	force_ifname[0] = '\0';
11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Create a new interface %s for the group",
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   ifname);
11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->p2p_group_idx++;
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->pending_interface_type = type;
11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_drv_if_add(wpa_s, type, ifname, NULL, NULL, force_ifname,
11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   wpa_s->pending_interface_addr, NULL) < 0) {
11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "P2P: Failed to create new group "
11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "interface");
11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (force_ifname[0]) {
11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Driver forced interface name %s",
11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   force_ifname);
11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_strlcpy(wpa_s->pending_interface_name, force_ifname,
11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sizeof(wpa_s->pending_interface_name));
11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_strlcpy(wpa_s->pending_interface_name, ifname,
11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sizeof(wpa_s->pending_interface_name));
11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Created pending virtual interface %s addr "
11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   MACSTR, wpa_s->pending_interface_name,
11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   MAC2STR(wpa_s->pending_interface_addr));
11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_p2p_remove_pending_group_interface(
12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s)
12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!wpa_s->pending_interface_name[0] ||
12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    is_zero_ether_addr(wpa_s->pending_interface_addr))
12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* No pending virtual interface */
12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Removing pending group interface %s",
12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   wpa_s->pending_interface_name);
12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_drv_if_remove(wpa_s, wpa_s->pending_interface_type,
12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  wpa_s->pending_interface_name);
12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(wpa_s->pending_interface_addr, 0, ETH_ALEN);
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->pending_interface_name[0] = '\0';
12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_supplicant *
12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpas_p2p_init_group_interface(struct wpa_supplicant *wpa_s, int go)
12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_interface iface;
12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *group_wpa_s;
12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!wpa_s->pending_interface_name[0]) {
12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "P2P: No pending group interface");
12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!wpas_p2p_create_iface(wpa_s))
12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Something has forced us to remove the pending interface; try
12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * to create a new one and hope for the best that we will get
12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * the same local address.
12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpas_p2p_add_group_interface(wpa_s, go ? WPA_IF_P2P_GO :
12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 WPA_IF_P2P_CLIENT) < 0)
12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&iface, 0, sizeof(iface));
12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	iface.ifname = wpa_s->pending_interface_name;
12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	iface.driver = wpa_s->driver->name;
123934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (wpa_s->conf->ctrl_interface == NULL &&
124034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	    wpa_s->parent != wpa_s &&
124134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	    wpa_s->p2p_mgmt &&
124234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	    (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE))
124334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		iface.ctrl_interface = wpa_s->parent->conf->ctrl_interface;
124434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	else
124534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		iface.ctrl_interface = wpa_s->conf->ctrl_interface;
12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	iface.driver_param = wpa_s->conf->driver_param;
12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group_wpa_s = wpa_supplicant_add_iface(wpa_s->global, &iface);
12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group_wpa_s == NULL) {
12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "P2P: Failed to create new "
12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "wpa_supplicant interface");
12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->pending_interface_name[0] = '\0';
12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group_wpa_s->parent = wpa_s;
12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group_wpa_s->p2p_group_interface = go ? P2P_GROUP_INTERFACE_GO :
12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		P2P_GROUP_INTERFACE_CLIENT;
12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->global->p2p_group_formation = group_wpa_s;
12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_p2p_clone_config(group_wpa_s, wpa_s);
12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return group_wpa_s;
12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_p2p_group_formation_timeout(void *eloop_ctx,
12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     void *timeout_ctx)
12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = eloop_ctx;
12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Group Formation timed out");
127034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpas_p2p_group_formation_failed(wpa_s);
127134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
127234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
127334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
127434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtvoid wpas_p2p_group_formation_failed(struct wpa_supplicant *wpa_s)
127534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
127634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
127734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			     wpa_s->parent, NULL);
12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p)
12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_group_formation_failed(wpa_s->global->p2p);
12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_drv_p2p_group_formation_failed(wpa_s);
12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_group_formation_completed(wpa_s, 0);
12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1286391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtvoid wpas_p2p_ap_setup_failed(struct wpa_supplicant *wpa_s)
1287391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{
1288391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (wpa_s->global->p2p_group_formation != wpa_s)
1289391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		return;
1290391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	/* Speed up group formation timeout since this cannot succeed */
1291391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
1292391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			     wpa_s->parent, NULL);
1293391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	eloop_register_timeout(0, 0, wpas_p2p_group_formation_timeout,
1294391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			       wpa_s->parent, NULL);
1295391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt}
1296391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
1297391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res)
12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->off_channel_freq || wpa_s->roc_waiting_drv_freq) {
13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_drv_cancel_remain_on_channel(wpa_s);
13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->off_channel_freq = 0;
13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->roc_waiting_drv_freq = 0;
13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res->status) {
1309b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		wpa_msg_global(wpa_s, MSG_INFO,
1310b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       P2P_EVENT_GO_NEG_FAILURE "status=%d",
1311b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       res->status);
13121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpas_notify_p2p_go_neg_completed(wpa_s, res);
13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_p2p_remove_pending_group_interface(wpa_s);
13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
131761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (wpa_s->p2p_go_ht40)
131861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		res->ht40 = 1;
131961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
1320b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_GO_NEG_SUCCESS "role=%s "
1321b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		       "freq=%d ht40=%d peer_dev=" MACSTR " peer_iface=" MACSTR
1322b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		       " wps_method=%s",
1323b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		       res->role_go ? "GO" : "client", res->freq, res->ht40,
1324b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		       MAC2STR(res->peer_device_addr),
1325b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		       MAC2STR(res->peer_interface_addr),
1326b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		       p2p_wps_method_text(res->wps_method));
13271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpas_notify_p2p_go_neg_completed(wpa_s, res);
13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
132904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (res->role_go && wpa_s->p2p_persistent_id >= 0) {
133004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		struct wpa_ssid *ssid;
133104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		ssid = wpa_config_get_network(wpa_s->conf,
133204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					      wpa_s->p2p_persistent_id);
133304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (ssid && ssid->disabled == 2 &&
133404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		    ssid->mode == WPAS_MODE_P2P_GO && ssid->passphrase) {
133504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			size_t len = os_strlen(ssid->passphrase);
133604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Override passphrase based "
133704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				   "on requested persistent group");
133804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			os_memcpy(res->passphrase, ssid->passphrase, len);
133904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			res->passphrase[len] = '\0';
134004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
134104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
134204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->create_p2p_iface) {
13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct wpa_supplicant *group_wpa_s =
13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpas_p2p_init_group_interface(wpa_s, res->role_go);
13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (group_wpa_s == NULL) {
13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpas_p2p_remove_pending_group_interface(wpa_s);
13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (group_wpa_s != wpa_s) {
13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(group_wpa_s->p2p_pin, wpa_s->p2p_pin,
13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  sizeof(group_wpa_s->p2p_pin));
13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group_wpa_s->p2p_wps_method = wpa_s->p2p_wps_method;
13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(wpa_s->pending_interface_addr, 0, ETH_ALEN);
13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->pending_interface_name[0] = '\0';
13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group_wpa_s->p2p_in_provisioning = 1;
13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res->role_go)
13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpas_start_wps_go(group_wpa_s, res, 1);
13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpas_start_wps_enrollee(group_wpa_s, res);
13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->p2p_in_provisioning = 1;
13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->global->p2p_group_formation = wpa_s;
13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res->role_go)
13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpas_start_wps_go(wpa_s, res, 1);
13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpas_start_wps_enrollee(ctx, res);
13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->p2p_long_listen = 0;
13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL);
13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s, NULL);
13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(15 + res->peer_config_timeout / 100,
13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       (res->peer_config_timeout % 100) * 10000,
13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       wpas_p2p_group_formation_timeout, wpa_s, NULL);
13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_go_neg_req_rx(void *ctx, const u8 *src, u16 dev_passwd_id)
13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
1386b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_GO_NEG_REQUEST MACSTR
1387b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		       " dev_passwd_id=%u", MAC2STR(src), dev_passwd_id);
13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_notify_p2p_go_neg_req(wpa_s, src, dev_passwd_id);
13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_dev_found(void *ctx, const u8 *addr,
13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    const struct p2p_peer_info *info,
13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    int new_device)
13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifndef CONFIG_NO_STDOUT_DEBUG
13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char devtype[WPS_DEV_TYPE_BUFSIZE];
14008367dc909f536f600c7474582fe0a96bef7c78fcIrfan Sheriff#define WFD_DEV_INFO_SIZE 9
14018367dc909f536f600c7474582fe0a96bef7c78fcIrfan Sheriff	char wfd_dev_info_hex[2 * WFD_DEV_INFO_SIZE + 1];
14028d96518810ad721dc2f07d3b08a186ce23db06ffIrfan Sheriff	os_memset(wfd_dev_info_hex, 0, sizeof(wfd_dev_info_hex));
14038367dc909f536f600c7474582fe0a96bef7c78fcIrfan Sheriff#ifdef CONFIG_WIFI_DISPLAY
14048367dc909f536f600c7474582fe0a96bef7c78fcIrfan Sheriff	if (info->wfd_subelems) {
14058367dc909f536f600c7474582fe0a96bef7c78fcIrfan Sheriff		wpa_snprintf_hex(wfd_dev_info_hex, sizeof(wfd_dev_info_hex),
14068367dc909f536f600c7474582fe0a96bef7c78fcIrfan Sheriff					wpabuf_head(info->wfd_subelems),
14078367dc909f536f600c7474582fe0a96bef7c78fcIrfan Sheriff					WFD_DEV_INFO_SIZE);
14088367dc909f536f600c7474582fe0a96bef7c78fcIrfan Sheriff	}
14098367dc909f536f600c7474582fe0a96bef7c78fcIrfan Sheriff#endif /* CONFIG_WIFI_DISPLAY */
1410b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_DEVICE_FOUND MACSTR
1411b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		       " p2p_dev_addr=" MACSTR
1412b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		       " pri_dev_type=%s name='%s' config_methods=0x%x "
1413b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		       "dev_capab=0x%x group_capab=0x%x%s%s",
1414b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		       MAC2STR(addr), MAC2STR(info->p2p_device_addr),
1415b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		       wps_dev_type_bin2str(info->pri_dev_type, devtype,
1416b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt					    sizeof(devtype)),
1417b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		       info->device_name, info->config_methods,
1418b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		       info->dev_capab, info->group_capab,
1419b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		       wfd_dev_info_hex[0] ? " wfd_dev_info=0x" : "", wfd_dev_info_hex);
14201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_NO_STDOUT_DEBUG */
14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_notify_p2p_device_found(ctx, info->p2p_device_addr, new_device);
14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_dev_lost(void *ctx, const u8 *dev_addr)
14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
14291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1430b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_DEVICE_LOST
1431b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		       "p2p_dev_addr=" MACSTR, MAC2STR(dev_addr));
14321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_notify_p2p_device_lost(wpa_s, dev_addr);
14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1437b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidtstatic void wpas_find_stopped(void *ctx)
1438b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt{
1439b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
1440b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_FIND_STOPPED);
1441b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt}
1442b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
1443b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpas_start_listen(void *ctx, unsigned int freq,
14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     unsigned int duration,
14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     const struct wpabuf *probe_resp_ie)
14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_drv_set_ap_wps_ie(wpa_s, NULL, probe_resp_ie, NULL);
14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_drv_probe_req_report(wpa_s, 1) < 0) {
14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Failed to request the driver to "
14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "report received Probe Request frames");
14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->pending_listen_freq = freq;
14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->pending_listen_duration = duration;
14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_drv_remain_on_channel(wpa_s, freq, duration) < 0) {
14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Failed to request the driver "
14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "to remain on channel (%u MHz) for Listen "
14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "state", freq);
14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->pending_listen_freq = 0;
14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->off_channel_freq = 0;
14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->roc_waiting_drv_freq = freq;
14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_stop_listen(void *ctx)
14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->off_channel_freq || wpa_s->roc_waiting_drv_freq) {
14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_drv_cancel_remain_on_channel(wpa_s);
14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->off_channel_freq = 0;
14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->roc_waiting_drv_freq = 0;
14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_drv_set_ap_wps_ie(wpa_s, NULL, NULL, NULL);
14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_drv_probe_req_report(wpa_s, 0);
14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpas_send_probe_resp(void *ctx, const struct wpabuf *buf)
14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
14911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1);
14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1495d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt/*
1496d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * DNS Header section is used only to calculate compression pointers, so the
1497d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * contents of this data does not matter, but the length needs to be reserved
1498d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * in the virtual packet.
1499d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt */
1500d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#define DNS_HEADER_LEN 12
1501d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1502d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt/*
1503d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * 27-octet in-memory packet from P2P specification containing two implied
1504d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * queries for _tcp.lcoal. PTR IN and _udp.local. PTR IN
1505d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt */
1506d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#define P2P_SD_IN_MEMORY_LEN 27
1507d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1508d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic int p2p_sd_dns_uncompress_label(char **upos, char *uend, u8 *start,
1509d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				       u8 **spos, const u8 *end)
1510d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt{
1511d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	while (*spos < end) {
1512d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		u8 val = ((*spos)[0] & 0xc0) >> 6;
1513d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		int len;
1514d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1515d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (val == 1 || val == 2) {
1516d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			/* These are reserved values in RFC 1035 */
1517d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Invalid domain name "
1518d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				   "sequence starting with 0x%x", val);
1519d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			return -1;
1520d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		}
1521d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1522d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (val == 3) {
1523d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			u16 offset;
1524d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			u8 *spos_tmp;
1525d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1526d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			/* Offset */
1527d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			if (*spos + 2 > end) {
1528d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				wpa_printf(MSG_DEBUG, "P2P: No room for full "
1529d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt					   "DNS offset field");
1530d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				return -1;
1531d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			}
1532d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1533d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			offset = (((*spos)[0] & 0x3f) << 8) | (*spos)[1];
1534d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			if (offset >= *spos - start) {
1535d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				wpa_printf(MSG_DEBUG, "P2P: Invalid DNS "
1536d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt					   "pointer offset %u", offset);
1537d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				return -1;
1538d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			}
1539d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1540d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			(*spos) += 2;
1541d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			spos_tmp = start + offset;
1542d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			return p2p_sd_dns_uncompress_label(upos, uend, start,
1543d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt							   &spos_tmp,
1544d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt							   *spos - 2);
1545d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		}
1546d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1547d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		/* Label */
1548d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		len = (*spos)[0] & 0x3f;
1549d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (len == 0)
1550d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			return 0;
1551d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1552d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		(*spos)++;
1553d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (*spos + len > end) {
1554d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Invalid domain name "
1555d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				   "sequence - no room for label with length "
1556d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				   "%u", len);
1557d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			return -1;
1558d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		}
1559d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1560d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (*upos + len + 2 > uend)
1561d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			return -2;
1562d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1563d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		os_memcpy(*upos, *spos, len);
1564d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		*spos += len;
1565d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		*upos += len;
1566d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		(*upos)[0] = '.';
1567d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		(*upos)++;
1568d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		(*upos)[0] = '\0';
1569d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
1570d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1571d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	return 0;
1572d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt}
1573d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1574d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1575d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt/* Uncompress domain names per RFC 1035 using the P2P SD in-memory packet.
1576d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * Returns -1 on parsing error (invalid input sequence), -2 if output buffer is
1577d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * not large enough */
1578d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic int p2p_sd_dns_uncompress(char *buf, size_t buf_len, const u8 *msg,
1579d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				 size_t msg_len, size_t offset)
1580d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt{
1581d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	/* 27-octet in-memory packet from P2P specification */
1582d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	const char *prefix = "\x04_tcp\x05local\x00\x00\x0C\x00\x01"
1583d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		"\x04_udp\xC0\x11\x00\x0C\x00\x01";
1584d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	u8 *tmp, *end, *spos;
1585d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	char *upos, *uend;
1586d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	int ret = 0;
1587d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1588d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (buf_len < 2)
1589d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return -1;
1590d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (offset > msg_len)
1591d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return -1;
1592d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1593d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	tmp = os_malloc(DNS_HEADER_LEN + P2P_SD_IN_MEMORY_LEN + msg_len);
1594d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (tmp == NULL)
1595d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return -1;
1596d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	spos = tmp + DNS_HEADER_LEN + P2P_SD_IN_MEMORY_LEN;
1597d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	end = spos + msg_len;
1598d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	spos += offset;
1599d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1600d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	os_memset(tmp, 0, DNS_HEADER_LEN);
1601d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	os_memcpy(tmp + DNS_HEADER_LEN, prefix, P2P_SD_IN_MEMORY_LEN);
1602d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	os_memcpy(tmp + DNS_HEADER_LEN + P2P_SD_IN_MEMORY_LEN, msg, msg_len);
1603d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1604d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	upos = buf;
1605d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	uend = buf + buf_len;
1606d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1607d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	ret = p2p_sd_dns_uncompress_label(&upos, uend, tmp, &spos, end);
1608d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (ret) {
1609d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		os_free(tmp);
1610d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return ret;
1611d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
1612d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1613d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (upos == buf) {
1614d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		upos[0] = '.';
1615d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		upos[1] = '\0';
1616d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	} else if (upos[-1] == '.')
1617d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		upos[-1] = '\0';
1618d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1619d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	os_free(tmp);
1620d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	return 0;
1621d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt}
1622d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1623d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct p2p_srv_bonjour *
16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpas_p2p_service_get_bonjour(struct wpa_supplicant *wpa_s,
16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     const struct wpabuf *query)
16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_srv_bonjour *bsrv;
16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = wpabuf_len(query);
16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(bsrv, &wpa_s->global->p2p_srv_bonjour,
16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 struct p2p_srv_bonjour, list) {
16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len == wpabuf_len(bsrv->query) &&
16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_memcmp(wpabuf_head(query), wpabuf_head(bsrv->query),
16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      len) == 0)
16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return bsrv;
16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct p2p_srv_upnp *
16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpas_p2p_service_get_upnp(struct wpa_supplicant *wpa_s, u8 version,
16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  const char *service)
16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_srv_upnp *usrv;
16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(usrv, &wpa_s->global->p2p_srv_upnp,
16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 struct p2p_srv_upnp, list) {
16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (version == usrv->version &&
16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_strcmp(service, usrv->service) == 0)
16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return usrv;
16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_sd_add_proto_not_avail(struct wpabuf *resp, u8 srv_proto,
16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					u8 srv_trans_id)
16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len_pos;
16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpabuf_tailroom(resp) < 5)
16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Length (to be filled) */
16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len_pos = wpabuf_put(resp, 2);
16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(resp, srv_proto);
16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(resp, srv_trans_id);
16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Status Code */
16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(resp, P2P_SD_PROTO_NOT_AVAILABLE);
16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Response Data: empty */
16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos - 2);
16758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_sd_all_bonjour(struct wpa_supplicant *wpa_s,
16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				struct wpabuf *resp, u8 srv_trans_id)
16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_srv_bonjour *bsrv;
16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len_pos;
16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: SD Request for all Bonjour services");
16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dl_list_empty(&wpa_s->global->p2p_srv_bonjour)) {
16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Bonjour protocol not available");
16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(bsrv, &wpa_s->global->p2p_srv_bonjour,
16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 struct p2p_srv_bonjour, list) {
16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpabuf_tailroom(resp) <
16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    5 + wpabuf_len(bsrv->query) + wpabuf_len(bsrv->resp))
16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Length (to be filled) */
16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len_pos = wpabuf_put(resp, 2);
16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(resp, P2P_SERV_BONJOUR);
16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(resp, srv_trans_id);
17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Status Code */
17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(resp, P2P_SD_SUCCESS);
17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "P2P: Matching Bonjour service",
17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  wpabuf_head(bsrv->resp),
17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  wpabuf_len(bsrv->resp));
17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Response Data */
17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_buf(resp, bsrv->query); /* Key */
17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_buf(resp, bsrv->resp); /* Value */
17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos -
17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     2);
17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1714d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic int match_bonjour_query(struct p2p_srv_bonjour *bsrv, const u8 *query,
1715d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			       size_t query_len)
1716d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt{
1717d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	char str_rx[256], str_srv[256];
1718d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1719d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (query_len < 3 || wpabuf_len(bsrv->query) < 3)
1720d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return 0; /* Too short to include DNS Type and Version */
1721d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (os_memcmp(query + query_len - 3,
1722d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		      wpabuf_head_u8(bsrv->query) + wpabuf_len(bsrv->query) - 3,
1723d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		      3) != 0)
1724d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return 0; /* Mismatch in DNS Type or Version */
1725d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (query_len == wpabuf_len(bsrv->query) &&
1726d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	    os_memcmp(query, wpabuf_head(bsrv->query), query_len - 3) == 0)
1727d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return 1; /* Binary match */
1728d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1729d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (p2p_sd_dns_uncompress(str_rx, sizeof(str_rx), query, query_len - 3,
1730d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				  0))
1731d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return 0; /* Failed to uncompress query */
1732d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (p2p_sd_dns_uncompress(str_srv, sizeof(str_srv),
1733d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				  wpabuf_head(bsrv->query),
1734d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				  wpabuf_len(bsrv->query) - 3, 0))
1735d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return 0; /* Failed to uncompress service */
1736d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1737d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	return os_strcmp(str_rx, str_srv) == 0;
1738d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt}
1739d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1740d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_sd_req_bonjour(struct wpa_supplicant *wpa_s,
17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				struct wpabuf *resp, u8 srv_trans_id,
17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				const u8 *query, size_t query_len)
17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_srv_bonjour *bsrv;
17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len_pos;
1747d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	int matches = 0;
17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "P2P: SD Request for Bonjour",
17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  query, query_len);
17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dl_list_empty(&wpa_s->global->p2p_srv_bonjour)) {
17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Bonjour protocol not available");
17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_sd_add_proto_not_avail(resp, P2P_SERV_BONJOUR,
17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    srv_trans_id);
17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (query_len == 0) {
17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_sd_all_bonjour(wpa_s, resp, srv_trans_id);
17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1763d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	dl_list_for_each(bsrv, &wpa_s->global->p2p_srv_bonjour,
1764d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			 struct p2p_srv_bonjour, list) {
1765d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (!match_bonjour_query(bsrv, query, query_len))
1766d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			continue;
1767d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1768d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (wpabuf_tailroom(resp) <
1769d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		    5 + query_len + wpabuf_len(bsrv->resp))
1770d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			return;
1771d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1772d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		matches++;
17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1774d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		/* Length (to be filled) */
1775d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		len_pos = wpabuf_put(resp, 2);
1776d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wpabuf_put_u8(resp, P2P_SERV_BONJOUR);
1777d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wpabuf_put_u8(resp, srv_trans_id);
1778d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1779d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		/* Status Code */
1780d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wpabuf_put_u8(resp, P2P_SD_SUCCESS);
1781d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "P2P: Matching Bonjour service",
1782d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				  wpabuf_head(bsrv->resp),
1783d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				  wpabuf_len(bsrv->resp));
1784d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1785d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		/* Response Data */
1786d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wpabuf_put_data(resp, query, query_len); /* Key */
1787d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wpabuf_put_buf(resp, bsrv->resp); /* Value */
1788d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1789d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos - 2);
1790d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
1791d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1792d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (matches == 0) {
17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Requested Bonjour service not "
17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "available");
1795d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (wpabuf_tailroom(resp) < 5)
1796d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			return;
1797d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1798d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		/* Length (to be filled) */
1799d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		len_pos = wpabuf_put(resp, 2);
1800d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wpabuf_put_u8(resp, P2P_SERV_BONJOUR);
1801d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wpabuf_put_u8(resp, srv_trans_id);
18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Status Code */
18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(resp, P2P_SD_REQUESTED_INFO_NOT_AVAILABLE);
18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Response Data: empty */
18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos -
18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     2);
18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_sd_all_upnp(struct wpa_supplicant *wpa_s,
18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     struct wpabuf *resp, u8 srv_trans_id)
18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_srv_upnp *usrv;
18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len_pos;
18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: SD Request for all UPnP services");
18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dl_list_empty(&wpa_s->global->p2p_srv_upnp)) {
18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: UPnP protocol not available");
18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(usrv, &wpa_s->global->p2p_srv_upnp,
18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 struct p2p_srv_upnp, list) {
18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpabuf_tailroom(resp) < 5 + 1 + os_strlen(usrv->service))
18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Length (to be filled) */
18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len_pos = wpabuf_put(resp, 2);
18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(resp, P2P_SERV_UPNP);
18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(resp, srv_trans_id);
18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Status Code */
18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(resp, P2P_SD_SUCCESS);
18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Response Data */
18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(resp, usrv->version);
18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Matching UPnP Service: %s",
18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   usrv->service);
18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_str(resp, usrv->service);
18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos -
18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     2);
18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_sd_req_upnp(struct wpa_supplicant *wpa_s,
18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     struct wpabuf *resp, u8 srv_trans_id,
18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     const u8 *query, size_t query_len)
18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_srv_upnp *usrv;
18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len_pos;
18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 version;
18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *str;
18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int count = 0;
18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "P2P: SD Request for UPnP",
18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  query, query_len);
18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dl_list_empty(&wpa_s->global->p2p_srv_upnp)) {
18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: UPnP protocol not available");
18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_sd_add_proto_not_avail(resp, P2P_SERV_UPNP,
18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    srv_trans_id);
18658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (query_len == 0) {
18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_sd_all_upnp(wpa_s, resp, srv_trans_id);
18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpabuf_tailroom(resp) < 5)
18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Length (to be filled) */
18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len_pos = wpabuf_put(resp, 2);
18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(resp, P2P_SERV_UPNP);
18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(resp, srv_trans_id);
18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	version = query[0];
18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	str = os_malloc(query_len);
18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (str == NULL)
18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(str, query + 1, query_len - 1);
18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	str[query_len - 1] = '\0';
18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(usrv, &wpa_s->global->p2p_srv_upnp,
18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 struct p2p_srv_upnp, list) {
18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (version != usrv->version)
18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strcmp(str, "ssdp:all") != 0 &&
18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_strstr(usrv->service, str) == NULL)
18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpabuf_tailroom(resp) < 2)
18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (count == 0) {
19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* Status Code */
19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpabuf_put_u8(resp, P2P_SD_SUCCESS);
19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* Response Data */
19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpabuf_put_u8(resp, version);
19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else
19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpabuf_put_u8(resp, ',');
19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		count++;
19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Matching UPnP Service: %s",
19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   usrv->service);
19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpabuf_tailroom(resp) < os_strlen(usrv->service))
19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_str(resp, usrv->service);
19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(str);
19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (count == 0) {
19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Requested UPnP service not "
19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "available");
19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Status Code */
19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(resp, P2P_SD_REQUESTED_INFO_NOT_AVAILABLE);
19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Response Data: empty */
19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos - 2);
19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
192961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
193061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void wpas_sd_req_wfd(struct wpa_supplicant *wpa_s,
193161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			    struct wpabuf *resp, u8 srv_trans_id,
193261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			    const u8 *query, size_t query_len)
193361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
193461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	const u8 *pos;
193561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 role;
193661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 *len_pos;
193761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
193861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "P2P: SD Request for WFD", query, query_len);
193961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
194061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (!wpa_s->global->wifi_display) {
194161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: WFD protocol not available");
194261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpas_sd_add_proto_not_avail(resp, P2P_SERV_WIFI_DISPLAY,
194361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					    srv_trans_id);
194461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return;
194561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
194661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
194761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (query_len < 1) {
194861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Missing WFD Requested Device "
194961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			   "Role");
195061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return;
195161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
195261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
195361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (wpabuf_tailroom(resp) < 5)
195461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return;
195561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
195661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	pos = query;
195761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	role = *pos++;
195861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: WSD for device role 0x%x", role);
195961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
196061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	/* TODO: role specific handling */
196161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
196261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	/* Length (to be filled) */
196361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	len_pos = wpabuf_put(resp, 2);
196461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_put_u8(resp, P2P_SERV_WIFI_DISPLAY);
196561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_put_u8(resp, srv_trans_id);
196661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_put_u8(resp, P2P_SD_SUCCESS); /* Status Code */
196761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
196861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	while (pos < query + query_len) {
196961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (*pos < MAX_WFD_SUBELEMS &&
197061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		    wpa_s->global->wfd_subelem[*pos] &&
197161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		    wpabuf_tailroom(resp) >=
197261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		    wpabuf_len(wpa_s->global->wfd_subelem[*pos])) {
197361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Add WSD response "
197461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   "subelement %u", *pos);
197561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpabuf_put_buf(resp, wpa_s->global->wfd_subelem[*pos]);
197661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
197761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos++;
197861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
197961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
198061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos - 2);
198161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
198261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
198361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
198461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_sd_request(void *ctx, int freq, const u8 *sa, u8 dialog_token,
19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     u16 update_indic, const u8 *tlvs, size_t tlvs_len)
19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos = tlvs;
19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *end = tlvs + tlvs_len;
19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *tlv_end;
19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 slen;
19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 srv_proto, srv_trans_id;
19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t buf_len;
19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *buf;
19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "P2P: Service Discovery Request TLVs",
19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    tlvs, tlvs_len);
20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf_len = 2 * tlvs_len + 1;
20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_malloc(buf_len);
20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf) {
20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_snprintf_hex(buf, buf_len, tlvs, tlvs_len);
20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg_ctrl(wpa_s, MSG_INFO, P2P_EVENT_SERV_DISC_REQ "%d "
20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     MACSTR " %u %u %s",
20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     freq, MAC2STR(sa), dialog_token, update_indic,
20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     buf);
20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_s->p2p_sd_over_ctrl_iface) {
20121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpas_notify_p2p_sd_request(wpa_s, freq, sa, dialog_token,
20131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   update_indic, tlvs, tlvs_len);
20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* to be processed by an external program */
20151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = wpabuf_alloc(10000);
20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
20198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos + 1 < end) {
20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Service Request TLV");
20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		slen = WPA_GET_LE16(pos);
20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 2;
20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos + slen > end || slen < 2) {
20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Unexpected Query Data "
20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "length");
20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpabuf_free(resp);
20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
20318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlv_end = pos + slen;
20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		srv_proto = *pos++;
20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Service Protocol Type %u",
20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   srv_proto);
20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		srv_trans_id = *pos++;
20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Service Transaction ID %u",
20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   srv_trans_id);
20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "P2P: Query Data",
20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    pos, tlv_end - pos);
20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_s->force_long_sd) {
20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: SD test - force long "
20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "response");
20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpas_sd_all_bonjour(wpa_s, resp, srv_trans_id);
20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpas_sd_all_upnp(wpa_s, resp, srv_trans_id);
20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto done;
20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (srv_proto) {
20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case P2P_SERV_ALL_SERVICES:
20548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Service Discovery Request "
20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "for all services");
20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dl_list_empty(&wpa_s->global->p2p_srv_upnp) &&
20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    dl_list_empty(&wpa_s->global->p2p_srv_bonjour)) {
20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "P2P: No service "
20598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "discovery protocols available");
20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpas_sd_add_proto_not_avail(
20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					resp, P2P_SERV_ALL_SERVICES,
20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					srv_trans_id);
20638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpas_sd_all_bonjour(wpa_s, resp, srv_trans_id);
20668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpas_sd_all_upnp(wpa_s, resp, srv_trans_id);
20678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case P2P_SERV_BONJOUR:
20698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpas_sd_req_bonjour(wpa_s, resp, srv_trans_id,
20708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    pos, tlv_end - pos);
20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
20728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case P2P_SERV_UPNP:
20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpas_sd_req_upnp(wpa_s, resp, srv_trans_id,
20748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 pos, tlv_end - pos);
20758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
207661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
207761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		case P2P_SERV_WIFI_DISPLAY:
207861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpas_sd_req_wfd(wpa_s, resp, srv_trans_id,
207961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					pos, tlv_end - pos);
208061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			break;
208161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
20828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
20838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Unavailable service "
20848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "protocol %u", srv_proto);
20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpas_sd_add_proto_not_avail(resp, srv_proto,
20868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    srv_trans_id);
20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
20888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
20898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = tlv_end;
20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtdone:
20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_notify_p2p_sd_request(wpa_s, freq, sa, dialog_token,
20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   update_indic, tlvs, tlvs_len);
20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_p2p_sd_response(wpa_s, freq, sa, dialog_token, resp);
20988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(resp);
21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_sd_response(void *ctx, const u8 *sa, u16 update_indic,
21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      const u8 *tlvs, size_t tlvs_len)
21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos = tlvs;
21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *end = tlvs + tlvs_len;
21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *tlv_end;
21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 slen;
21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t buf_len;
21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *buf;
21138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "P2P: Service Discovery Response TLVs",
21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    tlvs, tlvs_len);
21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlvs_len > 1500) {
21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO: better way for handling this */
21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg_ctrl(wpa_s, MSG_INFO,
21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     P2P_EVENT_SERV_DISC_RESP MACSTR
21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     " %u <long response: %u bytes>",
21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     MAC2STR(sa), update_indic,
21228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     (unsigned int) tlvs_len);
21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf_len = 2 * tlvs_len + 1;
21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf = os_malloc(buf_len);
21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (buf) {
21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_snprintf_hex(buf, buf_len, tlvs, tlvs_len);
21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg_ctrl(wpa_s, MSG_INFO,
21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     P2P_EVENT_SERV_DISC_RESP MACSTR " %u %s",
21308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     MAC2STR(sa), update_indic, buf);
21318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(buf);
21328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
21338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos < end) {
21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 srv_proto, srv_trans_id, status;
21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Service Response TLV");
21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		slen = WPA_GET_LE16(pos);
21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 2;
21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos + slen > end || slen < 3) {
21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Unexpected Response Data "
21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "length");
21448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlv_end = pos + slen;
21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		srv_proto = *pos++;
21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Service Protocol Type %u",
21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   srv_proto);
21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		srv_trans_id = *pos++;
21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Service Transaction ID %u",
21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   srv_trans_id);
21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		status = *pos++;
21558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Status Code ID %u",
21568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   status);
21578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "P2P: Response Data",
21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    pos, tlv_end - pos);
21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = tlv_end;
21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_notify_p2p_sd_response(wpa_s, sa, update_indic, tlvs, tlvs_len);
21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtu64 wpas_p2p_sd_request(struct wpa_supplicant *wpa_s, const u8 *dst,
21691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			const struct wpabuf *tlvs)
21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
21721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return wpa_drv_p2p_sd_request(wpa_s, dst, tlvs);
21738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
21741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
21751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return (uintptr_t) p2p_sd_request(wpa_s->global->p2p, dst, tlvs);
21768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtu64 wpas_p2p_sd_request_upnp(struct wpa_supplicant *wpa_s, const u8 *dst,
21801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			     u8 version, const char *query)
21818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *tlvs;
21831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	u64 ret;
21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tlvs = wpabuf_alloc(2 + 1 + 1 + 1 + os_strlen(query));
21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlvs == NULL)
21871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_le16(tlvs, 1 + 1 + 1 + os_strlen(query));
21898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(tlvs, P2P_SERV_UPNP); /* Service Protocol Type */
21908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(tlvs, 1); /* Service Transaction ID */
21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(tlvs, version);
21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_str(tlvs, query);
21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = wpas_p2p_sd_request(wpa_s, dst, tlvs);
21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(tlvs);
21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
219961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
220061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
220161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic u64 wpas_p2p_sd_request_wfd(struct wpa_supplicant *wpa_s, const u8 *dst,
220261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   const struct wpabuf *tlvs)
220361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
220461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
220561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return 0;
220661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
220761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return 0;
220861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return (uintptr_t) p2p_sd_request_wfd(wpa_s->global->p2p, dst, tlvs);
220961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
221061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
221161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
221261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#define MAX_WFD_SD_SUBELEMS 20
221361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
221461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void wfd_add_sd_req_role(struct wpabuf *tlvs, u8 id, u8 role,
221561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				const char *subelems)
221661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
221761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 *len;
221861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	const char *pos;
221961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	int val;
222061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	int count = 0;
222161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
222261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	len = wpabuf_put(tlvs, 2);
222361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_put_u8(tlvs, P2P_SERV_WIFI_DISPLAY); /* Service Protocol Type */
222461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_put_u8(tlvs, id); /* Service Transaction ID */
222561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
222661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_put_u8(tlvs, role);
222761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
222861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	pos = subelems;
222961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	while (*pos) {
223061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		val = atoi(pos);
223161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (val >= 0 && val < 256) {
223261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpabuf_put_u8(tlvs, val);
223361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			count++;
223461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if (count == MAX_WFD_SD_SUBELEMS)
223561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				break;
223661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
223761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos = os_strchr(pos + 1, ',');
223861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (pos == NULL)
223961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			break;
224061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos++;
224161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
224261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
224361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	WPA_PUT_LE16(len, (u8 *) wpabuf_put(tlvs, 0) - len - 2);
224461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
224561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
224661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
224761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtu64 wpas_p2p_sd_request_wifi_display(struct wpa_supplicant *wpa_s,
224861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				     const u8 *dst, const char *role)
224961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
225061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct wpabuf *tlvs;
225161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u64 ret;
225261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	const char *subelems;
225361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 id = 1;
225461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
225561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	subelems = os_strchr(role, ' ');
225661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (subelems == NULL)
225761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return 0;
225861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	subelems++;
225961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
226061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	tlvs = wpabuf_alloc(4 * (2 + 1 + 1 + 1 + MAX_WFD_SD_SUBELEMS));
226161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (tlvs == NULL)
226261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return 0;
226361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
226461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (os_strstr(role, "[source]"))
226561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wfd_add_sd_req_role(tlvs, id++, 0x00, subelems);
226661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (os_strstr(role, "[pri-sink]"))
226761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wfd_add_sd_req_role(tlvs, id++, 0x01, subelems);
226861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (os_strstr(role, "[sec-sink]"))
226961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wfd_add_sd_req_role(tlvs, id++, 0x02, subelems);
227061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (os_strstr(role, "[source+sink]"))
227161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wfd_add_sd_req_role(tlvs, id++, 0x03, subelems);
227261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
227361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	ret = wpas_p2p_sd_request_wfd(wpa_s, dst, tlvs);
227461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(tlvs);
227561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return ret;
227661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
227761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
227861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
227961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
228061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
22811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint wpas_p2p_sd_cancel_request(struct wpa_supplicant *wpa_s, u64 req)
22828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
22841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return wpa_drv_p2p_sd_cancel_request(wpa_s, req);
22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
22871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return p2p_sd_cancel_request(wpa_s->global->p2p,
22881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				     (void *) (uintptr_t) req);
22898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_p2p_sd_response(struct wpa_supplicant *wpa_s, int freq,
22938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  const u8 *dst, u8 dialog_token,
22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  const struct wpabuf *resp_tlvs)
22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_drv_p2p_sd_response(wpa_s, freq, dst, dialog_token,
22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					resp_tlvs);
22998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
23008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
23028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
23038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_sd_response(wpa_s->global->p2p, freq, dst, dialog_token,
23048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			resp_tlvs);
23058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2307eaf261d3b8eef1dcb8d645e0cd2b9016bb66cdfdDmitry Shmidt
23088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_p2p_sd_service_update(struct wpa_supplicant *wpa_s)
23098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
23118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_drv_p2p_service_update(wpa_s);
23128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
23138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p)
23158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_sd_service_update(wpa_s->global->p2p);
23168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_p2p_srv_bonjour_free(struct p2p_srv_bonjour *bsrv)
23208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_del(&bsrv->list);
23228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(bsrv->query);
23238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(bsrv->resp);
23248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(bsrv);
23258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_p2p_srv_upnp_free(struct p2p_srv_upnp *usrv)
23298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_del(&usrv->list);
23318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(usrv->service);
23328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(usrv);
23338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_p2p_service_flush(struct wpa_supplicant *wpa_s)
23378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_srv_bonjour *bsrv, *bn;
23398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_srv_upnp *usrv, *un;
23408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each_safe(bsrv, bn, &wpa_s->global->p2p_srv_bonjour,
23428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      struct p2p_srv_bonjour, list)
23438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_p2p_srv_bonjour_free(bsrv);
23448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each_safe(usrv, un, &wpa_s->global->p2p_srv_upnp,
23468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      struct p2p_srv_upnp, list)
23478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_p2p_srv_upnp_free(usrv);
23488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_p2p_sd_service_update(wpa_s);
23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_service_add_bonjour(struct wpa_supplicant *wpa_s,
23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 struct wpabuf *query, struct wpabuf *resp)
23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_srv_bonjour *bsrv;
23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bsrv = os_zalloc(sizeof(*bsrv));
23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bsrv == NULL)
23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bsrv->query = query;
23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bsrv->resp = resp;
23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_add(&wpa_s->global->p2p_srv_bonjour, &bsrv->list);
23648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_p2p_sd_service_update(wpa_s);
23668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
23678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_service_del_bonjour(struct wpa_supplicant *wpa_s,
23718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const struct wpabuf *query)
23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_srv_bonjour *bsrv;
23748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bsrv = wpas_p2p_service_get_bonjour(wpa_s, query);
23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bsrv == NULL)
23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_p2p_srv_bonjour_free(bsrv);
23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_p2p_sd_service_update(wpa_s);
23808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_service_add_upnp(struct wpa_supplicant *wpa_s, u8 version,
23858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      const char *service)
23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_srv_upnp *usrv;
23888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpas_p2p_service_get_upnp(wpa_s, version, service))
23908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* Already listed */
23918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	usrv = os_zalloc(sizeof(*usrv));
23928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (usrv == NULL)
23938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
23948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	usrv->version = version;
23958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	usrv->service = os_strdup(service);
23968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (usrv->service == NULL) {
23978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(usrv);
23988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
23998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_add(&wpa_s->global->p2p_srv_upnp, &usrv->list);
24018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_p2p_sd_service_update(wpa_s);
24038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
24048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_service_del_upnp(struct wpa_supplicant *wpa_s, u8 version,
24088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      const char *service)
24098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_srv_upnp *usrv;
24118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	usrv = wpas_p2p_service_get_upnp(wpa_s, version, service);
24138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (usrv == NULL)
24148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
24158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_p2p_srv_upnp_free(usrv);
24168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_p2p_sd_service_update(wpa_s);
24178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
24188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_prov_disc_local_display(struct wpa_supplicant *wpa_s,
24228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 const u8 *peer, const char *params,
24238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 unsigned int generated_pin)
24248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2425b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_SHOW_PIN MACSTR
2426b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		       " %08d%s", MAC2STR(peer), generated_pin, params);
24278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_prov_disc_local_keypad(struct wpa_supplicant *wpa_s,
24318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					const u8 *peer, const char *params)
24328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2433b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_ENTER_PIN MACSTR
2434b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		       "%s", MAC2STR(peer), params);
24358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_prov_disc_req(void *ctx, const u8 *peer, u16 config_methods,
24398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const u8 *dev_addr, const u8 *pri_dev_type,
24408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const char *dev_name, u16 supp_config_methods,
24411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			u8 dev_capab, u8 group_capab, const u8 *group_id,
24421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			size_t group_id_len)
24438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
24458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char devtype[WPS_DEV_TYPE_BUFSIZE];
24461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	char params[300];
24478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 empty_dev_type[8];
24488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int generated_pin = 0;
24491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct wpa_supplicant *group = NULL;
24501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
24511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (group_id) {
24521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		for (group = wpa_s->global->ifaces; group; group = group->next)
24531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		{
24541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			struct wpa_ssid *s = group->current_ssid;
24551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (s != NULL &&
24561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			    s->mode == WPAS_MODE_P2P_GO &&
24571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			    group_id_len - ETH_ALEN == s->ssid_len &&
24581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			    os_memcmp(group_id + ETH_ALEN, s->ssid,
24591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      s->ssid_len) == 0)
24601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				break;
24611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
24621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
24638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pri_dev_type == NULL) {
24658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(empty_dev_type, 0, sizeof(empty_dev_type));
24668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pri_dev_type = empty_dev_type;
24678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(params, sizeof(params), " p2p_dev_addr=" MACSTR
24698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    " pri_dev_type=%s name='%s' config_methods=0x%x "
24701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    "dev_capab=0x%x group_capab=0x%x%s%s",
24718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    MAC2STR(dev_addr),
24728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    wps_dev_type_bin2str(pri_dev_type, devtype,
24738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 sizeof(devtype)),
24741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    dev_name, supp_config_methods, dev_capab, group_capab,
24751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    group ? " group=" : "",
24761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    group ? group->ifname : "");
24778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params[sizeof(params) - 1] = '\0';
2478c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
24798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config_methods & WPS_CONFIG_DISPLAY) {
24808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		generated_pin = wps_generate_pin();
24818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_prov_disc_local_display(wpa_s, peer, params,
24828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     generated_pin);
24838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (config_methods & WPS_CONFIG_KEYPAD)
24848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_prov_disc_local_keypad(wpa_s, peer, params);
24858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (config_methods & WPS_CONFIG_PUSHBUTTON)
2486b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_PBC_REQ
2487b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       MACSTR "%s", MAC2STR(peer), params);
248875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
248975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	wpas_notify_p2p_provision_discovery(wpa_s, peer, 1 /* request */,
249075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen					    P2P_PROV_DISC_SUCCESS,
249175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen					    config_methods, generated_pin);
24928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_prov_disc_resp(void *ctx, const u8 *peer, u16 config_methods)
24968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
24988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int generated_pin = 0;
249904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	char params[20];
25008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2501c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (wpa_s->pending_pd_before_join &&
2502c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	    (os_memcmp(peer, wpa_s->pending_join_dev_addr, ETH_ALEN) == 0 ||
2503c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	     os_memcmp(peer, wpa_s->pending_join_iface_addr, ETH_ALEN) == 0)) {
2504c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpa_s->pending_pd_before_join = 0;
2505c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Starting pending "
2506c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			   "join-existing-group operation");
2507c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpas_p2p_join_start(wpa_s);
2508c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return;
2509c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
2510c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
251104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (wpa_s->pending_pd_use == AUTO_PD_JOIN ||
251204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    wpa_s->pending_pd_use == AUTO_PD_GO_NEG)
251304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_snprintf(params, sizeof(params), " peer_go=%d",
251404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			    wpa_s->pending_pd_use == AUTO_PD_JOIN);
251504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	else
251604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		params[0] = '\0';
251704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
25188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config_methods & WPS_CONFIG_DISPLAY)
251904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpas_prov_disc_local_keypad(wpa_s, peer, params);
25208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (config_methods & WPS_CONFIG_KEYPAD) {
25218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		generated_pin = wps_generate_pin();
252204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpas_prov_disc_local_display(wpa_s, peer, params,
252304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					     generated_pin);
25248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (config_methods & WPS_CONFIG_PUSHBUTTON)
2525b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_PBC_RESP
2526b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       MACSTR "%s", MAC2STR(peer), params);
25278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
252875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	wpas_notify_p2p_provision_discovery(wpa_s, peer, 0 /* response */,
252975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen					    P2P_PROV_DISC_SUCCESS,
253075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen					    config_methods, generated_pin);
25318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void wpas_prov_disc_fail(void *ctx, const u8 *peer,
25351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				enum p2p_prov_disc_status status)
253675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
253775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	struct wpa_supplicant *wpa_s = ctx;
253875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
253904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (wpa_s->p2p_fallback_to_go_neg) {
254004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: PD for p2p_connect-auto "
254104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			"failed - fall back to GO Negotiation");
254204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpas_p2p_fallback_to_go_neg(wpa_s, 0);
254304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return;
254404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
254504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
2546d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (status == P2P_PROV_DISC_TIMEOUT_JOIN) {
25472b380488c6b5d21e54e98397c7a8d6a9f16dd8b5Dmitry Shmidt		wpa_s->pending_pd_before_join = 0;
2548d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Starting pending "
2549d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			   "join-existing-group operation (no ACK for PD "
2550d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			   "Req attempts)");
2551d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wpas_p2p_join_start(wpa_s);
2552d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return;
25532b380488c6b5d21e54e98397c7a8d6a9f16dd8b5Dmitry Shmidt	}
2554d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
2555b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_FAILURE
2556b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		       " p2p_dev_addr=" MACSTR " status=%d",
2557b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		       MAC2STR(peer), status);
255804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
255975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	wpas_notify_p2p_provision_discovery(wpa_s, peer, 0 /* response */,
256075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen					    status, 0, 0);
256175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
256275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
256375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
2564f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidtstatic int freq_included(const struct p2p_channels *channels, unsigned int freq)
2565f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt{
2566f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	if (channels == NULL)
2567f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt		return 1; /* Assume no restrictions */
2568f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	return p2p_channels_includes_freq(channels, freq);
2569f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt
2570f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt}
2571f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt
2572f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt
25738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 wpas_invitation_process(void *ctx, const u8 *sa, const u8 *bssid,
25748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  const u8 *go_dev_addr, const u8 *ssid,
25758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  size_t ssid_len, int *go, u8 *group_bssid,
2576f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt				  int *force_freq, int persistent_group,
2577f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt				  const struct p2p_channels *channels)
25788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
25808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *s;
25818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
25828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *grp;
25838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!persistent_group) {
25858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Invitation from " MACSTR
25868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " to join an active group", MAC2STR(sa));
25878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!is_zero_ether_addr(wpa_s->p2p_auth_invite) &&
25888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (os_memcmp(go_dev_addr, wpa_s->p2p_auth_invite, ETH_ALEN)
25898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     == 0 ||
25908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     os_memcmp(sa, wpa_s->p2p_auth_invite, ETH_ALEN) == 0)) {
25918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Accept previously "
25928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "authorized invitation");
25938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto accept_inv;
25948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
25958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
25968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Do not accept the invitation automatically; notify user and
25978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * request approval.
25988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
25998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
26008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	grp = wpas_get_p2p_group(wpa_s, ssid, ssid_len, go);
26038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (grp) {
26048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Accept invitation to already "
26058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "running persistent group");
26068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*go)
26078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(group_bssid, grp->own_addr, ETH_ALEN);
26088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto accept_inv;
26098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26117a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt	if (!is_zero_ether_addr(wpa_s->p2p_auth_invite) &&
26127a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt	    os_memcmp(sa, wpa_s->p2p_auth_invite, ETH_ALEN) == 0) {
26137a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Accept previously initiated "
26147a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt			   "invitation to re-invoke a persistent group");
26157a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt	} else if (!wpa_s->conf->persistent_reconnect)
26168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
26178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (s = wpa_s->conf->ssid; s; s = s->next) {
26198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (s->disabled == 2 &&
26208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_memcmp(s->bssid, go_dev_addr, ETH_ALEN) == 0 &&
26218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    s->ssid_len == ssid_len &&
26228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_memcmp(ssid, s->ssid, ssid_len) == 0)
26238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
26248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!s) {
26278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Invitation from " MACSTR
26288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " requested reinvocation of an unknown group",
26298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   MAC2STR(sa));
26308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return P2P_SC_FAIL_UNKNOWN_GROUP;
26318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (s->mode == WPAS_MODE_P2P_GO && !wpas_p2p_create_iface(wpa_s)) {
26348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*go = 1;
26358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
26368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: The only available "
26378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "interface is already in use - reject "
26388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "invitation");
26398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
26408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
26418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(group_bssid, wpa_s->own_addr, ETH_ALEN);
26428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (s->mode == WPAS_MODE_P2P_GO) {
26438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*go = 1;
26448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpas_p2p_add_group_interface(wpa_s, WPA_IF_P2P_GO) < 0)
26458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		{
26468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "P2P: Failed to allocate a new "
26478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "interface address for the group");
26488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
26498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
26508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(group_bssid, wpa_s->pending_interface_addr,
26518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
26528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtaccept_inv:
2655700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	wpas_p2p_set_own_freq_preference(wpa_s, 0);
2656700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt
2657c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	/* Get one of the frequencies currently in use */
2658c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	if (wpas_p2p_valid_oper_freqs(wpa_s, &res, 1) > 0) {
2659c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Trying to force channel to match a channel already used by one of the interfaces");
26608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*force_freq = res;
2661700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt		wpas_p2p_set_own_freq_preference(wpa_s, res);
26628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2664c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	if (*force_freq > 0 && wpa_s->num_multichan_concurrent > 1 &&
2665c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	    wpas_p2p_num_unused_channels(wpa_s) > 0) {
2666f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt		if (*go == 0) {
2667f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt			/* We are the client */
2668f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Peer was found to be "
2669f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt				   "running a GO but we are capable of MCC, "
2670f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt				   "figure out the best channel to use");
2671f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt			*force_freq = 0;
2672f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt		} else if (!freq_included(channels, *force_freq)) {
2673f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt			/* We are the GO, and *force_freq is not in the
2674f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt			 * intersection */
2675f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Forced GO freq %d MHz not "
2676f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt				   "in intersection but we are capable of MCC, "
2677f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt				   "figure out the best channel to use",
2678f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt				   *force_freq);
2679f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt			*force_freq = 0;
2680f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt		}
2681f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	}
2682f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt
26838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return P2P_SC_SUCCESS;
26848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid,
26888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const u8 *ssid, size_t ssid_len,
26898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const u8 *go_dev_addr, u8 status,
26908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     int op_freq)
26918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
26938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *s;
26948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (s = wpa_s->conf->ssid; s; s = s->next) {
26968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (s->disabled == 2 &&
26978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    s->ssid_len == ssid_len &&
26988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_memcmp(ssid, s->ssid, ssid_len) == 0)
26998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
27008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (status == P2P_SC_SUCCESS) {
27038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Invitation from peer " MACSTR
27048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " was accepted; op_freq=%d MHz",
27058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   MAC2STR(sa), op_freq);
27068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (s) {
270791c40cdce17424d9a4718876becf0b7811cf68f2Dmitry Shmidt			int go = s->mode == WPAS_MODE_P2P_GO;
27088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpas_p2p_group_add_persistent(
27097a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt				wpa_s, s, go, go ? op_freq : 0, 0, NULL);
27108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (bssid) {
2711d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			wpa_s->user_initiated_pd = 0;
27128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpas_p2p_join(wpa_s, bssid, go_dev_addr,
271304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				      wpa_s->p2p_wps_method, 0);
27148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
27158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
27168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (status != P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) {
27198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Invitation from peer " MACSTR
27208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " was rejected (status %u)", MAC2STR(sa), status);
27218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
27228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!s) {
27258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (bssid) {
2726b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			wpa_msg_global(wpa_s, MSG_INFO,
2727b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       P2P_EVENT_INVITATION_RECEIVED
2728b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       "sa=" MACSTR " go_dev_addr=" MACSTR
2729b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       " bssid=" MACSTR " unknown-network",
2730b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       MAC2STR(sa), MAC2STR(go_dev_addr),
2731b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       MAC2STR(bssid));
27328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
2733b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			wpa_msg_global(wpa_s, MSG_INFO,
2734b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       P2P_EVENT_INVITATION_RECEIVED
2735b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       "sa=" MACSTR " go_dev_addr=" MACSTR
2736b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       " unknown-network",
2737b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       MAC2STR(sa), MAC2STR(go_dev_addr));
27388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
27398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
27408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27427a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt	if (s->mode == WPAS_MODE_P2P_GO && op_freq) {
2743b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RECEIVED
2744b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       "sa=" MACSTR " persistent=%d freq=%d",
2745b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       MAC2STR(sa), s->id, op_freq);
27467a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt	} else {
2747b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RECEIVED
2748b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       "sa=" MACSTR " persistent=%d",
2749b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       MAC2STR(sa), s->id);
27507a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt	}
27518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2754700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidtstatic void wpas_remove_persistent_peer(struct wpa_supplicant *wpa_s,
2755700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt					struct wpa_ssid *ssid,
2756391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt					const u8 *peer, int inv)
2757700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt{
2758700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	size_t i;
2759700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt
2760700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	if (ssid == NULL)
2761700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt		return;
2762700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt
2763700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	for (i = 0; ssid->p2p_client_list && i < ssid->num_p2p_clients; i++) {
2764700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt		if (os_memcmp(ssid->p2p_client_list + i * ETH_ALEN, peer,
2765700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt			      ETH_ALEN) == 0)
2766700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt			break;
2767700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	}
2768700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	if (i >= ssid->num_p2p_clients) {
2769700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt		if (ssid->mode != WPAS_MODE_P2P_GO &&
2770700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt		    os_memcmp(ssid->bssid, peer, ETH_ALEN) == 0) {
2771700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Remove persistent group %d "
2772700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt				   "due to invitation result", ssid->id);
2773700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt			wpas_notify_network_removed(wpa_s, ssid);
2774700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt			wpa_config_remove_network(wpa_s->conf, ssid->id);
2775700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt			return;
2776700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt		}
2777700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt		return; /* Peer not found in client list */
2778700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	}
2779700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt
2780700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Remove peer " MACSTR " from persistent "
2781391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		   "group %d client list%s",
2782391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		   MAC2STR(peer), ssid->id,
2783391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		   inv ? " due to invitation result" : "");
2784700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	os_memmove(ssid->p2p_client_list + i * ETH_ALEN,
2785700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt		   ssid->p2p_client_list + (i + 1) * ETH_ALEN,
2786700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt		   (ssid->num_p2p_clients - i - 1) * ETH_ALEN);
2787700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	ssid->num_p2p_clients--;
2788700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt#ifndef CONFIG_NO_CONFIG_WRITE
2789700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	if (wpa_s->parent->conf->update_config &&
2790700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	    wpa_config_write(wpa_s->parent->confname, wpa_s->parent->conf))
2791700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
2792700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt#endif /* CONFIG_NO_CONFIG_WRITE */
2793700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt}
2794700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt
2795700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt
2796700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidtstatic void wpas_remove_persistent_client(struct wpa_supplicant *wpa_s,
2797700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt					  const u8 *peer)
2798700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt{
2799700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	struct wpa_ssid *ssid;
2800700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt
2801700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	wpa_s = wpa_s->global->p2p_invite_group;
2802700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	if (wpa_s == NULL)
2803700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt		return; /* No known invitation group */
2804700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	ssid = wpa_s->current_ssid;
2805700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
2806700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	    !ssid->p2p_persistent_group)
2807700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt		return; /* Not operating as a GO in persistent group */
2808700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	ssid = wpas_p2p_get_persistent(wpa_s->parent, peer,
2809700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt				       ssid->ssid, ssid->ssid_len);
2810391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	wpas_remove_persistent_peer(wpa_s, ssid, peer, 1);
2811700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt}
2812700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt
2813700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt
28147a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidtstatic void wpas_invitation_result(void *ctx, int status, const u8 *bssid,
2815700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt				   const struct p2p_channels *channels,
2816700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt				   const u8 *peer)
28178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
28198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid;
28208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bssid) {
2822b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RESULT
2823b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       "status=%d " MACSTR,
2824b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       status, MAC2STR(bssid));
28258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
2826b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RESULT
2827b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       "status=%d ", status);
28288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_notify_p2p_invitation_result(wpa_s, status, bssid);
28308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2831700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Invitation result - status=%d peer=" MACSTR,
2832700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt		   status, MAC2STR(peer));
2833700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	if (wpa_s->pending_invite_ssid_id == -1) {
2834700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt		if (status == P2P_SC_FAIL_UNKNOWN_GROUP)
2835700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt			wpas_remove_persistent_client(wpa_s, peer);
28368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* Invitation to active group */
2837700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	}
28388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28397a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt	if (status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) {
28407a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Waiting for peer to start another "
28417a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt			   "invitation exchange to indicate readiness for "
28427a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt			   "re-invocation");
28437a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt	}
28447a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt
28458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (status != P2P_SC_SUCCESS) {
2846700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt		if (status == P2P_SC_FAIL_UNKNOWN_GROUP) {
2847700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt			ssid = wpa_config_get_network(
2848700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt				wpa_s->conf, wpa_s->pending_invite_ssid_id);
2849391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			wpas_remove_persistent_peer(wpa_s, ssid, peer, 1);
2850700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt		}
28518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_p2p_remove_pending_group_interface(wpa_s);
28528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
28538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid = wpa_config_get_network(wpa_s->conf,
28568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      wpa_s->pending_invite_ssid_id);
28578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid == NULL) {
28588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "P2P: Could not find persistent group "
28598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "data matching with invitation");
28608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
28618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28632c5b17df4c29abdf11a85216c2f6272af796c576Jouni Malinen	/*
28642c5b17df4c29abdf11a85216c2f6272af796c576Jouni Malinen	 * The peer could have missed our ctrl::ack frame for Invitation
28652c5b17df4c29abdf11a85216c2f6272af796c576Jouni Malinen	 * Response and continue retransmitting the frame. To reduce the
28662c5b17df4c29abdf11a85216c2f6272af796c576Jouni Malinen	 * likelihood of the peer not getting successful TX status for the
28672c5b17df4c29abdf11a85216c2f6272af796c576Jouni Malinen	 * Invitation Response frame, wait a short time here before starting
28682c5b17df4c29abdf11a85216c2f6272af796c576Jouni Malinen	 * the persistent group so that we will remain on the current channel to
28692c5b17df4c29abdf11a85216c2f6272af796c576Jouni Malinen	 * acknowledge any possible retransmission from the peer.
28702c5b17df4c29abdf11a85216c2f6272af796c576Jouni Malinen	 */
287181931b8bb302c38828763358f9e15af2b22c52c6Irfan Sheriff#ifndef ANDROID_P2P
28722c5b17df4c29abdf11a85216c2f6272af796c576Jouni Malinen	wpa_dbg(wpa_s, MSG_DEBUG, "P2P: 50 ms wait on current channel before "
28732c5b17df4c29abdf11a85216c2f6272af796c576Jouni Malinen		"starting persistent group");
28742c5b17df4c29abdf11a85216c2f6272af796c576Jouni Malinen	os_sleep(0, 50000);
287581931b8bb302c38828763358f9e15af2b22c52c6Irfan Sheriff#else
287681931b8bb302c38828763358f9e15af2b22c52c6Irfan Sheriff	wpa_dbg(wpa_s, MSG_DEBUG, "P2P: 100 ms wait on current channel before "
287781931b8bb302c38828763358f9e15af2b22c52c6Irfan Sheriff		"starting persistent group");
287881931b8bb302c38828763358f9e15af2b22c52c6Irfan Sheriff	os_sleep(0, 100000);
287981931b8bb302c38828763358f9e15af2b22c52c6Irfan Sheriff#endif
28802c5b17df4c29abdf11a85216c2f6272af796c576Jouni Malinen
28818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_p2p_group_add_persistent(wpa_s, ssid,
288231be0a4b946ecab910c0a9af3837dbccea5d204bJouni Malinen				      ssid->mode == WPAS_MODE_P2P_GO,
288331be0a4b946ecab910c0a9af3837dbccea5d204bJouni Malinen				      wpa_s->p2p_persistent_go_freq,
28847a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt				      wpa_s->p2p_go_ht40, channels);
28858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
288804949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int wpas_p2p_disallowed_freq(struct wpa_global *global,
288904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				    unsigned int freq)
289004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
289104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	unsigned int i;
289204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
289304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (global->p2p_disallow_freq == NULL)
289404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 0;
289504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
289604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	for (i = 0; i < global->num_p2p_disallow_freq; i++) {
289704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (freq >= global->p2p_disallow_freq[i].min &&
289804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		    freq <= global->p2p_disallow_freq[i].max)
289904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			return 1;
290004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
290104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
290204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return 0;
290304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
290404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
290504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
290604949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void wpas_p2p_add_chan(struct p2p_reg_class *reg, u8 chan)
290704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
290804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	reg->channel[reg->channels] = chan;
290904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	reg->channels++;
291004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
291104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
291204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
29138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpas_p2p_default_channels(struct wpa_supplicant *wpa_s,
29148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     struct p2p_channels *chan)
29158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i, cla = 0;
29178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Enable operating classes for 2.4 GHz "
29198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "band");
29208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Operating class 81 - 2.4 GHz band channels 1..13 */
29228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	chan->reg_class[cla].reg_class = 81;
292304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	chan->reg_class[cla].channels = 0;
292404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	for (i = 0; i < 11; i++) {
292504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (!wpas_p2p_disallowed_freq(wpa_s->global, 2412 + i * 5))
292604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpas_p2p_add_chan(&chan->reg_class[cla], i + 1);
292704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
292804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (chan->reg_class[cla].channels)
292904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		cla++;
29308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Enable operating classes for lower 5 GHz "
29328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "band");
29338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Operating class 115 - 5 GHz, channels 36-48 */
29358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	chan->reg_class[cla].reg_class = 115;
293604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	chan->reg_class[cla].channels = 0;
293704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 36 * 5))
293804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpas_p2p_add_chan(&chan->reg_class[cla], 36);
293904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 40 * 5))
294004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpas_p2p_add_chan(&chan->reg_class[cla], 40);
294104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 44 * 5))
294204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpas_p2p_add_chan(&chan->reg_class[cla], 44);
294304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 48 * 5))
294404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpas_p2p_add_chan(&chan->reg_class[cla], 48);
294504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (chan->reg_class[cla].channels)
294604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		cla++;
29478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Enable operating classes for higher 5 GHz "
29498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "band");
29508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Operating class 124 - 5 GHz, channels 149,153,157,161 */
29528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	chan->reg_class[cla].reg_class = 124;
295304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	chan->reg_class[cla].channels = 0;
295404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 149 * 5))
295504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpas_p2p_add_chan(&chan->reg_class[cla], 149);
295604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 153 * 5))
295704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpas_p2p_add_chan(&chan->reg_class[cla], 153);
295804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 156 * 5))
295904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpas_p2p_add_chan(&chan->reg_class[cla], 157);
296004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 161 * 5))
296104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpas_p2p_add_chan(&chan->reg_class[cla], 161);
296204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (chan->reg_class[cla].channels)
296304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		cla++;
29648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	chan->reg_classes = cla;
29668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
29678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
29718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  u16 num_modes,
29728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  enum hostapd_hw_mode mode)
29738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 i;
29758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_modes; i++) {
29778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (modes[i].mode == mode)
29788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return &modes[i];
29798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
29828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
298504949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int has_channel(struct wpa_global *global,
298604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		       struct hostapd_hw_modes *mode, u8 chan, int *flags)
29878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
298904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	unsigned int freq;
299004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
299104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	freq = (mode->mode == HOSTAPD_MODE_IEEE80211A ? 5000 : 2407) +
299204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		chan * 5;
299304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (wpas_p2p_disallowed_freq(global, freq))
299404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 0;
29958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < mode->num_channels; i++) {
29978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (mode->channels[i].chan == chan) {
29988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (flags)
29998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				*flags = mode->channels[i].flag;
30008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return !(mode->channels[i].flag &
30018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 (HOSTAPD_CHAN_DISABLED |
30028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  HOSTAPD_CHAN_PASSIVE_SCAN |
30038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  HOSTAPD_CHAN_NO_IBSS |
30048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  HOSTAPD_CHAN_RADAR));
30058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
30068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
30098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
30108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_oper_class_map {
30138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum hostapd_hw_mode mode;
30148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 op_class;
30158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 min_chan;
30168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 max_chan;
30178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 inc;
30188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum { BW20, BW40PLUS, BW40MINUS } bw;
30198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
30208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
302161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic struct p2p_oper_class_map op_class[] = {
302261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211G, 81, 1, 13, 1, BW20 },
302361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#if 0 /* Do not enable HT40 on 2 GHz for now */
302461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211G, 83, 1, 9, 1, BW40PLUS },
302561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211G, 84, 5, 13, 1, BW40MINUS },
302661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif
302761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211A, 115, 36, 48, 4, BW20 },
302861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211A, 124, 149, 161, 4, BW20 },
302961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211A, 116, 36, 44, 8, BW40PLUS },
303061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211A, 117, 40, 48, 8, BW40MINUS },
303161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211A, 126, 149, 157, 8, BW40PLUS },
303261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211A, 127, 153, 161, 8, BW40MINUS },
303361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	{ -1, 0, 0, 0, 0, BW20 }
303461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt};
303561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
303661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
303761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int wpas_p2p_verify_channel(struct wpa_supplicant *wpa_s,
303861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   struct hostapd_hw_modes *mode,
303961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   u8 channel, u8 bw)
304061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
304161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	int flag;
304261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
304361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (!has_channel(wpa_s->global, mode, channel, &flag))
304461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
304561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (bw == BW40MINUS &&
304661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	    (!(flag & HOSTAPD_CHAN_HT40MINUS) ||
304761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	     !has_channel(wpa_s->global, mode, channel - 4, NULL)))
304861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return 0;
304961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (bw == BW40PLUS &&
305061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	    (!(flag & HOSTAPD_CHAN_HT40PLUS) ||
305161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	     !has_channel(wpa_s->global, mode, channel + 4, NULL)))
305261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return 0;
305361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 1;
305461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
305561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
305661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
30578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s,
30588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   struct p2p_channels *chan)
30598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
30601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct hostapd_hw_modes *mode;
30618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int cla, op;
30628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_s->hw.modes == NULL) {
30648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Driver did not support fetching "
30658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "of all supported channels; assume dualband "
30668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "support");
30678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wpas_p2p_default_channels(wpa_s, chan);
30688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cla = 0;
30718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (op = 0; op_class[op].op_class; op++) {
30738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct p2p_oper_class_map *o = &op_class[op];
30748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 ch;
30758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct p2p_reg_class *reg = NULL;
30768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, o->mode);
30788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (mode == NULL)
30798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
30808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
308161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if (wpas_p2p_verify_channel(wpa_s, mode, ch, o->bw) < 1)
30828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				continue;
30838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (reg == NULL) {
30848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "P2P: Add operating "
30858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "class %u", o->op_class);
30868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				reg = &chan->reg_class[cla];
30878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				cla++;
30888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				reg->reg_class = o->op_class;
30898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
30908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			reg->channel[reg->channels] = ch;
30918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			reg->channels++;
30928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
30938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (reg) {
30948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG, "P2P: Channels",
30958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    reg->channel, reg->channels);
30968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
30978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	chan->reg_classes = cla;
31008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
31028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
310561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint wpas_p2p_get_ht40_mode(struct wpa_supplicant *wpa_s,
310661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			   struct hostapd_hw_modes *mode, u8 channel)
310761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
310861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	int op, ret;
310961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
311061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	for (op = 0; op_class[op].op_class; op++) {
311161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		struct p2p_oper_class_map *o = &op_class[op];
311261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		u8 ch;
311361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
311461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
311561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if (o->mode != HOSTAPD_MODE_IEEE80211A ||
311661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			    o->bw == BW20 || ch != channel)
311761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				continue;
311861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			ret = wpas_p2p_verify_channel(wpa_s, mode, ch, o->bw);
311961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if (ret < 0)
312061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				continue;
312161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			else if (ret > 0)
312261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				return (o->bw == BW40MINUS) ? -1 : 1;
312361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			else
312461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				return 0;
312561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
312661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
312761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
312861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
312961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
313061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
31318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpas_get_noa(void *ctx, const u8 *interface_addr, u8 *buf,
31328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			size_t buf_len)
31338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
31348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
31358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
31378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(wpa_s->own_addr, interface_addr, ETH_ALEN) == 0)
31388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
31398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s == NULL)
31418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
31428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_drv_get_noa(wpa_s, buf, buf_len);
31448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3147c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic int wpas_go_connected(void *ctx, const u8 *dev_addr)
3148c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{
3149c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
3150c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
3151c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3152c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		struct wpa_ssid *ssid = wpa_s->current_ssid;
3153c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (ssid == NULL)
3154c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			continue;
3155c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (ssid->mode != WPAS_MODE_INFRA)
3156c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			continue;
3157c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (wpa_s->wpa_state != WPA_COMPLETED &&
3158c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		    wpa_s->wpa_state != WPA_GROUP_HANDSHAKE)
3159c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			continue;
3160c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (os_memcmp(wpa_s->go_dev_addr, dev_addr, ETH_ALEN) == 0)
3161c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			return 1;
3162c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
3163c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
3164c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	return 0;
3165c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt}
3166c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
3167c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
3168b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidtstatic void wpas_p2p_debug_print(void *ctx, int level, const char *msg)
3169b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt{
3170b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
3171b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	wpa_msg_global(wpa_s, level, "P2P: %s", msg);
3172b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt}
3173b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
3174b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
317534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtint wpas_p2p_add_p2pdev_interface(struct wpa_supplicant *wpa_s)
317634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
317734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	struct wpa_interface iface;
317834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	struct wpa_supplicant *p2pdev_wpa_s;
317934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	char ifname[100];
318034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	char force_name[100];
318134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	int ret;
318234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
318334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	os_snprintf(ifname, sizeof(ifname), P2P_MGMT_DEVICE_PREFIX "%s",
318434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		    wpa_s->ifname);
318534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	force_name[0] = '\0';
318634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_s->pending_interface_type = WPA_IF_P2P_DEVICE;
318734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	ret = wpa_drv_if_add(wpa_s, WPA_IF_P2P_DEVICE, ifname, NULL, NULL,
318834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			     force_name, wpa_s->pending_interface_addr, NULL);
318934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (ret < 0) {
319034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Failed to create P2P Device interface");
319134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return ret;
319234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
319334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	os_strlcpy(wpa_s->pending_interface_name, ifname,
319434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		   sizeof(wpa_s->pending_interface_name));
319534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
319634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	os_memset(&iface, 0, sizeof(iface));
319734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	iface.p2p_mgmt = 1;
319834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	iface.ifname = wpa_s->pending_interface_name;
319934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	iface.driver = wpa_s->driver->name;
320034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	iface.driver_param = wpa_s->conf->driver_param;
320134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	iface.confname = wpa_s->confname;
320234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	p2pdev_wpa_s = wpa_supplicant_add_iface(wpa_s->global, &iface);
320334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (!p2pdev_wpa_s) {
320434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Failed to add P2P Device interface");
320534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return -1;
320634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
320734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	p2pdev_wpa_s->parent = wpa_s;
320834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
320934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_s->pending_interface_name[0] = '\0';
321034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	return 0;
321134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
321234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
321334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
32148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
32158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpas_p2p_init - Initialize P2P module for %wpa_supplicant
32168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @global: Pointer to global data from wpa_supplicant_init()
32178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface()
32188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
32198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
32208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
32218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
32228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_config p2p;
32238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int r;
32248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
32258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3226391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (wpa_s->conf->p2p_disabled)
3227391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		return 0;
3228391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
32298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_CAPABLE))
32308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
32318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (global->p2p)
32338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
32348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
32368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct p2p_params params;
32378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Use driver-based P2P management");
32398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(&params, 0, sizeof(params));
32408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		params.dev_name = wpa_s->conf->device_name;
32418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(params.pri_dev_type, wpa_s->conf->device_type,
32428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  WPS_DEV_TYPE_LEN);
32438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		params.num_sec_dev_types = wpa_s->conf->num_sec_device_types;
32448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(params.sec_dev_type,
32458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  wpa_s->conf->sec_device_type,
32468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  params.num_sec_dev_types * WPS_DEV_TYPE_LEN);
32478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_drv_p2p_set_params(wpa_s, &params) < 0)
32498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
32508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
32528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&p2p, 0, sizeof(p2p));
32558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.cb_ctx = wpa_s;
3256b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p.debug_print = wpas_p2p_debug_print;
32578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.p2p_scan = wpas_p2p_scan;
32588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.send_action = wpas_send_action;
32598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.send_action_done = wpas_send_action_done;
32608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.go_neg_completed = wpas_go_neg_completed;
32618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.go_neg_req_rx = wpas_go_neg_req_rx;
32628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.dev_found = wpas_dev_found;
32638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.dev_lost = wpas_dev_lost;
3264b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p.find_stopped = wpas_find_stopped;
32658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.start_listen = wpas_start_listen;
32668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.stop_listen = wpas_stop_listen;
32678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.send_probe_resp = wpas_send_probe_resp;
32688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.sd_request = wpas_sd_request;
32698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.sd_response = wpas_sd_response;
32708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.prov_disc_req = wpas_prov_disc_req;
32718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.prov_disc_resp = wpas_prov_disc_resp;
327275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p.prov_disc_fail = wpas_prov_disc_fail;
32738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.invitation_process = wpas_invitation_process;
32748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.invitation_received = wpas_invitation_received;
32758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.invitation_result = wpas_invitation_result;
32768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.get_noa = wpas_get_noa;
3277c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	p2p.go_connected = wpas_go_connected;
32788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN);
32801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_memcpy(p2p.dev_addr, wpa_s->global->p2p_dev_addr, ETH_ALEN);
32818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.dev_name = wpa_s->conf->device_name;
32828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.manufacturer = wpa_s->conf->manufacturer;
32838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.model_name = wpa_s->conf->model_name;
32848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.model_number = wpa_s->conf->model_number;
32858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.serial_number = wpa_s->conf->serial_number;
32868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->wps) {
32878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p.uuid, wpa_s->wps->uuid, 16);
32888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p.config_methods = wpa_s->wps->config_methods;
32898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->conf->p2p_listen_reg_class &&
32928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_s->conf->p2p_listen_channel) {
32938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p.reg_class = wpa_s->conf->p2p_listen_reg_class;
32948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p.channel = wpa_s->conf->p2p_listen_channel;
32958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
32968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p.reg_class = 81;
32978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
32988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Pick one of the social channels randomly as the listen
32998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * channel.
33008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
33018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_get_random((u8 *) &r, sizeof(r));
33028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p.channel = 1 + (r % 3) * 5;
33038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Own listen channel: %d", p2p.channel);
33058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->conf->p2p_oper_reg_class &&
33078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_s->conf->p2p_oper_channel) {
33088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p.op_reg_class = wpa_s->conf->p2p_oper_reg_class;
33098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p.op_channel = wpa_s->conf->p2p_oper_channel;
33108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p.cfg_op_channel = 1;
33118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Configured operating channel: "
33128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "%d:%d", p2p.op_reg_class, p2p.op_channel);
33138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
33158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p.op_reg_class = 81;
33168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
33178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Use random operation channel from (1, 6, 11) if no other
33188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * preference is indicated.
33198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
33208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_get_random((u8 *) &r, sizeof(r));
33218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p.op_channel = 1 + (r % 3) * 5;
33228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p.cfg_op_channel = 0;
33238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Random operating channel: "
33248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "%d:%d", p2p.op_reg_class, p2p.op_channel);
33258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
332644c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidt
332744c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidt	if (wpa_s->conf->p2p_pref_chan && wpa_s->conf->num_p2p_pref_chan) {
332844c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidt		p2p.pref_chan = wpa_s->conf->p2p_pref_chan;
332944c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidt		p2p.num_pref_chan = wpa_s->conf->num_p2p_pref_chan;
333044c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidt	}
333144c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidt
33328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
33338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p.country, wpa_s->conf->country, 2);
33348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p.country[2] = 0x04;
33358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
33368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p.country, "XX\x04", 3);
33378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpas_p2p_setup_channels(wpa_s, &p2p.channels)) {
33398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "P2P: Failed to configure supported "
33408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "channel list");
33418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
33428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p.pri_dev_type, wpa_s->conf->device_type,
33458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  WPS_DEV_TYPE_LEN);
33468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.num_sec_dev_types = wpa_s->conf->num_sec_device_types;
33488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(p2p.sec_dev_type, wpa_s->conf->sec_device_type,
33498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  p2p.num_sec_dev_types * WPS_DEV_TYPE_LEN);
33508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.concurrent_operations = !!(wpa_s->drv_flags &
33528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       WPA_DRIVER_FLAGS_P2P_CONCURRENT);
33538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.max_peers = 100;
33558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->conf->p2p_ssid_postfix) {
33578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p.ssid_postfix_len =
33588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_strlen(wpa_s->conf->p2p_ssid_postfix);
33598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p.ssid_postfix_len > sizeof(p2p.ssid_postfix))
33608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p.ssid_postfix_len = sizeof(p2p.ssid_postfix);
33618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(p2p.ssid_postfix, wpa_s->conf->p2p_ssid_postfix,
33628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  p2p.ssid_postfix_len);
33638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p.p2p_intra_bss = wpa_s->conf->p2p_intra_bss;
33668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3367d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p.max_listen = wpa_s->max_remain_on_chan;
3368d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
33698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	global->p2p = p2p_init(&p2p);
33708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (global->p2p == NULL)
33718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
337204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	global->p2p_init_wpa_s = wpa_s;
33738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < MAX_WPS_VENDOR_EXT; i++) {
33758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_s->conf->wps_vendor_ext[i] == NULL)
33768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
33778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_add_wps_vendor_extension(
33788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			global->p2p, wpa_s->conf->wps_vendor_ext[i]);
33798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
33808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
33828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
33838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
33868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpas_p2p_deinit - Deinitialize per-interface P2P data
33878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface()
33888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
33898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function deinitialize per-interface P2P data.
33908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
33918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_p2p_deinit(struct wpa_supplicant *wpa_s)
33928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
33938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->driver && wpa_s->drv_priv)
33948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_drv_probe_req_report(wpa_s, 0);
33951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
33961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_s->go_params) {
33971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Clear any stored provisioning info */
33981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_clear_provisioning_info(
33991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_s->global->p2p,
340004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpa_s->go_params->peer_device_addr);
34011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
34021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
34038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(wpa_s->go_params);
34048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->go_params = NULL;
34051cf4573e05a4e7ce02e0ccc46771a1da5f303411Dmitry Shmidt#ifdef ANDROID_P2P
34061cf4573e05a4e7ce02e0ccc46771a1da5f303411Dmitry Shmidt	eloop_cancel_timeout(wpas_p2p_group_freq_conflict, wpa_s, NULL);
34071cf4573e05a4e7ce02e0ccc46771a1da5f303411Dmitry Shmidt#endif
34088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s, NULL);
34098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
34108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->p2p_long_listen = 0;
34118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL);
34128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL);
34138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_p2p_remove_pending_group_interface(wpa_s);
34148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: remove group interface from the driver if this wpa_s instance
34168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * is on top of a P2P group interface */
34178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
34218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpas_p2p_deinit_global - Deinitialize global P2P module
34228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @global: Pointer to global data from wpa_supplicant_init()
34238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
34248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function deinitializes the global (per device) P2P module.
34258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
34268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_p2p_deinit_global(struct wpa_global *global)
34278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s, *tmp;
34298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
343061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpa_s = global->ifaces;
343161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (wpa_s)
343261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpas_p2p_service_flush(wpa_s);
343361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
34348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (global->p2p == NULL)
34358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
34368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Remove remaining P2P group interfaces */
34388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (wpa_s && wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
34398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s = wpa_s->next;
34408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (wpa_s) {
34418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tmp = global->ifaces;
34428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (tmp &&
34438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       (tmp == wpa_s ||
34448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tmp->p2p_group_interface == NOT_P2P_GROUP_INTERFACE)) {
34458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tmp = tmp->next;
34468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
34478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tmp == NULL)
34488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
344904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/* Disconnect from the P2P group and deinit the interface */
345004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpas_p2p_disconnect(tmp);
34518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
34548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Deinit GO data on any possibly remaining interface (if main
34558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * interface is used as GO).
34568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
34578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
34588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_s->ap_iface)
34598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpas_p2p_group_deinit(wpa_s);
34608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_deinit(global->p2p);
34638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	global->p2p = NULL;
346404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	global->p2p_init_wpa_s = NULL;
34658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s)
34698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
347034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
347134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	    wpa_s->conf->p2p_no_group_iface)
3472d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return 0; /* separate interface disabled per configuration */
34738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->drv_flags &
34748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE |
34758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P))
34768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* P2P group requires a new interface in every case
34778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   */
34788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_CONCURRENT))
34798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* driver does not support concurrent operations */
34808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->ifaces->next)
34818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* more that one interface already in use */
34828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
34838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* this interface is already in use */
34848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
34858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
34868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
34888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpas_p2p_start_go_neg(struct wpa_supplicant *wpa_s,
34898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const u8 *peer_addr,
34908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 enum p2p_wps_method wps_method,
34918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 int go_intent, const u8 *own_interface_addr,
349204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 unsigned int force_freq, int persistent_group,
3493d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				 struct wpa_ssid *ssid, unsigned int pref_freq)
34948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
34951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (persistent_group && wpa_s->conf->persistent_reconnect)
34961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		persistent_group = 2;
34971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
34988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
34998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wpa_drv_p2p_connect(wpa_s, peer_addr, wps_method,
35008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   go_intent, own_interface_addr,
35018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   force_freq, persistent_group);
35028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
35038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
350461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	/*
350561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * Increase GO config timeout if HT40 is used since it takes some time
350661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * to scan channels for coex purposes before the BSS can be started.
350761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 */
350861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_set_config_timeout(wpa_s->global->p2p,
350961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			       wpa_s->p2p_go_ht40 ? 255 : 100, 20);
351061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
35118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_connect(wpa_s->global->p2p, peer_addr, wps_method,
35128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   go_intent, own_interface_addr, force_freq,
351304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   persistent_group, ssid ? ssid->ssid : NULL,
351404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   ssid ? ssid->ssid_len : 0,
3515d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			   wpa_s->p2p_pd_before_go_neg, pref_freq);
35168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
35178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpas_p2p_auth_go_neg(struct wpa_supplicant *wpa_s,
35208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				const u8 *peer_addr,
35218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				enum p2p_wps_method wps_method,
35228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				int go_intent, const u8 *own_interface_addr,
352304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				unsigned int force_freq, int persistent_group,
3524d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				struct wpa_ssid *ssid, unsigned int pref_freq)
35258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
35261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (persistent_group && wpa_s->conf->persistent_reconnect)
35271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		persistent_group = 2;
35281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
35298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
35308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
35318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_authorize(wpa_s->global->p2p, peer_addr, wps_method,
35338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     go_intent, own_interface_addr, force_freq,
353404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			     persistent_group, ssid ? ssid->ssid : NULL,
3535d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			     ssid ? ssid->ssid_len : 0, pref_freq);
35368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
35378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_p2p_check_join_scan_limit(struct wpa_supplicant *wpa_s)
35408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
35418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->p2p_join_scan_count++;
35428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Join scan attempt %d",
35438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   wpa_s->p2p_join_scan_count);
35448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->p2p_join_scan_count > P2P_MAX_JOIN_SCAN_ATTEMPTS) {
35458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Failed to find GO " MACSTR
35468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " for join operationg - stop join attempt",
35478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   MAC2STR(wpa_s->pending_join_iface_addr));
35488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
354904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (wpa_s->p2p_auto_pd) {
355004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpa_s->p2p_auto_pd = 0;
3551b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			wpa_msg_global(wpa_s, MSG_INFO,
3552b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       P2P_EVENT_PROV_DISC_FAILURE
3553b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       " p2p_dev_addr=" MACSTR " status=N/A",
3554b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       MAC2STR(wpa_s->pending_join_dev_addr));
355504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			return;
355604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
3557b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		wpa_msg_global(wpa_s->parent, MSG_INFO,
3558b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       P2P_EVENT_GROUP_FORMATION_FAILURE);
35598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
35608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
35618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
356304949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int wpas_check_freq_conflict(struct wpa_supplicant *wpa_s, int freq)
356404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
3565c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	int *freqs, res, num, i;
356604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
3567c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	if (wpas_p2p_num_unused_channels(wpa_s) > 0) {
3568c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		/* Multiple channels are supported and not all are in use */
356904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 0;
3570c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	}
357104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
3572c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	freqs = os_calloc(wpa_s->num_multichan_concurrent, sizeof(int));
3573c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	if (!freqs)
3574c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		return 1;
357504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
3576c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	num = wpas_p2p_valid_oper_freqs(wpa_s, freqs,
3577c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt					wpa_s->num_multichan_concurrent);
3578c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	if (num < 0) {
3579c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		res = 1;
3580c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		goto exit_free;
358104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
358204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
3583c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	for (i = 0; i < num; i++) {
3584c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		if (freqs[i] == freq) {
3585c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Frequency %d MHz in use by another virtual interface and can be used",
3586c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				   freq);
3587c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			res = 0;
3588c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			goto exit_free;
3589c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		}
359004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
359104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
3592c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	res = 1;
3593c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
3594c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidtexit_free:
3595c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	os_free(freqs);
3596c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	return res;
359704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
359804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
359904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
360004949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int wpas_p2p_peer_go(struct wpa_supplicant *wpa_s,
360104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			    const u8 *peer_dev_addr)
360204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
360304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct wpa_bss *bss;
360404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	int updated;
360504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
360604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	bss = wpa_bss_get_p2p_dev_addr(wpa_s, peer_dev_addr);
360704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (bss == NULL)
360804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return -1;
360904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (bss->last_update_idx < wpa_s->bss_update_idx) {
361004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Peer BSS entry not updated in the "
361104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   "last scan");
361204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 0;
361304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
361404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
361504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	updated = os_time_before(&wpa_s->p2p_auto_started, &bss->last_update);
361604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Current BSS entry for peer updated at "
361704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   "%ld.%06ld (%supdated in last scan)",
361804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   bss->last_update.sec, bss->last_update.usec,
361904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   updated ? "": "not ");
362004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
362104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return updated;
362204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
362304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
362404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
36258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
36268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   struct wpa_scan_results *scan_res)
36278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
36288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_bss *bss;
36298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
36308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 iface_addr[ETH_ALEN];
363104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
36328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
36338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_disabled)
36358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
36368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
363704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Scan results received (%d BSS) for %sjoin",
363804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   scan_res ? (int) scan_res->num : -1,
363904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   wpa_s->p2p_auto_join ? "auto_" : "");
36408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (scan_res)
36428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_p2p_scan_res_handler(wpa_s, scan_res);
36438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
364404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (wpa_s->p2p_auto_pd) {
364504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		int join = wpas_p2p_peer_go(wpa_s,
364604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					    wpa_s->pending_join_dev_addr);
364704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (join == 0 &&
364804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		    wpa_s->auto_pd_scan_retry < P2P_AUTO_PD_SCAN_ATTEMPTS) {
364904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpa_s->auto_pd_scan_retry++;
3650444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt			bss = wpa_bss_get_bssid_latest(
3651444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt				wpa_s, wpa_s->pending_join_dev_addr);
365204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			if (bss) {
365304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				freq = bss->freq;
365404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				wpa_printf(MSG_DEBUG, "P2P: Scan retry %d for "
365504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					   "the peer " MACSTR " at %d MHz",
365604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					   wpa_s->auto_pd_scan_retry,
365704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					   MAC2STR(wpa_s->
365804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt						   pending_join_dev_addr),
365904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					   freq);
366004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				wpas_p2p_join_scan_req(wpa_s, freq);
366104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				return;
366204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			}
366304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
366404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
366504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (join < 0)
366604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			join = 0;
366704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
366804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_s->p2p_auto_pd = 0;
366904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_s->pending_pd_use = join ? AUTO_PD_JOIN : AUTO_PD_GO_NEG;
367004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Auto PD with " MACSTR " join=%d",
367104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   MAC2STR(wpa_s->pending_join_dev_addr), join);
367204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (p2p_prov_disc_req(wpa_s->global->p2p,
367304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				      wpa_s->pending_join_dev_addr,
367404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				      wpa_s->pending_pd_config_methods, join,
3675d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				      0, wpa_s->user_initiated_pd) < 0) {
367604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpa_s->p2p_auto_pd = 0;
3677b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			wpa_msg_global(wpa_s, MSG_INFO,
3678b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       P2P_EVENT_PROV_DISC_FAILURE
3679b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       " p2p_dev_addr=" MACSTR " status=N/A",
3680b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       MAC2STR(wpa_s->pending_join_dev_addr));
368104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
368204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return;
368304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
368404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
368504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (wpa_s->p2p_auto_join) {
368604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		int join = wpas_p2p_peer_go(wpa_s,
368704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					    wpa_s->pending_join_dev_addr);
368804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (join < 0) {
368904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Peer was not found to be "
369004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				   "running a GO -> use GO Negotiation");
369104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpas_p2p_connect(wpa_s, wpa_s->pending_join_dev_addr,
369204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 wpa_s->p2p_pin, wpa_s->p2p_wps_method,
369304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 wpa_s->p2p_persistent_group, 0, 0, 0,
369404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 wpa_s->p2p_go_intent,
369504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 wpa_s->p2p_connect_freq,
369604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 wpa_s->p2p_persistent_id,
369761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					 wpa_s->p2p_pd_before_go_neg,
369861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					 wpa_s->p2p_go_ht40);
369904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			return;
370004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
370104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
370204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Peer was found running GO%s -> "
370304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   "try to join the group", join ? "" :
370404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   " in older scan");
370504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (!join)
370604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpa_s->p2p_fallback_to_go_neg = 1;
370704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
370804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
37098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	freq = p2p_get_oper_freq(wpa_s->global->p2p,
37108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 wpa_s->pending_join_iface_addr);
37118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq < 0 &&
37128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    p2p_get_interface_addr(wpa_s->global->p2p,
37138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   wpa_s->pending_join_dev_addr,
37148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   iface_addr) == 0 &&
37158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(iface_addr, wpa_s->pending_join_dev_addr, ETH_ALEN) != 0)
37168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
37178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Overwrite pending interface "
37188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "address for join from " MACSTR " to " MACSTR
37198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " based on newly discovered P2P peer entry",
37208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   MAC2STR(wpa_s->pending_join_iface_addr),
37218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   MAC2STR(iface_addr));
37228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(wpa_s->pending_join_iface_addr, iface_addr,
37238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  ETH_ALEN);
37248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		freq = p2p_get_oper_freq(wpa_s->global->p2p,
37268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 wpa_s->pending_join_iface_addr);
37278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq >= 0) {
37298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Target GO operating frequency "
37308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "from P2P peer table: %d MHz", freq);
37318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3732444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt	bss = wpa_bss_get_bssid_latest(wpa_s, wpa_s->pending_join_iface_addr);
37338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bss) {
37348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		freq = bss->freq;
37358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Target GO operating frequency "
37368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "from BSS table: %d MHz", freq);
37378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq > 0) {
37398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u16 method;
37408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
374104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (wpas_check_freq_conflict(wpa_s, freq) > 0) {
3742b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			wpa_msg_global(wpa_s->parent, MSG_INFO,
3743b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       P2P_EVENT_GROUP_FORMATION_FAILURE
3744b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       "reason=FREQ_CONFLICT");
374504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			return;
374604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
374704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
37488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Send Provision Discovery Request "
37498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "prior to joining an existing group (GO " MACSTR
37508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " freq=%u MHz)",
37518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   MAC2STR(wpa_s->pending_join_dev_addr), freq);
37528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->pending_pd_before_join = 1;
37538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (wpa_s->pending_join_wps_method) {
37558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case WPS_PIN_DISPLAY:
37568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			method = WPS_CONFIG_KEYPAD;
37578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
37588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case WPS_PIN_KEYPAD:
37598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			method = WPS_CONFIG_DISPLAY;
37608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
37618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case WPS_PBC:
37628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			method = WPS_CONFIG_PUSHBUTTON;
37638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
37648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
37658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			method = 0;
37668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
37678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
37688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if ((p2p_get_provisioning_info(wpa_s->global->p2p,
37701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					       wpa_s->pending_join_dev_addr) ==
37711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		     method)) {
37721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			/*
37731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			 * We have already performed provision discovery for
37741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			 * joining the group. Proceed directly to join
37751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			 * operation without duplicated provision discovery. */
37761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Provision discovery "
37771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   "with " MACSTR " already done - proceed to "
37781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   "join",
37791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   MAC2STR(wpa_s->pending_join_dev_addr));
37801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_s->pending_pd_before_join = 0;
37811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			goto start;
37821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
37831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
37848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p_prov_disc_req(wpa_s->global->p2p,
37851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      wpa_s->pending_join_dev_addr, method, 1,
3786d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				      freq, wpa_s->user_initiated_pd) < 0) {
37878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Failed to send Provision "
37888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Discovery Request before joining an "
37898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "existing group");
37908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_s->pending_pd_before_join = 0;
37918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto start;
37928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
37938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
37948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
37958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
37968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Failed to find BSS/GO - try again later");
37978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
37988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(1, 0, wpas_p2p_join_scan, wpa_s, NULL);
37998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_p2p_check_join_scan_limit(wpa_s);
38008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return;
38018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstart:
38038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Start join operation immediately */
38048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_p2p_join_start(wpa_s);
38058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
38068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
380804949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq)
38098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
38108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
38118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_scan_params params;
38128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *wps_ie, *ies;
38131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	size_t ielen;
381404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	int freqs[2] = { 0, 0 };
3815ad266fb3da6083126e7619e525153839b918aa44Dmitry Shmidt#ifdef ANDROID_P2P
3816ad266fb3da6083126e7619e525153839b918aa44Dmitry Shmidt	int oper_freq;
38178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3818ad266fb3da6083126e7619e525153839b918aa44Dmitry Shmidt	/* If freq is not provided, check the operating freq of the GO and do a
3819ad266fb3da6083126e7619e525153839b918aa44Dmitry Shmidt	 * a directed scan to save time
3820ad266fb3da6083126e7619e525153839b918aa44Dmitry Shmidt	 */
3821ad266fb3da6083126e7619e525153839b918aa44Dmitry Shmidt	if(!freq) {
3822ad266fb3da6083126e7619e525153839b918aa44Dmitry Shmidt		freq = (oper_freq = p2p_get_oper_freq(wpa_s->global->p2p,
3823ad266fb3da6083126e7619e525153839b918aa44Dmitry Shmidt			 wpa_s->pending_join_iface_addr) == -1) ? 0 : oper_freq;
3824ad266fb3da6083126e7619e525153839b918aa44Dmitry Shmidt	}
3825ad266fb3da6083126e7619e525153839b918aa44Dmitry Shmidt#endif
38268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&params, 0, sizeof(params));
38278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P Wildcard SSID */
38298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.num_ssids = 1;
38308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.ssids[0].ssid = (u8 *) P2P_WILDCARD_SSID;
38318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
38328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->wps->dev.p2p = 1;
383404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wps_ie = wps_build_probe_req_ie(DEV_PW_DEFAULT, &wpa_s->wps->dev,
383504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					wpa_s->wps->uuid, WPS_REQ_ENROLLEE, 0,
383604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					NULL);
38378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wps_ie == NULL) {
38388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_p2p_scan_res_join(wpa_s, NULL);
38398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
38408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
38431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen);
38448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ies == NULL) {
38458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(wps_ie);
38468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_p2p_scan_res_join(wpa_s, NULL);
38478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
38488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_buf(ies, wps_ie);
38508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(wps_ie);
38518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3852c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	p2p_scan_ie(wpa_s->global->p2p, ies, NULL);
38538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	params.p2p_probe = 1;
38558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.extra_ies = wpabuf_head(ies);
38568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.extra_ies_len = wpabuf_len(ies);
385704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (freq > 0) {
385804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		freqs[0] = freq;
385904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		params.freqs = freqs;
386004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
38618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
38638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Run a scan to update BSS table and start Provision Discovery once
38648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * the new scan results become available.
38658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
38661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ret = wpa_drv_scan(wpa_s, &params);
3867444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt	if (!ret) {
3868444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt		os_get_time(&wpa_s->scan_trigger_time);
386904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_s->scan_res_handler = wpas_p2p_scan_res_join;
3870444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt	}
38718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(ies);
38738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret) {
38758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Failed to start scan for join - "
38768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "try again later");
38778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
38788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(1, 0, wpas_p2p_join_scan, wpa_s, NULL);
38798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_p2p_check_join_scan_limit(wpa_s);
38808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
38818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
38828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
38838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
388404949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx)
388504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
388604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct wpa_supplicant *wpa_s = eloop_ctx;
388704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpas_p2p_join_scan_req(wpa_s, 0);
388804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
388904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
389004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
38918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr,
389204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 const u8 *dev_addr, enum p2p_wps_method wps_method,
389304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 int auto_join)
38948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
38958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Request to join existing group (iface "
389604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   MACSTR " dev " MACSTR ")%s",
389704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   MAC2STR(iface_addr), MAC2STR(dev_addr),
389804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   auto_join ? " (auto_join)" : "");
38998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
390004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_s->p2p_auto_pd = 0;
390104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_s->p2p_auto_join = !!auto_join;
39028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(wpa_s->pending_join_iface_addr, iface_addr, ETH_ALEN);
39038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(wpa_s->pending_join_dev_addr, dev_addr, ETH_ALEN);
39048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->pending_join_wps_method = wps_method;
39058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Make sure we are not running find during connection establishment */
39078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_p2p_stop_find(wpa_s);
39088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->p2p_join_scan_count = 0;
39108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_p2p_join_scan(wpa_s, NULL);
39118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
39128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpas_p2p_join_start(struct wpa_supplicant *wpa_s)
39168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
39178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *group;
39188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_go_neg_results res;
391904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct wpa_bss *bss;
39208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group = wpas_p2p_get_group_iface(wpa_s, 0, 0);
39228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group == NULL)
39238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
39248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group != wpa_s) {
39258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(group->p2p_pin, wpa_s->p2p_pin,
39268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(group->p2p_pin));
39278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group->p2p_wps_method = wpa_s->p2p_wps_method;
39284b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt	} else {
39294b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt		/*
39304b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt		 * Need to mark the current interface for p2p_group_formation
39314b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt		 * when a separate group interface is not used. This is needed
39324b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt		 * to allow p2p_cancel stop a pending p2p_connect-join.
39334b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt		 * wpas_p2p_init_group_interface() addresses this for the case
39344b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt		 * where a separate group interface is used.
39354b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt		 */
39364b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt		wpa_s->global->p2p_group_formation = wpa_s;
39378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
39388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->p2p_in_provisioning = 1;
394004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	group->p2p_fallback_to_go_neg = wpa_s->p2p_fallback_to_go_neg;
39418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&res, 0, sizeof(res));
39438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(res.peer_interface_addr, wpa_s->pending_join_iface_addr,
39448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  ETH_ALEN);
39458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res.wps_method = wpa_s->pending_join_wps_method;
3946444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt	bss = wpa_bss_get_bssid_latest(wpa_s, wpa_s->pending_join_iface_addr);
394704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (bss) {
394804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		res.freq = bss->freq;
394904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		res.ssid_len = bss->ssid_len;
395004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(res.ssid, bss->ssid, bss->ssid_len);
395104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
395204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
3953c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (wpa_s->off_channel_freq || wpa_s->roc_waiting_drv_freq) {
3954c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Cancel remain-on-channel prior to "
3955c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			   "starting client");
3956c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpa_drv_cancel_remain_on_channel(wpa_s);
3957c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpa_s->off_channel_freq = 0;
3958c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpa_s->roc_waiting_drv_freq = 0;
3959c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
39608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_start_wps_enrollee(group, &res);
39618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
39638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Allow a longer timeout for join-a-running-group than normal 15
39648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * second group formation timeout since the GO may not have authorized
39658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * our connection yet.
39668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
39678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s, NULL);
39688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(60, 0, wpas_p2p_group_formation_timeout,
39698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       wpa_s, NULL);
39708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
39728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
39738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39757a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidtstatic int wpas_p2p_setup_freqs(struct wpa_supplicant *wpa_s, int freq,
3976c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				int *force_freq, int *pref_freq)
39777a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt{
3978c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	int *freqs, res;
3979c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	unsigned int freq_in_use = 0, num, i;
3980c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
3981c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	freqs = os_calloc(wpa_s->num_multichan_concurrent, sizeof(int));
3982c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	if (!freqs)
3983c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		return -1;
3984c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
3985c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	num = get_shared_radio_freqs(wpa_s, freqs,
3986c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				     wpa_s->num_multichan_concurrent);
3987b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	wpa_printf(MSG_DEBUG,
3988b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		   "P2P: Setup freqs: freq=%d num_MCC=%d shared_freqs=%u",
3989b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		   freq, wpa_s->num_multichan_concurrent, num);
3990c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
39917a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt	if (freq > 0) {
39927a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		if (!p2p_supported_freq(wpa_s->global->p2p, freq)) {
39937a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: The forced channel "
39947a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt				   "(%u MHz) is not supported for P2P uses",
39957a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt				   freq);
3996c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			res = -3;
3997c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			goto exit_free;
39987a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		}
39997a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt
4000c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		for (i = 0; i < num; i++) {
4001c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			if (freqs[i] == freq)
4002c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				freq_in_use = 1;
4003c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		}
4004c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
4005c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		if (num == wpa_s->num_multichan_concurrent && !freq_in_use) {
4006c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Cannot start P2P group on %u MHz as there are no available channels",
4007c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				   freq);
4008c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			res = -2;
4009c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			goto exit_free;
40107a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		}
40117a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Trying to force us to use the "
40127a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt			   "requested channel (%u MHz)", freq);
40137a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		*force_freq = freq;
4014c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		goto exit_ok;
4015c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	}
4016c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
4017c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	for (i = 0; i < num; i++) {
4018c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		if (!p2p_supported_freq(wpa_s->global->p2p, freqs[i]))
4019c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			continue;
4020c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
402151a47d533b6bf0efff06cc80195a588852a45058Dmitry Shmidt#ifndef ANDROID_P2P
4022c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Try to force us to use frequency (%u MHz) which is already in use",
4023c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			   *force_freq);
4024c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		*force_freq = freqs[i];
402551a47d533b6bf0efff06cc80195a588852a45058Dmitry Shmidt#endif
4026c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
4027c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		if (*pref_freq == 0 && num < wpa_s->num_multichan_concurrent) {
4028c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Try to prefer a frequency we are already using");
402951a47d533b6bf0efff06cc80195a588852a45058Dmitry Shmidt			*pref_freq = freqs[i];
403051a47d533b6bf0efff06cc80195a588852a45058Dmitry Shmidt#ifdef ANDROID_P2P
403151a47d533b6bf0efff06cc80195a588852a45058Dmitry Shmidt		} else {
403251a47d533b6bf0efff06cc80195a588852a45058Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Try to force us to use frequency (%u MHz) which is already in use",
403351a47d533b6bf0efff06cc80195a588852a45058Dmitry Shmidt				   *force_freq);
403451a47d533b6bf0efff06cc80195a588852a45058Dmitry Shmidt			*force_freq = freqs[i];
403551a47d533b6bf0efff06cc80195a588852a45058Dmitry Shmidt#endif
40367a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		}
4037c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		break;
40387a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt	}
40397a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt
4040c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	if (i == num) {
4041c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		if (num < wpa_s->num_multichan_concurrent) {
4042c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Current operating channels are not available for P2P. Try to use another channel");
4043c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			*force_freq = 0;
4044c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		} else {
4045c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: All channels are in use and none of them are P2P enabled. Cannot start P2P group");
4046c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			res = -2;
4047c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			goto exit_free;
4048c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		}
4049c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	}
4050c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
4051c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidtexit_ok:
4052c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	res = 0;
4053c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidtexit_free:
4054c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	os_free(freqs);
4055c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	return res;
40567a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt}
40577a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt
40587a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt
40598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
40608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpas_p2p_connect - Request P2P Group Formation to be started
40618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface()
40628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peer_addr: Address of the peer P2P Device
40638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pin: PIN to use during provisioning or %NULL to indicate PBC mode
40648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @persistent_group: Whether to create a persistent group
406504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * @auto_join: Whether to select join vs. GO Negotiation automatically
40668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @join: Whether to join an existing group (as a client) instead of starting
40678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *	Group Owner negotiation; @peer_addr is BSSID in that case
40688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @auth: Whether to only authorize the connection instead of doing that and
40698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *	initiating Group Owner negotiation
40708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @go_intent: GO Intent or -1 to use default
40718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @freq: Frequency for the group or 0 for auto-selection
407204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * @persistent_id: Persistent group credentials to use for forcing GO
407304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt *	parameters or -1 to generate new values (SSID/passphrase)
407404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * @pd: Whether to send Provision Discovery prior to GO Negotiation as an
407504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt *	interoperability workaround when initiating group formation
407661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * @ht40: Start GO with 40 MHz channel width
40778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 or new PIN (if pin was %NULL) on success, -1 on unspecified
40788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *	failure, -2 on failure due to channel not currently available,
40798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *	-3 if forced channel is not supported
40808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
40818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
40828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     const char *pin, enum p2p_wps_method wps_method,
408304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		     int persistent_group, int auto_join, int join, int auth,
408461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		     int go_intent, int freq, int persistent_id, int pd,
408561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		     int ht40)
40868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4087c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	int force_freq = 0, pref_freq = 0;
40887a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt	int ret = 0, res;
40898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum wpa_driver_if_type iftype;
40901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	const u8 *if_addr;
409104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct wpa_ssid *ssid = NULL;
40928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
40948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
40958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
409604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (persistent_id >= 0) {
409704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
409804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (ssid == NULL || ssid->disabled != 2 ||
409904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		    ssid->mode != WPAS_MODE_P2P_GO)
410004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			return -1;
410104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
410204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
4103391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	os_free(wpa_s->global->add_psk);
4104391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	wpa_s->global->add_psk = NULL;
4105391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
41068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (go_intent < 0)
41078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		go_intent = wpa_s->conf->p2p_go_intent;
41088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!auth)
41108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->p2p_long_listen = 0;
41118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->p2p_wps_method = wps_method;
411304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_s->p2p_persistent_group = !!persistent_group;
411404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_s->p2p_persistent_id = persistent_id;
411504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_s->p2p_go_intent = go_intent;
411604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_s->p2p_connect_freq = freq;
411704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_s->p2p_fallback_to_go_neg = 0;
411804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_s->p2p_pd_before_go_neg = !!pd;
411961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpa_s->p2p_go_ht40 = !!ht40;
41208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pin)
41228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_strlcpy(wpa_s->p2p_pin, pin, sizeof(wpa_s->p2p_pin));
41238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (wps_method == WPS_PIN_DISPLAY) {
41248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = wps_generate_pin();
41258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(wpa_s->p2p_pin, sizeof(wpa_s->p2p_pin), "%08d",
41268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    ret);
41278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Randomly generated PIN: %s",
41288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   wpa_s->p2p_pin);
41298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
41308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->p2p_pin[0] = '\0';
41318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
413204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (join || auto_join) {
41338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 iface_addr[ETH_ALEN], dev_addr[ETH_ALEN];
41348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (auth) {
41358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Authorize invitation to "
41368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "connect a running group from " MACSTR,
41378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   MAC2STR(peer_addr));
41388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(wpa_s->p2p_auth_invite, peer_addr, ETH_ALEN);
41398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return ret;
41408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
41418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dev_addr, peer_addr, ETH_ALEN);
41428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p_get_interface_addr(wpa_s->global->p2p, peer_addr,
41438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   iface_addr) < 0) {
41448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(iface_addr, peer_addr, ETH_ALEN);
41458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_get_dev_addr(wpa_s->global->p2p, peer_addr,
41468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 dev_addr);
41478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
414804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (auto_join) {
414904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			os_get_time(&wpa_s->p2p_auto_started);
415004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Auto join started at "
415104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				   "%ld.%06ld",
415204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				   wpa_s->p2p_auto_started.sec,
415304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				   wpa_s->p2p_auto_started.usec);
415404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
4155d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wpa_s->user_initiated_pd = 1;
415604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (wpas_p2p_join(wpa_s, iface_addr, dev_addr, wps_method,
415704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  auto_join) < 0)
41588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
41598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return ret;
41608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
41618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4162c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	res = wpas_p2p_setup_freqs(wpa_s, freq, &force_freq, &pref_freq);
41637a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt	if (res)
41647a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		return res;
4165c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	wpas_p2p_set_own_freq_preference(wpa_s, force_freq);
41668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->create_p2p_iface = wpas_p2p_create_iface(wpa_s);
41688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_s->create_p2p_iface) {
41701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Prepare to add a new interface for the group */
41711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		iftype = WPA_IF_P2P_GROUP;
41721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (go_intent == 15)
41731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			iftype = WPA_IF_P2P_GO;
41741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (wpas_p2p_add_group_interface(wpa_s, iftype) < 0) {
41751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_printf(MSG_ERROR, "P2P: Failed to allocate a new "
41761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   "interface for the group");
41778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
41781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
41798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if_addr = wpa_s->pending_interface_addr;
41811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	} else
41821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if_addr = wpa_s->own_addr;
41838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (auth) {
41858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpas_p2p_auth_go_neg(wpa_s, peer_addr, wps_method,
41861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					 go_intent, if_addr,
4187d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt					 force_freq, persistent_group, ssid,
4188d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt					 pref_freq) < 0)
41898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
41908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return ret;
41918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
41921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
41931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpas_p2p_start_go_neg(wpa_s, peer_addr, wps_method,
41941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				  go_intent, if_addr, force_freq,
4195d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				  persistent_group, ssid, pref_freq) < 0) {
41961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (wpa_s->create_p2p_iface)
41971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpas_p2p_remove_pending_group_interface(wpa_s);
41988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
41998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
42008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
42018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
42028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
42058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpas_p2p_remain_on_channel_cb - Indication of remain-on-channel start
42068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface()
42078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @freq: Frequency of the channel in MHz
42088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @duration: Duration of the stay on the channel in milliseconds
42098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
42108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This callback is called when the driver indicates that it has started the
42118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * requested remain-on-channel duration.
42128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
42138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_p2p_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
42148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   unsigned int freq, unsigned int duration)
42158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
42168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
42178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
42188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->off_channel_freq == wpa_s->pending_listen_freq) {
42198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_listen_cb(wpa_s->global->p2p, wpa_s->pending_listen_freq,
42208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      wpa_s->pending_listen_duration);
42218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->pending_listen_freq = 0;
42228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
42238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
42248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpas_p2p_listen_start(struct wpa_supplicant *wpa_s,
42278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 unsigned int timeout)
42288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
42298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Limit maximum Listen state time based on driver limitation. */
42308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (timeout > wpa_s->max_remain_on_chan)
42318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		timeout = wpa_s->max_remain_on_chan;
42328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
42348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wpa_drv_p2p_listen(wpa_s, timeout);
42358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_listen(wpa_s->global->p2p, timeout);
42378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
42388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
42418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpas_p2p_cancel_remain_on_channel_cb - Remain-on-channel timeout
42428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface()
42438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @freq: Frequency of the channel in MHz
42448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
42458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This callback is called when the driver indicates that a remain-on-channel
42468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * operation has been completed, i.e., the duration on the requested channel
42478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * has timed out.
42488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
42498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_p2p_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
42508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  unsigned int freq)
42518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
42528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Cancel remain-on-channel callback "
42538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "(p2p_long_listen=%d ms pending_action_tx=%p)",
4254a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		   wpa_s->p2p_long_listen, offchannel_pending_action_tx(wpa_s));
42558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
42568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
42578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_listen_end(wpa_s->global->p2p, freq) > 0)
42588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* P2P module started a new operation */
4259a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (offchannel_pending_action_tx(wpa_s))
42608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
42618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->p2p_long_listen > 0)
42628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->p2p_long_listen -= wpa_s->max_remain_on_chan;
42638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->p2p_long_listen > 0) {
42648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Continuing long Listen state");
42658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_p2p_listen_start(wpa_s, wpa_s->p2p_long_listen);
4266391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	} else {
4267391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		/*
4268391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		 * When listen duration is over, stop listen & update p2p_state
4269391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		 * to IDLE.
4270391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		 */
4271391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		p2p_stop_listen(wpa_s->global->p2p);
42728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
42738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
42748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
42778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpas_p2p_group_remove - Remove a P2P group
42788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface()
42798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ifname: Network interface name of the group interface or "*" to remove all
42808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *	groups
42818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
42828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
42838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to remove a P2P group. This can be used to disconnect
42848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * from a group in which the local end is a P2P Client or to end a P2P Group in
42858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * case the local end is the Group Owner. If a virtual network interface was
42868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * created for this group, that interface will be removed. Otherwise, only the
42878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * configured P2P group network will be removed from the interface.
42888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
42898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname)
42908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
42918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_global *global = wpa_s->global;
42928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
42938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strcmp(ifname, "*") == 0) {
42948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct wpa_supplicant *prev;
42958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s = global->ifaces;
42968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (wpa_s) {
42978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			prev = wpa_s;
42988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_s = wpa_s->next;
4299b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt			if (prev->p2p_group_interface !=
4300b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt			    NOT_P2P_GROUP_INTERFACE ||
4301b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt			    (prev->current_ssid &&
4302b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt			     prev->current_ssid->p2p_group))
4303b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt				wpas_p2p_disconnect(prev);
43048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
43058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
43068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
43078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
43098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strcmp(wpa_s->ifname, ifname) == 0)
43108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
43118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
43128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpas_p2p_disconnect(wpa_s);
43148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
43158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43178bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidtstatic int wpas_p2p_select_go_freq(struct wpa_supplicant *wpa_s, int freq)
43188bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt{
43198bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt	unsigned int r;
43208bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt
43218bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt	if (freq == 2) {
43228bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Request to start GO on 2.4 GHz "
43238bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt			   "band");
43248bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt		if (wpa_s->best_24_freq > 0 &&
43258bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt		    p2p_supported_freq(wpa_s->global->p2p,
43268bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt				       wpa_s->best_24_freq)) {
43278bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt			freq = wpa_s->best_24_freq;
43288bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Use best 2.4 GHz band "
43298bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt				   "channel: %d MHz", freq);
43308bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt		} else {
43318bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt			os_get_random((u8 *) &r, sizeof(r));
43328bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt			freq = 2412 + (r % 3) * 25;
43338bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Use random 2.4 GHz band "
43348bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt				   "channel: %d MHz", freq);
43358bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt		}
43368bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt	}
43378bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt
43388bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt	if (freq == 5) {
43398bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Request to start GO on 5 GHz "
43408bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt			   "band");
43418bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt		if (wpa_s->best_5_freq > 0 &&
43428bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt		    p2p_supported_freq(wpa_s->global->p2p,
43438bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt				       wpa_s->best_5_freq)) {
43448bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt			freq = wpa_s->best_5_freq;
43458bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Use best 5 GHz band "
43468bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt				   "channel: %d MHz", freq);
43478bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt		} else {
43488bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt			os_get_random((u8 *) &r, sizeof(r));
43498bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt			freq = 5180 + (r % 4) * 20;
43508bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt			if (!p2p_supported_freq(wpa_s->global->p2p, freq)) {
43518bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt				wpa_printf(MSG_DEBUG, "P2P: Could not select "
43528bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt					   "5 GHz channel for P2P group");
43538bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt				return -1;
43548bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt			}
43558bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Use random 5 GHz band "
43568bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt				   "channel: %d MHz", freq);
43578bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt		}
43588bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt	}
43598bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt
43608bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt	if (freq > 0 && !p2p_supported_freq(wpa_s->global->p2p, freq)) {
43618bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: The forced channel for GO "
43628bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt			   "(%u MHz) is not supported for P2P uses",
43638bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt			   freq);
43648bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt		return -1;
43658bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt	}
43668bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt
43678bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt	return freq;
43688bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt}
43698bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt
43708bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt
43711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
43721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   struct p2p_go_neg_results *params,
43737a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt				   int freq, int ht40,
43747a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt				   const struct p2p_channels *channels)
43758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4376c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	int res, *freqs;
437744c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidt	unsigned int pref_freq;
4378c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	unsigned int num, i;
43798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
43808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(params, 0, sizeof(*params));
43818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params->role_go = 1;
438261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	params->ht40 = ht40;
43838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq) {
43847a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		if (!freq_included(channels, freq)) {
43857a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Forced GO freq %d MHz not "
43867a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt				   "accepted", freq);
43877a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt			return -1;
43887a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		}
43898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on forced "
43908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "frequency %d MHz", freq);
43918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		params->freq = freq;
43928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (wpa_s->conf->p2p_oper_reg_class == 81 &&
43938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   wpa_s->conf->p2p_oper_channel >= 1 &&
43947a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		   wpa_s->conf->p2p_oper_channel <= 11 &&
43957a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		   freq_included(channels,
43967a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt				 2407 + 5 * wpa_s->conf->p2p_oper_channel)) {
43978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		params->freq = 2407 + 5 * wpa_s->conf->p2p_oper_channel;
43988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on configured "
43998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "frequency %d MHz", params->freq);
44007a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt	} else if ((wpa_s->conf->p2p_oper_reg_class == 115 ||
44017a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		    wpa_s->conf->p2p_oper_reg_class == 116 ||
44027a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		    wpa_s->conf->p2p_oper_reg_class == 117 ||
44037a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		    wpa_s->conf->p2p_oper_reg_class == 124 ||
44047a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		    wpa_s->conf->p2p_oper_reg_class == 126 ||
44057a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		    wpa_s->conf->p2p_oper_reg_class == 127) &&
44067a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		   freq_included(channels,
44077a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt				 5000 + 5 * wpa_s->conf->p2p_oper_channel)) {
44088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		params->freq = 5000 + 5 * wpa_s->conf->p2p_oper_channel;
44098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on configured "
44108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "frequency %d MHz", params->freq);
44118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (wpa_s->conf->p2p_oper_channel == 0 &&
44128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   wpa_s->best_overall_freq > 0 &&
44138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   p2p_supported_freq(wpa_s->global->p2p,
44147a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt				      wpa_s->best_overall_freq) &&
44157a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		   freq_included(channels, wpa_s->best_overall_freq)) {
44168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		params->freq = wpa_s->best_overall_freq;
44178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best overall "
44188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "channel %d MHz", params->freq);
44198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (wpa_s->conf->p2p_oper_channel == 0 &&
44208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   wpa_s->best_24_freq > 0 &&
44218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   p2p_supported_freq(wpa_s->global->p2p,
44227a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt				      wpa_s->best_24_freq) &&
44237a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		   freq_included(channels, wpa_s->best_24_freq)) {
44248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		params->freq = wpa_s->best_24_freq;
44258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best 2.4 GHz "
44268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "channel %d MHz", params->freq);
44278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (wpa_s->conf->p2p_oper_channel == 0 &&
44288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   wpa_s->best_5_freq > 0 &&
44298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   p2p_supported_freq(wpa_s->global->p2p,
44307a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt				      wpa_s->best_5_freq) &&
44317a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		   freq_included(channels, wpa_s->best_5_freq)) {
44328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		params->freq = wpa_s->best_5_freq;
44338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best 5 GHz "
44348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "channel %d MHz", params->freq);
443544c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidt	} else if ((pref_freq = p2p_get_pref_freq(wpa_s->global->p2p,
443644c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidt						  channels))) {
443744c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidt		params->freq = pref_freq;
443844c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Set GO freq %d MHz from preferred "
443944c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidt			   "channels", params->freq);
44408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
444104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		int chan;
444204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		for (chan = 0; chan < 11; chan++) {
444304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			params->freq = 2412 + chan * 5;
444404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			if (!wpas_p2p_disallowed_freq(wpa_s->global,
44457a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt						      params->freq) &&
44467a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt			    freq_included(channels, params->freq))
444704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				break;
444804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
444904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (chan == 11) {
445004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: No 2.4 GHz channel "
445104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				   "allowed");
445204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			return -1;
445304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
44548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Set GO freq %d MHz (no preference "
44558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "known)", params->freq);
44568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
44578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4458c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	freqs = os_calloc(wpa_s->num_multichan_concurrent, sizeof(int));
4459c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	if (!freqs)
4460c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		return -1;
4461c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
4462c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	res = wpas_p2p_valid_oper_freqs(wpa_s, freqs,
4463c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt					wpa_s->num_multichan_concurrent);
4464c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	if (res < 0) {
4465c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		os_free(freqs);
4466c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		return -1;
4467c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	}
4468c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	num = res;
4469c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
4470c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	if (!freq) {
4471c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		for (i = 0; i < num; i++) {
4472c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			if (freq_included(channels, freqs[i])) {
4473c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				wpa_printf(MSG_DEBUG, "P2P: Force GO on a channel we are already using (%u MHz)",
4474c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt					   freqs[i]);
4475c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				params->freq = freqs[i];
4476c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				break;
4477700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt			}
44787a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		}
44798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4480c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		if (i == num) {
4481c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			if (num == wpa_s->num_multichan_concurrent) {
4482c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				wpa_printf(MSG_DEBUG, "P2P: Cannot force GO on any of the channels we are already using");
4483c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				os_free(freqs);
4484c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				return -1;
4485c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			} else {
4486c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				wpa_printf(MSG_DEBUG, "P2P: Cannot force GO on any of the channels we are already using. Use one of the free channels");
4487c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			}
4488700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt		}
4489c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	} else {
4490c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		for (i = 0; i < num; i++) {
4491c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			if (freqs[i] == freq)
4492c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				break;
44937a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		}
44941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
4495c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		if (i == num) {
4496c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			if (num == wpa_s->num_multichan_concurrent) {
4497c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				wpa_printf(MSG_DEBUG, "P2P: Cannot force GO on freq (%u MHz) as all the channels are in use", freq);
4498c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				os_free(freqs);
4499c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				return -1;
4500c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			} else {
4501c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				wpa_printf(MSG_DEBUG, "P2P: Cannot force GO on any of the channels we are already using. Use one of the free channels");
4502c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			}
4503c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		}
4504c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	}
4505c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	os_free(freqs);
45061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return 0;
45078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
45088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_supplicant *
45118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
45128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 int go)
45138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
45148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *group_wpa_s;
45158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4516aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt	if (!wpas_p2p_create_iface(wpa_s)) {
4517aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use same interface for group "
4518aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt			"operations");
45198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wpa_s;
4520aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt	}
45218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpas_p2p_add_group_interface(wpa_s, go ? WPA_IF_P2P_GO :
4523aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt					 WPA_IF_P2P_CLIENT) < 0) {
4524b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		wpa_msg_global(wpa_s, MSG_ERROR,
4525b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       "P2P: Failed to add group interface");
45268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4527aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt	}
45288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group_wpa_s = wpas_p2p_init_group_interface(wpa_s, go);
45298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group_wpa_s == NULL) {
4530b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		wpa_msg_global(wpa_s, MSG_ERROR,
4531b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       "P2P: Failed to initialize group interface");
45328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_p2p_remove_pending_group_interface(wpa_s);
45338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
45348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
45358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4536aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use separate group interface %s",
4537aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt		group_wpa_s->ifname);
45388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return group_wpa_s;
45398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
45408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
45438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpas_p2p_group_add - Add a new P2P group with local end as Group Owner
45448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface()
45458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @persistent_group: Whether to create a persistent group
45468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @freq: Frequency for the group or 0 to indicate no hardcoding
45478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
45488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
45498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function creates a new P2P group with the local end as the Group Owner,
45508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * i.e., without using Group Owner Negotiation.
45518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
45528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
455361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		       int freq, int ht40)
45548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
45558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_go_neg_results params;
45568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
45588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
45598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4560391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	os_free(wpa_s->global->add_psk);
4561391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	wpa_s->global->add_psk = NULL;
4562391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
4563dca3979ccdf869f140f096b83df322a0efc84f22Dmitry Shmidt	/* Make sure we are not running find during connection establishment */
45641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Stop any on-going P2P FIND");
4565d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	wpas_p2p_stop_find_oper(wpa_s);
4566dca3979ccdf869f140f096b83df322a0efc84f22Dmitry Shmidt
45678bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt	freq = wpas_p2p_select_go_freq(wpa_s, freq);
45688bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt	if (freq < 0)
45698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
45708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45717a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt	if (wpas_p2p_init_go_params(wpa_s, &params, freq, ht40, NULL))
45721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
457304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (params.freq &&
457404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    !p2p_supported_freq(wpa_s->global->p2p, params.freq)) {
457504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: The selected channel for GO "
457604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   "(%u MHz) is not supported for P2P uses",
457704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   params.freq);
457804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return -1;
457904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
45808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_go_params(wpa_s->global->p2p, &params);
45818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.persistent_group = persistent_group;
45828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s = wpas_p2p_get_group_iface(wpa_s, 0, 1);
45848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s == NULL)
45858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
45868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_start_wps_go(wpa_s, &params, 0);
45878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
45898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
45908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpas_start_p2p_client(struct wpa_supplicant *wpa_s,
45938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 struct wpa_ssid *params, int addr_allocated)
45948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
45958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid;
45968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
45978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s = wpas_p2p_get_group_iface(wpa_s, addr_allocated, 0);
45988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s == NULL)
45998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4600391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	wpa_s->p2p_last_4way_hs_fail = NULL;
46018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_ap_deinit(wpa_s);
46038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid = wpa_config_add_network(wpa_s->conf);
46058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid == NULL)
46068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
46078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_set_network_defaults(ssid);
46088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->temporary = 1;
46098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->proto = WPA_PROTO_RSN;
46108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->pairwise_cipher = WPA_CIPHER_CCMP;
46118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->group_cipher = WPA_CIPHER_CCMP;
46128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->key_mgmt = WPA_KEY_MGMT_PSK;
46138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->ssid = os_malloc(params->ssid_len);
46148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->ssid == NULL) {
46158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_config_remove_network(wpa_s->conf, ssid->id);
46168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
46178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
46188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(ssid->ssid, params->ssid, params->ssid_len);
46198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->ssid_len = params->ssid_len;
46208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->p2p_group = 1;
46218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid->export_keys = 1;
46228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (params->psk_set) {
46238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(ssid->psk, params->psk, 32);
46248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid->psk_set = 1;
46258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
46268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (params->passphrase)
46278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid->passphrase = os_strdup(params->passphrase);
46288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_select_network(wpa_s, ssid);
46308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->show_group_started = 1;
46328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
46348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
46358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
46388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  struct wpa_ssid *ssid, int addr_allocated,
46397a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt				  int freq, int ht40,
46407a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt				  const struct p2p_channels *channels)
46418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
46428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_go_neg_results params;
46438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int go = 0;
46448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->disabled != 2 || ssid->ssid == NULL)
46468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
46478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpas_get_p2p_group(wpa_s, ssid->ssid, ssid->ssid_len, &go) &&
46498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    go == (ssid->mode == WPAS_MODE_P2P_GO)) {
46508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Requested persistent group is "
46518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "already running");
46528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
46538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
46548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4655391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	os_free(wpa_s->global->add_psk);
4656391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	wpa_s->global->add_psk = NULL;
4657391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
46588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Make sure we are not running find during connection establishment */
4659d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	wpas_p2p_stop_find_oper(wpa_s);
46608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
466104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_s->p2p_fallback_to_go_neg = 0;
466204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
46638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->mode == WPAS_MODE_INFRA)
46648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wpas_start_p2p_client(wpa_s, ssid, addr_allocated);
46658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->mode != WPAS_MODE_P2P_GO)
46678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
46688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46698bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt	freq = wpas_p2p_select_go_freq(wpa_s, freq);
46708bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt	if (freq < 0)
46718bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt		return -1;
46728bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt
46737a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt	if (wpas_p2p_init_go_params(wpa_s, &params, freq, ht40, channels))
46741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
46758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.role_go = 1;
4677d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	params.psk_set = ssid->psk_set;
4678d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (params.psk_set)
4679d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		os_memcpy(params.psk, ssid->psk, sizeof(params.psk));
4680a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (ssid->passphrase) {
4681a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		if (os_strlen(ssid->passphrase) >= sizeof(params.passphrase)) {
4682a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			wpa_printf(MSG_ERROR, "P2P: Invalid passphrase in "
4683a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt				   "persistent group");
4684a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			return -1;
4685a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		}
4686a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		os_strlcpy(params.passphrase, ssid->passphrase,
4687a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			   sizeof(params.passphrase));
46888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
46898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(params.ssid, ssid->ssid, ssid->ssid_len);
46908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.ssid_len = ssid->ssid_len;
46918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.persistent_group = 1;
46928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s = wpas_p2p_get_group_iface(wpa_s, addr_allocated, 1);
46948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s == NULL)
46958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
46968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_start_wps_go(wpa_s, &params, 0);
46988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
46998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
47008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
47018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_p2p_ie_update(void *ctx, struct wpabuf *beacon_ies,
47048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       struct wpabuf *proberesp_ies)
47058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
47068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
47078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->ap_iface) {
47088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct hostapd_data *hapd = wpa_s->ap_iface->bss[0];
47091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (!(hapd->conf->p2p & P2P_GROUP_OWNER)) {
47101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpabuf_free(beacon_ies);
47111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpabuf_free(proberesp_ies);
47121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return;
47131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
47148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (beacon_ies) {
47158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpabuf_free(hapd->p2p_beacon_ie);
47168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hapd->p2p_beacon_ie = beacon_ies;
47178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
47188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(hapd->p2p_probe_resp_ie);
47198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hapd->p2p_probe_resp_ie = proberesp_ies;
47208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
47218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(beacon_ies);
47228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(proberesp_ies);
47238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
47248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_ap_update_beacon(wpa_s);
47258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
47268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_p2p_idle_update(void *ctx, int idle)
47298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
47308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
47318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!wpa_s->ap_iface)
47328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
47338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: GO - group %sidle", idle ? "" : "not ");
473404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (idle)
47358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_p2p_set_group_idle_timeout(wpa_s);
47368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
47378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL);
47388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
47398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
474204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				       struct wpa_ssid *ssid)
47438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
47448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group *group;
47458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_config *cfg;
47468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
47488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
47498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
47508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
47518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cfg = os_zalloc(sizeof(*cfg));
47538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfg == NULL)
47548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
47558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
475604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (ssid->p2p_persistent_group && wpa_s->conf->persistent_reconnect)
47571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		cfg->persistent_group = 2;
475804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	else if (ssid->p2p_persistent_group)
47591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		cfg->persistent_group = 1;
47608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(cfg->interface_addr, wpa_s->own_addr, ETH_ALEN);
47618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->max_stations &&
47628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_s->max_stations < wpa_s->conf->max_num_sta)
47638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cfg->max_clients = wpa_s->max_stations;
47648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
47658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cfg->max_clients = wpa_s->conf->max_num_sta;
476604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	os_memcpy(cfg->ssid, ssid->ssid, ssid->ssid_len);
476704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	cfg->ssid_len = ssid->ssid_len;
47688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cfg->cb_ctx = wpa_s;
47698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cfg->ie_update = wpas_p2p_ie_update;
47708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cfg->idle_update = wpas_p2p_idle_update;
47718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group = p2p_group_init(wpa_s->global->p2p, cfg);
47738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group == NULL)
47748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(cfg);
477504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION)
47768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_group_notif_formation_done(group);
47778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->p2p_group = group;
47788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return group;
47798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
47808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
47838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  int registrar)
47848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
478504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct wpa_ssid *ssid = wpa_s->current_ssid;
478604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
47878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!wpa_s->p2p_in_provisioning) {
47888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Ignore WPS success event - P2P "
47898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "provisioning not in progress");
47908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
47918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
47928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
479304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (ssid && ssid->mode == WPAS_MODE_INFRA) {
479404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		u8 go_dev_addr[ETH_ALEN];
479504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(go_dev_addr, wpa_s->bssid, ETH_ALEN);
479604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpas_p2p_persistent_group(wpa_s, go_dev_addr, ssid->ssid,
479704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					  ssid->ssid_len);
479804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/* Clear any stored provisioning info */
479904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p_clear_provisioning_info(wpa_s->global->p2p, go_dev_addr);
480004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
48011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
48028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->parent,
48038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     NULL);
480404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (ssid && ssid->mode == WPAS_MODE_INFRA) {
480504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/*
480604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * Use a separate timeout for initial data connection to
480704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * complete to allow the group to be removed automatically if
480804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * something goes wrong in this step before the P2P group idle
480904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * timeout mechanism is taken into use.
481004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 */
481104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT, 0,
481204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				       wpas_p2p_group_formation_timeout,
481304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				       wpa_s->parent, NULL);
481404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
48158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p)
48168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_wps_success_cb(wpa_s->global->p2p, peer_addr);
48178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
48188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_drv_wps_success_cb(wpa_s, peer_addr);
48198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_group_formation_completed(wpa_s, 1);
48208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
48218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
482375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenvoid wpas_p2p_wps_failed(struct wpa_supplicant *wpa_s,
482475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			 struct wps_event_fail *fail)
482575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
482675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (!wpa_s->p2p_in_provisioning) {
482775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		wpa_printf(MSG_DEBUG, "P2P: Ignore WPS fail event - P2P "
482875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			   "provisioning not in progress");
482975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
483075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	}
48311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
48321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_s->go_params) {
48331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_clear_provisioning_info(
48341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_s->global->p2p,
483504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpa_s->go_params->peer_device_addr);
48361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
48371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
483875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	wpas_notify_p2p_wps_failed(wpa_s, fail);
483975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
484075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
484175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
48428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_prov_disc(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
484304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		       const char *config_method,
484404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		       enum wpas_p2p_prov_disc_use use)
48458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
48468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 config_methods;
48478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
484804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_s->p2p_fallback_to_go_neg = 0;
484904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_s->pending_pd_use = NORMAL_PD;
48501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (os_strncmp(config_method, "display", 7) == 0)
48518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		config_methods = WPS_CONFIG_DISPLAY;
48521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	else if (os_strncmp(config_method, "keypad", 6) == 0)
48538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		config_methods = WPS_CONFIG_KEYPAD;
48541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	else if (os_strncmp(config_method, "pbc", 3) == 0 ||
48551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 os_strncmp(config_method, "pushbutton", 10) == 0)
48568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		config_methods = WPS_CONFIG_PUSHBUTTON;
48571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	else {
48581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Unknown config method");
48598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
48601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
48618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
486204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (use == WPAS_P2P_PD_AUTO) {
486304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_memcpy(wpa_s->pending_join_dev_addr, peer_addr, ETH_ALEN);
486404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_s->pending_pd_config_methods = config_methods;
486504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_s->p2p_auto_pd = 1;
486604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_s->p2p_auto_join = 0;
486704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_s->pending_pd_before_join = 0;
486804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_s->auto_pd_scan_retry = 0;
486904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpas_p2p_stop_find(wpa_s);
487004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_s->p2p_join_scan_count = 0;
487104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_get_time(&wpa_s->p2p_auto_started);
487204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Auto PD started at %ld.%06ld",
487304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   wpa_s->p2p_auto_started.sec,
487404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   wpa_s->p2p_auto_started.usec);
487504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpas_p2p_join_scan(wpa_s, NULL);
487604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 0;
487704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
487804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
48798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
48808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wpa_drv_p2p_prov_disc_req(wpa_s, peer_addr,
488104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt						 config_methods,
488204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt						 use == WPAS_P2P_PD_FOR_JOIN);
48838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
48848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled)
48868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
48878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_prov_disc_req(wpa_s->global->p2p, peer_addr,
488904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 config_methods, use == WPAS_P2P_PD_FOR_JOIN,
4890d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				 0, 1);
48918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
48928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_scan_result_text(const u8 *ies, size_t ies_len, char *buf,
48958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      char *end)
48968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
48978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_scan_result_text(ies, ies_len, buf, end);
48988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
48998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_p2p_clear_pending_action_tx(struct wpa_supplicant *wpa_s)
49028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4903a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (!offchannel_pending_action_tx(wpa_s))
49048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
49058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Drop pending Action TX due to new "
49078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "operation request");
4908a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	offchannel_clear_pending_action_tx(wpa_s);
49098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
49108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_find(struct wpa_supplicant *wpa_s, unsigned int timeout,
49138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  enum p2p_discovery_type type,
4914c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		  unsigned int num_req_dev_types, const u8 *req_dev_types,
491561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		  const u8 *dev_id, unsigned int search_delay)
49168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
49178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_p2p_clear_pending_action_tx(wpa_s);
49188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->p2p_long_listen = 0;
49198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
49218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wpa_drv_p2p_find(wpa_s, timeout, type);
49228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
492304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL ||
492404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    wpa_s->p2p_in_provisioning)
49258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
49268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4927c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	wpa_supplicant_cancel_sched_scan(wpa_s);
4928c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
49298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_find(wpa_s->global->p2p, timeout, type,
493061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			num_req_dev_types, req_dev_types, dev_id,
493161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			search_delay);
49328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
49338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4935d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic int wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s)
49368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
49378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_p2p_clear_pending_action_tx(wpa_s);
49388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->p2p_long_listen = 0;
49398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL);
49408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
4941dc7b71324df9788e194745e8ab9386a4619a623aJouni Malinen	wpa_s->global->p2p_cb_on_scan_complete = 0;
49428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
49448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_drv_p2p_stop_find(wpa_s);
4945d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return 1;
49468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
49478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p)
49498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_stop_find(wpa_s->global->p2p);
49508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4951d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	return 0;
4952d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt}
4953d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
4954d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
4955d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtvoid wpas_p2p_stop_find(struct wpa_supplicant *wpa_s)
4956d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt{
4957d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (wpas_p2p_stop_find_oper(wpa_s) > 0)
4958d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return;
49598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_p2p_remove_pending_group_interface(wpa_s);
49608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
49618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_p2p_long_listen_timeout(void *eloop_ctx, void *timeout_ctx)
49648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
49658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = eloop_ctx;
49668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->p2p_long_listen = 0;
49678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
49688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_listen(struct wpa_supplicant *wpa_s, unsigned int timeout)
49718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
49728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
49738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
49758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
49768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4977c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	wpa_supplicant_cancel_sched_scan(wpa_s);
49788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_p2p_clear_pending_action_tx(wpa_s);
49798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (timeout == 0) {
49818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
49828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * This is a request for unlimited Listen state. However, at
49838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * least for now, this is mapped to a Listen state for one
49848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * hour.
49858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
49868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		timeout = 3600;
49878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
49888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL);
49898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->p2p_long_listen = 0;
49908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
49911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	/*
49921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	 * Stop previous find/listen operation to avoid trying to request a new
49931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	 * remain-on-channel operation while the driver is still running the
49941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	 * previous one.
49951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	 */
49961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_s->global->p2p)
49971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		p2p_stop_find(wpa_s->global->p2p);
49981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
49998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = wpas_p2p_listen_start(wpa_s, timeout * 1000);
50008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res == 0 && timeout * 1000 > wpa_s->max_remain_on_chan) {
50018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->p2p_long_listen = timeout * 1000;
50028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(timeout, 0,
50038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       wpas_p2p_long_listen_timeout,
50048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       wpa_s, NULL);
50058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
50068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
50078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
50088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
50098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
50108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
50118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_assoc_req_ie(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
50128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  u8 *buf, size_t len, int p2p_group)
50138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
50148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *p2p_ie;
50158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
50168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
50178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_disabled)
50188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
50198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p == NULL)
50208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
50218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bss == NULL)
50228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
50238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
50248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_ie = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
50258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = p2p_assoc_req_ie(wpa_s->global->p2p, bss->bssid, buf, len,
50268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       p2p_group, p2p_ie);
50278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(p2p_ie);
50288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
50298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
50308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
50318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
50328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
50338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_probe_req_rx(struct wpa_supplicant *wpa_s, const u8 *addr,
50341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			  const u8 *dst, const u8 *bssid,
503504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			  const u8 *ie, size_t ie_len, int ssi_signal)
50368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
50378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_disabled)
50388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
50398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p == NULL)
50408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
50418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
504204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	switch (p2p_probe_req_rx(wpa_s->global->p2p, addr, dst, bssid,
504304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 ie, ie_len)) {
504404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case P2P_PREQ_NOT_P2P:
504504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpas_notify_preq(wpa_s, addr, dst, bssid, ie, ie_len,
504604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 ssi_signal);
504704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/* fall through */
504804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case P2P_PREQ_MALFORMED:
504904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case P2P_PREQ_NOT_LISTEN:
505004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case P2P_PREQ_NOT_PROCESSED:
505104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	default: /* make gcc happy */
505204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 0;
505304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case P2P_PREQ_PROCESSED:
505404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 1;
505504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
50568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
50578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
50588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
50598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_p2p_rx_action(struct wpa_supplicant *wpa_s, const u8 *da,
50608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const u8 *sa, const u8 *bssid,
50618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 category, const u8 *data, size_t len, int freq)
50628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
50638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_disabled)
50648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
50658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p == NULL)
50668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
50678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
50688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_rx_action(wpa_s->global->p2p, da, sa, bssid, category, data, len,
50698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      freq);
50708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
50718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
50728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
50738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_p2p_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ies)
50748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
50758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_disabled)
50768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
50778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p == NULL)
50788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
50798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5080c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	p2p_scan_ie(wpa_s->global->p2p, ies, NULL);
50818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
50828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
50838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
50848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_p2p_group_deinit(struct wpa_supplicant *wpa_s)
50858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
50868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_group_deinit(wpa_s->p2p_group);
50878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->p2p_group = NULL;
50881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
50891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_s->ap_configured_cb = NULL;
50901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_s->ap_configured_cb_ctx = NULL;
50911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_s->ap_configured_cb_data = NULL;
50921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_s->connect_without_scan = NULL;
50938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
50948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
50958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
50968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr)
50978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
50988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->p2p_long_listen = 0;
50998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
51008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
51018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wpa_drv_p2p_reject(wpa_s, addr);
51028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
51038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
51048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
51058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
51068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_reject(wpa_s->global->p2p, addr);
51078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
51088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
51098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
51108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Invite to reinvoke a persistent group */
51118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
511231be0a4b946ecab910c0a9af3837dbccea5d204bJouni Malinen		    struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
51137a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		    int ht40, int pref_freq)
51148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
51158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum p2p_invite_role role;
5116c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	u8 *bssid = NULL;
5117c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	int force_freq = 0;
51187a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt	int res;
51197a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt
5120700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	wpa_s->global->p2p_invite_group = NULL;
51217a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt	if (peer_addr)
51227a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		os_memcpy(wpa_s->p2p_auth_invite, peer_addr, ETH_ALEN);
51237a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt	else
51247a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
51258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
512631be0a4b946ecab910c0a9af3837dbccea5d204bJouni Malinen	wpa_s->p2p_persistent_go_freq = freq;
512731be0a4b946ecab910c0a9af3837dbccea5d204bJouni Malinen	wpa_s->p2p_go_ht40 = !!ht40;
51288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->mode == WPAS_MODE_P2P_GO) {
51298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		role = P2P_INVITE_ROLE_GO;
51308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (peer_addr == NULL) {
51318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Missing peer "
51328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "address in invitation command");
51338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
51348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
51358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpas_p2p_create_iface(wpa_s)) {
51368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (wpas_p2p_add_group_interface(wpa_s,
51378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							 WPA_IF_P2P_GO) < 0) {
51388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_ERROR, "P2P: Failed to "
51398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "allocate a new interface for the "
51408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "group");
51418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
51428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
51438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			bssid = wpa_s->pending_interface_addr;
51448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else
51458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			bssid = wpa_s->own_addr;
51468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
51478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		role = P2P_INVITE_ROLE_CLIENT;
51488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		peer_addr = ssid->bssid;
51498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
51508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->pending_invite_ssid_id = ssid->id;
51518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5152c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	res = wpas_p2p_setup_freqs(wpa_s, freq, &force_freq, &pref_freq);
51537a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt	if (res)
51547a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		return res;
5155af84a575044f6556994fcc124a955fc0ac0a6736Irfan Sheriff
51568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
51578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wpa_drv_p2p_invite(wpa_s, peer_addr, role, bssid,
51588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  ssid->ssid, ssid->ssid_len,
51598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  go_dev_addr, 1);
51608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
51618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
51628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
51638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
51648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid,
51657a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt			  ssid->ssid, ssid->ssid_len, force_freq, go_dev_addr,
51667a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt			  1, pref_freq);
51678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
51688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
51698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
51708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Invite to join an active group */
51718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
51728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  const u8 *peer_addr, const u8 *go_dev_addr)
51738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
51748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_global *global = wpa_s->global;
51758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum p2p_invite_role role;
5176c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	u8 *bssid = NULL;
51778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid;
5178c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	int persistent;
5179c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	int force_freq = 0, pref_freq = 0;
51807a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt	int res;
51818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
518231be0a4b946ecab910c0a9af3837dbccea5d204bJouni Malinen	wpa_s->p2p_persistent_go_freq = 0;
518331be0a4b946ecab910c0a9af3837dbccea5d204bJouni Malinen	wpa_s->p2p_go_ht40 = 0;
518431be0a4b946ecab910c0a9af3837dbccea5d204bJouni Malinen
51858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
51868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strcmp(wpa_s->ifname, ifname) == 0)
51878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
51888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
51898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s == NULL) {
51908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Interface '%s' not found", ifname);
51918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
51928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
51938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
51948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid = wpa_s->current_ssid;
51958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid == NULL) {
51968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: No current SSID to use for "
51978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "invitation");
51988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
51998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
52008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5201700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	wpa_s->global->p2p_invite_group = wpa_s;
5202c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	persistent = ssid->p2p_persistent_group &&
5203c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpas_p2p_get_persistent(wpa_s->parent, peer_addr,
5204c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt					ssid->ssid, ssid->ssid_len);
5205c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
52068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->mode == WPAS_MODE_P2P_GO) {
52078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		role = P2P_INVITE_ROLE_ACTIVE_GO;
52088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		bssid = wpa_s->own_addr;
52098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (go_dev_addr == NULL)
52101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			go_dev_addr = wpa_s->global->p2p_dev_addr;
52118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
52128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		role = P2P_INVITE_ROLE_CLIENT;
52138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_s->wpa_state < WPA_ASSOCIATED) {
52148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Not associated - cannot "
52158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "invite to current group");
52168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
52178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
52188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		bssid = wpa_s->bssid;
52198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (go_dev_addr == NULL &&
52208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    !is_zero_ether_addr(wpa_s->go_dev_addr))
52218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			go_dev_addr = wpa_s->go_dev_addr;
52228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
52238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->parent->pending_invite_ssid_id = -1;
52248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
52258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
52268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wpa_drv_p2p_invite(wpa_s, peer_addr, role, bssid,
52278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  ssid->ssid, ssid->ssid_len,
5228c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt					  go_dev_addr, persistent);
52298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
52308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
52318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
52328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5233c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	res = wpas_p2p_setup_freqs(wpa_s, 0, &force_freq, &pref_freq);
52347a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt	if (res)
52357a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt		return res;
5236c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	wpas_p2p_set_own_freq_preference(wpa_s, force_freq);
52377a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt
52388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid,
52397a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt			  ssid->ssid, ssid->ssid_len, force_freq,
52407a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt			  go_dev_addr, persistent, pref_freq);
52418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
52428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
52438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
52448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_p2p_completed(struct wpa_supplicant *wpa_s)
52458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
52468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid = wpa_s->current_ssid;
52478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *ssid_txt;
52488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 go_dev_addr[ETH_ALEN];
524975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	int network_id = -1;
52508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int persistent;
52511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int freq;
52528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
525304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION) {
525404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
525504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				     wpa_s->parent, NULL);
525604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
525704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
52588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!wpa_s->show_group_started || !ssid)
525961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		goto done;
52608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
52618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->show_group_started = 0;
52628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
52638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid_txt = wpa_ssid_txt(ssid->ssid, ssid->ssid_len);
52648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(go_dev_addr, 0, ETH_ALEN);
52658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->bssid_set)
52668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(go_dev_addr, ssid->bssid, ETH_ALEN);
52678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	persistent = wpas_p2p_persistent_group(wpa_s, go_dev_addr, ssid->ssid,
52688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       ssid->ssid_len);
52698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(wpa_s->go_dev_addr, go_dev_addr, ETH_ALEN);
52708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
52718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_group_formation == wpa_s)
52728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->global->p2p_group_formation = NULL;
52738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
52741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	freq = wpa_s->current_bss ? wpa_s->current_bss->freq :
52751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		(int) wpa_s->assoc_freq;
52768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->passphrase == NULL && ssid->psk_set) {
52778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char psk[65];
52788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_snprintf_hex(psk, sizeof(psk), ssid->psk, 32);
5279b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		wpa_msg_global(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
5280b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       "%s client ssid=\"%s\" freq=%d psk=%s "
5281b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       "go_dev_addr=" MACSTR "%s",
5282b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       wpa_s->ifname, ssid_txt, freq, psk,
5283b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       MAC2STR(go_dev_addr),
5284b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       persistent ? " [PERSISTENT]" : "");
52858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
5286b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		wpa_msg_global(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
5287b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       "%s client ssid=\"%s\" freq=%d "
5288b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       "passphrase=\"%s\" go_dev_addr=" MACSTR "%s",
5289b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       wpa_s->ifname, ssid_txt, freq,
5290b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       ssid->passphrase ? ssid->passphrase : "",
5291b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       MAC2STR(go_dev_addr),
5292b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       persistent ? " [PERSISTENT]" : "");
52938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
52948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
52958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (persistent)
529675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		network_id = wpas_p2p_store_persistent_group(wpa_s->parent,
529775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen							     ssid, go_dev_addr);
529875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (network_id < 0)
529975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		network_id = ssid->id;
530075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	wpas_notify_p2p_group_started(wpa_s, ssid, network_id, 1);
530161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
530261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtdone:
530337d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt	wpas_p2p_continue_after_scan(wpa_s);
53048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
53058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
53068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
53078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_presence_req(struct wpa_supplicant *wpa_s, u32 duration1,
53088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  u32 interval1, u32 duration2, u32 interval2)
53098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
53108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
53118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
53128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
53138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
53148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
53158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->wpa_state < WPA_ASSOCIATED ||
53168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_s->current_ssid == NULL ||
53178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_s->current_ssid->mode != WPAS_MODE_INFRA)
53188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
53198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
53208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_presence_req(wpa_s->global->p2p, wpa_s->bssid,
53218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_s->own_addr, wpa_s->assoc_freq,
53228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				duration1, interval1, duration2, interval2);
53238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
53248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
53258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
53268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_ext_listen(struct wpa_supplicant *wpa_s, unsigned int period,
53278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			unsigned int interval)
53288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
53298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
53308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
53318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
53328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
53338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
53348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
53358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_ext_listen(wpa_s->global->p2p, period, interval);
53368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
53378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
53388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
53391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int wpas_p2p_is_client(struct wpa_supplicant *wpa_s)
53401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
5341d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (wpa_s->current_ssid == NULL) {
5342d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		/*
5343d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		 * current_ssid can be cleared when P2P client interface gets
5344d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		 * disconnected, so assume this interface was used as P2P
5345d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		 * client.
5346d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		 */
5347d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return 1;
5348d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
5349d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	return wpa_s->current_ssid->p2p_group &&
53501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_s->current_ssid->mode == WPAS_MODE_INFRA;
53511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
53521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
53531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
53548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_p2p_group_idle_timeout(void *eloop_ctx, void *timeout_ctx)
53558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
53568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = eloop_ctx;
53578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
53581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_s->conf->p2p_group_idle == 0 && !wpas_p2p_is_client(wpa_s)) {
53598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Ignore group idle timeout - "
53608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "disabled");
53618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
53628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
53638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
536404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Group idle timeout reached - terminate "
536504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   "group");
536661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpas_p2p_group_delete(wpa_s, P2P_GROUP_REMOVAL_IDLE_TIMEOUT);
53678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
53688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
53698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
53708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_p2p_set_group_idle_timeout(struct wpa_supplicant *wpa_s)
53718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
537204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	int timeout;
537304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
537404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL) > 0)
537504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group idle timeout");
53761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
53771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_s->current_ssid == NULL || !wpa_s->current_ssid->p2p_group)
53788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
53798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
53801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	timeout = wpa_s->conf->p2p_group_idle;
53811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
53821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    (timeout == 0 || timeout > P2P_MAX_CLIENT_IDLE))
53831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    timeout = P2P_MAX_CLIENT_IDLE;
53841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
53851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (timeout == 0)
53868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
53878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
538804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (timeout < 0) {
538904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (wpa_s->current_ssid->mode == WPAS_MODE_INFRA)
539004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			timeout = 0; /* special client mode no-timeout */
539104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		else
539204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			return;
539304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
539404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
539504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (wpa_s->p2p_in_provisioning) {
539604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/*
539704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * Use the normal group formation timeout during the
539804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * provisioning phase to avoid terminating this process too
539904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * early due to group idle timeout.
540004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 */
540104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Do not use P2P group idle timeout "
540204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   "during provisioning");
540304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return;
540404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
54059e4e8acef07b7053e93024a621489286900b9ec7Deepthi Gowri
540604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (wpa_s->show_group_started) {
540704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/*
540804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * Use the normal group formation timeout between the end of
540904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * the provisioning phase and completion of 4-way handshake to
541004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * avoid terminating this process too early due to group idle
541104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * timeout.
541204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 */
541304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Do not use P2P group idle timeout "
541404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   "while waiting for initial 4-way handshake to "
541504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   "complete");
541604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return;
541704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
541804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
54198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Set P2P group idle timeout to %u seconds",
54201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		   timeout);
54211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_register_timeout(timeout, 0, wpas_p2p_group_idle_timeout,
54221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			       wpa_s, NULL);
54238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
54248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
54258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
54262b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen/* Returns 1 if the interface was removed */
54272b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinenint wpas_p2p_deauth_notif(struct wpa_supplicant *wpa_s, const u8 *bssid,
54282b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen			  u16 reason_code, const u8 *ie, size_t ie_len,
54292b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen			  int locally_generated)
54308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
54318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
54322b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen		return 0;
54338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
54342b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen		return 0;
54358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
543604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (!locally_generated)
543704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p_deauth_notif(wpa_s->global->p2p, bssid, reason_code, ie,
543804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 ie_len);
543904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
544004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (reason_code == WLAN_REASON_DEAUTH_LEAVING && !locally_generated &&
544104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    wpa_s->current_ssid &&
544204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    wpa_s->current_ssid->p2p_group &&
544304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    wpa_s->current_ssid->mode == WPAS_MODE_INFRA) {
544404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: GO indicated that the P2P Group "
544504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   "session is ending");
54462b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen		if (wpas_p2p_group_delete(wpa_s,
54472b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen					  P2P_GROUP_REMOVAL_GO_ENDING_SESSION)
54482b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen		    > 0)
54492b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen			return 1;
545004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
54512b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen
54522b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen	return 0;
54538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
54548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
54558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
54568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_p2p_disassoc_notif(struct wpa_supplicant *wpa_s, const u8 *bssid,
545704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			     u16 reason_code, const u8 *ie, size_t ie_len,
545804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			     int locally_generated)
54598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
54608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
54618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
54628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
54638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
54648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
546504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (!locally_generated)
546604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p_disassoc_notif(wpa_s->global->p2p, bssid, reason_code, ie,
546704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				   ie_len);
54688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
54698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
54708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
54718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_p2p_update_config(struct wpa_supplicant *wpa_s)
54728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
54738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = wpa_s->global->p2p;
54748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
54758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p == NULL)
54768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
54778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
54788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_CAPABLE))
54798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
54808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
54818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->conf->changed_parameters & CFG_CHANGED_DEVICE_NAME)
54828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_dev_name(p2p, wpa_s->conf->device_name);
54838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
54848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->conf->changed_parameters & CFG_CHANGED_DEVICE_TYPE)
54858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_pri_dev_type(p2p, wpa_s->conf->device_type);
54868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
54878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->wps &&
54888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (wpa_s->conf->changed_parameters & CFG_CHANGED_CONFIG_METHODS))
54898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_config_methods(p2p, wpa_s->wps->config_methods);
54908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
54918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->wps && (wpa_s->conf->changed_parameters & CFG_CHANGED_UUID))
54928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_uuid(p2p, wpa_s->wps->uuid);
54938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
54948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->conf->changed_parameters & CFG_CHANGED_WPS_STRING) {
54958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_manufacturer(p2p, wpa_s->conf->manufacturer);
54968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_model_name(p2p, wpa_s->conf->model_name);
54978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_model_number(p2p, wpa_s->conf->model_number);
54988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_serial_number(p2p, wpa_s->conf->serial_number);
54998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
55008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
55018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->conf->changed_parameters & CFG_CHANGED_SEC_DEVICE_TYPE)
55028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_sec_dev_types(p2p,
55038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      (void *) wpa_s->conf->sec_device_type,
55048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      wpa_s->conf->num_sec_device_types);
55058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
55068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->conf->changed_parameters & CFG_CHANGED_VENDOR_EXTENSION) {
55078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int i;
55088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_remove_wps_vendor_extensions(p2p);
55098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (i = 0; i < MAX_WPS_VENDOR_EXT; i++) {
55108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (wpa_s->conf->wps_vendor_ext[i] == NULL)
55118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				continue;
55128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p_add_wps_vendor_extension(
55138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p, wpa_s->conf->wps_vendor_ext[i]);
55148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
55158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
55168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
55178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
55188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
55198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char country[3];
55208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		country[0] = wpa_s->conf->country[0];
55218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		country[1] = wpa_s->conf->country[1];
55228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		country[2] = 0x04;
55238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_country(p2p, country);
55248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
55258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
55268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->conf->changed_parameters & CFG_CHANGED_P2P_SSID_POSTFIX) {
55278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_ssid_postfix(p2p, (u8 *) wpa_s->conf->p2p_ssid_postfix,
55288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     wpa_s->conf->p2p_ssid_postfix ?
55298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     os_strlen(wpa_s->conf->p2p_ssid_postfix) :
55308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     0);
55318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
55328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
55338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->conf->changed_parameters & CFG_CHANGED_P2P_INTRA_BSS)
55348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_set_intra_bss_dist(p2p, wpa_s->conf->p2p_intra_bss);
553575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
553675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (wpa_s->conf->changed_parameters & CFG_CHANGED_P2P_LISTEN_CHANNEL) {
553775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		u8 reg_class, channel;
553875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		int ret;
553975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		unsigned int r;
554075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (wpa_s->conf->p2p_listen_reg_class &&
554175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		    wpa_s->conf->p2p_listen_channel) {
554275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			reg_class = wpa_s->conf->p2p_listen_reg_class;
554375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			channel = wpa_s->conf->p2p_listen_channel;
554475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		} else {
554575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			reg_class = 81;
554675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			/*
554775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			 * Pick one of the social channels randomly as the
554875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			 * listen channel.
554975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			 */
555075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			os_get_random((u8 *) &r, sizeof(r));
555175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			channel = 1 + (r % 3) * 5;
555275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		}
555375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		ret = p2p_set_listen_channel(p2p, reg_class, channel);
555475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (ret)
555575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			wpa_printf(MSG_ERROR, "P2P: Own listen channel update "
555675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen				   "failed: %d", ret);
555775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	}
555875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (wpa_s->conf->changed_parameters & CFG_CHANGED_P2P_OPER_CHANNEL) {
555975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		u8 op_reg_class, op_channel, cfg_op_channel;
556075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		int ret = 0;
556175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		unsigned int r;
556275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (wpa_s->conf->p2p_oper_reg_class &&
556375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		    wpa_s->conf->p2p_oper_channel) {
556475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			op_reg_class = wpa_s->conf->p2p_oper_reg_class;
556575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			op_channel = wpa_s->conf->p2p_oper_channel;
556675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			cfg_op_channel = 1;
556775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		} else {
556875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			op_reg_class = 81;
556975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			/*
557075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			 * Use random operation channel from (1, 6, 11)
557175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			 *if no other preference is indicated.
557275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			 */
557375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			os_get_random((u8 *) &r, sizeof(r));
557475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			op_channel = 1 + (r % 3) * 5;
557575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			cfg_op_channel = 0;
557675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		}
557775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		ret = p2p_set_oper_channel(p2p, op_reg_class, op_channel,
557875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen					   cfg_op_channel);
557975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (ret)
558075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			wpa_printf(MSG_ERROR, "P2P: Own oper channel update "
558175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen				   "failed: %d", ret);
558275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	}
558304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
558404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (wpa_s->conf->changed_parameters & CFG_CHANGED_P2P_PREF_CHAN) {
558504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (p2p_set_pref_chan(p2p, wpa_s->conf->num_p2p_pref_chan,
558604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				      wpa_s->conf->p2p_pref_chan) < 0) {
558704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpa_printf(MSG_ERROR, "P2P: Preferred channel list "
558804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				   "update failed");
558904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
559004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
55918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
55928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
55938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
55948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_set_noa(struct wpa_supplicant *wpa_s, u8 count, int start,
55958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     int duration)
55968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
55978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!wpa_s->ap_iface)
55988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
55998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return hostapd_p2p_set_noa(wpa_s->ap_iface->bss[0], count, start,
56008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   duration);
56018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
56028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
56038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
56048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_set_cross_connect(struct wpa_supplicant *wpa_s, int enabled)
56058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
56068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
56078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
56088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
56098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
56108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
56118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->global->cross_connection = enabled;
56128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_cross_connect(wpa_s->global->p2p, enabled);
56138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
56148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!enabled) {
56158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct wpa_supplicant *iface;
56168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
56178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (iface = wpa_s->global->ifaces; iface; iface = iface->next)
56188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		{
56198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (iface->cross_connect_enabled == 0)
56208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				continue;
56218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
56228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			iface->cross_connect_enabled = 0;
56238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			iface->cross_connect_in_use = 0;
5624b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			wpa_msg_global(iface->parent, MSG_INFO,
5625b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
5626b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       iface->ifname,
5627b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				       iface->cross_connect_uplink);
56288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
56298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
56308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
56318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
56328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
56338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
56348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
56358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_p2p_enable_cross_connect(struct wpa_supplicant *uplink)
56368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
56378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *iface;
56388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
56398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!uplink->global->cross_connection)
56408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
56418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
56428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (iface = uplink->global->ifaces; iface; iface = iface->next) {
56438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!iface->cross_connect_enabled)
56448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
56458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strcmp(uplink->ifname, iface->cross_connect_uplink) !=
56468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    0)
56478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
56488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (iface->ap_iface == NULL)
56498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
56508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (iface->cross_connect_in_use)
56518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
56528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
56538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		iface->cross_connect_in_use = 1;
5654b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		wpa_msg_global(iface->parent, MSG_INFO,
5655b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       P2P_EVENT_CROSS_CONNECT_ENABLE "%s %s",
5656b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       iface->ifname, iface->cross_connect_uplink);
56578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
56588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
56598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
56608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
56618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_p2p_disable_cross_connect(struct wpa_supplicant *uplink)
56628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
56638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *iface;
56648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
56658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (iface = uplink->global->ifaces; iface; iface = iface->next) {
56668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!iface->cross_connect_enabled)
56678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
56688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strcmp(uplink->ifname, iface->cross_connect_uplink) !=
56698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    0)
56708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
56718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!iface->cross_connect_in_use)
56728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
56738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5674b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		wpa_msg_global(iface->parent, MSG_INFO,
5675b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
5676b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       iface->ifname, iface->cross_connect_uplink);
56778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		iface->cross_connect_in_use = 0;
56788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
56798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
56808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
56818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
56828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_p2p_notif_connected(struct wpa_supplicant *wpa_s)
56838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
56848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->ap_iface || wpa_s->current_ssid == NULL ||
56858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_s->current_ssid->mode != WPAS_MODE_INFRA ||
56868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_s->cross_connect_disallowed)
56878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_p2p_disable_cross_connect(wpa_s);
56888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
56898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_p2p_enable_cross_connect(wpa_s);
569004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (!wpa_s->ap_iface &&
569104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL) > 0)
569204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group idle timeout");
56938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
56948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
56958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
56968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_p2p_notif_disconnected(struct wpa_supplicant *wpa_s)
56978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
56988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_p2p_disable_cross_connect(wpa_s);
56991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (!wpa_s->ap_iface &&
57001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    !eloop_is_timeout_registered(wpas_p2p_group_idle_timeout,
57011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					 wpa_s, NULL))
57028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_p2p_set_group_idle_timeout(wpa_s);
57038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
57048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
57058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
57068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpas_p2p_cross_connect_setup(struct wpa_supplicant *wpa_s)
57078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
57088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *iface;
57098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
57108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!wpa_s->global->cross_connection)
57118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
57128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
57138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (iface = wpa_s->global->ifaces; iface; iface = iface->next) {
57148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (iface == wpa_s)
57158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
57168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (iface->drv_flags &
57178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)
57188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
57198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (iface->drv_flags & WPA_DRIVER_FLAGS_P2P_CAPABLE)
57208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
57218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
57228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->cross_connect_enabled = 1;
57238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_strlcpy(wpa_s->cross_connect_uplink, iface->ifname,
57248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sizeof(wpa_s->cross_connect_uplink));
57258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Enable cross connection from "
57268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "%s to %s whenever uplink is available",
57278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   wpa_s->ifname, wpa_s->cross_connect_uplink);
57288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
57298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (iface->ap_iface || iface->current_ssid == NULL ||
57308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    iface->current_ssid->mode != WPAS_MODE_INFRA ||
57318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    iface->cross_connect_disallowed ||
57328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    iface->wpa_state != WPA_COMPLETED)
57338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
57348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
57358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->cross_connect_in_use = 1;
5736b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		wpa_msg_global(wpa_s->parent, MSG_INFO,
5737b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       P2P_EVENT_CROSS_CONNECT_ENABLE "%s %s",
5738b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			       wpa_s->ifname, wpa_s->cross_connect_uplink);
57398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
57408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
57418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
57428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
57438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
57448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_notif_pbc_overlap(struct wpa_supplicant *wpa_s)
57458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
57468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->p2p_group_interface != P2P_GROUP_INTERFACE_CLIENT &&
57478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !wpa_s->p2p_in_provisioning)
57488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* not P2P client operation */
57498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
57508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Terminate connection due to WPS PBC "
57518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "session overlap");
57528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s != wpa_s->parent)
57538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg_ctrl(wpa_s->parent, MSG_INFO, WPS_EVENT_OVERLAP);
575434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpas_p2p_group_formation_failed(wpa_s);
57558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 1;
57568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
57578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
57588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
57598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s)
57608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
57618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_channels chan;
57628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
57638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->global == NULL || wpa_s->global->p2p == NULL)
57648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
57658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
57668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&chan, 0, sizeof(chan));
57678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpas_p2p_setup_channels(wpa_s, &chan)) {
57688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "P2P: Failed to update supported "
57698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "channel list");
57708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
57718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
57728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
57738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_update_channel_list(wpa_s->global->p2p, &chan);
57748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
57758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
57768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5777a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtstatic void wpas_p2p_scan_res_ignore(struct wpa_supplicant *wpa_s,
5778a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt				     struct wpa_scan_results *scan_res)
5779a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{
5780a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Ignore scan results");
5781a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt}
5782a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
5783a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
57848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_cancel(struct wpa_supplicant *wpa_s)
57858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
57868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_global *global = wpa_s->global;
57878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int found = 0;
57888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *peer;
57898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
57908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (global->p2p == NULL)
57918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
57928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
57938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Request to cancel group formation");
57948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
57958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->pending_interface_name[0] &&
57968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !is_zero_ether_addr(wpa_s->pending_interface_addr))
57978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		found = 1;
57988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
57998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peer = p2p_get_go_neg_peer(global->p2p);
58008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (peer) {
58018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Unauthorize pending GO Neg peer "
58028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   MACSTR, MAC2STR(peer));
58038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_unauthorize(global->p2p, peer);
580404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		found = 1;
58058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
58068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5807a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (wpa_s->scan_res_handler == wpas_p2p_scan_res_join) {
5808a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Stop pending scan for join");
5809a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		wpa_s->scan_res_handler = wpas_p2p_scan_res_ignore;
5810a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		found = 1;
5811a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
5812a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
5813a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (wpa_s->pending_pd_before_join) {
5814a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Stop pending PD before join");
5815a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		wpa_s->pending_pd_before_join = 0;
5816a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		found = 1;
5817a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
5818a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
58198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_p2p_stop_find(wpa_s);
58208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
58218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
58228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_s == global->p2p_group_formation &&
58238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (wpa_s->p2p_in_provisioning ||
58248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     wpa_s->parent->pending_interface_type ==
58258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     WPA_IF_P2P_CLIENT)) {
58268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Interface %s in group "
58278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "formation found - cancelling",
58288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   wpa_s->ifname);
58298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			found = 1;
58308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
58318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     wpa_s->parent, NULL);
5832adddfc48d2d7bfa2b1a2405ab8f404b6383ec236Jouni Malinen			if (wpa_s->p2p_in_provisioning) {
5833adddfc48d2d7bfa2b1a2405ab8f404b6383ec236Jouni Malinen				wpas_group_formation_completed(wpa_s, 0);
5834adddfc48d2d7bfa2b1a2405ab8f404b6383ec236Jouni Malinen				break;
5835adddfc48d2d7bfa2b1a2405ab8f404b6383ec236Jouni Malinen			}
583661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpas_p2p_group_delete(wpa_s,
583761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					      P2P_GROUP_REMOVAL_REQUESTED);
58388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
58398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
58408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
58418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
58428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!found) {
58438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: No ongoing group formation found");
58448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
58458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
58468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
58478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
58488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
58498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
58508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
58518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_p2p_interface_unavailable(struct wpa_supplicant *wpa_s)
58528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
58538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->current_ssid == NULL || !wpa_s->current_ssid->p2p_group)
58548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
58558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
58568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Remove group due to driver resource not "
58578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "being available anymore");
585861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpas_p2p_group_delete(wpa_s, P2P_GROUP_REMOVAL_UNAVAILABLE);
58598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
58608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
58618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
58628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpas_p2p_update_best_channels(struct wpa_supplicant *wpa_s,
58638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   int freq_24, int freq_5, int freq_overall)
58648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
58658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = wpa_s->global->p2p;
58668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p == NULL || (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT))
58678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
58688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_set_best_channels(p2p, freq_24, freq_5, freq_overall);
58698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
58708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
58718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
58728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_unauthorize(struct wpa_supplicant *wpa_s, const char *addr)
58738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
58748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 peer[ETH_ALEN];
58758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = wpa_s->global->p2p;
58768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
58778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p == NULL || (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT))
58788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
58798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
58808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hwaddr_aton(addr, peer))
58818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
58828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
58838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_unauthorize(p2p, peer);
58848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
58858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
58868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
58878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
58888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpas_p2p_disconnect - Disconnect from a P2P Group
58898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data
58908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
58918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
58928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This can be used to disconnect from a group in which the local end is a P2P
58938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Client or to end a P2P Group in case the local end is the Group Owner. If a
58948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * virtual network interface was created for this group, that interface will be
58958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * removed. Otherwise, only the configured P2P group network will be removed
58968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * from the interface.
58978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
58988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpas_p2p_disconnect(struct wpa_supplicant *wpa_s)
58998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
59008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
59018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s == NULL)
59028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
59038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
59042b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen	return wpas_p2p_group_delete(wpa_s, P2P_GROUP_REMOVAL_REQUESTED) < 0 ?
59052b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen		-1 : 0;
59068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
59071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
59081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
59091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint wpas_p2p_in_progress(struct wpa_supplicant *wpa_s)
59101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
5911f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	int ret;
5912f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
59131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
59141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
59151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
5916f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	ret = p2p_in_progress(wpa_s->global->p2p);
5917f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	if (ret == 0) {
5918f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		/*
5919f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * Check whether there is an ongoing WPS provisioning step (or
5920f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * other parts of group formation) on another interface since
5921f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * p2p_in_progress() does not report this to avoid issues for
5922f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 * scans during such provisioning step.
5923f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		 */
5924f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		if (wpa_s->global->p2p_group_formation &&
5925f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		    wpa_s->global->p2p_group_formation != wpa_s) {
5926f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Another interface (%s) "
5927f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt				"in group formation",
5928f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt				wpa_s->global->p2p_group_formation->ifname);
5929f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			ret = 1;
5930f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		}
5931f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	}
5932f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
593392c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt	if (!ret && wpa_s->global->p2p_go_wait_client.sec) {
593492c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt		struct os_time now;
593592c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt		os_get_time(&now);
593692c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt		if (now.sec > wpa_s->global->p2p_go_wait_client.sec +
593792c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt		    P2P_MAX_INITIAL_CONN_WAIT_GO) {
593892c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt			/* Wait for the first client has expired */
593992c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt			wpa_s->global->p2p_go_wait_client.sec = 0;
594092c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt		} else {
594192c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Waiting for initial client connection during group formation");
594292c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt			ret = 1;
594392c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt		}
594492c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt	}
594592c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt
5946f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	return ret;
59471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
59481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
59491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
59501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid wpas_p2p_network_removed(struct wpa_supplicant *wpa_s,
59511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      struct wpa_ssid *ssid)
59521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
59531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_s->p2p_in_provisioning && ssid->p2p_group &&
59541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
59551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				 wpa_s->parent, NULL) > 0) {
595604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/**
595704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * Remove the network by scheduling the group formation
595804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * timeout to happen immediately. The teardown code
595904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * needs to be scheduled to run asynch later so that we
596004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * don't delete data from under ourselves unexpectedly.
596104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * Calling wpas_p2p_group_formation_timeout directly
596204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * causes a series of crashes in WPS failure scenarios.
596304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 */
59641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Canceled group formation due to "
59651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			   "P2P group network getting removed");
596604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		eloop_register_timeout(0, 0, wpas_p2p_group_formation_timeout,
596704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				       wpa_s->parent, NULL);
59681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
59691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
59701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
59711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
59721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstruct wpa_ssid * wpas_p2p_get_persistent(struct wpa_supplicant *wpa_s,
5973c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt					  const u8 *addr, const u8 *ssid,
5974c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt					  size_t ssid_len)
59751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
59761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct wpa_ssid *s;
59771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	size_t i;
59781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
59791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (s = wpa_s->conf->ssid; s; s = s->next) {
59801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (s->disabled != 2)
59811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			continue;
5982c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (ssid &&
5983c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		    (ssid_len != s->ssid_len ||
5984c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		     os_memcmp(ssid, s->ssid, ssid_len) != 0))
5985c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			continue;
5986391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		if (addr == NULL) {
5987391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			if (s->mode == WPAS_MODE_P2P_GO)
5988391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt				return s;
5989391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			continue;
5990391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		}
59911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (os_memcmp(s->bssid, addr, ETH_ALEN) == 0)
59921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return s; /* peer is GO in the persistent group */
59931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (s->mode != WPAS_MODE_P2P_GO || s->p2p_client_list == NULL)
59941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			continue;
59951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		for (i = 0; i < s->num_p2p_clients; i++) {
59961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (os_memcmp(s->p2p_client_list + i * ETH_ALEN,
59971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      addr, ETH_ALEN) == 0)
59981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				return s; /* peer is P2P client in persistent
59991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   * group */
60001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
60011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
60021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
60031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return NULL;
60041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
60051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
60061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
60071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s,
60081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				       const u8 *addr)
60091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
601092c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt	wpa_s->global->p2p_go_wait_client.sec = 0;
60111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (addr == NULL)
60121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
60131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpas_p2p_add_persistent_group_client(wpa_s, addr);
60141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
6015c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
601604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
601704949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
601804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					int group_added)
601904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
602004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct wpa_supplicant *group = wpa_s;
602104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (wpa_s->global->p2p_group_formation)
602204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		group = wpa_s->global->p2p_group_formation;
602304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_s = wpa_s->parent;
602404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	offchannel_send_action_done(wpa_s);
602504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (group_added)
602661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpas_p2p_group_delete(group, P2P_GROUP_REMOVAL_SILENT);
602704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Fall back to GO Negotiation");
602804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpas_p2p_connect(wpa_s, wpa_s->pending_join_dev_addr, wpa_s->p2p_pin,
602904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 wpa_s->p2p_wps_method, wpa_s->p2p_persistent_group, 0,
603004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 0, 0, wpa_s->p2p_go_intent, wpa_s->p2p_connect_freq,
603104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 wpa_s->p2p_persistent_id,
603261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			 wpa_s->p2p_pd_before_go_neg,
603361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			 wpa_s->p2p_go_ht40);
603404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
603504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
603604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
603704949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint wpas_p2p_scan_no_go_seen(struct wpa_supplicant *wpa_s)
603804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
603904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (!wpa_s->p2p_fallback_to_go_neg ||
604004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    wpa_s->p2p_in_provisioning <= 5)
604104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 0;
604204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
604304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (wpas_p2p_peer_go(wpa_s, wpa_s->pending_join_dev_addr) > 0)
604404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 0; /* peer operating as a GO */
604504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
604604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "P2P: GO not found for p2p_connect-auto - "
604704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		"fallback to GO Negotiation");
604804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpas_p2p_fallback_to_go_neg(wpa_s, 1);
604904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
605004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return 1;
605104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
605204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
605361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
605461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtunsigned int wpas_p2p_search_delay(struct wpa_supplicant *wpa_s)
605561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
605661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	const char *rn, *rn2;
605761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct wpa_supplicant *ifs;
605861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
605961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (wpa_s->wpa_state > WPA_SCANNING) {
606061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use %u ms search delay due to "
606161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			"concurrent operation",
606261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			P2P_CONCURRENT_SEARCH_DELAY);
606361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return P2P_CONCURRENT_SEARCH_DELAY;
606461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
606561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
606661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (!wpa_s->driver->get_radio_name)
606761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return 0;
606861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
606961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (rn == NULL || rn[0] == '\0')
607061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return 0;
607161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
607261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
607361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (ifs == wpa_s || !ifs->driver->get_radio_name)
607461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			continue;
607561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
607661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		rn2 = ifs->driver->get_radio_name(ifs->drv_priv);
607761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (!rn2 || os_strcmp(rn, rn2) != 0)
607861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			continue;
607961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (ifs->wpa_state > WPA_SCANNING) {
608061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use %u ms search "
608161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				"delay due to concurrent operation on "
608261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				"interface %s",
608361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				P2P_CONCURRENT_SEARCH_DELAY, ifs->ifname);
608461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return P2P_CONCURRENT_SEARCH_DELAY;
608561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
608661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
608761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
608861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
608961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
609061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
609137d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt
609237d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidtvoid wpas_p2p_continue_after_scan(struct wpa_supplicant *wpa_s)
609337d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt{
609437d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Station mode scan operation not "
609537d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt		"pending anymore (sta_scan_pending=%d "
609637d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt		"p2p_cb_on_scan_complete=%d)", wpa_s->sta_scan_pending,
609737d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt		wpa_s->global->p2p_cb_on_scan_complete);
609837d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt	wpa_s->sta_scan_pending = 0;
609937d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt
610037d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt	if (!wpa_s->global->p2p_cb_on_scan_complete)
610137d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt		return;
610237d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt	wpa_s->global->p2p_cb_on_scan_complete = 0;
610337d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt
610437d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
610537d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt		return;
610637d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt
610737d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt	if (p2p_other_scan_completed(wpa_s->global->p2p) == 1) {
610837d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Pending P2P operation "
610937d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt			"continued after successful connection");
611037d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt		p2p_increase_search_delay(wpa_s->global->p2p,
611137d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt					  wpas_p2p_search_delay(wpa_s));
611237d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt	}
611337d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt}
611437d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt
6115391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6116391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic int wpas_p2p_remove_psk_entry(struct wpa_supplicant *wpa_s,
6117391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt				     struct wpa_ssid *s, const u8 *addr,
6118391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt				     int iface_addr)
6119391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{
6120391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	struct psk_list_entry *psk, *tmp;
6121391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	int changed = 0;
6122391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6123391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	dl_list_for_each_safe(psk, tmp, &s->psk_list, struct psk_list_entry,
6124391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			      list) {
6125391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		if ((iface_addr && !psk->p2p &&
6126391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		     os_memcmp(addr, psk->addr, ETH_ALEN) == 0) ||
6127391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		    (!iface_addr && psk->p2p &&
6128391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		     os_memcmp(addr, psk->addr, ETH_ALEN) == 0)) {
6129391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG,
6130391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt				"P2P: Remove persistent group PSK list entry for "
6131391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt				MACSTR " p2p=%u",
6132391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt				MAC2STR(psk->addr), psk->p2p);
6133391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			dl_list_del(&psk->list);
6134391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			os_free(psk);
6135391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			changed++;
6136391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		}
6137391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	}
6138391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6139391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	return changed;
6140391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt}
6141391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6142391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6143391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtvoid wpas_p2p_new_psk_cb(struct wpa_supplicant *wpa_s, const u8 *mac_addr,
6144391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			 const u8 *p2p_dev_addr,
6145391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			 const u8 *psk, size_t psk_len)
6146391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{
6147391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	struct wpa_ssid *ssid = wpa_s->current_ssid;
6148391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	struct wpa_ssid *persistent;
6149391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	struct psk_list_entry *p;
6150391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6151391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (psk_len != sizeof(p->psk))
6152391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		return;
6153391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6154391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (p2p_dev_addr) {
6155391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: New PSK for addr=" MACSTR
6156391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			" p2p_dev_addr=" MACSTR,
6157391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			MAC2STR(mac_addr), MAC2STR(p2p_dev_addr));
6158391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		if (is_zero_ether_addr(p2p_dev_addr))
6159391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			p2p_dev_addr = NULL;
6160391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	} else {
6161391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: New PSK for addr=" MACSTR,
6162391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			MAC2STR(mac_addr));
6163391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	}
6164391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6165391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
6166391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: new_psk_cb during group formation");
6167391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		/* To be added to persistent group once created */
6168391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		if (wpa_s->global->add_psk == NULL) {
6169391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			wpa_s->global->add_psk = os_zalloc(sizeof(*p));
6170391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			if (wpa_s->global->add_psk == NULL)
6171391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt				return;
6172391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		}
6173391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		p = wpa_s->global->add_psk;
6174391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		if (p2p_dev_addr) {
6175391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			p->p2p = 1;
6176391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			os_memcpy(p->addr, p2p_dev_addr, ETH_ALEN);
6177391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		} else {
6178391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			p->p2p = 0;
6179391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			os_memcpy(p->addr, mac_addr, ETH_ALEN);
6180391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		}
6181391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		os_memcpy(p->psk, psk, psk_len);
6182391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		return;
6183391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	}
6184391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6185391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (ssid->mode != WPAS_MODE_P2P_GO || !ssid->p2p_persistent_group) {
6186391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Ignore new_psk_cb on not-persistent GO");
6187391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		return;
6188391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	}
6189391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6190391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	persistent = wpas_p2p_get_persistent(wpa_s->parent, NULL, ssid->ssid,
6191391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt					     ssid->ssid_len);
6192391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (!persistent) {
6193391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Could not find persistent group information to store the new PSK");
6194391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		return;
6195391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	}
6196391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6197391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	p = os_zalloc(sizeof(*p));
6198391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (p == NULL)
6199391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		return;
6200391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (p2p_dev_addr) {
6201391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		p->p2p = 1;
6202391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		os_memcpy(p->addr, p2p_dev_addr, ETH_ALEN);
6203391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	} else {
6204391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		p->p2p = 0;
6205391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		os_memcpy(p->addr, mac_addr, ETH_ALEN);
6206391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	}
6207391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	os_memcpy(p->psk, psk, psk_len);
6208391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6209391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (dl_list_len(&persistent->psk_list) > P2P_MAX_STORED_CLIENTS) {
6210391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		struct psk_list_entry *last;
6211391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		last = dl_list_last(&persistent->psk_list,
6212391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt				    struct psk_list_entry, list);
6213391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Remove oldest PSK entry for "
6214391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			MACSTR " (p2p=%u) to make room for a new one",
6215391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			MAC2STR(last->addr), last->p2p);
6216391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		dl_list_del(&last->list);
6217391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		os_free(last);
6218391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	}
6219391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6220391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	wpas_p2p_remove_psk_entry(wpa_s->parent, persistent,
6221391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt				  p2p_dev_addr ? p2p_dev_addr : mac_addr,
6222391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt				  p2p_dev_addr == NULL);
6223391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (p2p_dev_addr) {
6224391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Add new PSK for p2p_dev_addr="
6225391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			MACSTR, MAC2STR(p2p_dev_addr));
6226391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	} else {
6227391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Add new PSK for addr=" MACSTR,
6228391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			MAC2STR(mac_addr));
6229391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	}
6230391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	dl_list_add(&persistent->psk_list, &p->list);
6231391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6232391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#ifndef CONFIG_NO_CONFIG_WRITE
6233391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (wpa_s->parent->conf->update_config &&
6234391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	    wpa_config_write(wpa_s->parent->confname, wpa_s->parent->conf))
6235391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
6236391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#endif /* CONFIG_NO_CONFIG_WRITE */
6237391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt}
6238391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6239391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6240391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic void wpas_p2p_remove_psk(struct wpa_supplicant *wpa_s,
6241391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt				struct wpa_ssid *s, const u8 *addr,
6242391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt				int iface_addr)
6243391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{
6244391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	int res;
6245391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6246391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	res = wpas_p2p_remove_psk_entry(wpa_s, s, addr, iface_addr);
6247391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (res > 0) {
6248391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#ifndef CONFIG_NO_CONFIG_WRITE
6249391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		if (wpa_s->conf->update_config &&
6250391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		    wpa_config_write(wpa_s->confname, wpa_s->conf))
6251391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG,
6252391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt				"P2P: Failed to update configuration");
6253391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#endif /* CONFIG_NO_CONFIG_WRITE */
6254391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	}
6255391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt}
6256391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6257391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6258391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic void wpas_p2p_remove_client_go(struct wpa_supplicant *wpa_s,
6259391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt				      const u8 *peer, int iface_addr)
6260391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{
6261391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	struct hostapd_data *hapd;
6262391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	struct hostapd_wpa_psk *psk, *prev, *rem;
6263391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	struct sta_info *sta;
6264391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6265391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (wpa_s->ap_iface == NULL || wpa_s->current_ssid == NULL ||
6266391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	    wpa_s->current_ssid->mode != WPAS_MODE_P2P_GO)
6267391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		return;
6268391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6269391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	/* Remove per-station PSK entry */
6270391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	hapd = wpa_s->ap_iface->bss[0];
6271391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	prev = NULL;
6272391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	psk = hapd->conf->ssid.wpa_psk;
6273391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	while (psk) {
6274391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		if ((iface_addr && os_memcmp(peer, psk->addr, ETH_ALEN) == 0) ||
6275391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		    (!iface_addr &&
6276391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		     os_memcmp(peer, psk->p2p_dev_addr, ETH_ALEN) == 0)) {
6277391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Remove operating group PSK entry for "
6278391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt				MACSTR " iface_addr=%d",
6279391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt				MAC2STR(peer), iface_addr);
6280391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			if (prev)
6281391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt				prev->next = psk->next;
6282391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			else
6283391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt				hapd->conf->ssid.wpa_psk = psk->next;
6284391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			rem = psk;
6285391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			psk = psk->next;
6286391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			os_free(rem);
6287391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		} else {
6288391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			prev = psk;
6289391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			psk = psk->next;
6290391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		}
6291391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	}
6292391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6293391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	/* Disconnect from group */
6294391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (iface_addr)
6295391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		sta = ap_get_sta(hapd, peer);
6296391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	else
6297391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		sta = ap_get_sta_p2p(hapd, peer);
6298391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (sta) {
6299391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Disconnect peer " MACSTR
6300391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			" (iface_addr=%d) from group",
6301391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			MAC2STR(peer), iface_addr);
6302391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		hostapd_drv_sta_deauth(hapd, sta->addr,
6303391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt				       WLAN_REASON_DEAUTH_LEAVING);
6304391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		ap_sta_deauthenticate(hapd, sta, WLAN_REASON_DEAUTH_LEAVING);
6305391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	}
6306391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt}
6307391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6308391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6309391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtvoid wpas_p2p_remove_client(struct wpa_supplicant *wpa_s, const u8 *peer,
6310391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			    int iface_addr)
6311391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{
6312391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	struct wpa_ssid *s;
6313391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	struct wpa_supplicant *w;
6314391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6315391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Remove client " MACSTR, MAC2STR(peer));
6316391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6317391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	/* Remove from any persistent group */
6318391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	for (s = wpa_s->parent->conf->ssid; s; s = s->next) {
6319391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		if (s->disabled != 2 || s->mode != WPAS_MODE_P2P_GO)
6320391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			continue;
6321391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		if (!iface_addr)
6322391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			wpas_remove_persistent_peer(wpa_s, s, peer, 0);
6323391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		wpas_p2p_remove_psk(wpa_s->parent, s, peer, iface_addr);
6324391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	}
6325391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6326391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	/* Remove from any operating group */
6327391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	for (w = wpa_s->global->ifaces; w; w = w->next)
6328391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		wpas_p2p_remove_client_go(w, peer, iface_addr);
6329391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt}
6330391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6331391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6332391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic void wpas_p2p_psk_failure_removal(void *eloop_ctx, void *timeout_ctx)
6333391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{
6334391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	struct wpa_supplicant *wpa_s = eloop_ctx;
6335391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	wpas_p2p_group_delete(wpa_s, P2P_GROUP_REMOVAL_PSK_FAILURE);
6336391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt}
6337391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6338391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6339391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtint wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s)
6340391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{
6341391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	struct wpa_ssid *ssid = wpa_s->current_ssid;
6342391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6343391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (ssid == NULL || !ssid->p2p_group)
6344391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		return 0;
6345391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6346391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (wpa_s->p2p_last_4way_hs_fail &&
6347391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	    wpa_s->p2p_last_4way_hs_fail == ssid) {
6348391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		u8 go_dev_addr[ETH_ALEN];
6349391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		struct wpa_ssid *persistent;
6350391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6351391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		if (wpas_p2p_persistent_group(wpa_s, go_dev_addr,
6352391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt					      ssid->ssid,
6353391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt					      ssid->ssid_len) <= 0) {
6354391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Could not determine whether 4-way handshake failures were for a persistent group");
6355391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			goto disconnect;
6356391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		}
6357391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6358391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Two 4-way handshake failures for a P2P group - go_dev_addr="
6359391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			MACSTR, MAC2STR(go_dev_addr));
6360391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		persistent = wpas_p2p_get_persistent(wpa_s->parent, go_dev_addr,
6361391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt						     ssid->ssid,
6362391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt						     ssid->ssid_len);
6363391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		if (persistent == NULL || persistent->mode != WPAS_MODE_INFRA) {
6364391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "P2P: No matching persistent group stored");
6365391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			goto disconnect;
6366391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		}
6367391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		wpa_msg_global(wpa_s->parent, MSG_INFO,
6368391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			       P2P_EVENT_PERSISTENT_PSK_FAIL "%d",
6369391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			       persistent->id);
6370391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	disconnect:
6371391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		wpa_s->p2p_last_4way_hs_fail = NULL;
6372391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		/*
6373391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		 * Remove the group from a timeout to avoid issues with caller
6374391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		 * continuing to use the interface if this is on a P2P group
6375391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		 * interface.
6376391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		 */
6377391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		eloop_register_timeout(0, 0, wpas_p2p_psk_failure_removal,
6378391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt				       wpa_s, NULL);
6379391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		return 1;
6380391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	}
6381391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6382391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	wpa_s->p2p_last_4way_hs_fail = ssid;
6383391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	return 0;
6384391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt}
6385391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
6386c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef ANDROID_P2P
63871cf4573e05a4e7ce02e0ccc46771a1da5f303411Dmitry Shmidtstatic void wpas_p2p_group_freq_conflict(void *eloop_ctx, void *timeout_ctx)
63881cf4573e05a4e7ce02e0ccc46771a1da5f303411Dmitry Shmidt{
63891cf4573e05a4e7ce02e0ccc46771a1da5f303411Dmitry Shmidt	struct wpa_supplicant *wpa_s = eloop_ctx;
63901cf4573e05a4e7ce02e0ccc46771a1da5f303411Dmitry Shmidt
63911cf4573e05a4e7ce02e0ccc46771a1da5f303411Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Frequency conflict - terminate group");
63921cf4573e05a4e7ce02e0ccc46771a1da5f303411Dmitry Shmidt	wpas_p2p_group_delete(wpa_s, P2P_GROUP_REMOVAL_FREQ_CONFLICT);
63931cf4573e05a4e7ce02e0ccc46771a1da5f303411Dmitry Shmidt}
63941cf4573e05a4e7ce02e0ccc46771a1da5f303411Dmitry Shmidt
6395d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtint wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s, int freq,
6396d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	struct wpa_ssid *ssid)
6397c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{
6398c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	struct wpa_supplicant *iface = NULL;
6399c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	struct p2p_data *p2p = wpa_s->global->p2p;
6400c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
6401c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	for (iface = wpa_s->global->ifaces; iface; iface = iface->next) {
640212b1cd9e151d1e5c4d35aa38531f38b4ef5cc805Jeff Johnson		if ((iface->current_ssid) &&
640312b1cd9e151d1e5c4d35aa38531f38b4ef5cc805Jeff Johnson		    (iface->current_ssid->frequency != freq) &&
640412b1cd9e151d1e5c4d35aa38531f38b4ef5cc805Jeff Johnson		    ((iface->p2p_group_interface) ||
640512b1cd9e151d1e5c4d35aa38531f38b4ef5cc805Jeff Johnson		     (iface->current_ssid->p2p_group))) {
640612b1cd9e151d1e5c4d35aa38531f38b4ef5cc805Jeff Johnson
640712b1cd9e151d1e5c4d35aa38531f38b4ef5cc805Jeff Johnson			if ((iface->p2p_group_interface == P2P_GROUP_INTERFACE_GO)  ||
640812b1cd9e151d1e5c4d35aa38531f38b4ef5cc805Jeff Johnson			    (iface->current_ssid->mode == WPAS_MODE_P2P_GO)) {
640912b1cd9e151d1e5c4d35aa38531f38b4ef5cc805Jeff Johnson				/* Try to see whether we can move the GO. If it
641012b1cd9e151d1e5c4d35aa38531f38b4ef5cc805Jeff Johnson				 * is not possible, remove the GO interface
641112b1cd9e151d1e5c4d35aa38531f38b4ef5cc805Jeff Johnson				 */
641212b1cd9e151d1e5c4d35aa38531f38b4ef5cc805Jeff Johnson				if (wpa_drv_switch_channel(iface, freq) == 0) {
641312b1cd9e151d1e5c4d35aa38531f38b4ef5cc805Jeff Johnson					wpa_printf(MSG_ERROR, "P2P: GO Moved to freq(%d)", freq);
641412b1cd9e151d1e5c4d35aa38531f38b4ef5cc805Jeff Johnson					iface->current_ssid->frequency = freq;
641512b1cd9e151d1e5c4d35aa38531f38b4ef5cc805Jeff Johnson					continue;
641612b1cd9e151d1e5c4d35aa38531f38b4ef5cc805Jeff Johnson				}
6417c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			}
6418c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
6419c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			/* If GO cannot be moved or if the conflicting interface is a
6420c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 * P2P Client, remove the interface depending up on the connection
6421c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 * priority */
6422d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			if(!wpas_is_p2p_prioritized(iface)) {
6423f4f5db315918f3f048324ea43dc37a3b0fb31eccDmitry Shmidt				/* STA connection has priority over existing
6424c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				 * P2P connection. So remove the interface */
6425d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				wpa_printf(MSG_DEBUG, "P2P: Removing P2P connection due to Single channel"
6426687922c7347bdc3b4f8c921efe1d1388cb3baac0Dmitry Shmidt						"concurrent mode frequency conflict");
64271cf4573e05a4e7ce02e0ccc46771a1da5f303411Dmitry Shmidt				eloop_register_timeout(0, 0, wpas_p2p_group_freq_conflict,
64281cf4573e05a4e7ce02e0ccc46771a1da5f303411Dmitry Shmidt						       iface, NULL);
6429d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				/* If connection in progress is p2p connection, do not proceed for the connection */
6430d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				if (wpa_s == iface)
6431d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt					return -1;
6432d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				else
6433d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt					/* If connection in progress is STA connection, proceed for the connection */
6434d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt					return 0;
6435c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			} else {
6436d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				/* P2p connection has priority, disable the STA network*/
6437d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				wpa_supplicant_disable_network(wpa_s->global->ifaces, ssid);
6438d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				wpa_msg(wpa_s->global->ifaces, MSG_INFO, WPA_EVENT_FREQ_CONFLICT
6439d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt					" id=%d", ssid->id);
6440d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				os_memset(wpa_s->global->ifaces->pending_bssid, 0, ETH_ALEN);
6441d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				if (wpa_s == iface) {
6442d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt					/* p2p connection is in progress, continue connecting...*/
6443d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt					return 0;
6444d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				}
6445d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				else {
6446d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt					/* STA connection is in progress, do not allow to continue */
6447d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt					return -1;
6448d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				}
6449c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			}
6450c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		}
6451c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
6452c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	return 0;
6453c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt}
6454c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#endif
6455