blob: a8e003cd78bbdd9a6cc1739b05ab362ef6f839d5 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * wpa_supplicant - P2P
3 * Copyright (c) 2009-2010, Atheros Communications
4 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
8
9#include "includes.h"
10
11#include "common.h"
12#include "eloop.h"
13#include "common/ieee802_11_common.h"
14#include "common/ieee802_11_defs.h"
15#include "common/wpa_ctrl.h"
16#include "wps/wps_i.h"
17#include "p2p/p2p.h"
18#include "ap/hostapd.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080019#include "ap/ap_config.h"
Dmitry Shmidt391c59f2013-09-03 12:16:28 -070020#include "ap/sta_info.h"
21#include "ap/ap_drv_ops.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070022#include "ap/p2p_hostapd.h"
Jouni Malinen75ecf522011-06-27 15:19:46 -070023#include "eapol_supp/eapol_supp_sm.h"
24#include "rsn_supp/wpa.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070025#include "wpa_supplicant_i.h"
26#include "driver_i.h"
27#include "ap.h"
28#include "config_ssid.h"
29#include "config.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070030#include "notify.h"
31#include "scan.h"
32#include "bss.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080033#include "offchannel.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070034#include "wps_supplicant.h"
35#include "p2p_supplicant.h"
36
37
38/*
39 * How many times to try to scan to find the GO before giving up on join
40 * request.
41 */
42#define P2P_MAX_JOIN_SCAN_ATTEMPTS 10
43
Dmitry Shmidt04949592012-07-19 12:16:46 -070044#define P2P_AUTO_PD_SCAN_ATTEMPTS 5
45
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080046#ifndef P2P_MAX_CLIENT_IDLE
47/*
48 * How many seconds to try to reconnect to the GO when connection in P2P client
49 * role has been lost.
50 */
Dmitry Shmidt98f9e762012-05-30 11:18:46 -070051#ifdef ANDROID_P2P
52#define P2P_MAX_CLIENT_IDLE 20
53#else
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080054#define P2P_MAX_CLIENT_IDLE 10
Dmitry Shmidt98f9e762012-05-30 11:18:46 -070055#endif /* ANDROID_P2P */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080056#endif /* P2P_MAX_CLIENT_IDLE */
57
Dmitry Shmidt04949592012-07-19 12:16:46 -070058#ifndef P2P_MAX_INITIAL_CONN_WAIT
59/*
60 * How many seconds to wait for initial 4-way handshake to get completed after
61 * WPS provisioning step.
62 */
63#define P2P_MAX_INITIAL_CONN_WAIT 10
64#endif /* P2P_MAX_INITIAL_CONN_WAIT */
65
Dmitry Shmidt92c368d2013-08-29 12:37:21 -070066#ifndef P2P_MAX_INITIAL_CONN_WAIT_GO
67/*
68 * How many seconds to wait for initial 4-way handshake to get completed after
69 * WPS provisioning step on the GO. This controls the extra time the P2P
70 * operation is considered to be in progress (e.g., to delay other scans) after
71 * WPS provisioning has been completed on the GO during group formation.
72 */
73#define P2P_MAX_INITIAL_CONN_WAIT_GO 10
74#endif /* P2P_MAX_INITIAL_CONN_WAIT_GO */
75
Dmitry Shmidt56052862013-10-04 10:23:25 -070076#ifndef P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE
77/*
78 * How many seconds to wait for initial 4-way handshake to get completed after
79 * re-invocation of a persistent group on the GO when the client is expected
80 * to connect automatically (no user interaction).
81 */
82#define P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE 15
83#endif /* P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE */
84
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070085#ifndef P2P_CONCURRENT_SEARCH_DELAY
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070086#define P2P_CONCURRENT_SEARCH_DELAY 500
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070087#endif /* P2P_CONCURRENT_SEARCH_DELAY */
88
Dmitry Shmidt34af3062013-07-11 10:46:32 -070089#define P2P_MGMT_DEVICE_PREFIX "p2p-dev-"
90
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070091enum p2p_group_removal_reason {
92 P2P_GROUP_REMOVAL_UNKNOWN,
93 P2P_GROUP_REMOVAL_SILENT,
94 P2P_GROUP_REMOVAL_FORMATION_FAILED,
95 P2P_GROUP_REMOVAL_REQUESTED,
96 P2P_GROUP_REMOVAL_IDLE_TIMEOUT,
97 P2P_GROUP_REMOVAL_UNAVAILABLE,
98 P2P_GROUP_REMOVAL_GO_ENDING_SESSION,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -070099 P2P_GROUP_REMOVAL_PSK_FAILURE,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700100#ifdef ANDROID_P2P
101 P2P_GROUP_REMOVAL_FREQ_CONFLICT
102#endif
103};
104
Jouni Malinendc7b7132012-09-14 12:53:47 -0700105
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700106static void wpas_p2p_long_listen_timeout(void *eloop_ctx, void *timeout_ctx);
107static struct wpa_supplicant *
108wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
109 int go);
110static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700111static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700112static void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx);
113static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr,
Dmitry Shmidt04949592012-07-19 12:16:46 -0700114 const u8 *dev_addr, enum p2p_wps_method wps_method,
115 int auto_join);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700116static int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s);
117static void wpas_p2p_cross_connect_setup(struct wpa_supplicant *wpa_s);
118static void wpas_p2p_group_idle_timeout(void *eloop_ctx, void *timeout_ctx);
119static void wpas_p2p_set_group_idle_timeout(struct wpa_supplicant *wpa_s);
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800120static void wpas_p2p_group_formation_timeout(void *eloop_ctx,
121 void *timeout_ctx);
Dmitry Shmidt1cf45732013-04-29 17:36:45 -0700122#ifdef ANDROID_P2P
123static void wpas_p2p_group_freq_conflict(void *eloop_ctx, void *timeout_ctx);
124#endif
Dmitry Shmidt04949592012-07-19 12:16:46 -0700125static void wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
126 int group_added);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800127static int wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700128
129
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700130/*
131 * Get the number of concurrent channels that the HW can operate, but that are
132 * currently not in use by any of the wpa_supplicant interfaces.
133 */
134static int wpas_p2p_num_unused_channels(struct wpa_supplicant *wpa_s)
135{
136 int *freqs;
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800137 int num, unused;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700138
139 freqs = os_calloc(wpa_s->num_multichan_concurrent, sizeof(int));
140 if (!freqs)
141 return -1;
142
143 num = get_shared_radio_freqs(wpa_s, freqs,
144 wpa_s->num_multichan_concurrent);
145 os_free(freqs);
146
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800147 unused = wpa_s->num_multichan_concurrent - num;
148 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: num_unused_channels: %d", unused);
149 return unused;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700150}
151
152
153/*
154 * Get the frequencies that are currently in use by one or more of the virtual
155 * interfaces, and that are also valid for P2P operation.
156 */
157static int wpas_p2p_valid_oper_freqs(struct wpa_supplicant *wpa_s,
158 int *p2p_freqs, unsigned int len)
159{
160 int *freqs;
161 unsigned int num, i, j;
162
163 freqs = os_calloc(wpa_s->num_multichan_concurrent, sizeof(int));
164 if (!freqs)
165 return -1;
166
167 num = get_shared_radio_freqs(wpa_s, freqs,
168 wpa_s->num_multichan_concurrent);
169
170 os_memset(p2p_freqs, 0, sizeof(int) * len);
171
172 for (i = 0, j = 0; i < num && j < len; i++) {
173 if (p2p_supported_freq(wpa_s->global->p2p, freqs[i]))
174 p2p_freqs[j++] = freqs[i];
175 }
176
177 os_free(freqs);
178
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800179 dump_freq_array(wpa_s, "valid for P2P", p2p_freqs, j);
180
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700181 return j;
182}
183
184
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700185static void wpas_p2p_set_own_freq_preference(struct wpa_supplicant *wpa_s,
186 int freq)
187{
188 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
189 return;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700190 if (freq > 0 && wpa_s->num_multichan_concurrent > 1 &&
191 wpas_p2p_num_unused_channels(wpa_s) > 0 &&
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700192 wpa_s->parent->conf->p2p_ignore_shared_freq)
193 freq = 0;
194 p2p_set_own_freq_preference(wpa_s->global->p2p, freq);
195}
196
197
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700198static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s,
199 struct wpa_scan_results *scan_res)
200{
201 size_t i;
202
203 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
204 return;
205
206 wpa_printf(MSG_DEBUG, "P2P: Scan results received (%d BSS)",
207 (int) scan_res->num);
208
209 for (i = 0; i < scan_res->num; i++) {
210 struct wpa_scan_res *bss = scan_res->res[i];
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800211 struct os_time time_tmp_age, entry_ts;
Dmitry Shmidt96571392013-10-14 12:54:46 -0700212 const u8 *ies;
213 size_t ies_len;
214
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800215 time_tmp_age.sec = bss->age / 1000;
216 time_tmp_age.usec = (bss->age % 1000) * 1000;
217 os_time_sub(&scan_res->fetch_time, &time_tmp_age, &entry_ts);
Dmitry Shmidt96571392013-10-14 12:54:46 -0700218
219 ies = (const u8 *) (bss + 1);
220 ies_len = bss->ie_len;
221 if (bss->beacon_ie_len > 0 &&
222 !wpa_scan_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) &&
223 wpa_scan_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) {
224 wpa_printf(MSG_DEBUG, "P2P: Use P2P IE(s) from Beacon frame since no P2P IE(s) in Probe Response frames received for "
225 MACSTR, MAC2STR(bss->bssid));
226 ies = ies + ies_len;
227 ies_len = bss->beacon_ie_len;
228 }
229
230
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700231 if (p2p_scan_res_handler(wpa_s->global->p2p, bss->bssid,
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800232 bss->freq, &entry_ts, bss->level,
Dmitry Shmidt96571392013-10-14 12:54:46 -0700233 ies, ies_len) > 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700234 break;
235 }
236
237 p2p_scan_res_handled(wpa_s->global->p2p);
238}
239
240
241static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
242 unsigned int num_req_dev_types,
Dmitry Shmidt04949592012-07-19 12:16:46 -0700243 const u8 *req_dev_types, const u8 *dev_id, u16 pw_id)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700244{
245 struct wpa_supplicant *wpa_s = ctx;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700246 struct wpa_supplicant *ifs;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700247 struct wpa_driver_scan_params params;
248 int ret;
249 struct wpabuf *wps_ie, *ies;
250 int social_channels[] = { 2412, 2437, 2462, 0, 0 };
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800251 size_t ielen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700252
253 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
254 return -1;
255
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700256 for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
257 if (ifs->sta_scan_pending &&
Dmitry Shmidt37d4d6a2013-03-18 13:09:42 -0700258 (wpas_scan_scheduled(ifs) || ifs->scanning) &&
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700259 wpas_p2p_in_progress(wpa_s) == 2) {
260 wpa_printf(MSG_DEBUG, "Delaying P2P scan to allow "
261 "pending station mode scan to be "
262 "completed on interface %s", ifs->ifname);
Jouni Malinendc7b7132012-09-14 12:53:47 -0700263 wpa_s->global->p2p_cb_on_scan_complete = 1;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700264 wpa_supplicant_req_scan(ifs, 0, 0);
265 return 1;
266 }
267 }
268
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700269 os_memset(&params, 0, sizeof(params));
270
271 /* P2P Wildcard SSID */
272 params.num_ssids = 1;
273 params.ssids[0].ssid = (u8 *) P2P_WILDCARD_SSID;
274 params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
275
276 wpa_s->wps->dev.p2p = 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -0700277 wps_ie = wps_build_probe_req_ie(pw_id, &wpa_s->wps->dev,
278 wpa_s->wps->uuid, WPS_REQ_ENROLLEE,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700279 num_req_dev_types, req_dev_types);
280 if (wps_ie == NULL)
281 return -1;
282
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800283 ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
284 ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700285 if (ies == NULL) {
286 wpabuf_free(wps_ie);
287 return -1;
288 }
289 wpabuf_put_buf(ies, wps_ie);
290 wpabuf_free(wps_ie);
291
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800292 p2p_scan_ie(wpa_s->global->p2p, ies, dev_id);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700293
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800294 params.p2p_probe = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700295 params.extra_ies = wpabuf_head(ies);
296 params.extra_ies_len = wpabuf_len(ies);
297
298 switch (type) {
299 case P2P_SCAN_SOCIAL:
300 params.freqs = social_channels;
301 break;
302 case P2P_SCAN_FULL:
303 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700304 case P2P_SCAN_SOCIAL_PLUS_ONE:
305 social_channels[3] = freq;
306 params.freqs = social_channels;
307 break;
308 }
309
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800310 ret = wpa_drv_scan(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700311
312 wpabuf_free(ies);
313
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800314 if (ret) {
Jouni Malinen043a5a92012-09-13 18:03:14 -0700315 for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
316 if (ifs->scanning ||
317 ifs->scan_res_handler == wpas_p2p_scan_res_handler) {
318 wpa_s->global->p2p_cb_on_scan_complete = 1;
319 ret = 1;
320 break;
321 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800322 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -0700323 } else {
324 os_get_time(&wpa_s->scan_trigger_time);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700325 wpa_s->scan_res_handler = wpas_p2p_scan_res_handler;
Dmitry Shmidt444d5672013-04-01 13:08:44 -0700326 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800327
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700328 return ret;
329}
330
331
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700332static enum wpa_driver_if_type wpas_p2p_if_type(int p2p_group_interface)
333{
334 switch (p2p_group_interface) {
335 case P2P_GROUP_INTERFACE_PENDING:
336 return WPA_IF_P2P_GROUP;
337 case P2P_GROUP_INTERFACE_GO:
338 return WPA_IF_P2P_GO;
339 case P2P_GROUP_INTERFACE_CLIENT:
340 return WPA_IF_P2P_CLIENT;
341 }
342
343 return WPA_IF_P2P_GROUP;
344}
345
346
347static struct wpa_supplicant * wpas_get_p2p_group(struct wpa_supplicant *wpa_s,
348 const u8 *ssid,
349 size_t ssid_len, int *go)
350{
351 struct wpa_ssid *s;
352
353 for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
354 for (s = wpa_s->conf->ssid; s; s = s->next) {
355 if (s->disabled != 0 || !s->p2p_group ||
356 s->ssid_len != ssid_len ||
357 os_memcmp(ssid, s->ssid, ssid_len) != 0)
358 continue;
359 if (s->mode == WPAS_MODE_P2P_GO &&
360 s != wpa_s->current_ssid)
361 continue;
362 if (go)
363 *go = s->mode == WPAS_MODE_P2P_GO;
364 return wpa_s;
365 }
366 }
367
368 return NULL;
369}
370
371
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700372static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s,
373 enum p2p_group_removal_reason removal_reason)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700374{
375 struct wpa_ssid *ssid;
376 char *gtype;
377 const char *reason;
378
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700379 ssid = wpa_s->current_ssid;
380 if (ssid == NULL) {
381 /*
382 * The current SSID was not known, but there may still be a
Dmitry Shmidtaa532512012-09-24 10:35:31 -0700383 * pending P2P group interface waiting for provisioning or a
384 * P2P group that is trying to reconnect.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700385 */
386 ssid = wpa_s->conf->ssid;
387 while (ssid) {
Jouni Malinen9d712832012-10-05 11:01:57 -0700388 if (ssid->p2p_group && ssid->disabled != 2)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700389 break;
390 ssid = ssid->next;
391 }
Jouni Malinen5c44edb2012-08-31 21:35:32 +0300392 if (ssid == NULL &&
393 wpa_s->p2p_group_interface == NOT_P2P_GROUP_INTERFACE)
394 {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700395 wpa_printf(MSG_ERROR, "P2P: P2P group interface "
396 "not found");
397 return -1;
398 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700399 }
400 if (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_GO)
401 gtype = "GO";
402 else if (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT ||
403 (ssid && ssid->mode == WPAS_MODE_INFRA)) {
404 wpa_s->reassociate = 0;
405 wpa_s->disconnected = 1;
406 wpa_supplicant_deauthenticate(wpa_s,
407 WLAN_REASON_DEAUTH_LEAVING);
408 gtype = "client";
409 } else
410 gtype = "GO";
411 if (wpa_s->cross_connect_in_use) {
412 wpa_s->cross_connect_in_use = 0;
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -0700413 wpa_msg_global(wpa_s->parent, MSG_INFO,
414 P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
415 wpa_s->ifname, wpa_s->cross_connect_uplink);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700416 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700417 switch (removal_reason) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700418 case P2P_GROUP_REMOVAL_REQUESTED:
419 reason = " reason=REQUESTED";
420 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700421 case P2P_GROUP_REMOVAL_FORMATION_FAILED:
422 reason = " reason=FORMATION_FAILED";
423 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700424 case P2P_GROUP_REMOVAL_IDLE_TIMEOUT:
425 reason = " reason=IDLE";
426 break;
427 case P2P_GROUP_REMOVAL_UNAVAILABLE:
428 reason = " reason=UNAVAILABLE";
429 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -0700430 case P2P_GROUP_REMOVAL_GO_ENDING_SESSION:
431 reason = " reason=GO_ENDING_SESSION";
432 break;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700433 case P2P_GROUP_REMOVAL_PSK_FAILURE:
434 reason = " reason=PSK_FAILURE";
435 break;
Dmitry Shmidt687922c2012-03-26 14:02:32 -0700436#ifdef ANDROID_P2P
437 case P2P_GROUP_REMOVAL_FREQ_CONFLICT:
438 reason = " reason=FREQ_CONFLICT";
439 break;
440#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700441 default:
442 reason = "";
443 break;
444 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700445 if (removal_reason != P2P_GROUP_REMOVAL_SILENT) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -0700446 wpa_msg_global(wpa_s->parent, MSG_INFO,
447 P2P_EVENT_GROUP_REMOVED "%s %s%s",
448 wpa_s->ifname, gtype, reason);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700449 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700450
Dmitry Shmidt1cf45732013-04-29 17:36:45 -0700451#ifdef ANDROID_P2P
452 eloop_cancel_timeout(wpas_p2p_group_freq_conflict, wpa_s, NULL);
453#endif
Dmitry Shmidt04949592012-07-19 12:16:46 -0700454 if (eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL) > 0)
455 wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group idle timeout");
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800456 if (eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
Dmitry Shmidt2f023192013-03-12 12:44:17 -0700457 wpa_s->parent, NULL) > 0) {
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800458 wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group formation "
459 "timeout");
Dmitry Shmidt2f023192013-03-12 12:44:17 -0700460 wpa_s->p2p_in_provisioning = 0;
461 }
Dmitry Shmidt04949592012-07-19 12:16:46 -0700462
Dmitry Shmidt96571392013-10-14 12:54:46 -0700463 /*
464 * Make sure wait for the first client does not remain active after the
465 * group has been removed.
466 */
467 wpa_s->global->p2p_go_wait_client.sec = 0;
468
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700469 if (removal_reason != P2P_GROUP_REMOVAL_SILENT && ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700470 wpas_notify_p2p_group_removed(wpa_s, ssid, gtype);
471
472 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE) {
473 struct wpa_global *global;
474 char *ifname;
475 enum wpa_driver_if_type type;
476 wpa_printf(MSG_DEBUG, "P2P: Remove group interface %s",
477 wpa_s->ifname);
478 global = wpa_s->global;
479 ifname = os_strdup(wpa_s->ifname);
480 type = wpas_p2p_if_type(wpa_s->p2p_group_interface);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -0700481 wpa_supplicant_remove_iface(wpa_s->global, wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700482 wpa_s = global->ifaces;
483 if (wpa_s && ifname)
484 wpa_drv_if_remove(wpa_s, type, ifname);
485 os_free(ifname);
Jouni Malinen2b89da82012-08-31 22:04:41 +0300486 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700487 }
488
Dmitry Shmidt96571392013-10-14 12:54:46 -0700489 if (!wpa_s->p2p_go_group_formation_completed) {
490 wpa_s->global->p2p_group_formation = NULL;
491 wpa_s->p2p_in_provisioning = 0;
492 }
493
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800494 wpa_s->show_group_started = 0;
495 os_free(wpa_s->go_params);
496 wpa_s->go_params = NULL;
497
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700498 wpa_printf(MSG_DEBUG, "P2P: Remove temporary group network");
499 if (ssid && (ssid->p2p_group ||
500 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION ||
501 (ssid->key_mgmt & WPA_KEY_MGMT_WPS))) {
502 int id = ssid->id;
Jouni Malinen75ecf522011-06-27 15:19:46 -0700503 if (ssid == wpa_s->current_ssid) {
504 wpa_sm_set_config(wpa_s->wpa, NULL);
505 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700506 wpa_s->current_ssid = NULL;
Jouni Malinen75ecf522011-06-27 15:19:46 -0700507 }
508 /*
509 * Networks objects created during any P2P activities are not
510 * exposed out as they might/will confuse certain non-P2P aware
511 * applications since these network objects won't behave like
512 * regular ones.
513 *
514 * Likewise, we don't send out network removed signals for such
515 * network objects.
516 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700517 wpa_config_remove_network(wpa_s->conf, id);
518 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800519 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt91c40cd2012-09-25 14:23:53 -0700520 wpa_s->sta_scan_pending = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700521 } else {
522 wpa_printf(MSG_DEBUG, "P2P: Temporary group network not "
523 "found");
524 }
Dmitry Shmidt04949592012-07-19 12:16:46 -0700525 if (wpa_s->ap_iface)
526 wpa_supplicant_ap_deinit(wpa_s);
527 else
528 wpa_drv_deinit_p2p_cli(wpa_s);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700529
530 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700531}
532
533
534static int wpas_p2p_persistent_group(struct wpa_supplicant *wpa_s,
535 u8 *go_dev_addr,
536 const u8 *ssid, size_t ssid_len)
537{
538 struct wpa_bss *bss;
539 const u8 *bssid;
540 struct wpabuf *p2p;
541 u8 group_capab;
542 const u8 *addr;
543
544 if (wpa_s->go_params)
545 bssid = wpa_s->go_params->peer_interface_addr;
546 else
547 bssid = wpa_s->bssid;
548
549 bss = wpa_bss_get(wpa_s, bssid, ssid, ssid_len);
550 if (bss == NULL) {
551 u8 iface_addr[ETH_ALEN];
552 if (p2p_get_interface_addr(wpa_s->global->p2p, bssid,
553 iface_addr) == 0)
554 bss = wpa_bss_get(wpa_s, iface_addr, ssid, ssid_len);
555 }
556 if (bss == NULL) {
557 wpa_printf(MSG_DEBUG, "P2P: Could not figure out whether "
558 "group is persistent - BSS " MACSTR " not found",
559 MAC2STR(bssid));
560 return 0;
561 }
562
563 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
Dmitry Shmidt96571392013-10-14 12:54:46 -0700564 if (p2p == NULL)
565 p2p = wpa_bss_get_vendor_ie_multi_beacon(bss,
566 P2P_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700567 if (p2p == NULL) {
568 wpa_printf(MSG_DEBUG, "P2P: Could not figure out whether "
569 "group is persistent - BSS " MACSTR
570 " did not include P2P IE", MAC2STR(bssid));
571 wpa_hexdump(MSG_DEBUG, "P2P: Probe Response IEs",
572 (u8 *) (bss + 1), bss->ie_len);
573 wpa_hexdump(MSG_DEBUG, "P2P: Beacon IEs",
574 ((u8 *) bss + 1) + bss->ie_len,
575 bss->beacon_ie_len);
576 return 0;
577 }
578
579 group_capab = p2p_get_group_capab(p2p);
580 addr = p2p_get_go_dev_addr(p2p);
581 wpa_printf(MSG_DEBUG, "P2P: Checking whether group is persistent: "
582 "group_capab=0x%x", group_capab);
583 if (addr) {
584 os_memcpy(go_dev_addr, addr, ETH_ALEN);
585 wpa_printf(MSG_DEBUG, "P2P: GO Device Address " MACSTR,
586 MAC2STR(addr));
587 } else
588 os_memset(go_dev_addr, 0, ETH_ALEN);
589 wpabuf_free(p2p);
590
591 wpa_printf(MSG_DEBUG, "P2P: BSS " MACSTR " group_capab=0x%x "
592 "go_dev_addr=" MACSTR,
593 MAC2STR(bssid), group_capab, MAC2STR(go_dev_addr));
594
595 return group_capab & P2P_GROUP_CAPAB_PERSISTENT_GROUP;
596}
597
598
Jouni Malinen75ecf522011-06-27 15:19:46 -0700599static int wpas_p2p_store_persistent_group(struct wpa_supplicant *wpa_s,
600 struct wpa_ssid *ssid,
601 const u8 *go_dev_addr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700602{
603 struct wpa_ssid *s;
604 int changed = 0;
605
606 wpa_printf(MSG_DEBUG, "P2P: Storing credentials for a persistent "
607 "group (GO Dev Addr " MACSTR ")", MAC2STR(go_dev_addr));
608 for (s = wpa_s->conf->ssid; s; s = s->next) {
609 if (s->disabled == 2 &&
610 os_memcmp(go_dev_addr, s->bssid, ETH_ALEN) == 0 &&
611 s->ssid_len == ssid->ssid_len &&
612 os_memcmp(ssid->ssid, s->ssid, ssid->ssid_len) == 0)
613 break;
614 }
615
616 if (s) {
617 wpa_printf(MSG_DEBUG, "P2P: Update existing persistent group "
618 "entry");
619 if (ssid->passphrase && !s->passphrase)
620 changed = 1;
621 else if (ssid->passphrase && s->passphrase &&
622 os_strcmp(ssid->passphrase, s->passphrase) != 0)
623 changed = 1;
624 } else {
625 wpa_printf(MSG_DEBUG, "P2P: Create a new persistent group "
626 "entry");
627 changed = 1;
628 s = wpa_config_add_network(wpa_s->conf);
629 if (s == NULL)
Jouni Malinen75ecf522011-06-27 15:19:46 -0700630 return -1;
631
632 /*
633 * Instead of network_added we emit persistent_group_added
634 * notification. Also to keep the defense checks in
635 * persistent_group obj registration method, we set the
636 * relevant flags in s to designate it as a persistent group.
637 */
638 s->p2p_group = 1;
639 s->p2p_persistent_group = 1;
640 wpas_notify_persistent_group_added(wpa_s, s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700641 wpa_config_set_network_defaults(s);
642 }
643
644 s->p2p_group = 1;
645 s->p2p_persistent_group = 1;
646 s->disabled = 2;
647 s->bssid_set = 1;
648 os_memcpy(s->bssid, go_dev_addr, ETH_ALEN);
649 s->mode = ssid->mode;
650 s->auth_alg = WPA_AUTH_ALG_OPEN;
651 s->key_mgmt = WPA_KEY_MGMT_PSK;
652 s->proto = WPA_PROTO_RSN;
653 s->pairwise_cipher = WPA_CIPHER_CCMP;
654 s->export_keys = 1;
655 if (ssid->passphrase) {
656 os_free(s->passphrase);
657 s->passphrase = os_strdup(ssid->passphrase);
658 }
659 if (ssid->psk_set) {
660 s->psk_set = 1;
661 os_memcpy(s->psk, ssid->psk, 32);
662 }
663 if (s->passphrase && !s->psk_set)
664 wpa_config_update_psk(s);
665 if (s->ssid == NULL || s->ssid_len < ssid->ssid_len) {
666 os_free(s->ssid);
667 s->ssid = os_malloc(ssid->ssid_len);
668 }
669 if (s->ssid) {
670 s->ssid_len = ssid->ssid_len;
671 os_memcpy(s->ssid, ssid->ssid, s->ssid_len);
672 }
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700673 if (ssid->mode == WPAS_MODE_P2P_GO && wpa_s->global->add_psk) {
674 dl_list_add(&s->psk_list, &wpa_s->global->add_psk->list);
675 wpa_s->global->add_psk = NULL;
676 changed = 1;
677 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700678
679#ifndef CONFIG_NO_CONFIG_WRITE
680 if (changed && wpa_s->conf->update_config &&
681 wpa_config_write(wpa_s->confname, wpa_s->conf)) {
682 wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
683 }
684#endif /* CONFIG_NO_CONFIG_WRITE */
Jouni Malinen75ecf522011-06-27 15:19:46 -0700685
686 return s->id;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700687}
688
689
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800690static void wpas_p2p_add_persistent_group_client(struct wpa_supplicant *wpa_s,
691 const u8 *addr)
692{
693 struct wpa_ssid *ssid, *s;
694 u8 *n;
695 size_t i;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700696 int found = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800697
698 ssid = wpa_s->current_ssid;
699 if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
700 !ssid->p2p_persistent_group)
701 return;
702
703 for (s = wpa_s->parent->conf->ssid; s; s = s->next) {
704 if (s->disabled != 2 || s->mode != WPAS_MODE_P2P_GO)
705 continue;
706
707 if (s->ssid_len == ssid->ssid_len &&
708 os_memcmp(s->ssid, ssid->ssid, s->ssid_len) == 0)
709 break;
710 }
711
712 if (s == NULL)
713 return;
714
715 for (i = 0; s->p2p_client_list && i < s->num_p2p_clients; i++) {
716 if (os_memcmp(s->p2p_client_list + i * ETH_ALEN, addr,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700717 ETH_ALEN) != 0)
718 continue;
719
720 if (i == s->num_p2p_clients - 1)
721 return; /* already the most recent entry */
722
723 /* move the entry to mark it most recent */
724 os_memmove(s->p2p_client_list + i * ETH_ALEN,
725 s->p2p_client_list + (i + 1) * ETH_ALEN,
726 (s->num_p2p_clients - i - 1) * ETH_ALEN);
727 os_memcpy(s->p2p_client_list +
728 (s->num_p2p_clients - 1) * ETH_ALEN, addr, ETH_ALEN);
729 found = 1;
730 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800731 }
732
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700733 if (!found && s->num_p2p_clients < P2P_MAX_STORED_CLIENTS) {
734 n = os_realloc_array(s->p2p_client_list,
735 s->num_p2p_clients + 1, ETH_ALEN);
736 if (n == NULL)
737 return;
738 os_memcpy(n + s->num_p2p_clients * ETH_ALEN, addr, ETH_ALEN);
739 s->p2p_client_list = n;
740 s->num_p2p_clients++;
741 } else if (!found) {
742 /* Not enough room for an additional entry - drop the oldest
743 * entry */
744 os_memmove(s->p2p_client_list,
745 s->p2p_client_list + ETH_ALEN,
746 (s->num_p2p_clients - 1) * ETH_ALEN);
747 os_memcpy(s->p2p_client_list +
748 (s->num_p2p_clients - 1) * ETH_ALEN,
749 addr, ETH_ALEN);
750 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800751
752#ifndef CONFIG_NO_CONFIG_WRITE
753 if (wpa_s->parent->conf->update_config &&
754 wpa_config_write(wpa_s->parent->confname, wpa_s->parent->conf))
755 wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
756#endif /* CONFIG_NO_CONFIG_WRITE */
757}
758
759
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700760static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s,
761 int success)
762{
763 struct wpa_ssid *ssid;
764 const char *ssid_txt;
765 int client;
766 int persistent;
767 u8 go_dev_addr[ETH_ALEN];
Jouni Malinen75ecf522011-06-27 15:19:46 -0700768 int network_id = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700769
770 /*
771 * This callback is likely called for the main interface. Update wpa_s
772 * to use the group interface if a new interface was created for the
773 * group.
774 */
775 if (wpa_s->global->p2p_group_formation)
776 wpa_s = wpa_s->global->p2p_group_formation;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700777 if (wpa_s->p2p_go_group_formation_completed) {
778 wpa_s->global->p2p_group_formation = NULL;
779 wpa_s->p2p_in_provisioning = 0;
780 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700781
782 if (!success) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -0700783 wpa_msg_global(wpa_s->parent, MSG_INFO,
784 P2P_EVENT_GROUP_FORMATION_FAILURE);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700785 wpas_p2p_group_delete(wpa_s,
786 P2P_GROUP_REMOVAL_FORMATION_FAILED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700787 return;
788 }
789
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -0700790 wpa_msg_global(wpa_s->parent, MSG_INFO,
791 P2P_EVENT_GROUP_FORMATION_SUCCESS);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700792
793 ssid = wpa_s->current_ssid;
794 if (ssid && ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
795 ssid->mode = WPAS_MODE_P2P_GO;
796 p2p_group_notif_formation_done(wpa_s->p2p_group);
797 wpa_supplicant_ap_mac_addr_filter(wpa_s, NULL);
798 }
799
800 persistent = 0;
801 if (ssid) {
802 ssid_txt = wpa_ssid_txt(ssid->ssid, ssid->ssid_len);
803 client = ssid->mode == WPAS_MODE_INFRA;
804 if (ssid->mode == WPAS_MODE_P2P_GO) {
805 persistent = ssid->p2p_persistent_group;
Dmitry Shmidt497c1d52011-07-21 15:19:46 -0700806 os_memcpy(go_dev_addr, wpa_s->global->p2p_dev_addr,
807 ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700808 } else
809 persistent = wpas_p2p_persistent_group(wpa_s,
810 go_dev_addr,
811 ssid->ssid,
812 ssid->ssid_len);
813 } else {
814 ssid_txt = "";
815 client = wpa_s->p2p_group_interface ==
816 P2P_GROUP_INTERFACE_CLIENT;
817 os_memset(go_dev_addr, 0, ETH_ALEN);
818 }
819
820 wpa_s->show_group_started = 0;
821 if (client) {
822 /*
823 * Indicate event only after successfully completed 4-way
824 * handshake, i.e., when the interface is ready for data
825 * packets.
826 */
827 wpa_s->show_group_started = 1;
Dmitry Shmidt4b86ea52012-09-04 11:06:50 -0700828#ifdef ANDROID_P2P
829 /* For client Second phase of Group formation (4-way handshake) can be still pending
830 * So we need to restore wpa_s->global->p2p_group_formation */
Dmitry Shmidta2854ab2012-09-10 16:15:47 -0700831 wpa_printf(MSG_INFO, "Restoring back wpa_s->global->p2p_group_formation to wpa_s %p\n", wpa_s);
Dmitry Shmidt4b86ea52012-09-04 11:06:50 -0700832 wpa_s->global->p2p_group_formation = wpa_s;
833#endif
834
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700835 } else if (ssid && ssid->passphrase == NULL && ssid->psk_set) {
836 char psk[65];
837 wpa_snprintf_hex(psk, sizeof(psk), ssid->psk, 32);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -0700838 wpa_msg_global(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
839 "%s GO ssid=\"%s\" freq=%d psk=%s go_dev_addr="
840 MACSTR "%s",
841 wpa_s->ifname, ssid_txt, ssid->frequency, psk,
842 MAC2STR(go_dev_addr),
843 persistent ? " [PERSISTENT]" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700844 wpas_p2p_cross_connect_setup(wpa_s);
845 wpas_p2p_set_group_idle_timeout(wpa_s);
846 } else {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -0700847 wpa_msg_global(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
848 "%s GO ssid=\"%s\" freq=%d passphrase=\"%s\" "
849 "go_dev_addr=" MACSTR "%s",
850 wpa_s->ifname, ssid_txt,
851 ssid ? ssid->frequency : 0,
852 ssid && ssid->passphrase ? ssid->passphrase : "",
853 MAC2STR(go_dev_addr),
854 persistent ? " [PERSISTENT]" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700855 wpas_p2p_cross_connect_setup(wpa_s);
856 wpas_p2p_set_group_idle_timeout(wpa_s);
857 }
858
859 if (persistent)
Jouni Malinen75ecf522011-06-27 15:19:46 -0700860 network_id = wpas_p2p_store_persistent_group(wpa_s->parent,
861 ssid, go_dev_addr);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700862 else {
863 os_free(wpa_s->global->add_psk);
864 wpa_s->global->add_psk = NULL;
865 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800866 if (network_id < 0 && ssid)
Jouni Malinen75ecf522011-06-27 15:19:46 -0700867 network_id = ssid->id;
Dmitry Shmidt92c368d2013-08-29 12:37:21 -0700868 if (!client) {
Jouni Malinen75ecf522011-06-27 15:19:46 -0700869 wpas_notify_p2p_group_started(wpa_s, ssid, network_id, 0);
Dmitry Shmidt92c368d2013-08-29 12:37:21 -0700870 os_get_time(&wpa_s->global->p2p_go_wait_client);
871 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700872}
873
874
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800875static void wpas_p2p_send_action_tx_status(struct wpa_supplicant *wpa_s,
876 unsigned int freq,
877 const u8 *dst, const u8 *src,
878 const u8 *bssid,
879 const u8 *data, size_t data_len,
880 enum offchannel_send_action_result
881 result)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700882{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800883 enum p2p_send_action_result res = P2P_SEND_ACTION_SUCCESS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700884
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700885 if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled)
886 return;
887 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
888 return;
889
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800890 switch (result) {
891 case OFFCHANNEL_SEND_ACTION_SUCCESS:
892 res = P2P_SEND_ACTION_SUCCESS;
893 break;
894 case OFFCHANNEL_SEND_ACTION_NO_ACK:
895 res = P2P_SEND_ACTION_NO_ACK;
896 break;
897 case OFFCHANNEL_SEND_ACTION_FAILED:
898 res = P2P_SEND_ACTION_FAILED;
899 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700900 }
901
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800902 p2p_send_action_cb(wpa_s->global->p2p, freq, dst, src, bssid, res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700903
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800904 if (result != OFFCHANNEL_SEND_ACTION_SUCCESS &&
905 wpa_s->pending_pd_before_join &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800906 (os_memcmp(dst, wpa_s->pending_join_dev_addr, ETH_ALEN) == 0 ||
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800907 os_memcmp(dst, wpa_s->pending_join_iface_addr, ETH_ALEN) == 0) &&
908 wpa_s->p2p_fallback_to_go_neg) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700909 wpa_s->pending_pd_before_join = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800910 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: No ACK for PD Req "
911 "during p2p_connect-auto");
912 wpas_p2p_fallback_to_go_neg(wpa_s, 0);
913 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700914 }
915}
916
917
918static int wpas_send_action(void *ctx, unsigned int freq, const u8 *dst,
919 const u8 *src, const u8 *bssid, const u8 *buf,
920 size_t len, unsigned int wait_time)
921{
922 struct wpa_supplicant *wpa_s = ctx;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800923 return offchannel_send_action(wpa_s, freq, dst, src, bssid, buf, len,
924 wait_time,
925 wpas_p2p_send_action_tx_status, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700926}
927
928
929static void wpas_send_action_done(void *ctx)
930{
931 struct wpa_supplicant *wpa_s = ctx;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800932 offchannel_send_action_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700933}
934
935
936static int wpas_copy_go_neg_results(struct wpa_supplicant *wpa_s,
937 struct p2p_go_neg_results *params)
938{
939 if (wpa_s->go_params == NULL) {
940 wpa_s->go_params = os_malloc(sizeof(*params));
941 if (wpa_s->go_params == NULL)
942 return -1;
943 }
944 os_memcpy(wpa_s->go_params, params, sizeof(*params));
945 return 0;
946}
947
948
949static void wpas_start_wps_enrollee(struct wpa_supplicant *wpa_s,
950 struct p2p_go_neg_results *res)
951{
952 wpa_printf(MSG_DEBUG, "P2P: Start WPS Enrollee for peer " MACSTR,
953 MAC2STR(res->peer_interface_addr));
954 wpa_hexdump_ascii(MSG_DEBUG, "P2P: Start WPS Enrollee for SSID",
955 res->ssid, res->ssid_len);
956 wpa_supplicant_ap_deinit(wpa_s);
957 wpas_copy_go_neg_results(wpa_s, res);
958 if (res->wps_method == WPS_PBC)
959 wpas_wps_start_pbc(wpa_s, res->peer_interface_addr, 1);
960 else {
961 u16 dev_pw_id = DEV_PW_DEFAULT;
962 if (wpa_s->p2p_wps_method == WPS_PIN_KEYPAD)
963 dev_pw_id = DEV_PW_REGISTRAR_SPECIFIED;
964 wpas_wps_start_pin(wpa_s, res->peer_interface_addr,
965 wpa_s->p2p_pin, 1, dev_pw_id);
966 }
967}
968
969
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700970static void wpas_p2p_add_psk_list(struct wpa_supplicant *wpa_s,
971 struct wpa_ssid *ssid)
972{
973 struct wpa_ssid *persistent;
974 struct psk_list_entry *psk;
975 struct hostapd_data *hapd;
976
977 if (!wpa_s->ap_iface)
978 return;
979
980 persistent = wpas_p2p_get_persistent(wpa_s->parent, NULL, ssid->ssid,
981 ssid->ssid_len);
982 if (persistent == NULL)
983 return;
984
985 hapd = wpa_s->ap_iface->bss[0];
986
987 dl_list_for_each(psk, &persistent->psk_list, struct psk_list_entry,
988 list) {
989 struct hostapd_wpa_psk *hpsk;
990
991 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Add persistent group PSK entry for "
992 MACSTR " psk=%d",
993 MAC2STR(psk->addr), psk->p2p);
994 hpsk = os_zalloc(sizeof(*hpsk));
995 if (hpsk == NULL)
996 break;
997 os_memcpy(hpsk->psk, psk->psk, PMK_LEN);
998 if (psk->p2p)
999 os_memcpy(hpsk->p2p_dev_addr, psk->addr, ETH_ALEN);
1000 else
1001 os_memcpy(hpsk->addr, psk->addr, ETH_ALEN);
1002 hpsk->next = hapd->conf->ssid.wpa_psk;
1003 hapd->conf->ssid.wpa_psk = hpsk;
1004 }
1005}
1006
1007
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001008static void p2p_go_configured(void *ctx, void *data)
1009{
1010 struct wpa_supplicant *wpa_s = ctx;
1011 struct p2p_go_neg_results *params = data;
1012 struct wpa_ssid *ssid;
Jouni Malinen75ecf522011-06-27 15:19:46 -07001013 int network_id = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001014
1015 ssid = wpa_s->current_ssid;
1016 if (ssid && ssid->mode == WPAS_MODE_P2P_GO) {
1017 wpa_printf(MSG_DEBUG, "P2P: Group setup without provisioning");
1018 if (wpa_s->global->p2p_group_formation == wpa_s)
1019 wpa_s->global->p2p_group_formation = NULL;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001020 if (os_strlen(params->passphrase) > 0) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001021 wpa_msg_global(wpa_s->parent, MSG_INFO,
1022 P2P_EVENT_GROUP_STARTED
1023 "%s GO ssid=\"%s\" freq=%d "
1024 "passphrase=\"%s\" go_dev_addr=" MACSTR
1025 "%s", wpa_s->ifname,
1026 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
1027 ssid->frequency, params->passphrase,
1028 MAC2STR(wpa_s->global->p2p_dev_addr),
1029 params->persistent_group ?
1030 " [PERSISTENT]" : "");
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001031 } else {
1032 char psk[65];
1033 wpa_snprintf_hex(psk, sizeof(psk), params->psk,
1034 sizeof(params->psk));
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001035 wpa_msg_global(wpa_s->parent, MSG_INFO,
1036 P2P_EVENT_GROUP_STARTED
1037 "%s GO ssid=\"%s\" freq=%d psk=%s "
1038 "go_dev_addr=" MACSTR "%s",
1039 wpa_s->ifname,
1040 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
1041 ssid->frequency, psk,
1042 MAC2STR(wpa_s->global->p2p_dev_addr),
1043 params->persistent_group ?
1044 " [PERSISTENT]" : "");
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001045 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001046
Dmitry Shmidt56052862013-10-04 10:23:25 -07001047 os_get_time(&wpa_s->global->p2p_go_wait_client);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001048 if (params->persistent_group) {
Jouni Malinen75ecf522011-06-27 15:19:46 -07001049 network_id = wpas_p2p_store_persistent_group(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001050 wpa_s->parent, ssid,
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07001051 wpa_s->global->p2p_dev_addr);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001052 wpas_p2p_add_psk_list(wpa_s, ssid);
1053 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07001054 if (network_id < 0)
1055 network_id = ssid->id;
1056 wpas_notify_p2p_group_started(wpa_s, ssid, network_id, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001057 wpas_p2p_cross_connect_setup(wpa_s);
1058 wpas_p2p_set_group_idle_timeout(wpa_s);
Dmitry Shmidt56052862013-10-04 10:23:25 -07001059
1060 if (wpa_s->p2p_first_connection_timeout) {
1061 wpa_dbg(wpa_s, MSG_DEBUG,
1062 "P2P: Start group formation timeout of %d seconds until first data connection on GO",
1063 wpa_s->p2p_first_connection_timeout);
1064 wpa_s->p2p_go_group_formation_completed = 0;
1065 wpa_s->global->p2p_group_formation = wpa_s;
1066 eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
1067 wpa_s->parent, NULL);
1068 eloop_register_timeout(
1069 wpa_s->p2p_first_connection_timeout, 0,
1070 wpas_p2p_group_formation_timeout,
1071 wpa_s->parent, NULL);
1072 }
1073
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001074 return;
1075 }
1076
1077 wpa_printf(MSG_DEBUG, "P2P: Setting up WPS for GO provisioning");
1078 if (wpa_supplicant_ap_mac_addr_filter(wpa_s,
1079 params->peer_interface_addr)) {
1080 wpa_printf(MSG_DEBUG, "P2P: Failed to setup MAC address "
1081 "filtering");
1082 return;
1083 }
1084 if (params->wps_method == WPS_PBC)
1085 wpa_supplicant_ap_wps_pbc(wpa_s, params->peer_interface_addr,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001086 params->peer_device_addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001087 else if (wpa_s->p2p_pin[0])
1088 wpa_supplicant_ap_wps_pin(wpa_s, params->peer_interface_addr,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001089 wpa_s->p2p_pin, NULL, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001090 os_free(wpa_s->go_params);
1091 wpa_s->go_params = NULL;
1092}
1093
1094
1095static void wpas_start_wps_go(struct wpa_supplicant *wpa_s,
1096 struct p2p_go_neg_results *params,
1097 int group_formation)
1098{
1099 struct wpa_ssid *ssid;
1100
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001101 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Starting GO");
1102 if (wpas_copy_go_neg_results(wpa_s, params) < 0) {
1103 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Could not copy GO Negotiation "
1104 "results");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001105 return;
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001106 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001107
1108 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001109 if (ssid == NULL) {
1110 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Could not add network for GO");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001111 return;
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001112 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001113
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001114 wpa_s->show_group_started = 0;
1115
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001116 wpa_config_set_network_defaults(ssid);
1117 ssid->temporary = 1;
1118 ssid->p2p_group = 1;
1119 ssid->p2p_persistent_group = params->persistent_group;
1120 ssid->mode = group_formation ? WPAS_MODE_P2P_GROUP_FORMATION :
1121 WPAS_MODE_P2P_GO;
1122 ssid->frequency = params->freq;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001123 ssid->ht40 = params->ht40;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001124 ssid->vht = params->vht;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001125 ssid->ssid = os_zalloc(params->ssid_len + 1);
1126 if (ssid->ssid) {
1127 os_memcpy(ssid->ssid, params->ssid, params->ssid_len);
1128 ssid->ssid_len = params->ssid_len;
1129 }
1130 ssid->auth_alg = WPA_AUTH_ALG_OPEN;
1131 ssid->key_mgmt = WPA_KEY_MGMT_PSK;
1132 ssid->proto = WPA_PROTO_RSN;
1133 ssid->pairwise_cipher = WPA_CIPHER_CCMP;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001134 if (os_strlen(params->passphrase) > 0) {
1135 ssid->passphrase = os_strdup(params->passphrase);
1136 if (ssid->passphrase == NULL) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001137 wpa_msg_global(wpa_s, MSG_ERROR,
1138 "P2P: Failed to copy passphrase for GO");
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001139 wpa_config_remove_network(wpa_s->conf, ssid->id);
1140 return;
1141 }
1142 } else
1143 ssid->passphrase = NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001144 ssid->psk_set = params->psk_set;
1145 if (ssid->psk_set)
1146 os_memcpy(ssid->psk, params->psk, sizeof(ssid->psk));
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001147 else if (ssid->passphrase)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001148 wpa_config_update_psk(ssid);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001149 ssid->ap_max_inactivity = wpa_s->parent->conf->p2p_go_max_inactivity;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001150
1151 wpa_s->ap_configured_cb = p2p_go_configured;
1152 wpa_s->ap_configured_cb_ctx = wpa_s;
1153 wpa_s->ap_configured_cb_data = wpa_s->go_params;
Jouni Malinen75ecf522011-06-27 15:19:46 -07001154 wpa_s->connect_without_scan = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001155 wpa_s->reassociate = 1;
1156 wpa_s->disconnected = 0;
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001157 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Request scan (that will be skipped) to "
1158 "start GO)");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001159 wpa_supplicant_req_scan(wpa_s, 0, 0);
1160}
1161
1162
1163static void wpas_p2p_clone_config(struct wpa_supplicant *dst,
1164 const struct wpa_supplicant *src)
1165{
1166 struct wpa_config *d;
1167 const struct wpa_config *s;
1168
1169 d = dst->conf;
1170 s = src->conf;
1171
1172#define C(n) if (s->n) d->n = os_strdup(s->n)
1173 C(device_name);
1174 C(manufacturer);
1175 C(model_name);
1176 C(model_number);
1177 C(serial_number);
1178 C(config_methods);
1179#undef C
1180
1181 os_memcpy(d->device_type, s->device_type, WPS_DEV_TYPE_LEN);
1182 os_memcpy(d->sec_device_type, s->sec_device_type,
1183 sizeof(d->sec_device_type));
1184 d->num_sec_device_types = s->num_sec_device_types;
1185
1186 d->p2p_group_idle = s->p2p_group_idle;
1187 d->p2p_intra_bss = s->p2p_intra_bss;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001188 d->persistent_reconnect = s->persistent_reconnect;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001189 d->max_num_sta = s->max_num_sta;
1190 d->pbc_in_m1 = s->pbc_in_m1;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001191 d->ignore_old_scan_res = s->ignore_old_scan_res;
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001192 d->beacon_int = s->beacon_int;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07001193 d->disassoc_low_ack = s->disassoc_low_ack;
Dmitry Shmidt96571392013-10-14 12:54:46 -07001194 d->disable_scan_offload = s->disable_scan_offload;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001195}
1196
1197
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001198static void wpas_p2p_get_group_ifname(struct wpa_supplicant *wpa_s,
1199 char *ifname, size_t len)
1200{
1201 char *ifname_ptr = wpa_s->ifname;
1202
1203 if (os_strncmp(wpa_s->ifname, P2P_MGMT_DEVICE_PREFIX,
1204 os_strlen(P2P_MGMT_DEVICE_PREFIX)) == 0) {
1205 ifname_ptr = os_strrchr(wpa_s->ifname, '-') + 1;
1206 }
1207
1208 os_snprintf(ifname, len, "p2p-%s-%d", ifname_ptr, wpa_s->p2p_group_idx);
1209 if (os_strlen(ifname) >= IFNAMSIZ &&
1210 os_strlen(wpa_s->ifname) < IFNAMSIZ) {
1211 /* Try to avoid going over the IFNAMSIZ length limit */
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001212 os_snprintf(ifname, len, "p2p-%d", wpa_s->p2p_group_idx);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001213 }
1214}
1215
1216
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001217static int wpas_p2p_add_group_interface(struct wpa_supplicant *wpa_s,
1218 enum wpa_driver_if_type type)
1219{
1220 char ifname[120], force_ifname[120];
1221
1222 if (wpa_s->pending_interface_name[0]) {
1223 wpa_printf(MSG_DEBUG, "P2P: Pending virtual interface exists "
1224 "- skip creation of a new one");
1225 if (is_zero_ether_addr(wpa_s->pending_interface_addr)) {
1226 wpa_printf(MSG_DEBUG, "P2P: Pending virtual address "
1227 "unknown?! ifname='%s'",
1228 wpa_s->pending_interface_name);
1229 return -1;
1230 }
1231 return 0;
1232 }
1233
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001234 wpas_p2p_get_group_ifname(wpa_s, ifname, sizeof(ifname));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001235 force_ifname[0] = '\0';
1236
1237 wpa_printf(MSG_DEBUG, "P2P: Create a new interface %s for the group",
1238 ifname);
1239 wpa_s->p2p_group_idx++;
1240
1241 wpa_s->pending_interface_type = type;
1242 if (wpa_drv_if_add(wpa_s, type, ifname, NULL, NULL, force_ifname,
1243 wpa_s->pending_interface_addr, NULL) < 0) {
1244 wpa_printf(MSG_ERROR, "P2P: Failed to create new group "
1245 "interface");
1246 return -1;
1247 }
1248
1249 if (force_ifname[0]) {
1250 wpa_printf(MSG_DEBUG, "P2P: Driver forced interface name %s",
1251 force_ifname);
1252 os_strlcpy(wpa_s->pending_interface_name, force_ifname,
1253 sizeof(wpa_s->pending_interface_name));
1254 } else
1255 os_strlcpy(wpa_s->pending_interface_name, ifname,
1256 sizeof(wpa_s->pending_interface_name));
1257 wpa_printf(MSG_DEBUG, "P2P: Created pending virtual interface %s addr "
1258 MACSTR, wpa_s->pending_interface_name,
1259 MAC2STR(wpa_s->pending_interface_addr));
1260
1261 return 0;
1262}
1263
1264
1265static void wpas_p2p_remove_pending_group_interface(
1266 struct wpa_supplicant *wpa_s)
1267{
1268 if (!wpa_s->pending_interface_name[0] ||
1269 is_zero_ether_addr(wpa_s->pending_interface_addr))
1270 return; /* No pending virtual interface */
1271
1272 wpa_printf(MSG_DEBUG, "P2P: Removing pending group interface %s",
1273 wpa_s->pending_interface_name);
1274 wpa_drv_if_remove(wpa_s, wpa_s->pending_interface_type,
1275 wpa_s->pending_interface_name);
1276 os_memset(wpa_s->pending_interface_addr, 0, ETH_ALEN);
1277 wpa_s->pending_interface_name[0] = '\0';
1278}
1279
1280
1281static struct wpa_supplicant *
1282wpas_p2p_init_group_interface(struct wpa_supplicant *wpa_s, int go)
1283{
1284 struct wpa_interface iface;
1285 struct wpa_supplicant *group_wpa_s;
1286
1287 if (!wpa_s->pending_interface_name[0]) {
1288 wpa_printf(MSG_ERROR, "P2P: No pending group interface");
1289 if (!wpas_p2p_create_iface(wpa_s))
1290 return NULL;
1291 /*
1292 * Something has forced us to remove the pending interface; try
1293 * to create a new one and hope for the best that we will get
1294 * the same local address.
1295 */
1296 if (wpas_p2p_add_group_interface(wpa_s, go ? WPA_IF_P2P_GO :
1297 WPA_IF_P2P_CLIENT) < 0)
1298 return NULL;
1299 }
1300
1301 os_memset(&iface, 0, sizeof(iface));
1302 iface.ifname = wpa_s->pending_interface_name;
1303 iface.driver = wpa_s->driver->name;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001304 if (wpa_s->conf->ctrl_interface == NULL &&
1305 wpa_s->parent != wpa_s &&
1306 wpa_s->p2p_mgmt &&
1307 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE))
1308 iface.ctrl_interface = wpa_s->parent->conf->ctrl_interface;
1309 else
1310 iface.ctrl_interface = wpa_s->conf->ctrl_interface;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001311 iface.driver_param = wpa_s->conf->driver_param;
1312 group_wpa_s = wpa_supplicant_add_iface(wpa_s->global, &iface);
1313 if (group_wpa_s == NULL) {
1314 wpa_printf(MSG_ERROR, "P2P: Failed to create new "
1315 "wpa_supplicant interface");
1316 return NULL;
1317 }
1318 wpa_s->pending_interface_name[0] = '\0';
1319 group_wpa_s->parent = wpa_s;
1320 group_wpa_s->p2p_group_interface = go ? P2P_GROUP_INTERFACE_GO :
1321 P2P_GROUP_INTERFACE_CLIENT;
1322 wpa_s->global->p2p_group_formation = group_wpa_s;
1323
1324 wpas_p2p_clone_config(group_wpa_s, wpa_s);
1325
1326 return group_wpa_s;
1327}
1328
1329
1330static void wpas_p2p_group_formation_timeout(void *eloop_ctx,
1331 void *timeout_ctx)
1332{
1333 struct wpa_supplicant *wpa_s = eloop_ctx;
1334 wpa_printf(MSG_DEBUG, "P2P: Group Formation timed out");
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001335 wpas_p2p_group_formation_failed(wpa_s);
1336}
1337
1338
1339void wpas_p2p_group_formation_failed(struct wpa_supplicant *wpa_s)
1340{
1341 eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
1342 wpa_s->parent, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001343 if (wpa_s->global->p2p)
1344 p2p_group_formation_failed(wpa_s->global->p2p);
1345 else if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
1346 wpa_drv_p2p_group_formation_failed(wpa_s);
1347 wpas_group_formation_completed(wpa_s, 0);
1348}
1349
1350
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001351void wpas_p2p_ap_setup_failed(struct wpa_supplicant *wpa_s)
1352{
1353 if (wpa_s->global->p2p_group_formation != wpa_s)
1354 return;
1355 /* Speed up group formation timeout since this cannot succeed */
1356 eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
1357 wpa_s->parent, NULL);
1358 eloop_register_timeout(0, 0, wpas_p2p_group_formation_timeout,
1359 wpa_s->parent, NULL);
1360}
1361
1362
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001363void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res)
1364{
1365 struct wpa_supplicant *wpa_s = ctx;
1366
1367 if (wpa_s->off_channel_freq || wpa_s->roc_waiting_drv_freq) {
1368 wpa_drv_cancel_remain_on_channel(wpa_s);
1369 wpa_s->off_channel_freq = 0;
1370 wpa_s->roc_waiting_drv_freq = 0;
1371 }
1372
1373 if (res->status) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001374 wpa_msg_global(wpa_s, MSG_INFO,
1375 P2P_EVENT_GO_NEG_FAILURE "status=%d",
1376 res->status);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001377 wpas_notify_p2p_go_neg_completed(wpa_s, res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001378 wpas_p2p_remove_pending_group_interface(wpa_s);
1379 return;
1380 }
1381
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001382 if (wpa_s->p2p_go_ht40)
1383 res->ht40 = 1;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001384 if (wpa_s->p2p_go_vht)
1385 res->vht = 1;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001386
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07001387 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_GO_NEG_SUCCESS "role=%s "
1388 "freq=%d ht40=%d peer_dev=" MACSTR " peer_iface=" MACSTR
1389 " wps_method=%s",
1390 res->role_go ? "GO" : "client", res->freq, res->ht40,
1391 MAC2STR(res->peer_device_addr),
1392 MAC2STR(res->peer_interface_addr),
1393 p2p_wps_method_text(res->wps_method));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001394 wpas_notify_p2p_go_neg_completed(wpa_s, res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001395
Dmitry Shmidt04949592012-07-19 12:16:46 -07001396 if (res->role_go && wpa_s->p2p_persistent_id >= 0) {
1397 struct wpa_ssid *ssid;
1398 ssid = wpa_config_get_network(wpa_s->conf,
1399 wpa_s->p2p_persistent_id);
1400 if (ssid && ssid->disabled == 2 &&
1401 ssid->mode == WPAS_MODE_P2P_GO && ssid->passphrase) {
1402 size_t len = os_strlen(ssid->passphrase);
1403 wpa_printf(MSG_DEBUG, "P2P: Override passphrase based "
1404 "on requested persistent group");
1405 os_memcpy(res->passphrase, ssid->passphrase, len);
1406 res->passphrase[len] = '\0';
1407 }
1408 }
1409
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001410 if (wpa_s->create_p2p_iface) {
1411 struct wpa_supplicant *group_wpa_s =
1412 wpas_p2p_init_group_interface(wpa_s, res->role_go);
1413 if (group_wpa_s == NULL) {
1414 wpas_p2p_remove_pending_group_interface(wpa_s);
1415 return;
1416 }
1417 if (group_wpa_s != wpa_s) {
1418 os_memcpy(group_wpa_s->p2p_pin, wpa_s->p2p_pin,
1419 sizeof(group_wpa_s->p2p_pin));
1420 group_wpa_s->p2p_wps_method = wpa_s->p2p_wps_method;
1421 }
1422 os_memset(wpa_s->pending_interface_addr, 0, ETH_ALEN);
1423 wpa_s->pending_interface_name[0] = '\0';
1424 group_wpa_s->p2p_in_provisioning = 1;
1425
1426 if (res->role_go)
1427 wpas_start_wps_go(group_wpa_s, res, 1);
1428 else
1429 wpas_start_wps_enrollee(group_wpa_s, res);
1430 } else {
1431 wpa_s->p2p_in_provisioning = 1;
1432 wpa_s->global->p2p_group_formation = wpa_s;
1433
1434 if (res->role_go)
1435 wpas_start_wps_go(wpa_s, res, 1);
1436 else
1437 wpas_start_wps_enrollee(ctx, res);
1438 }
1439
1440 wpa_s->p2p_long_listen = 0;
1441 eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL);
1442
1443 eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s, NULL);
1444 eloop_register_timeout(15 + res->peer_config_timeout / 100,
1445 (res->peer_config_timeout % 100) * 10000,
1446 wpas_p2p_group_formation_timeout, wpa_s, NULL);
1447}
1448
1449
1450void wpas_go_neg_req_rx(void *ctx, const u8 *src, u16 dev_passwd_id)
1451{
1452 struct wpa_supplicant *wpa_s = ctx;
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001453 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_GO_NEG_REQUEST MACSTR
1454 " dev_passwd_id=%u", MAC2STR(src), dev_passwd_id);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001455
1456 wpas_notify_p2p_go_neg_req(wpa_s, src, dev_passwd_id);
1457}
1458
1459
1460void wpas_dev_found(void *ctx, const u8 *addr,
1461 const struct p2p_peer_info *info,
1462 int new_device)
1463{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001464#ifndef CONFIG_NO_STDOUT_DEBUG
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001465 struct wpa_supplicant *wpa_s = ctx;
1466 char devtype[WPS_DEV_TYPE_BUFSIZE];
Irfan Sheriff8367dc92012-09-09 17:08:19 -07001467#define WFD_DEV_INFO_SIZE 9
1468 char wfd_dev_info_hex[2 * WFD_DEV_INFO_SIZE + 1];
Irfan Sheriff8d965182012-09-11 08:58:24 -07001469 os_memset(wfd_dev_info_hex, 0, sizeof(wfd_dev_info_hex));
Irfan Sheriff8367dc92012-09-09 17:08:19 -07001470#ifdef CONFIG_WIFI_DISPLAY
1471 if (info->wfd_subelems) {
1472 wpa_snprintf_hex(wfd_dev_info_hex, sizeof(wfd_dev_info_hex),
1473 wpabuf_head(info->wfd_subelems),
1474 WFD_DEV_INFO_SIZE);
1475 }
1476#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001477 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_DEVICE_FOUND MACSTR
1478 " p2p_dev_addr=" MACSTR
1479 " pri_dev_type=%s name='%s' config_methods=0x%x "
1480 "dev_capab=0x%x group_capab=0x%x%s%s",
1481 MAC2STR(addr), MAC2STR(info->p2p_device_addr),
1482 wps_dev_type_bin2str(info->pri_dev_type, devtype,
1483 sizeof(devtype)),
1484 info->device_name, info->config_methods,
1485 info->dev_capab, info->group_capab,
1486 wfd_dev_info_hex[0] ? " wfd_dev_info=0x" : "", wfd_dev_info_hex);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001487#endif /* CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001488
1489 wpas_notify_p2p_device_found(ctx, info->p2p_device_addr, new_device);
1490}
1491
1492
1493static void wpas_dev_lost(void *ctx, const u8 *dev_addr)
1494{
1495 struct wpa_supplicant *wpa_s = ctx;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001496
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001497 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_DEVICE_LOST
1498 "p2p_dev_addr=" MACSTR, MAC2STR(dev_addr));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001499
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001500 wpas_notify_p2p_device_lost(wpa_s, dev_addr);
1501}
1502
1503
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001504static void wpas_find_stopped(void *ctx)
1505{
1506 struct wpa_supplicant *wpa_s = ctx;
1507 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_FIND_STOPPED);
1508}
1509
1510
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001511static int wpas_start_listen(void *ctx, unsigned int freq,
1512 unsigned int duration,
1513 const struct wpabuf *probe_resp_ie)
1514{
1515 struct wpa_supplicant *wpa_s = ctx;
1516
1517 wpa_drv_set_ap_wps_ie(wpa_s, NULL, probe_resp_ie, NULL);
1518
1519 if (wpa_drv_probe_req_report(wpa_s, 1) < 0) {
1520 wpa_printf(MSG_DEBUG, "P2P: Failed to request the driver to "
1521 "report received Probe Request frames");
1522 return -1;
1523 }
1524
1525 wpa_s->pending_listen_freq = freq;
1526 wpa_s->pending_listen_duration = duration;
1527
1528 if (wpa_drv_remain_on_channel(wpa_s, freq, duration) < 0) {
1529 wpa_printf(MSG_DEBUG, "P2P: Failed to request the driver "
1530 "to remain on channel (%u MHz) for Listen "
1531 "state", freq);
1532 wpa_s->pending_listen_freq = 0;
1533 return -1;
1534 }
1535 wpa_s->off_channel_freq = 0;
1536 wpa_s->roc_waiting_drv_freq = freq;
1537
1538 return 0;
1539}
1540
1541
1542static void wpas_stop_listen(void *ctx)
1543{
1544 struct wpa_supplicant *wpa_s = ctx;
1545 if (wpa_s->off_channel_freq || wpa_s->roc_waiting_drv_freq) {
1546 wpa_drv_cancel_remain_on_channel(wpa_s);
1547 wpa_s->off_channel_freq = 0;
1548 wpa_s->roc_waiting_drv_freq = 0;
1549 }
1550 wpa_drv_set_ap_wps_ie(wpa_s, NULL, NULL, NULL);
1551 wpa_drv_probe_req_report(wpa_s, 0);
1552}
1553
1554
1555static int wpas_send_probe_resp(void *ctx, const struct wpabuf *buf)
1556{
1557 struct wpa_supplicant *wpa_s = ctx;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001558 return wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001559}
1560
1561
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001562/*
1563 * DNS Header section is used only to calculate compression pointers, so the
1564 * contents of this data does not matter, but the length needs to be reserved
1565 * in the virtual packet.
1566 */
1567#define DNS_HEADER_LEN 12
1568
1569/*
1570 * 27-octet in-memory packet from P2P specification containing two implied
1571 * queries for _tcp.lcoal. PTR IN and _udp.local. PTR IN
1572 */
1573#define P2P_SD_IN_MEMORY_LEN 27
1574
1575static int p2p_sd_dns_uncompress_label(char **upos, char *uend, u8 *start,
1576 u8 **spos, const u8 *end)
1577{
1578 while (*spos < end) {
1579 u8 val = ((*spos)[0] & 0xc0) >> 6;
1580 int len;
1581
1582 if (val == 1 || val == 2) {
1583 /* These are reserved values in RFC 1035 */
1584 wpa_printf(MSG_DEBUG, "P2P: Invalid domain name "
1585 "sequence starting with 0x%x", val);
1586 return -1;
1587 }
1588
1589 if (val == 3) {
1590 u16 offset;
1591 u8 *spos_tmp;
1592
1593 /* Offset */
1594 if (*spos + 2 > end) {
1595 wpa_printf(MSG_DEBUG, "P2P: No room for full "
1596 "DNS offset field");
1597 return -1;
1598 }
1599
1600 offset = (((*spos)[0] & 0x3f) << 8) | (*spos)[1];
1601 if (offset >= *spos - start) {
1602 wpa_printf(MSG_DEBUG, "P2P: Invalid DNS "
1603 "pointer offset %u", offset);
1604 return -1;
1605 }
1606
1607 (*spos) += 2;
1608 spos_tmp = start + offset;
1609 return p2p_sd_dns_uncompress_label(upos, uend, start,
1610 &spos_tmp,
1611 *spos - 2);
1612 }
1613
1614 /* Label */
1615 len = (*spos)[0] & 0x3f;
1616 if (len == 0)
1617 return 0;
1618
1619 (*spos)++;
1620 if (*spos + len > end) {
1621 wpa_printf(MSG_DEBUG, "P2P: Invalid domain name "
1622 "sequence - no room for label with length "
1623 "%u", len);
1624 return -1;
1625 }
1626
1627 if (*upos + len + 2 > uend)
1628 return -2;
1629
1630 os_memcpy(*upos, *spos, len);
1631 *spos += len;
1632 *upos += len;
1633 (*upos)[0] = '.';
1634 (*upos)++;
1635 (*upos)[0] = '\0';
1636 }
1637
1638 return 0;
1639}
1640
1641
1642/* Uncompress domain names per RFC 1035 using the P2P SD in-memory packet.
1643 * Returns -1 on parsing error (invalid input sequence), -2 if output buffer is
1644 * not large enough */
1645static int p2p_sd_dns_uncompress(char *buf, size_t buf_len, const u8 *msg,
1646 size_t msg_len, size_t offset)
1647{
1648 /* 27-octet in-memory packet from P2P specification */
1649 const char *prefix = "\x04_tcp\x05local\x00\x00\x0C\x00\x01"
1650 "\x04_udp\xC0\x11\x00\x0C\x00\x01";
1651 u8 *tmp, *end, *spos;
1652 char *upos, *uend;
1653 int ret = 0;
1654
1655 if (buf_len < 2)
1656 return -1;
1657 if (offset > msg_len)
1658 return -1;
1659
1660 tmp = os_malloc(DNS_HEADER_LEN + P2P_SD_IN_MEMORY_LEN + msg_len);
1661 if (tmp == NULL)
1662 return -1;
1663 spos = tmp + DNS_HEADER_LEN + P2P_SD_IN_MEMORY_LEN;
1664 end = spos + msg_len;
1665 spos += offset;
1666
1667 os_memset(tmp, 0, DNS_HEADER_LEN);
1668 os_memcpy(tmp + DNS_HEADER_LEN, prefix, P2P_SD_IN_MEMORY_LEN);
1669 os_memcpy(tmp + DNS_HEADER_LEN + P2P_SD_IN_MEMORY_LEN, msg, msg_len);
1670
1671 upos = buf;
1672 uend = buf + buf_len;
1673
1674 ret = p2p_sd_dns_uncompress_label(&upos, uend, tmp, &spos, end);
1675 if (ret) {
1676 os_free(tmp);
1677 return ret;
1678 }
1679
1680 if (upos == buf) {
1681 upos[0] = '.';
1682 upos[1] = '\0';
1683 } else if (upos[-1] == '.')
1684 upos[-1] = '\0';
1685
1686 os_free(tmp);
1687 return 0;
1688}
1689
1690
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001691static struct p2p_srv_bonjour *
1692wpas_p2p_service_get_bonjour(struct wpa_supplicant *wpa_s,
1693 const struct wpabuf *query)
1694{
1695 struct p2p_srv_bonjour *bsrv;
1696 size_t len;
1697
1698 len = wpabuf_len(query);
1699 dl_list_for_each(bsrv, &wpa_s->global->p2p_srv_bonjour,
1700 struct p2p_srv_bonjour, list) {
1701 if (len == wpabuf_len(bsrv->query) &&
1702 os_memcmp(wpabuf_head(query), wpabuf_head(bsrv->query),
1703 len) == 0)
1704 return bsrv;
1705 }
1706 return NULL;
1707}
1708
1709
1710static struct p2p_srv_upnp *
1711wpas_p2p_service_get_upnp(struct wpa_supplicant *wpa_s, u8 version,
1712 const char *service)
1713{
1714 struct p2p_srv_upnp *usrv;
1715
1716 dl_list_for_each(usrv, &wpa_s->global->p2p_srv_upnp,
1717 struct p2p_srv_upnp, list) {
1718 if (version == usrv->version &&
1719 os_strcmp(service, usrv->service) == 0)
1720 return usrv;
1721 }
1722 return NULL;
1723}
1724
1725
1726static void wpas_sd_add_proto_not_avail(struct wpabuf *resp, u8 srv_proto,
1727 u8 srv_trans_id)
1728{
1729 u8 *len_pos;
1730
1731 if (wpabuf_tailroom(resp) < 5)
1732 return;
1733
1734 /* Length (to be filled) */
1735 len_pos = wpabuf_put(resp, 2);
1736 wpabuf_put_u8(resp, srv_proto);
1737 wpabuf_put_u8(resp, srv_trans_id);
1738 /* Status Code */
1739 wpabuf_put_u8(resp, P2P_SD_PROTO_NOT_AVAILABLE);
1740 /* Response Data: empty */
1741 WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos - 2);
1742}
1743
1744
1745static void wpas_sd_all_bonjour(struct wpa_supplicant *wpa_s,
1746 struct wpabuf *resp, u8 srv_trans_id)
1747{
1748 struct p2p_srv_bonjour *bsrv;
1749 u8 *len_pos;
1750
1751 wpa_printf(MSG_DEBUG, "P2P: SD Request for all Bonjour services");
1752
1753 if (dl_list_empty(&wpa_s->global->p2p_srv_bonjour)) {
1754 wpa_printf(MSG_DEBUG, "P2P: Bonjour protocol not available");
1755 return;
1756 }
1757
1758 dl_list_for_each(bsrv, &wpa_s->global->p2p_srv_bonjour,
1759 struct p2p_srv_bonjour, list) {
1760 if (wpabuf_tailroom(resp) <
1761 5 + wpabuf_len(bsrv->query) + wpabuf_len(bsrv->resp))
1762 return;
1763 /* Length (to be filled) */
1764 len_pos = wpabuf_put(resp, 2);
1765 wpabuf_put_u8(resp, P2P_SERV_BONJOUR);
1766 wpabuf_put_u8(resp, srv_trans_id);
1767 /* Status Code */
1768 wpabuf_put_u8(resp, P2P_SD_SUCCESS);
1769 wpa_hexdump_ascii(MSG_DEBUG, "P2P: Matching Bonjour service",
1770 wpabuf_head(bsrv->resp),
1771 wpabuf_len(bsrv->resp));
1772 /* Response Data */
1773 wpabuf_put_buf(resp, bsrv->query); /* Key */
1774 wpabuf_put_buf(resp, bsrv->resp); /* Value */
1775 WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos -
1776 2);
1777 }
1778}
1779
1780
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001781static int match_bonjour_query(struct p2p_srv_bonjour *bsrv, const u8 *query,
1782 size_t query_len)
1783{
1784 char str_rx[256], str_srv[256];
1785
1786 if (query_len < 3 || wpabuf_len(bsrv->query) < 3)
1787 return 0; /* Too short to include DNS Type and Version */
1788 if (os_memcmp(query + query_len - 3,
1789 wpabuf_head_u8(bsrv->query) + wpabuf_len(bsrv->query) - 3,
1790 3) != 0)
1791 return 0; /* Mismatch in DNS Type or Version */
1792 if (query_len == wpabuf_len(bsrv->query) &&
1793 os_memcmp(query, wpabuf_head(bsrv->query), query_len - 3) == 0)
1794 return 1; /* Binary match */
1795
1796 if (p2p_sd_dns_uncompress(str_rx, sizeof(str_rx), query, query_len - 3,
1797 0))
1798 return 0; /* Failed to uncompress query */
1799 if (p2p_sd_dns_uncompress(str_srv, sizeof(str_srv),
1800 wpabuf_head(bsrv->query),
1801 wpabuf_len(bsrv->query) - 3, 0))
1802 return 0; /* Failed to uncompress service */
1803
1804 return os_strcmp(str_rx, str_srv) == 0;
1805}
1806
1807
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001808static void wpas_sd_req_bonjour(struct wpa_supplicant *wpa_s,
1809 struct wpabuf *resp, u8 srv_trans_id,
1810 const u8 *query, size_t query_len)
1811{
1812 struct p2p_srv_bonjour *bsrv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001813 u8 *len_pos;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001814 int matches = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001815
1816 wpa_hexdump_ascii(MSG_DEBUG, "P2P: SD Request for Bonjour",
1817 query, query_len);
1818 if (dl_list_empty(&wpa_s->global->p2p_srv_bonjour)) {
1819 wpa_printf(MSG_DEBUG, "P2P: Bonjour protocol not available");
1820 wpas_sd_add_proto_not_avail(resp, P2P_SERV_BONJOUR,
1821 srv_trans_id);
1822 return;
1823 }
1824
1825 if (query_len == 0) {
1826 wpas_sd_all_bonjour(wpa_s, resp, srv_trans_id);
1827 return;
1828 }
1829
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001830 dl_list_for_each(bsrv, &wpa_s->global->p2p_srv_bonjour,
1831 struct p2p_srv_bonjour, list) {
1832 if (!match_bonjour_query(bsrv, query, query_len))
1833 continue;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001834
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001835 if (wpabuf_tailroom(resp) <
1836 5 + query_len + wpabuf_len(bsrv->resp))
1837 return;
1838
1839 matches++;
1840
1841 /* Length (to be filled) */
1842 len_pos = wpabuf_put(resp, 2);
1843 wpabuf_put_u8(resp, P2P_SERV_BONJOUR);
1844 wpabuf_put_u8(resp, srv_trans_id);
1845
1846 /* Status Code */
1847 wpabuf_put_u8(resp, P2P_SD_SUCCESS);
1848 wpa_hexdump_ascii(MSG_DEBUG, "P2P: Matching Bonjour service",
1849 wpabuf_head(bsrv->resp),
1850 wpabuf_len(bsrv->resp));
1851
1852 /* Response Data */
1853 wpabuf_put_data(resp, query, query_len); /* Key */
1854 wpabuf_put_buf(resp, bsrv->resp); /* Value */
1855
1856 WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos - 2);
1857 }
1858
1859 if (matches == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001860 wpa_printf(MSG_DEBUG, "P2P: Requested Bonjour service not "
1861 "available");
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001862 if (wpabuf_tailroom(resp) < 5)
1863 return;
1864
1865 /* Length (to be filled) */
1866 len_pos = wpabuf_put(resp, 2);
1867 wpabuf_put_u8(resp, P2P_SERV_BONJOUR);
1868 wpabuf_put_u8(resp, srv_trans_id);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001869
1870 /* Status Code */
1871 wpabuf_put_u8(resp, P2P_SD_REQUESTED_INFO_NOT_AVAILABLE);
1872 /* Response Data: empty */
1873 WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos -
1874 2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001875 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001876}
1877
1878
1879static void wpas_sd_all_upnp(struct wpa_supplicant *wpa_s,
1880 struct wpabuf *resp, u8 srv_trans_id)
1881{
1882 struct p2p_srv_upnp *usrv;
1883 u8 *len_pos;
1884
1885 wpa_printf(MSG_DEBUG, "P2P: SD Request for all UPnP services");
1886
1887 if (dl_list_empty(&wpa_s->global->p2p_srv_upnp)) {
1888 wpa_printf(MSG_DEBUG, "P2P: UPnP protocol not available");
1889 return;
1890 }
1891
1892 dl_list_for_each(usrv, &wpa_s->global->p2p_srv_upnp,
1893 struct p2p_srv_upnp, list) {
1894 if (wpabuf_tailroom(resp) < 5 + 1 + os_strlen(usrv->service))
1895 return;
1896
1897 /* Length (to be filled) */
1898 len_pos = wpabuf_put(resp, 2);
1899 wpabuf_put_u8(resp, P2P_SERV_UPNP);
1900 wpabuf_put_u8(resp, srv_trans_id);
1901
1902 /* Status Code */
1903 wpabuf_put_u8(resp, P2P_SD_SUCCESS);
1904 /* Response Data */
1905 wpabuf_put_u8(resp, usrv->version);
1906 wpa_printf(MSG_DEBUG, "P2P: Matching UPnP Service: %s",
1907 usrv->service);
1908 wpabuf_put_str(resp, usrv->service);
1909 WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos -
1910 2);
1911 }
1912}
1913
1914
1915static void wpas_sd_req_upnp(struct wpa_supplicant *wpa_s,
1916 struct wpabuf *resp, u8 srv_trans_id,
1917 const u8 *query, size_t query_len)
1918{
1919 struct p2p_srv_upnp *usrv;
1920 u8 *len_pos;
1921 u8 version;
1922 char *str;
1923 int count = 0;
1924
1925 wpa_hexdump_ascii(MSG_DEBUG, "P2P: SD Request for UPnP",
1926 query, query_len);
1927
1928 if (dl_list_empty(&wpa_s->global->p2p_srv_upnp)) {
1929 wpa_printf(MSG_DEBUG, "P2P: UPnP protocol not available");
1930 wpas_sd_add_proto_not_avail(resp, P2P_SERV_UPNP,
1931 srv_trans_id);
1932 return;
1933 }
1934
1935 if (query_len == 0) {
1936 wpas_sd_all_upnp(wpa_s, resp, srv_trans_id);
1937 return;
1938 }
1939
1940 if (wpabuf_tailroom(resp) < 5)
1941 return;
1942
1943 /* Length (to be filled) */
1944 len_pos = wpabuf_put(resp, 2);
1945 wpabuf_put_u8(resp, P2P_SERV_UPNP);
1946 wpabuf_put_u8(resp, srv_trans_id);
1947
1948 version = query[0];
1949 str = os_malloc(query_len);
1950 if (str == NULL)
1951 return;
1952 os_memcpy(str, query + 1, query_len - 1);
1953 str[query_len - 1] = '\0';
1954
1955 dl_list_for_each(usrv, &wpa_s->global->p2p_srv_upnp,
1956 struct p2p_srv_upnp, list) {
1957 if (version != usrv->version)
1958 continue;
1959
1960 if (os_strcmp(str, "ssdp:all") != 0 &&
1961 os_strstr(usrv->service, str) == NULL)
1962 continue;
1963
1964 if (wpabuf_tailroom(resp) < 2)
1965 break;
1966 if (count == 0) {
1967 /* Status Code */
1968 wpabuf_put_u8(resp, P2P_SD_SUCCESS);
1969 /* Response Data */
1970 wpabuf_put_u8(resp, version);
1971 } else
1972 wpabuf_put_u8(resp, ',');
1973
1974 count++;
1975
1976 wpa_printf(MSG_DEBUG, "P2P: Matching UPnP Service: %s",
1977 usrv->service);
1978 if (wpabuf_tailroom(resp) < os_strlen(usrv->service))
1979 break;
1980 wpabuf_put_str(resp, usrv->service);
1981 }
1982 os_free(str);
1983
1984 if (count == 0) {
1985 wpa_printf(MSG_DEBUG, "P2P: Requested UPnP service not "
1986 "available");
1987 /* Status Code */
1988 wpabuf_put_u8(resp, P2P_SD_REQUESTED_INFO_NOT_AVAILABLE);
1989 /* Response Data: empty */
1990 }
1991
1992 WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos - 2);
1993}
1994
1995
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001996#ifdef CONFIG_WIFI_DISPLAY
1997static void wpas_sd_req_wfd(struct wpa_supplicant *wpa_s,
1998 struct wpabuf *resp, u8 srv_trans_id,
1999 const u8 *query, size_t query_len)
2000{
2001 const u8 *pos;
2002 u8 role;
2003 u8 *len_pos;
2004
2005 wpa_hexdump(MSG_DEBUG, "P2P: SD Request for WFD", query, query_len);
2006
2007 if (!wpa_s->global->wifi_display) {
2008 wpa_printf(MSG_DEBUG, "P2P: WFD protocol not available");
2009 wpas_sd_add_proto_not_avail(resp, P2P_SERV_WIFI_DISPLAY,
2010 srv_trans_id);
2011 return;
2012 }
2013
2014 if (query_len < 1) {
2015 wpa_printf(MSG_DEBUG, "P2P: Missing WFD Requested Device "
2016 "Role");
2017 return;
2018 }
2019
2020 if (wpabuf_tailroom(resp) < 5)
2021 return;
2022
2023 pos = query;
2024 role = *pos++;
2025 wpa_printf(MSG_DEBUG, "P2P: WSD for device role 0x%x", role);
2026
2027 /* TODO: role specific handling */
2028
2029 /* Length (to be filled) */
2030 len_pos = wpabuf_put(resp, 2);
2031 wpabuf_put_u8(resp, P2P_SERV_WIFI_DISPLAY);
2032 wpabuf_put_u8(resp, srv_trans_id);
2033 wpabuf_put_u8(resp, P2P_SD_SUCCESS); /* Status Code */
2034
2035 while (pos < query + query_len) {
2036 if (*pos < MAX_WFD_SUBELEMS &&
2037 wpa_s->global->wfd_subelem[*pos] &&
2038 wpabuf_tailroom(resp) >=
2039 wpabuf_len(wpa_s->global->wfd_subelem[*pos])) {
2040 wpa_printf(MSG_DEBUG, "P2P: Add WSD response "
2041 "subelement %u", *pos);
2042 wpabuf_put_buf(resp, wpa_s->global->wfd_subelem[*pos]);
2043 }
2044 pos++;
2045 }
2046
2047 WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos - 2);
2048}
2049#endif /* CONFIG_WIFI_DISPLAY */
2050
2051
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002052void wpas_sd_request(void *ctx, int freq, const u8 *sa, u8 dialog_token,
2053 u16 update_indic, const u8 *tlvs, size_t tlvs_len)
2054{
2055 struct wpa_supplicant *wpa_s = ctx;
2056 const u8 *pos = tlvs;
2057 const u8 *end = tlvs + tlvs_len;
2058 const u8 *tlv_end;
2059 u16 slen;
2060 struct wpabuf *resp;
2061 u8 srv_proto, srv_trans_id;
2062 size_t buf_len;
2063 char *buf;
2064
2065 wpa_hexdump(MSG_MSGDUMP, "P2P: Service Discovery Request TLVs",
2066 tlvs, tlvs_len);
2067 buf_len = 2 * tlvs_len + 1;
2068 buf = os_malloc(buf_len);
2069 if (buf) {
2070 wpa_snprintf_hex(buf, buf_len, tlvs, tlvs_len);
2071 wpa_msg_ctrl(wpa_s, MSG_INFO, P2P_EVENT_SERV_DISC_REQ "%d "
2072 MACSTR " %u %u %s",
2073 freq, MAC2STR(sa), dialog_token, update_indic,
2074 buf);
2075 os_free(buf);
2076 }
2077
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002078 if (wpa_s->p2p_sd_over_ctrl_iface) {
2079 wpas_notify_p2p_sd_request(wpa_s, freq, sa, dialog_token,
2080 update_indic, tlvs, tlvs_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002081 return; /* to be processed by an external program */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002082 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002083
2084 resp = wpabuf_alloc(10000);
2085 if (resp == NULL)
2086 return;
2087
2088 while (pos + 1 < end) {
2089 wpa_printf(MSG_DEBUG, "P2P: Service Request TLV");
2090 slen = WPA_GET_LE16(pos);
2091 pos += 2;
2092 if (pos + slen > end || slen < 2) {
2093 wpa_printf(MSG_DEBUG, "P2P: Unexpected Query Data "
2094 "length");
2095 wpabuf_free(resp);
2096 return;
2097 }
2098 tlv_end = pos + slen;
2099
2100 srv_proto = *pos++;
2101 wpa_printf(MSG_DEBUG, "P2P: Service Protocol Type %u",
2102 srv_proto);
2103 srv_trans_id = *pos++;
2104 wpa_printf(MSG_DEBUG, "P2P: Service Transaction ID %u",
2105 srv_trans_id);
2106
2107 wpa_hexdump(MSG_MSGDUMP, "P2P: Query Data",
2108 pos, tlv_end - pos);
2109
2110
2111 if (wpa_s->force_long_sd) {
2112 wpa_printf(MSG_DEBUG, "P2P: SD test - force long "
2113 "response");
2114 wpas_sd_all_bonjour(wpa_s, resp, srv_trans_id);
2115 wpas_sd_all_upnp(wpa_s, resp, srv_trans_id);
2116 goto done;
2117 }
2118
2119 switch (srv_proto) {
2120 case P2P_SERV_ALL_SERVICES:
2121 wpa_printf(MSG_DEBUG, "P2P: Service Discovery Request "
2122 "for all services");
2123 if (dl_list_empty(&wpa_s->global->p2p_srv_upnp) &&
2124 dl_list_empty(&wpa_s->global->p2p_srv_bonjour)) {
2125 wpa_printf(MSG_DEBUG, "P2P: No service "
2126 "discovery protocols available");
2127 wpas_sd_add_proto_not_avail(
2128 resp, P2P_SERV_ALL_SERVICES,
2129 srv_trans_id);
2130 break;
2131 }
2132 wpas_sd_all_bonjour(wpa_s, resp, srv_trans_id);
2133 wpas_sd_all_upnp(wpa_s, resp, srv_trans_id);
2134 break;
2135 case P2P_SERV_BONJOUR:
2136 wpas_sd_req_bonjour(wpa_s, resp, srv_trans_id,
2137 pos, tlv_end - pos);
2138 break;
2139 case P2P_SERV_UPNP:
2140 wpas_sd_req_upnp(wpa_s, resp, srv_trans_id,
2141 pos, tlv_end - pos);
2142 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002143#ifdef CONFIG_WIFI_DISPLAY
2144 case P2P_SERV_WIFI_DISPLAY:
2145 wpas_sd_req_wfd(wpa_s, resp, srv_trans_id,
2146 pos, tlv_end - pos);
2147 break;
2148#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002149 default:
2150 wpa_printf(MSG_DEBUG, "P2P: Unavailable service "
2151 "protocol %u", srv_proto);
2152 wpas_sd_add_proto_not_avail(resp, srv_proto,
2153 srv_trans_id);
2154 break;
2155 }
2156
2157 pos = tlv_end;
2158 }
2159
2160done:
2161 wpas_notify_p2p_sd_request(wpa_s, freq, sa, dialog_token,
2162 update_indic, tlvs, tlvs_len);
2163
2164 wpas_p2p_sd_response(wpa_s, freq, sa, dialog_token, resp);
2165
2166 wpabuf_free(resp);
2167}
2168
2169
2170void wpas_sd_response(void *ctx, const u8 *sa, u16 update_indic,
2171 const u8 *tlvs, size_t tlvs_len)
2172{
2173 struct wpa_supplicant *wpa_s = ctx;
2174 const u8 *pos = tlvs;
2175 const u8 *end = tlvs + tlvs_len;
2176 const u8 *tlv_end;
2177 u16 slen;
2178 size_t buf_len;
2179 char *buf;
2180
2181 wpa_hexdump(MSG_MSGDUMP, "P2P: Service Discovery Response TLVs",
2182 tlvs, tlvs_len);
2183 if (tlvs_len > 1500) {
2184 /* TODO: better way for handling this */
2185 wpa_msg_ctrl(wpa_s, MSG_INFO,
2186 P2P_EVENT_SERV_DISC_RESP MACSTR
2187 " %u <long response: %u bytes>",
2188 MAC2STR(sa), update_indic,
2189 (unsigned int) tlvs_len);
2190 } else {
2191 buf_len = 2 * tlvs_len + 1;
2192 buf = os_malloc(buf_len);
2193 if (buf) {
2194 wpa_snprintf_hex(buf, buf_len, tlvs, tlvs_len);
2195 wpa_msg_ctrl(wpa_s, MSG_INFO,
2196 P2P_EVENT_SERV_DISC_RESP MACSTR " %u %s",
2197 MAC2STR(sa), update_indic, buf);
2198 os_free(buf);
2199 }
2200 }
2201
2202 while (pos < end) {
2203 u8 srv_proto, srv_trans_id, status;
2204
2205 wpa_printf(MSG_DEBUG, "P2P: Service Response TLV");
2206 slen = WPA_GET_LE16(pos);
2207 pos += 2;
2208 if (pos + slen > end || slen < 3) {
2209 wpa_printf(MSG_DEBUG, "P2P: Unexpected Response Data "
2210 "length");
2211 return;
2212 }
2213 tlv_end = pos + slen;
2214
2215 srv_proto = *pos++;
2216 wpa_printf(MSG_DEBUG, "P2P: Service Protocol Type %u",
2217 srv_proto);
2218 srv_trans_id = *pos++;
2219 wpa_printf(MSG_DEBUG, "P2P: Service Transaction ID %u",
2220 srv_trans_id);
2221 status = *pos++;
2222 wpa_printf(MSG_DEBUG, "P2P: Status Code ID %u",
2223 status);
2224
2225 wpa_hexdump(MSG_MSGDUMP, "P2P: Response Data",
2226 pos, tlv_end - pos);
2227
2228 pos = tlv_end;
2229 }
2230
2231 wpas_notify_p2p_sd_response(wpa_s, sa, update_indic, tlvs, tlvs_len);
2232}
2233
2234
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002235u64 wpas_p2p_sd_request(struct wpa_supplicant *wpa_s, const u8 *dst,
2236 const struct wpabuf *tlvs)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002237{
2238 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002239 return wpa_drv_p2p_sd_request(wpa_s, dst, tlvs);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002240 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002241 return 0;
2242 return (uintptr_t) p2p_sd_request(wpa_s->global->p2p, dst, tlvs);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002243}
2244
2245
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002246u64 wpas_p2p_sd_request_upnp(struct wpa_supplicant *wpa_s, const u8 *dst,
2247 u8 version, const char *query)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002248{
2249 struct wpabuf *tlvs;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002250 u64 ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002251
2252 tlvs = wpabuf_alloc(2 + 1 + 1 + 1 + os_strlen(query));
2253 if (tlvs == NULL)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002254 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002255 wpabuf_put_le16(tlvs, 1 + 1 + 1 + os_strlen(query));
2256 wpabuf_put_u8(tlvs, P2P_SERV_UPNP); /* Service Protocol Type */
2257 wpabuf_put_u8(tlvs, 1); /* Service Transaction ID */
2258 wpabuf_put_u8(tlvs, version);
2259 wpabuf_put_str(tlvs, query);
2260 ret = wpas_p2p_sd_request(wpa_s, dst, tlvs);
2261 wpabuf_free(tlvs);
2262 return ret;
2263}
2264
2265
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002266#ifdef CONFIG_WIFI_DISPLAY
2267
2268static u64 wpas_p2p_sd_request_wfd(struct wpa_supplicant *wpa_s, const u8 *dst,
2269 const struct wpabuf *tlvs)
2270{
2271 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
2272 return 0;
2273 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
2274 return 0;
2275 return (uintptr_t) p2p_sd_request_wfd(wpa_s->global->p2p, dst, tlvs);
2276}
2277
2278
2279#define MAX_WFD_SD_SUBELEMS 20
2280
2281static void wfd_add_sd_req_role(struct wpabuf *tlvs, u8 id, u8 role,
2282 const char *subelems)
2283{
2284 u8 *len;
2285 const char *pos;
2286 int val;
2287 int count = 0;
2288
2289 len = wpabuf_put(tlvs, 2);
2290 wpabuf_put_u8(tlvs, P2P_SERV_WIFI_DISPLAY); /* Service Protocol Type */
2291 wpabuf_put_u8(tlvs, id); /* Service Transaction ID */
2292
2293 wpabuf_put_u8(tlvs, role);
2294
2295 pos = subelems;
2296 while (*pos) {
2297 val = atoi(pos);
2298 if (val >= 0 && val < 256) {
2299 wpabuf_put_u8(tlvs, val);
2300 count++;
2301 if (count == MAX_WFD_SD_SUBELEMS)
2302 break;
2303 }
2304 pos = os_strchr(pos + 1, ',');
2305 if (pos == NULL)
2306 break;
2307 pos++;
2308 }
2309
2310 WPA_PUT_LE16(len, (u8 *) wpabuf_put(tlvs, 0) - len - 2);
2311}
2312
2313
2314u64 wpas_p2p_sd_request_wifi_display(struct wpa_supplicant *wpa_s,
2315 const u8 *dst, const char *role)
2316{
2317 struct wpabuf *tlvs;
2318 u64 ret;
2319 const char *subelems;
2320 u8 id = 1;
2321
2322 subelems = os_strchr(role, ' ');
2323 if (subelems == NULL)
2324 return 0;
2325 subelems++;
2326
2327 tlvs = wpabuf_alloc(4 * (2 + 1 + 1 + 1 + MAX_WFD_SD_SUBELEMS));
2328 if (tlvs == NULL)
2329 return 0;
2330
2331 if (os_strstr(role, "[source]"))
2332 wfd_add_sd_req_role(tlvs, id++, 0x00, subelems);
2333 if (os_strstr(role, "[pri-sink]"))
2334 wfd_add_sd_req_role(tlvs, id++, 0x01, subelems);
2335 if (os_strstr(role, "[sec-sink]"))
2336 wfd_add_sd_req_role(tlvs, id++, 0x02, subelems);
2337 if (os_strstr(role, "[source+sink]"))
2338 wfd_add_sd_req_role(tlvs, id++, 0x03, subelems);
2339
2340 ret = wpas_p2p_sd_request_wfd(wpa_s, dst, tlvs);
2341 wpabuf_free(tlvs);
2342 return ret;
2343}
2344
2345#endif /* CONFIG_WIFI_DISPLAY */
2346
2347
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002348int wpas_p2p_sd_cancel_request(struct wpa_supplicant *wpa_s, u64 req)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002349{
2350 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002351 return wpa_drv_p2p_sd_cancel_request(wpa_s, req);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002352 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
2353 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002354 return p2p_sd_cancel_request(wpa_s->global->p2p,
2355 (void *) (uintptr_t) req);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002356}
2357
2358
2359void wpas_p2p_sd_response(struct wpa_supplicant *wpa_s, int freq,
2360 const u8 *dst, u8 dialog_token,
2361 const struct wpabuf *resp_tlvs)
2362{
2363 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
2364 wpa_drv_p2p_sd_response(wpa_s, freq, dst, dialog_token,
2365 resp_tlvs);
2366 return;
2367 }
2368 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
2369 return;
2370 p2p_sd_response(wpa_s->global->p2p, freq, dst, dialog_token,
2371 resp_tlvs);
2372}
2373
Dmitry Shmidteaf261d2013-08-14 15:30:08 -07002374
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002375void wpas_p2p_sd_service_update(struct wpa_supplicant *wpa_s)
2376{
2377 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
2378 wpa_drv_p2p_service_update(wpa_s);
2379 return;
2380 }
2381 if (wpa_s->global->p2p)
2382 p2p_sd_service_update(wpa_s->global->p2p);
2383}
2384
2385
2386static void wpas_p2p_srv_bonjour_free(struct p2p_srv_bonjour *bsrv)
2387{
2388 dl_list_del(&bsrv->list);
2389 wpabuf_free(bsrv->query);
2390 wpabuf_free(bsrv->resp);
2391 os_free(bsrv);
2392}
2393
2394
2395static void wpas_p2p_srv_upnp_free(struct p2p_srv_upnp *usrv)
2396{
2397 dl_list_del(&usrv->list);
2398 os_free(usrv->service);
2399 os_free(usrv);
2400}
2401
2402
2403void wpas_p2p_service_flush(struct wpa_supplicant *wpa_s)
2404{
2405 struct p2p_srv_bonjour *bsrv, *bn;
2406 struct p2p_srv_upnp *usrv, *un;
2407
2408 dl_list_for_each_safe(bsrv, bn, &wpa_s->global->p2p_srv_bonjour,
2409 struct p2p_srv_bonjour, list)
2410 wpas_p2p_srv_bonjour_free(bsrv);
2411
2412 dl_list_for_each_safe(usrv, un, &wpa_s->global->p2p_srv_upnp,
2413 struct p2p_srv_upnp, list)
2414 wpas_p2p_srv_upnp_free(usrv);
2415
2416 wpas_p2p_sd_service_update(wpa_s);
2417}
2418
2419
2420int wpas_p2p_service_add_bonjour(struct wpa_supplicant *wpa_s,
2421 struct wpabuf *query, struct wpabuf *resp)
2422{
2423 struct p2p_srv_bonjour *bsrv;
2424
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002425 bsrv = os_zalloc(sizeof(*bsrv));
2426 if (bsrv == NULL)
2427 return -1;
2428 bsrv->query = query;
2429 bsrv->resp = resp;
2430 dl_list_add(&wpa_s->global->p2p_srv_bonjour, &bsrv->list);
2431
2432 wpas_p2p_sd_service_update(wpa_s);
2433 return 0;
2434}
2435
2436
2437int wpas_p2p_service_del_bonjour(struct wpa_supplicant *wpa_s,
2438 const struct wpabuf *query)
2439{
2440 struct p2p_srv_bonjour *bsrv;
2441
2442 bsrv = wpas_p2p_service_get_bonjour(wpa_s, query);
2443 if (bsrv == NULL)
2444 return -1;
2445 wpas_p2p_srv_bonjour_free(bsrv);
2446 wpas_p2p_sd_service_update(wpa_s);
2447 return 0;
2448}
2449
2450
2451int wpas_p2p_service_add_upnp(struct wpa_supplicant *wpa_s, u8 version,
2452 const char *service)
2453{
2454 struct p2p_srv_upnp *usrv;
2455
2456 if (wpas_p2p_service_get_upnp(wpa_s, version, service))
2457 return 0; /* Already listed */
2458 usrv = os_zalloc(sizeof(*usrv));
2459 if (usrv == NULL)
2460 return -1;
2461 usrv->version = version;
2462 usrv->service = os_strdup(service);
2463 if (usrv->service == NULL) {
2464 os_free(usrv);
2465 return -1;
2466 }
2467 dl_list_add(&wpa_s->global->p2p_srv_upnp, &usrv->list);
2468
2469 wpas_p2p_sd_service_update(wpa_s);
2470 return 0;
2471}
2472
2473
2474int wpas_p2p_service_del_upnp(struct wpa_supplicant *wpa_s, u8 version,
2475 const char *service)
2476{
2477 struct p2p_srv_upnp *usrv;
2478
2479 usrv = wpas_p2p_service_get_upnp(wpa_s, version, service);
2480 if (usrv == NULL)
2481 return -1;
2482 wpas_p2p_srv_upnp_free(usrv);
2483 wpas_p2p_sd_service_update(wpa_s);
2484 return 0;
2485}
2486
2487
2488static void wpas_prov_disc_local_display(struct wpa_supplicant *wpa_s,
2489 const u8 *peer, const char *params,
2490 unsigned int generated_pin)
2491{
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07002492 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_SHOW_PIN MACSTR
2493 " %08d%s", MAC2STR(peer), generated_pin, params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002494}
2495
2496
2497static void wpas_prov_disc_local_keypad(struct wpa_supplicant *wpa_s,
2498 const u8 *peer, const char *params)
2499{
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07002500 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_ENTER_PIN MACSTR
2501 "%s", MAC2STR(peer), params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002502}
2503
2504
2505void wpas_prov_disc_req(void *ctx, const u8 *peer, u16 config_methods,
2506 const u8 *dev_addr, const u8 *pri_dev_type,
2507 const char *dev_name, u16 supp_config_methods,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002508 u8 dev_capab, u8 group_capab, const u8 *group_id,
2509 size_t group_id_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002510{
2511 struct wpa_supplicant *wpa_s = ctx;
2512 char devtype[WPS_DEV_TYPE_BUFSIZE];
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002513 char params[300];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002514 u8 empty_dev_type[8];
2515 unsigned int generated_pin = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002516 struct wpa_supplicant *group = NULL;
2517
2518 if (group_id) {
2519 for (group = wpa_s->global->ifaces; group; group = group->next)
2520 {
2521 struct wpa_ssid *s = group->current_ssid;
2522 if (s != NULL &&
2523 s->mode == WPAS_MODE_P2P_GO &&
2524 group_id_len - ETH_ALEN == s->ssid_len &&
2525 os_memcmp(group_id + ETH_ALEN, s->ssid,
2526 s->ssid_len) == 0)
2527 break;
2528 }
2529 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002530
2531 if (pri_dev_type == NULL) {
2532 os_memset(empty_dev_type, 0, sizeof(empty_dev_type));
2533 pri_dev_type = empty_dev_type;
2534 }
2535 os_snprintf(params, sizeof(params), " p2p_dev_addr=" MACSTR
2536 " pri_dev_type=%s name='%s' config_methods=0x%x "
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002537 "dev_capab=0x%x group_capab=0x%x%s%s",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002538 MAC2STR(dev_addr),
2539 wps_dev_type_bin2str(pri_dev_type, devtype,
2540 sizeof(devtype)),
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002541 dev_name, supp_config_methods, dev_capab, group_capab,
2542 group ? " group=" : "",
2543 group ? group->ifname : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002544 params[sizeof(params) - 1] = '\0';
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002545
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002546 if (config_methods & WPS_CONFIG_DISPLAY) {
2547 generated_pin = wps_generate_pin();
2548 wpas_prov_disc_local_display(wpa_s, peer, params,
2549 generated_pin);
2550 } else if (config_methods & WPS_CONFIG_KEYPAD)
2551 wpas_prov_disc_local_keypad(wpa_s, peer, params);
2552 else if (config_methods & WPS_CONFIG_PUSHBUTTON)
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07002553 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_PBC_REQ
2554 MACSTR "%s", MAC2STR(peer), params);
Jouni Malinen75ecf522011-06-27 15:19:46 -07002555
2556 wpas_notify_p2p_provision_discovery(wpa_s, peer, 1 /* request */,
2557 P2P_PROV_DISC_SUCCESS,
2558 config_methods, generated_pin);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002559}
2560
2561
2562void wpas_prov_disc_resp(void *ctx, const u8 *peer, u16 config_methods)
2563{
2564 struct wpa_supplicant *wpa_s = ctx;
2565 unsigned int generated_pin = 0;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002566 char params[20];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002567
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002568 if (wpa_s->pending_pd_before_join &&
2569 (os_memcmp(peer, wpa_s->pending_join_dev_addr, ETH_ALEN) == 0 ||
2570 os_memcmp(peer, wpa_s->pending_join_iface_addr, ETH_ALEN) == 0)) {
2571 wpa_s->pending_pd_before_join = 0;
2572 wpa_printf(MSG_DEBUG, "P2P: Starting pending "
2573 "join-existing-group operation");
2574 wpas_p2p_join_start(wpa_s);
2575 return;
2576 }
2577
Dmitry Shmidt04949592012-07-19 12:16:46 -07002578 if (wpa_s->pending_pd_use == AUTO_PD_JOIN ||
2579 wpa_s->pending_pd_use == AUTO_PD_GO_NEG)
2580 os_snprintf(params, sizeof(params), " peer_go=%d",
2581 wpa_s->pending_pd_use == AUTO_PD_JOIN);
2582 else
2583 params[0] = '\0';
2584
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002585 if (config_methods & WPS_CONFIG_DISPLAY)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002586 wpas_prov_disc_local_keypad(wpa_s, peer, params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002587 else if (config_methods & WPS_CONFIG_KEYPAD) {
2588 generated_pin = wps_generate_pin();
Dmitry Shmidt04949592012-07-19 12:16:46 -07002589 wpas_prov_disc_local_display(wpa_s, peer, params,
2590 generated_pin);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002591 } else if (config_methods & WPS_CONFIG_PUSHBUTTON)
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07002592 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_PBC_RESP
2593 MACSTR "%s", MAC2STR(peer), params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002594
Jouni Malinen75ecf522011-06-27 15:19:46 -07002595 wpas_notify_p2p_provision_discovery(wpa_s, peer, 0 /* response */,
2596 P2P_PROV_DISC_SUCCESS,
2597 config_methods, generated_pin);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002598}
2599
2600
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002601static void wpas_prov_disc_fail(void *ctx, const u8 *peer,
2602 enum p2p_prov_disc_status status)
Jouni Malinen75ecf522011-06-27 15:19:46 -07002603{
2604 struct wpa_supplicant *wpa_s = ctx;
2605
Dmitry Shmidt04949592012-07-19 12:16:46 -07002606 if (wpa_s->p2p_fallback_to_go_neg) {
2607 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: PD for p2p_connect-auto "
2608 "failed - fall back to GO Negotiation");
2609 wpas_p2p_fallback_to_go_neg(wpa_s, 0);
2610 return;
2611 }
2612
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002613 if (status == P2P_PROV_DISC_TIMEOUT_JOIN) {
Dmitry Shmidt2b380482012-09-13 10:52:13 -07002614 wpa_s->pending_pd_before_join = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002615 wpa_printf(MSG_DEBUG, "P2P: Starting pending "
2616 "join-existing-group operation (no ACK for PD "
2617 "Req attempts)");
2618 wpas_p2p_join_start(wpa_s);
2619 return;
Dmitry Shmidt2b380482012-09-13 10:52:13 -07002620 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002621
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07002622 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_FAILURE
2623 " p2p_dev_addr=" MACSTR " status=%d",
2624 MAC2STR(peer), status);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002625
Jouni Malinen75ecf522011-06-27 15:19:46 -07002626 wpas_notify_p2p_provision_discovery(wpa_s, peer, 0 /* response */,
2627 status, 0, 0);
2628}
2629
2630
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002631static int freq_included(const struct p2p_channels *channels, unsigned int freq)
2632{
2633 if (channels == NULL)
2634 return 1; /* Assume no restrictions */
2635 return p2p_channels_includes_freq(channels, freq);
2636
2637}
2638
2639
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002640static u8 wpas_invitation_process(void *ctx, const u8 *sa, const u8 *bssid,
2641 const u8 *go_dev_addr, const u8 *ssid,
2642 size_t ssid_len, int *go, u8 *group_bssid,
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002643 int *force_freq, int persistent_group,
2644 const struct p2p_channels *channels)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002645{
2646 struct wpa_supplicant *wpa_s = ctx;
2647 struct wpa_ssid *s;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002648 int res;
2649 struct wpa_supplicant *grp;
2650
2651 if (!persistent_group) {
2652 wpa_printf(MSG_DEBUG, "P2P: Invitation from " MACSTR
2653 " to join an active group", MAC2STR(sa));
2654 if (!is_zero_ether_addr(wpa_s->p2p_auth_invite) &&
2655 (os_memcmp(go_dev_addr, wpa_s->p2p_auth_invite, ETH_ALEN)
2656 == 0 ||
2657 os_memcmp(sa, wpa_s->p2p_auth_invite, ETH_ALEN) == 0)) {
2658 wpa_printf(MSG_DEBUG, "P2P: Accept previously "
2659 "authorized invitation");
2660 goto accept_inv;
2661 }
2662 /*
2663 * Do not accept the invitation automatically; notify user and
2664 * request approval.
2665 */
2666 return P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
2667 }
2668
2669 grp = wpas_get_p2p_group(wpa_s, ssid, ssid_len, go);
2670 if (grp) {
2671 wpa_printf(MSG_DEBUG, "P2P: Accept invitation to already "
2672 "running persistent group");
2673 if (*go)
2674 os_memcpy(group_bssid, grp->own_addr, ETH_ALEN);
2675 goto accept_inv;
2676 }
2677
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08002678 if (!is_zero_ether_addr(wpa_s->p2p_auth_invite) &&
2679 os_memcmp(sa, wpa_s->p2p_auth_invite, ETH_ALEN) == 0) {
2680 wpa_printf(MSG_DEBUG, "P2P: Accept previously initiated "
2681 "invitation to re-invoke a persistent group");
2682 } else if (!wpa_s->conf->persistent_reconnect)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002683 return P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
2684
2685 for (s = wpa_s->conf->ssid; s; s = s->next) {
2686 if (s->disabled == 2 &&
2687 os_memcmp(s->bssid, go_dev_addr, ETH_ALEN) == 0 &&
2688 s->ssid_len == ssid_len &&
2689 os_memcmp(ssid, s->ssid, ssid_len) == 0)
2690 break;
2691 }
2692
2693 if (!s) {
2694 wpa_printf(MSG_DEBUG, "P2P: Invitation from " MACSTR
2695 " requested reinvocation of an unknown group",
2696 MAC2STR(sa));
2697 return P2P_SC_FAIL_UNKNOWN_GROUP;
2698 }
2699
2700 if (s->mode == WPAS_MODE_P2P_GO && !wpas_p2p_create_iface(wpa_s)) {
2701 *go = 1;
2702 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
2703 wpa_printf(MSG_DEBUG, "P2P: The only available "
2704 "interface is already in use - reject "
2705 "invitation");
2706 return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
2707 }
2708 os_memcpy(group_bssid, wpa_s->own_addr, ETH_ALEN);
2709 } else if (s->mode == WPAS_MODE_P2P_GO) {
2710 *go = 1;
2711 if (wpas_p2p_add_group_interface(wpa_s, WPA_IF_P2P_GO) < 0)
2712 {
2713 wpa_printf(MSG_ERROR, "P2P: Failed to allocate a new "
2714 "interface address for the group");
2715 return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
2716 }
2717 os_memcpy(group_bssid, wpa_s->pending_interface_addr,
2718 ETH_ALEN);
2719 }
2720
2721accept_inv:
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002722 wpas_p2p_set_own_freq_preference(wpa_s, 0);
2723
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07002724 /* Get one of the frequencies currently in use */
2725 if (wpas_p2p_valid_oper_freqs(wpa_s, &res, 1) > 0) {
2726 wpa_printf(MSG_DEBUG, "P2P: Trying to force channel to match a channel already used by one of the interfaces");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002727 *force_freq = res;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002728 wpas_p2p_set_own_freq_preference(wpa_s, res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002729 }
2730
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07002731 if (*force_freq > 0 && wpa_s->num_multichan_concurrent > 1 &&
2732 wpas_p2p_num_unused_channels(wpa_s) > 0) {
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002733 if (*go == 0) {
2734 /* We are the client */
2735 wpa_printf(MSG_DEBUG, "P2P: Peer was found to be "
2736 "running a GO but we are capable of MCC, "
2737 "figure out the best channel to use");
2738 *force_freq = 0;
2739 } else if (!freq_included(channels, *force_freq)) {
2740 /* We are the GO, and *force_freq is not in the
2741 * intersection */
2742 wpa_printf(MSG_DEBUG, "P2P: Forced GO freq %d MHz not "
2743 "in intersection but we are capable of MCC, "
2744 "figure out the best channel to use",
2745 *force_freq);
2746 *force_freq = 0;
2747 }
2748 }
2749
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002750 return P2P_SC_SUCCESS;
2751}
2752
2753
2754static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid,
2755 const u8 *ssid, size_t ssid_len,
2756 const u8 *go_dev_addr, u8 status,
2757 int op_freq)
2758{
2759 struct wpa_supplicant *wpa_s = ctx;
2760 struct wpa_ssid *s;
2761
2762 for (s = wpa_s->conf->ssid; s; s = s->next) {
2763 if (s->disabled == 2 &&
2764 s->ssid_len == ssid_len &&
2765 os_memcmp(ssid, s->ssid, ssid_len) == 0)
2766 break;
2767 }
2768
2769 if (status == P2P_SC_SUCCESS) {
2770 wpa_printf(MSG_DEBUG, "P2P: Invitation from peer " MACSTR
2771 " was accepted; op_freq=%d MHz",
2772 MAC2STR(sa), op_freq);
2773 if (s) {
Dmitry Shmidt91c40cd2012-09-25 14:23:53 -07002774 int go = s->mode == WPAS_MODE_P2P_GO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002775 wpas_p2p_group_add_persistent(
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002776 wpa_s, s, go, go ? op_freq : 0, 0, 0, NULL,
Dmitry Shmidt56052862013-10-04 10:23:25 -07002777 go ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002778 } else if (bssid) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002779 wpa_s->user_initiated_pd = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002780 wpas_p2p_join(wpa_s, bssid, go_dev_addr,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002781 wpa_s->p2p_wps_method, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002782 }
2783 return;
2784 }
2785
2786 if (status != P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) {
2787 wpa_printf(MSG_DEBUG, "P2P: Invitation from peer " MACSTR
2788 " was rejected (status %u)", MAC2STR(sa), status);
2789 return;
2790 }
2791
2792 if (!s) {
2793 if (bssid) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07002794 wpa_msg_global(wpa_s, MSG_INFO,
2795 P2P_EVENT_INVITATION_RECEIVED
2796 "sa=" MACSTR " go_dev_addr=" MACSTR
2797 " bssid=" MACSTR " unknown-network",
2798 MAC2STR(sa), MAC2STR(go_dev_addr),
2799 MAC2STR(bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002800 } else {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07002801 wpa_msg_global(wpa_s, MSG_INFO,
2802 P2P_EVENT_INVITATION_RECEIVED
2803 "sa=" MACSTR " go_dev_addr=" MACSTR
2804 " unknown-network",
2805 MAC2STR(sa), MAC2STR(go_dev_addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002806 }
2807 return;
2808 }
2809
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08002810 if (s->mode == WPAS_MODE_P2P_GO && op_freq) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07002811 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RECEIVED
2812 "sa=" MACSTR " persistent=%d freq=%d",
2813 MAC2STR(sa), s->id, op_freq);
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08002814 } else {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07002815 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RECEIVED
2816 "sa=" MACSTR " persistent=%d",
2817 MAC2STR(sa), s->id);
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08002818 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002819}
2820
2821
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002822static void wpas_remove_persistent_peer(struct wpa_supplicant *wpa_s,
2823 struct wpa_ssid *ssid,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002824 const u8 *peer, int inv)
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002825{
2826 size_t i;
2827
2828 if (ssid == NULL)
2829 return;
2830
2831 for (i = 0; ssid->p2p_client_list && i < ssid->num_p2p_clients; i++) {
2832 if (os_memcmp(ssid->p2p_client_list + i * ETH_ALEN, peer,
2833 ETH_ALEN) == 0)
2834 break;
2835 }
2836 if (i >= ssid->num_p2p_clients) {
2837 if (ssid->mode != WPAS_MODE_P2P_GO &&
2838 os_memcmp(ssid->bssid, peer, ETH_ALEN) == 0) {
2839 wpa_printf(MSG_DEBUG, "P2P: Remove persistent group %d "
2840 "due to invitation result", ssid->id);
2841 wpas_notify_network_removed(wpa_s, ssid);
2842 wpa_config_remove_network(wpa_s->conf, ssid->id);
2843 return;
2844 }
2845 return; /* Peer not found in client list */
2846 }
2847
2848 wpa_printf(MSG_DEBUG, "P2P: Remove peer " MACSTR " from persistent "
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002849 "group %d client list%s",
2850 MAC2STR(peer), ssid->id,
2851 inv ? " due to invitation result" : "");
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002852 os_memmove(ssid->p2p_client_list + i * ETH_ALEN,
2853 ssid->p2p_client_list + (i + 1) * ETH_ALEN,
2854 (ssid->num_p2p_clients - i - 1) * ETH_ALEN);
2855 ssid->num_p2p_clients--;
2856#ifndef CONFIG_NO_CONFIG_WRITE
2857 if (wpa_s->parent->conf->update_config &&
2858 wpa_config_write(wpa_s->parent->confname, wpa_s->parent->conf))
2859 wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
2860#endif /* CONFIG_NO_CONFIG_WRITE */
2861}
2862
2863
2864static void wpas_remove_persistent_client(struct wpa_supplicant *wpa_s,
2865 const u8 *peer)
2866{
2867 struct wpa_ssid *ssid;
2868
2869 wpa_s = wpa_s->global->p2p_invite_group;
2870 if (wpa_s == NULL)
2871 return; /* No known invitation group */
2872 ssid = wpa_s->current_ssid;
2873 if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
2874 !ssid->p2p_persistent_group)
2875 return; /* Not operating as a GO in persistent group */
2876 ssid = wpas_p2p_get_persistent(wpa_s->parent, peer,
2877 ssid->ssid, ssid->ssid_len);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002878 wpas_remove_persistent_peer(wpa_s, ssid, peer, 1);
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002879}
2880
2881
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08002882static void wpas_invitation_result(void *ctx, int status, const u8 *bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002883 const struct p2p_channels *channels,
2884 const u8 *peer)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002885{
2886 struct wpa_supplicant *wpa_s = ctx;
2887 struct wpa_ssid *ssid;
2888
2889 if (bssid) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07002890 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RESULT
2891 "status=%d " MACSTR,
2892 status, MAC2STR(bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002893 } else {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07002894 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RESULT
2895 "status=%d ", status);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002896 }
2897 wpas_notify_p2p_invitation_result(wpa_s, status, bssid);
2898
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002899 wpa_printf(MSG_DEBUG, "P2P: Invitation result - status=%d peer=" MACSTR,
2900 status, MAC2STR(peer));
2901 if (wpa_s->pending_invite_ssid_id == -1) {
2902 if (status == P2P_SC_FAIL_UNKNOWN_GROUP)
2903 wpas_remove_persistent_client(wpa_s, peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002904 return; /* Invitation to active group */
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002905 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002906
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08002907 if (status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) {
2908 wpa_printf(MSG_DEBUG, "P2P: Waiting for peer to start another "
2909 "invitation exchange to indicate readiness for "
2910 "re-invocation");
2911 }
2912
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002913 if (status != P2P_SC_SUCCESS) {
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002914 if (status == P2P_SC_FAIL_UNKNOWN_GROUP) {
2915 ssid = wpa_config_get_network(
2916 wpa_s->conf, wpa_s->pending_invite_ssid_id);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002917 wpas_remove_persistent_peer(wpa_s, ssid, peer, 1);
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002918 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002919 wpas_p2p_remove_pending_group_interface(wpa_s);
2920 return;
2921 }
2922
2923 ssid = wpa_config_get_network(wpa_s->conf,
2924 wpa_s->pending_invite_ssid_id);
2925 if (ssid == NULL) {
2926 wpa_printf(MSG_ERROR, "P2P: Could not find persistent group "
2927 "data matching with invitation");
2928 return;
2929 }
2930
Jouni Malinen2c5b17d2012-10-13 21:52:46 -07002931 /*
2932 * The peer could have missed our ctrl::ack frame for Invitation
2933 * Response and continue retransmitting the frame. To reduce the
2934 * likelihood of the peer not getting successful TX status for the
2935 * Invitation Response frame, wait a short time here before starting
2936 * the persistent group so that we will remain on the current channel to
2937 * acknowledge any possible retransmission from the peer.
2938 */
Irfan Sheriff81931b82012-10-16 21:40:46 -07002939#ifndef ANDROID_P2P
Jouni Malinen2c5b17d2012-10-13 21:52:46 -07002940 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: 50 ms wait on current channel before "
2941 "starting persistent group");
2942 os_sleep(0, 50000);
Irfan Sheriff81931b82012-10-16 21:40:46 -07002943#else
2944 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: 100 ms wait on current channel before "
2945 "starting persistent group");
2946 os_sleep(0, 100000);
2947#endif
Jouni Malinen2c5b17d2012-10-13 21:52:46 -07002948
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002949 wpas_p2p_group_add_persistent(wpa_s, ssid,
Jouni Malinen31be0a42012-08-31 21:20:51 +03002950 ssid->mode == WPAS_MODE_P2P_GO,
2951 wpa_s->p2p_persistent_go_freq,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002952 wpa_s->p2p_go_ht40, wpa_s->p2p_go_vht,
2953 channels,
Dmitry Shmidt56052862013-10-04 10:23:25 -07002954 ssid->mode == WPAS_MODE_P2P_GO ?
2955 P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
2956 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002957}
2958
2959
Dmitry Shmidt04949592012-07-19 12:16:46 -07002960static int wpas_p2p_disallowed_freq(struct wpa_global *global,
2961 unsigned int freq)
2962{
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002963 return freq_range_list_includes(&global->p2p_disallow_freq, freq);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002964}
2965
2966
2967static void wpas_p2p_add_chan(struct p2p_reg_class *reg, u8 chan)
2968{
2969 reg->channel[reg->channels] = chan;
2970 reg->channels++;
2971}
2972
2973
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002974static int wpas_p2p_default_channels(struct wpa_supplicant *wpa_s,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002975 struct p2p_channels *chan,
2976 struct p2p_channels *cli_chan)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002977{
2978 int i, cla = 0;
2979
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002980 os_memset(cli_chan, 0, sizeof(*cli_chan));
2981
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002982 wpa_printf(MSG_DEBUG, "P2P: Enable operating classes for 2.4 GHz "
2983 "band");
2984
2985 /* Operating class 81 - 2.4 GHz band channels 1..13 */
2986 chan->reg_class[cla].reg_class = 81;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002987 chan->reg_class[cla].channels = 0;
2988 for (i = 0; i < 11; i++) {
2989 if (!wpas_p2p_disallowed_freq(wpa_s->global, 2412 + i * 5))
2990 wpas_p2p_add_chan(&chan->reg_class[cla], i + 1);
2991 }
2992 if (chan->reg_class[cla].channels)
2993 cla++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002994
2995 wpa_printf(MSG_DEBUG, "P2P: Enable operating classes for lower 5 GHz "
2996 "band");
2997
2998 /* Operating class 115 - 5 GHz, channels 36-48 */
2999 chan->reg_class[cla].reg_class = 115;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003000 chan->reg_class[cla].channels = 0;
3001 if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 36 * 5))
3002 wpas_p2p_add_chan(&chan->reg_class[cla], 36);
3003 if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 40 * 5))
3004 wpas_p2p_add_chan(&chan->reg_class[cla], 40);
3005 if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 44 * 5))
3006 wpas_p2p_add_chan(&chan->reg_class[cla], 44);
3007 if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 48 * 5))
3008 wpas_p2p_add_chan(&chan->reg_class[cla], 48);
3009 if (chan->reg_class[cla].channels)
3010 cla++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003011
3012 wpa_printf(MSG_DEBUG, "P2P: Enable operating classes for higher 5 GHz "
3013 "band");
3014
3015 /* Operating class 124 - 5 GHz, channels 149,153,157,161 */
3016 chan->reg_class[cla].reg_class = 124;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003017 chan->reg_class[cla].channels = 0;
3018 if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 149 * 5))
3019 wpas_p2p_add_chan(&chan->reg_class[cla], 149);
3020 if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 153 * 5))
3021 wpas_p2p_add_chan(&chan->reg_class[cla], 153);
3022 if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 156 * 5))
3023 wpas_p2p_add_chan(&chan->reg_class[cla], 157);
3024 if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 161 * 5))
3025 wpas_p2p_add_chan(&chan->reg_class[cla], 161);
3026 if (chan->reg_class[cla].channels)
3027 cla++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003028
3029 chan->reg_classes = cla;
3030 return 0;
3031}
3032
3033
3034static struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
3035 u16 num_modes,
3036 enum hostapd_hw_mode mode)
3037{
3038 u16 i;
3039
3040 for (i = 0; i < num_modes; i++) {
3041 if (modes[i].mode == mode)
3042 return &modes[i];
3043 }
3044
3045 return NULL;
3046}
3047
3048
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003049enum chan_allowed {
3050 NOT_ALLOWED, PASSIVE_ONLY, ALLOWED
3051};
3052
Dmitry Shmidt04949592012-07-19 12:16:46 -07003053static int has_channel(struct wpa_global *global,
3054 struct hostapd_hw_modes *mode, u8 chan, int *flags)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003055{
3056 int i;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003057 unsigned int freq;
3058
3059 freq = (mode->mode == HOSTAPD_MODE_IEEE80211A ? 5000 : 2407) +
3060 chan * 5;
3061 if (wpas_p2p_disallowed_freq(global, freq))
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003062 return NOT_ALLOWED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003063
3064 for (i = 0; i < mode->num_channels; i++) {
3065 if (mode->channels[i].chan == chan) {
3066 if (flags)
3067 *flags = mode->channels[i].flag;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003068 if (mode->channels[i].flag &
3069 (HOSTAPD_CHAN_DISABLED |
3070 HOSTAPD_CHAN_RADAR))
3071 return NOT_ALLOWED;
3072 if (mode->channels[i].flag &
3073 (HOSTAPD_CHAN_PASSIVE_SCAN |
3074 HOSTAPD_CHAN_NO_IBSS))
3075 return PASSIVE_ONLY;
3076 return ALLOWED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003077 }
3078 }
3079
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003080 return NOT_ALLOWED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003081}
3082
3083
3084struct p2p_oper_class_map {
3085 enum hostapd_hw_mode mode;
3086 u8 op_class;
3087 u8 min_chan;
3088 u8 max_chan;
3089 u8 inc;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003090 enum { BW20, BW40PLUS, BW40MINUS, BW80 } bw;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003091};
3092
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003093static struct p2p_oper_class_map op_class[] = {
3094 { HOSTAPD_MODE_IEEE80211G, 81, 1, 13, 1, BW20 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003095#if 0 /* Do not enable HT40 on 2 GHz for now */
3096 { HOSTAPD_MODE_IEEE80211G, 83, 1, 9, 1, BW40PLUS },
3097 { HOSTAPD_MODE_IEEE80211G, 84, 5, 13, 1, BW40MINUS },
3098#endif
3099 { HOSTAPD_MODE_IEEE80211A, 115, 36, 48, 4, BW20 },
3100 { HOSTAPD_MODE_IEEE80211A, 124, 149, 161, 4, BW20 },
3101 { HOSTAPD_MODE_IEEE80211A, 116, 36, 44, 8, BW40PLUS },
3102 { HOSTAPD_MODE_IEEE80211A, 117, 40, 48, 8, BW40MINUS },
3103 { HOSTAPD_MODE_IEEE80211A, 126, 149, 157, 8, BW40PLUS },
3104 { HOSTAPD_MODE_IEEE80211A, 127, 153, 161, 8, BW40MINUS },
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003105
3106 /*
3107 * IEEE P802.11ac/D7.0 Table E-4 actually talks about channel center
3108 * frequency index 42, 58, 106, 122, 138, 155 with channel spacing of
3109 * 80 MHz, but currently use the following definition for simplicity
3110 * (these center frequencies are not actual channels, which makes
3111 * has_channel() fail). wpas_p2p_verify_80mhz() should take care of
3112 * removing invalid channels.
3113 */
3114 { HOSTAPD_MODE_IEEE80211A, 128, 36, 161, 4, BW80 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003115 { -1, 0, 0, 0, 0, BW20 }
3116};
3117
3118
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003119static int wpas_p2p_get_center_80mhz(struct wpa_supplicant *wpa_s,
3120 struct hostapd_hw_modes *mode,
3121 u8 channel)
3122{
3123 u8 center_channels[] = { 42, 58, 106, 122, 138, 155 };
3124 unsigned int i;
3125
3126 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
3127 return 0;
3128
3129 for (i = 0; i < ARRAY_SIZE(center_channels); i++)
3130 /*
3131 * In 80 MHz, the bandwidth "spans" 12 channels (e.g., 36-48),
3132 * so the center channel is 6 channels away from the start/end.
3133 */
3134 if (channel >= center_channels[i] - 6 &&
3135 channel <= center_channels[i] + 6)
3136 return center_channels[i];
3137
3138 return 0;
3139}
3140
3141
3142static enum chan_allowed wpas_p2p_verify_80mhz(struct wpa_supplicant *wpa_s,
3143 struct hostapd_hw_modes *mode,
3144 u8 channel, u8 bw)
3145{
3146 u8 center_chan;
3147 int i, flags;
3148 enum chan_allowed res, ret = ALLOWED;
3149
3150 center_chan = wpas_p2p_get_center_80mhz(wpa_s, mode, channel);
3151 if (!center_chan)
3152 return NOT_ALLOWED;
3153 if (center_chan >= 58 && center_chan <= 138)
3154 return NOT_ALLOWED; /* Do not allow DFS channels for P2P */
3155
3156 /* check all the channels are available */
3157 for (i = 0; i < 4; i++) {
3158 int adj_chan = center_chan - 6 + i * 4;
3159
3160 res = has_channel(wpa_s->global, mode, adj_chan, &flags);
3161 if (res == NOT_ALLOWED)
3162 return NOT_ALLOWED;
3163 if (res == PASSIVE_ONLY)
3164 ret = PASSIVE_ONLY;
3165
3166 if (i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_70))
3167 return NOT_ALLOWED;
3168 if (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_50))
3169 return NOT_ALLOWED;
3170 if (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_30))
3171 return NOT_ALLOWED;
3172 if (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_10))
3173 return NOT_ALLOWED;
3174 }
3175
3176 return ret;
3177}
3178
3179
3180static enum chan_allowed wpas_p2p_verify_channel(struct wpa_supplicant *wpa_s,
3181 struct hostapd_hw_modes *mode,
3182 u8 channel, u8 bw)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003183{
3184 int flag;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003185 enum chan_allowed res, res2;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003186
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003187 res2 = res = has_channel(wpa_s->global, mode, channel, &flag);
3188 if (bw == BW40MINUS) {
3189 if (!(flag & HOSTAPD_CHAN_HT40MINUS))
3190 return NOT_ALLOWED;
3191 res2 = has_channel(wpa_s->global, mode, channel - 4, NULL);
3192 } else if (bw == BW40PLUS) {
3193 if (!(flag & HOSTAPD_CHAN_HT40PLUS))
3194 return NOT_ALLOWED;
3195 res2 = has_channel(wpa_s->global, mode, channel + 4, NULL);
3196 } else if (bw == BW80) {
3197 res2 = wpas_p2p_verify_80mhz(wpa_s, mode, channel, bw);
3198 }
3199
3200 if (res == NOT_ALLOWED || res2 == NOT_ALLOWED)
3201 return NOT_ALLOWED;
3202 if (res == PASSIVE_ONLY || res2 == PASSIVE_ONLY)
3203 return PASSIVE_ONLY;
3204 return res;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003205}
3206
3207
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003208static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003209 struct p2p_channels *chan,
3210 struct p2p_channels *cli_chan)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003211{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003212 struct hostapd_hw_modes *mode;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003213 int cla, op, cli_cla;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003214
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003215 if (wpa_s->hw.modes == NULL) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003216 wpa_printf(MSG_DEBUG, "P2P: Driver did not support fetching "
3217 "of all supported channels; assume dualband "
3218 "support");
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003219 return wpas_p2p_default_channels(wpa_s, chan, cli_chan);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003220 }
3221
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003222 cla = cli_cla = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003223
3224 for (op = 0; op_class[op].op_class; op++) {
3225 struct p2p_oper_class_map *o = &op_class[op];
3226 u8 ch;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003227 struct p2p_reg_class *reg = NULL, *cli_reg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003228
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003229 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, o->mode);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003230 if (mode == NULL)
3231 continue;
3232 for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003233 enum chan_allowed res;
3234 res = wpas_p2p_verify_channel(wpa_s, mode, ch, o->bw);
3235 if (res == ALLOWED) {
3236 if (reg == NULL) {
3237 wpa_printf(MSG_DEBUG, "P2P: Add operating class %u",
3238 o->op_class);
3239 reg = &chan->reg_class[cla];
3240 cla++;
3241 reg->reg_class = o->op_class;
3242 }
3243 reg->channel[reg->channels] = ch;
3244 reg->channels++;
3245 } else if (res == PASSIVE_ONLY &&
3246 wpa_s->conf->p2p_add_cli_chan) {
3247 if (cli_reg == NULL) {
3248 wpa_printf(MSG_DEBUG, "P2P: Add operating class %u (client only)",
3249 o->op_class);
3250 cli_reg = &cli_chan->reg_class[cli_cla];
3251 cli_cla++;
3252 cli_reg->reg_class = o->op_class;
3253 }
3254 cli_reg->channel[cli_reg->channels] = ch;
3255 cli_reg->channels++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003256 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003257 }
3258 if (reg) {
3259 wpa_hexdump(MSG_DEBUG, "P2P: Channels",
3260 reg->channel, reg->channels);
3261 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003262 if (cli_reg) {
3263 wpa_hexdump(MSG_DEBUG, "P2P: Channels (client only)",
3264 cli_reg->channel, cli_reg->channels);
3265 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003266 }
3267
3268 chan->reg_classes = cla;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003269 cli_chan->reg_classes = cli_cla;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003270
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003271 return 0;
3272}
3273
3274
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003275int wpas_p2p_get_ht40_mode(struct wpa_supplicant *wpa_s,
3276 struct hostapd_hw_modes *mode, u8 channel)
3277{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003278 int op;
3279 enum chan_allowed ret;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003280
3281 for (op = 0; op_class[op].op_class; op++) {
3282 struct p2p_oper_class_map *o = &op_class[op];
3283 u8 ch;
3284
3285 for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
3286 if (o->mode != HOSTAPD_MODE_IEEE80211A ||
3287 o->bw == BW20 || ch != channel)
3288 continue;
3289 ret = wpas_p2p_verify_channel(wpa_s, mode, ch, o->bw);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003290 if (ret == ALLOWED)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003291 return (o->bw == BW40MINUS) ? -1 : 1;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003292 }
3293 }
3294 return 0;
3295}
3296
3297
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003298int wpas_p2p_get_vht80_center(struct wpa_supplicant *wpa_s,
3299 struct hostapd_hw_modes *mode, u8 channel)
3300{
3301 if (!wpas_p2p_verify_channel(wpa_s, mode, channel, BW80))
3302 return 0;
3303
3304 return wpas_p2p_get_center_80mhz(wpa_s, mode, channel);
3305}
3306
3307
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003308static int wpas_get_noa(void *ctx, const u8 *interface_addr, u8 *buf,
3309 size_t buf_len)
3310{
3311 struct wpa_supplicant *wpa_s = ctx;
3312
3313 for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3314 if (os_memcmp(wpa_s->own_addr, interface_addr, ETH_ALEN) == 0)
3315 break;
3316 }
3317 if (wpa_s == NULL)
3318 return -1;
3319
3320 return wpa_drv_get_noa(wpa_s, buf, buf_len);
3321}
3322
3323
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003324static int wpas_go_connected(void *ctx, const u8 *dev_addr)
3325{
3326 struct wpa_supplicant *wpa_s = ctx;
3327
3328 for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3329 struct wpa_ssid *ssid = wpa_s->current_ssid;
3330 if (ssid == NULL)
3331 continue;
3332 if (ssid->mode != WPAS_MODE_INFRA)
3333 continue;
3334 if (wpa_s->wpa_state != WPA_COMPLETED &&
3335 wpa_s->wpa_state != WPA_GROUP_HANDSHAKE)
3336 continue;
3337 if (os_memcmp(wpa_s->go_dev_addr, dev_addr, ETH_ALEN) == 0)
3338 return 1;
3339 }
3340
3341 return 0;
3342}
3343
3344
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003345static void wpas_p2p_debug_print(void *ctx, int level, const char *msg)
3346{
3347 struct wpa_supplicant *wpa_s = ctx;
3348 wpa_msg_global(wpa_s, level, "P2P: %s", msg);
3349}
3350
3351
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003352int wpas_p2p_add_p2pdev_interface(struct wpa_supplicant *wpa_s)
3353{
3354 struct wpa_interface iface;
3355 struct wpa_supplicant *p2pdev_wpa_s;
3356 char ifname[100];
3357 char force_name[100];
3358 int ret;
3359
3360 os_snprintf(ifname, sizeof(ifname), P2P_MGMT_DEVICE_PREFIX "%s",
3361 wpa_s->ifname);
3362 force_name[0] = '\0';
3363 wpa_s->pending_interface_type = WPA_IF_P2P_DEVICE;
3364 ret = wpa_drv_if_add(wpa_s, WPA_IF_P2P_DEVICE, ifname, NULL, NULL,
3365 force_name, wpa_s->pending_interface_addr, NULL);
3366 if (ret < 0) {
3367 wpa_printf(MSG_DEBUG, "P2P: Failed to create P2P Device interface");
3368 return ret;
3369 }
3370 os_strlcpy(wpa_s->pending_interface_name, ifname,
3371 sizeof(wpa_s->pending_interface_name));
3372
3373 os_memset(&iface, 0, sizeof(iface));
3374 iface.p2p_mgmt = 1;
3375 iface.ifname = wpa_s->pending_interface_name;
3376 iface.driver = wpa_s->driver->name;
3377 iface.driver_param = wpa_s->conf->driver_param;
3378 iface.confname = wpa_s->confname;
3379 p2pdev_wpa_s = wpa_supplicant_add_iface(wpa_s->global, &iface);
3380 if (!p2pdev_wpa_s) {
3381 wpa_printf(MSG_DEBUG, "P2P: Failed to add P2P Device interface");
3382 return -1;
3383 }
3384 p2pdev_wpa_s->parent = wpa_s;
3385
3386 wpa_s->pending_interface_name[0] = '\0';
3387 return 0;
3388}
3389
3390
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003391/**
3392 * wpas_p2p_init - Initialize P2P module for %wpa_supplicant
3393 * @global: Pointer to global data from wpa_supplicant_init()
3394 * @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface()
3395 * Returns: 0 on success, -1 on failure
3396 */
3397int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
3398{
3399 struct p2p_config p2p;
3400 unsigned int r;
3401 int i;
3402
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003403 if (wpa_s->conf->p2p_disabled)
3404 return 0;
3405
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003406 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_CAPABLE))
3407 return 0;
3408
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003409 if (global->p2p)
3410 return 0;
3411
3412 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
3413 struct p2p_params params;
3414
3415 wpa_printf(MSG_DEBUG, "P2P: Use driver-based P2P management");
3416 os_memset(&params, 0, sizeof(params));
3417 params.dev_name = wpa_s->conf->device_name;
3418 os_memcpy(params.pri_dev_type, wpa_s->conf->device_type,
3419 WPS_DEV_TYPE_LEN);
3420 params.num_sec_dev_types = wpa_s->conf->num_sec_device_types;
3421 os_memcpy(params.sec_dev_type,
3422 wpa_s->conf->sec_device_type,
3423 params.num_sec_dev_types * WPS_DEV_TYPE_LEN);
3424
3425 if (wpa_drv_p2p_set_params(wpa_s, &params) < 0)
3426 return -1;
3427
3428 return 0;
3429 }
3430
3431 os_memset(&p2p, 0, sizeof(p2p));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003432 p2p.cb_ctx = wpa_s;
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003433 p2p.debug_print = wpas_p2p_debug_print;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003434 p2p.p2p_scan = wpas_p2p_scan;
3435 p2p.send_action = wpas_send_action;
3436 p2p.send_action_done = wpas_send_action_done;
3437 p2p.go_neg_completed = wpas_go_neg_completed;
3438 p2p.go_neg_req_rx = wpas_go_neg_req_rx;
3439 p2p.dev_found = wpas_dev_found;
3440 p2p.dev_lost = wpas_dev_lost;
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003441 p2p.find_stopped = wpas_find_stopped;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003442 p2p.start_listen = wpas_start_listen;
3443 p2p.stop_listen = wpas_stop_listen;
3444 p2p.send_probe_resp = wpas_send_probe_resp;
3445 p2p.sd_request = wpas_sd_request;
3446 p2p.sd_response = wpas_sd_response;
3447 p2p.prov_disc_req = wpas_prov_disc_req;
3448 p2p.prov_disc_resp = wpas_prov_disc_resp;
Jouni Malinen75ecf522011-06-27 15:19:46 -07003449 p2p.prov_disc_fail = wpas_prov_disc_fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003450 p2p.invitation_process = wpas_invitation_process;
3451 p2p.invitation_received = wpas_invitation_received;
3452 p2p.invitation_result = wpas_invitation_result;
3453 p2p.get_noa = wpas_get_noa;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003454 p2p.go_connected = wpas_go_connected;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003455
3456 os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003457 os_memcpy(p2p.dev_addr, wpa_s->global->p2p_dev_addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003458 p2p.dev_name = wpa_s->conf->device_name;
3459 p2p.manufacturer = wpa_s->conf->manufacturer;
3460 p2p.model_name = wpa_s->conf->model_name;
3461 p2p.model_number = wpa_s->conf->model_number;
3462 p2p.serial_number = wpa_s->conf->serial_number;
3463 if (wpa_s->wps) {
3464 os_memcpy(p2p.uuid, wpa_s->wps->uuid, 16);
3465 p2p.config_methods = wpa_s->wps->config_methods;
3466 }
3467
3468 if (wpa_s->conf->p2p_listen_reg_class &&
3469 wpa_s->conf->p2p_listen_channel) {
3470 p2p.reg_class = wpa_s->conf->p2p_listen_reg_class;
3471 p2p.channel = wpa_s->conf->p2p_listen_channel;
3472 } else {
3473 p2p.reg_class = 81;
3474 /*
3475 * Pick one of the social channels randomly as the listen
3476 * channel.
3477 */
3478 os_get_random((u8 *) &r, sizeof(r));
3479 p2p.channel = 1 + (r % 3) * 5;
3480 }
3481 wpa_printf(MSG_DEBUG, "P2P: Own listen channel: %d", p2p.channel);
3482
3483 if (wpa_s->conf->p2p_oper_reg_class &&
3484 wpa_s->conf->p2p_oper_channel) {
3485 p2p.op_reg_class = wpa_s->conf->p2p_oper_reg_class;
3486 p2p.op_channel = wpa_s->conf->p2p_oper_channel;
3487 p2p.cfg_op_channel = 1;
3488 wpa_printf(MSG_DEBUG, "P2P: Configured operating channel: "
3489 "%d:%d", p2p.op_reg_class, p2p.op_channel);
3490
3491 } else {
3492 p2p.op_reg_class = 81;
3493 /*
3494 * Use random operation channel from (1, 6, 11) if no other
3495 * preference is indicated.
3496 */
3497 os_get_random((u8 *) &r, sizeof(r));
3498 p2p.op_channel = 1 + (r % 3) * 5;
3499 p2p.cfg_op_channel = 0;
3500 wpa_printf(MSG_DEBUG, "P2P: Random operating channel: "
3501 "%d:%d", p2p.op_reg_class, p2p.op_channel);
3502 }
Dmitry Shmidt44c95782013-05-17 09:51:35 -07003503
3504 if (wpa_s->conf->p2p_pref_chan && wpa_s->conf->num_p2p_pref_chan) {
3505 p2p.pref_chan = wpa_s->conf->p2p_pref_chan;
3506 p2p.num_pref_chan = wpa_s->conf->num_p2p_pref_chan;
3507 }
3508
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003509 if (wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
3510 os_memcpy(p2p.country, wpa_s->conf->country, 2);
3511 p2p.country[2] = 0x04;
3512 } else
3513 os_memcpy(p2p.country, "XX\x04", 3);
3514
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003515 if (wpas_p2p_setup_channels(wpa_s, &p2p.channels, &p2p.cli_channels)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003516 wpa_printf(MSG_ERROR, "P2P: Failed to configure supported "
3517 "channel list");
3518 return -1;
3519 }
3520
3521 os_memcpy(p2p.pri_dev_type, wpa_s->conf->device_type,
3522 WPS_DEV_TYPE_LEN);
3523
3524 p2p.num_sec_dev_types = wpa_s->conf->num_sec_device_types;
3525 os_memcpy(p2p.sec_dev_type, wpa_s->conf->sec_device_type,
3526 p2p.num_sec_dev_types * WPS_DEV_TYPE_LEN);
3527
3528 p2p.concurrent_operations = !!(wpa_s->drv_flags &
3529 WPA_DRIVER_FLAGS_P2P_CONCURRENT);
3530
3531 p2p.max_peers = 100;
3532
3533 if (wpa_s->conf->p2p_ssid_postfix) {
3534 p2p.ssid_postfix_len =
3535 os_strlen(wpa_s->conf->p2p_ssid_postfix);
3536 if (p2p.ssid_postfix_len > sizeof(p2p.ssid_postfix))
3537 p2p.ssid_postfix_len = sizeof(p2p.ssid_postfix);
3538 os_memcpy(p2p.ssid_postfix, wpa_s->conf->p2p_ssid_postfix,
3539 p2p.ssid_postfix_len);
3540 }
3541
3542 p2p.p2p_intra_bss = wpa_s->conf->p2p_intra_bss;
3543
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003544 p2p.max_listen = wpa_s->max_remain_on_chan;
3545
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003546 global->p2p = p2p_init(&p2p);
3547 if (global->p2p == NULL)
3548 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003549 global->p2p_init_wpa_s = wpa_s;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003550
3551 for (i = 0; i < MAX_WPS_VENDOR_EXT; i++) {
3552 if (wpa_s->conf->wps_vendor_ext[i] == NULL)
3553 continue;
3554 p2p_add_wps_vendor_extension(
3555 global->p2p, wpa_s->conf->wps_vendor_ext[i]);
3556 }
3557
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003558 p2p_set_no_go_freq(global->p2p, &wpa_s->conf->p2p_no_go_freq);
3559
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003560 return 0;
3561}
3562
3563
3564/**
3565 * wpas_p2p_deinit - Deinitialize per-interface P2P data
3566 * @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface()
3567 *
3568 * This function deinitialize per-interface P2P data.
3569 */
3570void wpas_p2p_deinit(struct wpa_supplicant *wpa_s)
3571{
3572 if (wpa_s->driver && wpa_s->drv_priv)
3573 wpa_drv_probe_req_report(wpa_s, 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003574
3575 if (wpa_s->go_params) {
3576 /* Clear any stored provisioning info */
3577 p2p_clear_provisioning_info(
3578 wpa_s->global->p2p,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003579 wpa_s->go_params->peer_device_addr);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003580 }
3581
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003582 os_free(wpa_s->go_params);
3583 wpa_s->go_params = NULL;
Dmitry Shmidt1cf45732013-04-29 17:36:45 -07003584#ifdef ANDROID_P2P
3585 eloop_cancel_timeout(wpas_p2p_group_freq_conflict, wpa_s, NULL);
3586#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003587 eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s, NULL);
3588 eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
3589 wpa_s->p2p_long_listen = 0;
3590 eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL);
3591 eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL);
3592 wpas_p2p_remove_pending_group_interface(wpa_s);
3593
3594 /* TODO: remove group interface from the driver if this wpa_s instance
3595 * is on top of a P2P group interface */
3596}
3597
3598
3599/**
3600 * wpas_p2p_deinit_global - Deinitialize global P2P module
3601 * @global: Pointer to global data from wpa_supplicant_init()
3602 *
3603 * This function deinitializes the global (per device) P2P module.
3604 */
3605void wpas_p2p_deinit_global(struct wpa_global *global)
3606{
3607 struct wpa_supplicant *wpa_s, *tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003608
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003609 wpa_s = global->ifaces;
3610 if (wpa_s)
3611 wpas_p2p_service_flush(wpa_s);
3612
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003613 if (global->p2p == NULL)
3614 return;
3615
3616 /* Remove remaining P2P group interfaces */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003617 while (wpa_s && wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
3618 wpa_s = wpa_s->next;
3619 while (wpa_s) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003620 tmp = global->ifaces;
3621 while (tmp &&
3622 (tmp == wpa_s ||
3623 tmp->p2p_group_interface == NOT_P2P_GROUP_INTERFACE)) {
3624 tmp = tmp->next;
3625 }
3626 if (tmp == NULL)
3627 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003628 /* Disconnect from the P2P group and deinit the interface */
3629 wpas_p2p_disconnect(tmp);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003630 }
3631
3632 /*
3633 * Deinit GO data on any possibly remaining interface (if main
3634 * interface is used as GO).
3635 */
3636 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3637 if (wpa_s->ap_iface)
3638 wpas_p2p_group_deinit(wpa_s);
3639 }
3640
3641 p2p_deinit(global->p2p);
3642 global->p2p = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003643 global->p2p_init_wpa_s = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003644}
3645
3646
3647static int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s)
3648{
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003649 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
3650 wpa_s->conf->p2p_no_group_iface)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003651 return 0; /* separate interface disabled per configuration */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003652 if (wpa_s->drv_flags &
3653 (WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE |
3654 WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P))
3655 return 1; /* P2P group requires a new interface in every case
3656 */
3657 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_CONCURRENT))
3658 return 0; /* driver does not support concurrent operations */
3659 if (wpa_s->global->ifaces->next)
3660 return 1; /* more that one interface already in use */
3661 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3662 return 1; /* this interface is already in use */
3663 return 0;
3664}
3665
3666
3667static int wpas_p2p_start_go_neg(struct wpa_supplicant *wpa_s,
3668 const u8 *peer_addr,
3669 enum p2p_wps_method wps_method,
3670 int go_intent, const u8 *own_interface_addr,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003671 unsigned int force_freq, int persistent_group,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003672 struct wpa_ssid *ssid, unsigned int pref_freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003673{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003674 if (persistent_group && wpa_s->conf->persistent_reconnect)
3675 persistent_group = 2;
3676
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003677 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
3678 return wpa_drv_p2p_connect(wpa_s, peer_addr, wps_method,
3679 go_intent, own_interface_addr,
3680 force_freq, persistent_group);
3681 }
3682
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003683 /*
3684 * Increase GO config timeout if HT40 is used since it takes some time
3685 * to scan channels for coex purposes before the BSS can be started.
3686 */
3687 p2p_set_config_timeout(wpa_s->global->p2p,
3688 wpa_s->p2p_go_ht40 ? 255 : 100, 20);
3689
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003690 return p2p_connect(wpa_s->global->p2p, peer_addr, wps_method,
3691 go_intent, own_interface_addr, force_freq,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003692 persistent_group, ssid ? ssid->ssid : NULL,
3693 ssid ? ssid->ssid_len : 0,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003694 wpa_s->p2p_pd_before_go_neg, pref_freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003695}
3696
3697
3698static int wpas_p2p_auth_go_neg(struct wpa_supplicant *wpa_s,
3699 const u8 *peer_addr,
3700 enum p2p_wps_method wps_method,
3701 int go_intent, const u8 *own_interface_addr,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003702 unsigned int force_freq, int persistent_group,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003703 struct wpa_ssid *ssid, unsigned int pref_freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003704{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003705 if (persistent_group && wpa_s->conf->persistent_reconnect)
3706 persistent_group = 2;
3707
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003708 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
3709 return -1;
3710
3711 return p2p_authorize(wpa_s->global->p2p, peer_addr, wps_method,
3712 go_intent, own_interface_addr, force_freq,
Dmitry Shmidt04949592012-07-19 12:16:46 -07003713 persistent_group, ssid ? ssid->ssid : NULL,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003714 ssid ? ssid->ssid_len : 0, pref_freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003715}
3716
3717
3718static void wpas_p2p_check_join_scan_limit(struct wpa_supplicant *wpa_s)
3719{
3720 wpa_s->p2p_join_scan_count++;
3721 wpa_printf(MSG_DEBUG, "P2P: Join scan attempt %d",
3722 wpa_s->p2p_join_scan_count);
3723 if (wpa_s->p2p_join_scan_count > P2P_MAX_JOIN_SCAN_ATTEMPTS) {
3724 wpa_printf(MSG_DEBUG, "P2P: Failed to find GO " MACSTR
3725 " for join operationg - stop join attempt",
3726 MAC2STR(wpa_s->pending_join_iface_addr));
3727 eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003728 if (wpa_s->p2p_auto_pd) {
3729 wpa_s->p2p_auto_pd = 0;
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003730 wpa_msg_global(wpa_s, MSG_INFO,
3731 P2P_EVENT_PROV_DISC_FAILURE
3732 " p2p_dev_addr=" MACSTR " status=N/A",
3733 MAC2STR(wpa_s->pending_join_dev_addr));
Dmitry Shmidt04949592012-07-19 12:16:46 -07003734 return;
3735 }
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003736 wpa_msg_global(wpa_s->parent, MSG_INFO,
3737 P2P_EVENT_GROUP_FORMATION_FAILURE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003738 }
3739}
3740
3741
Dmitry Shmidt04949592012-07-19 12:16:46 -07003742static int wpas_check_freq_conflict(struct wpa_supplicant *wpa_s, int freq)
3743{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003744 int *freqs, res, num, i;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003745
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003746 if (wpas_p2p_num_unused_channels(wpa_s) > 0) {
3747 /* Multiple channels are supported and not all are in use */
Dmitry Shmidt04949592012-07-19 12:16:46 -07003748 return 0;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003749 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07003750
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003751 freqs = os_calloc(wpa_s->num_multichan_concurrent, sizeof(int));
3752 if (!freqs)
3753 return 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003754
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003755 num = wpas_p2p_valid_oper_freqs(wpa_s, freqs,
3756 wpa_s->num_multichan_concurrent);
3757 if (num < 0) {
3758 res = 1;
3759 goto exit_free;
3760 }
3761
3762 for (i = 0; i < num; i++) {
3763 if (freqs[i] == freq) {
3764 wpa_printf(MSG_DEBUG, "P2P: Frequency %d MHz in use by another virtual interface and can be used",
3765 freq);
3766 res = 0;
3767 goto exit_free;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003768 }
3769 }
3770
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003771 res = 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003772
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003773exit_free:
3774 os_free(freqs);
3775 return res;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003776}
3777
3778
3779static int wpas_p2p_peer_go(struct wpa_supplicant *wpa_s,
3780 const u8 *peer_dev_addr)
3781{
3782 struct wpa_bss *bss;
3783 int updated;
3784
3785 bss = wpa_bss_get_p2p_dev_addr(wpa_s, peer_dev_addr);
3786 if (bss == NULL)
3787 return -1;
3788 if (bss->last_update_idx < wpa_s->bss_update_idx) {
3789 wpa_printf(MSG_DEBUG, "P2P: Peer BSS entry not updated in the "
3790 "last scan");
3791 return 0;
3792 }
3793
3794 updated = os_time_before(&wpa_s->p2p_auto_started, &bss->last_update);
3795 wpa_printf(MSG_DEBUG, "P2P: Current BSS entry for peer updated at "
3796 "%ld.%06ld (%supdated in last scan)",
3797 bss->last_update.sec, bss->last_update.usec,
3798 updated ? "": "not ");
3799
3800 return updated;
3801}
3802
3803
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003804static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
3805 struct wpa_scan_results *scan_res)
3806{
3807 struct wpa_bss *bss;
3808 int freq;
3809 u8 iface_addr[ETH_ALEN];
Dmitry Shmidt04949592012-07-19 12:16:46 -07003810
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003811 eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
3812
3813 if (wpa_s->global->p2p_disabled)
3814 return;
3815
Dmitry Shmidt04949592012-07-19 12:16:46 -07003816 wpa_printf(MSG_DEBUG, "P2P: Scan results received (%d BSS) for %sjoin",
3817 scan_res ? (int) scan_res->num : -1,
3818 wpa_s->p2p_auto_join ? "auto_" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003819
3820 if (scan_res)
3821 wpas_p2p_scan_res_handler(wpa_s, scan_res);
3822
Dmitry Shmidt04949592012-07-19 12:16:46 -07003823 if (wpa_s->p2p_auto_pd) {
3824 int join = wpas_p2p_peer_go(wpa_s,
3825 wpa_s->pending_join_dev_addr);
3826 if (join == 0 &&
3827 wpa_s->auto_pd_scan_retry < P2P_AUTO_PD_SCAN_ATTEMPTS) {
3828 wpa_s->auto_pd_scan_retry++;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003829 bss = wpa_bss_get_bssid_latest(
3830 wpa_s, wpa_s->pending_join_dev_addr);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003831 if (bss) {
3832 freq = bss->freq;
3833 wpa_printf(MSG_DEBUG, "P2P: Scan retry %d for "
3834 "the peer " MACSTR " at %d MHz",
3835 wpa_s->auto_pd_scan_retry,
3836 MAC2STR(wpa_s->
3837 pending_join_dev_addr),
3838 freq);
3839 wpas_p2p_join_scan_req(wpa_s, freq);
3840 return;
3841 }
3842 }
3843
3844 if (join < 0)
3845 join = 0;
3846
3847 wpa_s->p2p_auto_pd = 0;
3848 wpa_s->pending_pd_use = join ? AUTO_PD_JOIN : AUTO_PD_GO_NEG;
3849 wpa_printf(MSG_DEBUG, "P2P: Auto PD with " MACSTR " join=%d",
3850 MAC2STR(wpa_s->pending_join_dev_addr), join);
3851 if (p2p_prov_disc_req(wpa_s->global->p2p,
3852 wpa_s->pending_join_dev_addr,
3853 wpa_s->pending_pd_config_methods, join,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003854 0, wpa_s->user_initiated_pd) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003855 wpa_s->p2p_auto_pd = 0;
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003856 wpa_msg_global(wpa_s, MSG_INFO,
3857 P2P_EVENT_PROV_DISC_FAILURE
3858 " p2p_dev_addr=" MACSTR " status=N/A",
3859 MAC2STR(wpa_s->pending_join_dev_addr));
Dmitry Shmidt04949592012-07-19 12:16:46 -07003860 }
3861 return;
3862 }
3863
3864 if (wpa_s->p2p_auto_join) {
3865 int join = wpas_p2p_peer_go(wpa_s,
3866 wpa_s->pending_join_dev_addr);
3867 if (join < 0) {
3868 wpa_printf(MSG_DEBUG, "P2P: Peer was not found to be "
3869 "running a GO -> use GO Negotiation");
3870 wpas_p2p_connect(wpa_s, wpa_s->pending_join_dev_addr,
3871 wpa_s->p2p_pin, wpa_s->p2p_wps_method,
3872 wpa_s->p2p_persistent_group, 0, 0, 0,
3873 wpa_s->p2p_go_intent,
3874 wpa_s->p2p_connect_freq,
3875 wpa_s->p2p_persistent_id,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003876 wpa_s->p2p_pd_before_go_neg,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003877 wpa_s->p2p_go_ht40,
3878 wpa_s->p2p_go_vht);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003879 return;
3880 }
3881
3882 wpa_printf(MSG_DEBUG, "P2P: Peer was found running GO%s -> "
3883 "try to join the group", join ? "" :
3884 " in older scan");
3885 if (!join)
3886 wpa_s->p2p_fallback_to_go_neg = 1;
3887 }
3888
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003889 freq = p2p_get_oper_freq(wpa_s->global->p2p,
3890 wpa_s->pending_join_iface_addr);
3891 if (freq < 0 &&
3892 p2p_get_interface_addr(wpa_s->global->p2p,
3893 wpa_s->pending_join_dev_addr,
3894 iface_addr) == 0 &&
3895 os_memcmp(iface_addr, wpa_s->pending_join_dev_addr, ETH_ALEN) != 0)
3896 {
3897 wpa_printf(MSG_DEBUG, "P2P: Overwrite pending interface "
3898 "address for join from " MACSTR " to " MACSTR
3899 " based on newly discovered P2P peer entry",
3900 MAC2STR(wpa_s->pending_join_iface_addr),
3901 MAC2STR(iface_addr));
3902 os_memcpy(wpa_s->pending_join_iface_addr, iface_addr,
3903 ETH_ALEN);
3904
3905 freq = p2p_get_oper_freq(wpa_s->global->p2p,
3906 wpa_s->pending_join_iface_addr);
3907 }
3908 if (freq >= 0) {
3909 wpa_printf(MSG_DEBUG, "P2P: Target GO operating frequency "
3910 "from P2P peer table: %d MHz", freq);
3911 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003912 bss = wpa_bss_get_bssid_latest(wpa_s, wpa_s->pending_join_iface_addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003913 if (bss) {
3914 freq = bss->freq;
3915 wpa_printf(MSG_DEBUG, "P2P: Target GO operating frequency "
Dmitry Shmidt051af732013-10-22 13:52:46 -07003916 "from BSS table: %d MHz (SSID %s)", freq,
3917 wpa_ssid_txt(bss->ssid, bss->ssid_len));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003918 }
3919 if (freq > 0) {
3920 u16 method;
3921
Dmitry Shmidt04949592012-07-19 12:16:46 -07003922 if (wpas_check_freq_conflict(wpa_s, freq) > 0) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003923 wpa_msg_global(wpa_s->parent, MSG_INFO,
3924 P2P_EVENT_GROUP_FORMATION_FAILURE
3925 "reason=FREQ_CONFLICT");
Dmitry Shmidt04949592012-07-19 12:16:46 -07003926 return;
3927 }
3928
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003929 wpa_printf(MSG_DEBUG, "P2P: Send Provision Discovery Request "
3930 "prior to joining an existing group (GO " MACSTR
3931 " freq=%u MHz)",
3932 MAC2STR(wpa_s->pending_join_dev_addr), freq);
3933 wpa_s->pending_pd_before_join = 1;
3934
3935 switch (wpa_s->pending_join_wps_method) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003936 case WPS_PIN_DISPLAY:
3937 method = WPS_CONFIG_KEYPAD;
3938 break;
3939 case WPS_PIN_KEYPAD:
3940 method = WPS_CONFIG_DISPLAY;
3941 break;
3942 case WPS_PBC:
3943 method = WPS_CONFIG_PUSHBUTTON;
3944 break;
3945 default:
3946 method = 0;
3947 break;
3948 }
3949
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003950 if ((p2p_get_provisioning_info(wpa_s->global->p2p,
3951 wpa_s->pending_join_dev_addr) ==
3952 method)) {
3953 /*
3954 * We have already performed provision discovery for
3955 * joining the group. Proceed directly to join
3956 * operation without duplicated provision discovery. */
3957 wpa_printf(MSG_DEBUG, "P2P: Provision discovery "
3958 "with " MACSTR " already done - proceed to "
3959 "join",
3960 MAC2STR(wpa_s->pending_join_dev_addr));
3961 wpa_s->pending_pd_before_join = 0;
3962 goto start;
3963 }
3964
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003965 if (p2p_prov_disc_req(wpa_s->global->p2p,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003966 wpa_s->pending_join_dev_addr, method, 1,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003967 freq, wpa_s->user_initiated_pd) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003968 wpa_printf(MSG_DEBUG, "P2P: Failed to send Provision "
3969 "Discovery Request before joining an "
3970 "existing group");
3971 wpa_s->pending_pd_before_join = 0;
3972 goto start;
3973 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003974 return;
3975 }
3976
3977 wpa_printf(MSG_DEBUG, "P2P: Failed to find BSS/GO - try again later");
3978 eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
3979 eloop_register_timeout(1, 0, wpas_p2p_join_scan, wpa_s, NULL);
3980 wpas_p2p_check_join_scan_limit(wpa_s);
3981 return;
3982
3983start:
3984 /* Start join operation immediately */
3985 wpas_p2p_join_start(wpa_s);
3986}
3987
3988
Dmitry Shmidt04949592012-07-19 12:16:46 -07003989static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003990{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003991 int ret;
3992 struct wpa_driver_scan_params params;
3993 struct wpabuf *wps_ie, *ies;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003994 size_t ielen;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003995 int freqs[2] = { 0, 0 };
Dmitry Shmidtad266fb2012-08-24 17:03:35 -07003996#ifdef ANDROID_P2P
3997 int oper_freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003998
Dmitry Shmidtad266fb2012-08-24 17:03:35 -07003999 /* If freq is not provided, check the operating freq of the GO and do a
4000 * a directed scan to save time
4001 */
4002 if(!freq) {
4003 freq = (oper_freq = p2p_get_oper_freq(wpa_s->global->p2p,
4004 wpa_s->pending_join_iface_addr) == -1) ? 0 : oper_freq;
4005 }
4006#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004007 os_memset(&params, 0, sizeof(params));
4008
4009 /* P2P Wildcard SSID */
4010 params.num_ssids = 1;
4011 params.ssids[0].ssid = (u8 *) P2P_WILDCARD_SSID;
4012 params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
4013
4014 wpa_s->wps->dev.p2p = 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004015 wps_ie = wps_build_probe_req_ie(DEV_PW_DEFAULT, &wpa_s->wps->dev,
4016 wpa_s->wps->uuid, WPS_REQ_ENROLLEE, 0,
4017 NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004018 if (wps_ie == NULL) {
4019 wpas_p2p_scan_res_join(wpa_s, NULL);
4020 return;
4021 }
4022
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004023 ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
4024 ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004025 if (ies == NULL) {
4026 wpabuf_free(wps_ie);
4027 wpas_p2p_scan_res_join(wpa_s, NULL);
4028 return;
4029 }
4030 wpabuf_put_buf(ies, wps_ie);
4031 wpabuf_free(wps_ie);
4032
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004033 p2p_scan_ie(wpa_s->global->p2p, ies, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004034
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004035 params.p2p_probe = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004036 params.extra_ies = wpabuf_head(ies);
4037 params.extra_ies_len = wpabuf_len(ies);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004038 if (freq > 0) {
4039 freqs[0] = freq;
4040 params.freqs = freqs;
4041 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004042
4043 /*
4044 * Run a scan to update BSS table and start Provision Discovery once
4045 * the new scan results become available.
4046 */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004047 ret = wpa_drv_scan(wpa_s, &params);
Dmitry Shmidt444d5672013-04-01 13:08:44 -07004048 if (!ret) {
4049 os_get_time(&wpa_s->scan_trigger_time);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004050 wpa_s->scan_res_handler = wpas_p2p_scan_res_join;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07004051 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004052
4053 wpabuf_free(ies);
4054
4055 if (ret) {
4056 wpa_printf(MSG_DEBUG, "P2P: Failed to start scan for join - "
4057 "try again later");
4058 eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
4059 eloop_register_timeout(1, 0, wpas_p2p_join_scan, wpa_s, NULL);
4060 wpas_p2p_check_join_scan_limit(wpa_s);
4061 }
4062}
4063
4064
Dmitry Shmidt04949592012-07-19 12:16:46 -07004065static void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx)
4066{
4067 struct wpa_supplicant *wpa_s = eloop_ctx;
4068 wpas_p2p_join_scan_req(wpa_s, 0);
4069}
4070
4071
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004072static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr,
Dmitry Shmidt04949592012-07-19 12:16:46 -07004073 const u8 *dev_addr, enum p2p_wps_method wps_method,
4074 int auto_join)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004075{
4076 wpa_printf(MSG_DEBUG, "P2P: Request to join existing group (iface "
Dmitry Shmidt04949592012-07-19 12:16:46 -07004077 MACSTR " dev " MACSTR ")%s",
4078 MAC2STR(iface_addr), MAC2STR(dev_addr),
4079 auto_join ? " (auto_join)" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004080
Dmitry Shmidt04949592012-07-19 12:16:46 -07004081 wpa_s->p2p_auto_pd = 0;
4082 wpa_s->p2p_auto_join = !!auto_join;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004083 os_memcpy(wpa_s->pending_join_iface_addr, iface_addr, ETH_ALEN);
4084 os_memcpy(wpa_s->pending_join_dev_addr, dev_addr, ETH_ALEN);
4085 wpa_s->pending_join_wps_method = wps_method;
4086
4087 /* Make sure we are not running find during connection establishment */
4088 wpas_p2p_stop_find(wpa_s);
4089
4090 wpa_s->p2p_join_scan_count = 0;
4091 wpas_p2p_join_scan(wpa_s, NULL);
4092 return 0;
4093}
4094
4095
4096static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s)
4097{
4098 struct wpa_supplicant *group;
4099 struct p2p_go_neg_results res;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004100 struct wpa_bss *bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004101
4102 group = wpas_p2p_get_group_iface(wpa_s, 0, 0);
4103 if (group == NULL)
4104 return -1;
4105 if (group != wpa_s) {
4106 os_memcpy(group->p2p_pin, wpa_s->p2p_pin,
4107 sizeof(group->p2p_pin));
4108 group->p2p_wps_method = wpa_s->p2p_wps_method;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004109 } else {
4110 /*
4111 * Need to mark the current interface for p2p_group_formation
4112 * when a separate group interface is not used. This is needed
4113 * to allow p2p_cancel stop a pending p2p_connect-join.
4114 * wpas_p2p_init_group_interface() addresses this for the case
4115 * where a separate group interface is used.
4116 */
4117 wpa_s->global->p2p_group_formation = wpa_s;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004118 }
4119
4120 group->p2p_in_provisioning = 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004121 group->p2p_fallback_to_go_neg = wpa_s->p2p_fallback_to_go_neg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004122
4123 os_memset(&res, 0, sizeof(res));
4124 os_memcpy(res.peer_interface_addr, wpa_s->pending_join_iface_addr,
4125 ETH_ALEN);
4126 res.wps_method = wpa_s->pending_join_wps_method;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07004127 bss = wpa_bss_get_bssid_latest(wpa_s, wpa_s->pending_join_iface_addr);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004128 if (bss) {
4129 res.freq = bss->freq;
4130 res.ssid_len = bss->ssid_len;
4131 os_memcpy(res.ssid, bss->ssid, bss->ssid_len);
Dmitry Shmidt051af732013-10-22 13:52:46 -07004132 wpa_printf(MSG_DEBUG, "P2P: Join target GO operating frequency "
4133 "from BSS table: %d MHz (SSID %s)", bss->freq,
4134 wpa_ssid_txt(bss->ssid, bss->ssid_len));
Dmitry Shmidt04949592012-07-19 12:16:46 -07004135 }
4136
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004137 if (wpa_s->off_channel_freq || wpa_s->roc_waiting_drv_freq) {
4138 wpa_printf(MSG_DEBUG, "P2P: Cancel remain-on-channel prior to "
4139 "starting client");
4140 wpa_drv_cancel_remain_on_channel(wpa_s);
4141 wpa_s->off_channel_freq = 0;
4142 wpa_s->roc_waiting_drv_freq = 0;
4143 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004144 wpas_start_wps_enrollee(group, &res);
4145
4146 /*
4147 * Allow a longer timeout for join-a-running-group than normal 15
4148 * second group formation timeout since the GO may not have authorized
4149 * our connection yet.
4150 */
4151 eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s, NULL);
4152 eloop_register_timeout(60, 0, wpas_p2p_group_formation_timeout,
4153 wpa_s, NULL);
4154
4155 return 0;
4156}
4157
4158
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08004159static int wpas_p2p_setup_freqs(struct wpa_supplicant *wpa_s, int freq,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004160 int *force_freq, int *pref_freq, int go)
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08004161{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004162 int *freqs, res;
4163 unsigned int freq_in_use = 0, num, i;
4164
4165 freqs = os_calloc(wpa_s->num_multichan_concurrent, sizeof(int));
4166 if (!freqs)
4167 return -1;
4168
4169 num = get_shared_radio_freqs(wpa_s, freqs,
4170 wpa_s->num_multichan_concurrent);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004171 wpa_printf(MSG_DEBUG,
4172 "P2P: Setup freqs: freq=%d num_MCC=%d shared_freqs=%u",
4173 freq, wpa_s->num_multichan_concurrent, num);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004174
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08004175 if (freq > 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004176 int ret;
4177 if (go)
4178 ret = p2p_supported_freq(wpa_s->global->p2p, freq);
4179 else
4180 ret = p2p_supported_freq_cli(wpa_s->global->p2p, freq);
4181 if (!ret) {
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08004182 wpa_printf(MSG_DEBUG, "P2P: The forced channel "
4183 "(%u MHz) is not supported for P2P uses",
4184 freq);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004185 res = -3;
4186 goto exit_free;
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08004187 }
4188
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004189 for (i = 0; i < num; i++) {
4190 if (freqs[i] == freq)
4191 freq_in_use = 1;
4192 }
4193
4194 if (num == wpa_s->num_multichan_concurrent && !freq_in_use) {
4195 wpa_printf(MSG_DEBUG, "P2P: Cannot start P2P group on %u MHz as there are no available channels",
4196 freq);
4197 res = -2;
4198 goto exit_free;
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08004199 }
4200 wpa_printf(MSG_DEBUG, "P2P: Trying to force us to use the "
4201 "requested channel (%u MHz)", freq);
4202 *force_freq = freq;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004203 goto exit_ok;
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08004204 }
4205
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004206 for (i = 0; i < num; i++) {
4207 if (!p2p_supported_freq(wpa_s->global->p2p, freqs[i]))
4208 continue;
4209
Dmitry Shmidt51a47d52013-09-10 10:52:57 -07004210#ifndef ANDROID_P2P
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004211 wpa_printf(MSG_DEBUG, "P2P: Try to force us to use frequency (%u MHz) which is already in use",
4212 *force_freq);
4213 *force_freq = freqs[i];
Dmitry Shmidt51a47d52013-09-10 10:52:57 -07004214#endif
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004215
4216 if (*pref_freq == 0 && num < wpa_s->num_multichan_concurrent) {
4217 wpa_printf(MSG_DEBUG, "P2P: Try to prefer a frequency we are already using");
Dmitry Shmidt51a47d52013-09-10 10:52:57 -07004218 *pref_freq = freqs[i];
4219#ifdef ANDROID_P2P
4220 } else {
4221 wpa_printf(MSG_DEBUG, "P2P: Try to force us to use frequency (%u MHz) which is already in use",
4222 *force_freq);
4223 *force_freq = freqs[i];
4224#endif
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004225 }
4226 break;
4227 }
4228
4229 if (i == num) {
4230 if (num < wpa_s->num_multichan_concurrent) {
4231 wpa_printf(MSG_DEBUG, "P2P: Current operating channels are not available for P2P. Try to use another channel");
4232 *force_freq = 0;
4233 } else {
4234 wpa_printf(MSG_DEBUG, "P2P: All channels are in use and none of them are P2P enabled. Cannot start P2P group");
4235 res = -2;
4236 goto exit_free;
4237 }
4238 }
4239
4240exit_ok:
4241 res = 0;
4242exit_free:
4243 os_free(freqs);
4244 return res;
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08004245}
4246
4247
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004248/**
4249 * wpas_p2p_connect - Request P2P Group Formation to be started
4250 * @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface()
4251 * @peer_addr: Address of the peer P2P Device
4252 * @pin: PIN to use during provisioning or %NULL to indicate PBC mode
4253 * @persistent_group: Whether to create a persistent group
Dmitry Shmidt04949592012-07-19 12:16:46 -07004254 * @auto_join: Whether to select join vs. GO Negotiation automatically
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004255 * @join: Whether to join an existing group (as a client) instead of starting
4256 * Group Owner negotiation; @peer_addr is BSSID in that case
4257 * @auth: Whether to only authorize the connection instead of doing that and
4258 * initiating Group Owner negotiation
4259 * @go_intent: GO Intent or -1 to use default
4260 * @freq: Frequency for the group or 0 for auto-selection
Dmitry Shmidt04949592012-07-19 12:16:46 -07004261 * @persistent_id: Persistent group credentials to use for forcing GO
4262 * parameters or -1 to generate new values (SSID/passphrase)
4263 * @pd: Whether to send Provision Discovery prior to GO Negotiation as an
4264 * interoperability workaround when initiating group formation
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004265 * @ht40: Start GO with 40 MHz channel width
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004266 * @vht: Start GO with VHT support
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004267 * Returns: 0 or new PIN (if pin was %NULL) on success, -1 on unspecified
4268 * failure, -2 on failure due to channel not currently available,
4269 * -3 if forced channel is not supported
4270 */
4271int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
4272 const char *pin, enum p2p_wps_method wps_method,
Dmitry Shmidt04949592012-07-19 12:16:46 -07004273 int persistent_group, int auto_join, int join, int auth,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004274 int go_intent, int freq, int persistent_id, int pd,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004275 int ht40, int vht)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004276{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004277 int force_freq = 0, pref_freq = 0;
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08004278 int ret = 0, res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004279 enum wpa_driver_if_type iftype;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004280 const u8 *if_addr;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004281 struct wpa_ssid *ssid = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004282
4283 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
4284 return -1;
4285
Dmitry Shmidt04949592012-07-19 12:16:46 -07004286 if (persistent_id >= 0) {
4287 ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
4288 if (ssid == NULL || ssid->disabled != 2 ||
4289 ssid->mode != WPAS_MODE_P2P_GO)
4290 return -1;
4291 }
4292
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07004293 os_free(wpa_s->global->add_psk);
4294 wpa_s->global->add_psk = NULL;
4295
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004296 if (go_intent < 0)
4297 go_intent = wpa_s->conf->p2p_go_intent;
4298
4299 if (!auth)
4300 wpa_s->p2p_long_listen = 0;
4301
4302 wpa_s->p2p_wps_method = wps_method;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004303 wpa_s->p2p_persistent_group = !!persistent_group;
4304 wpa_s->p2p_persistent_id = persistent_id;
4305 wpa_s->p2p_go_intent = go_intent;
4306 wpa_s->p2p_connect_freq = freq;
4307 wpa_s->p2p_fallback_to_go_neg = 0;
4308 wpa_s->p2p_pd_before_go_neg = !!pd;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004309 wpa_s->p2p_go_ht40 = !!ht40;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004310 wpa_s->p2p_go_vht = !!vht;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004311
4312 if (pin)
4313 os_strlcpy(wpa_s->p2p_pin, pin, sizeof(wpa_s->p2p_pin));
4314 else if (wps_method == WPS_PIN_DISPLAY) {
4315 ret = wps_generate_pin();
4316 os_snprintf(wpa_s->p2p_pin, sizeof(wpa_s->p2p_pin), "%08d",
4317 ret);
4318 wpa_printf(MSG_DEBUG, "P2P: Randomly generated PIN: %s",
4319 wpa_s->p2p_pin);
4320 } else
4321 wpa_s->p2p_pin[0] = '\0';
4322
Dmitry Shmidt04949592012-07-19 12:16:46 -07004323 if (join || auto_join) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004324 u8 iface_addr[ETH_ALEN], dev_addr[ETH_ALEN];
4325 if (auth) {
4326 wpa_printf(MSG_DEBUG, "P2P: Authorize invitation to "
4327 "connect a running group from " MACSTR,
4328 MAC2STR(peer_addr));
4329 os_memcpy(wpa_s->p2p_auth_invite, peer_addr, ETH_ALEN);
4330 return ret;
4331 }
4332 os_memcpy(dev_addr, peer_addr, ETH_ALEN);
4333 if (p2p_get_interface_addr(wpa_s->global->p2p, peer_addr,
4334 iface_addr) < 0) {
4335 os_memcpy(iface_addr, peer_addr, ETH_ALEN);
4336 p2p_get_dev_addr(wpa_s->global->p2p, peer_addr,
4337 dev_addr);
4338 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07004339 if (auto_join) {
4340 os_get_time(&wpa_s->p2p_auto_started);
4341 wpa_printf(MSG_DEBUG, "P2P: Auto join started at "
4342 "%ld.%06ld",
4343 wpa_s->p2p_auto_started.sec,
4344 wpa_s->p2p_auto_started.usec);
4345 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004346 wpa_s->user_initiated_pd = 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004347 if (wpas_p2p_join(wpa_s, iface_addr, dev_addr, wps_method,
4348 auto_join) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004349 return -1;
4350 return ret;
4351 }
4352
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004353 res = wpas_p2p_setup_freqs(wpa_s, freq, &force_freq, &pref_freq,
4354 go_intent == 15);
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08004355 if (res)
4356 return res;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004357 wpas_p2p_set_own_freq_preference(wpa_s, force_freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004358
4359 wpa_s->create_p2p_iface = wpas_p2p_create_iface(wpa_s);
4360
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004361 if (wpa_s->create_p2p_iface) {
4362 /* Prepare to add a new interface for the group */
4363 iftype = WPA_IF_P2P_GROUP;
4364 if (go_intent == 15)
4365 iftype = WPA_IF_P2P_GO;
4366 if (wpas_p2p_add_group_interface(wpa_s, iftype) < 0) {
4367 wpa_printf(MSG_ERROR, "P2P: Failed to allocate a new "
4368 "interface for the group");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004369 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004370 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004371
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004372 if_addr = wpa_s->pending_interface_addr;
4373 } else
4374 if_addr = wpa_s->own_addr;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004375
4376 if (auth) {
4377 if (wpas_p2p_auth_go_neg(wpa_s, peer_addr, wps_method,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004378 go_intent, if_addr,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004379 force_freq, persistent_group, ssid,
4380 pref_freq) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004381 return -1;
4382 return ret;
4383 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004384
4385 if (wpas_p2p_start_go_neg(wpa_s, peer_addr, wps_method,
4386 go_intent, if_addr, force_freq,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004387 persistent_group, ssid, pref_freq) < 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004388 if (wpa_s->create_p2p_iface)
4389 wpas_p2p_remove_pending_group_interface(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004390 return -1;
4391 }
4392 return ret;
4393}
4394
4395
4396/**
4397 * wpas_p2p_remain_on_channel_cb - Indication of remain-on-channel start
4398 * @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface()
4399 * @freq: Frequency of the channel in MHz
4400 * @duration: Duration of the stay on the channel in milliseconds
4401 *
4402 * This callback is called when the driver indicates that it has started the
4403 * requested remain-on-channel duration.
4404 */
4405void wpas_p2p_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
4406 unsigned int freq, unsigned int duration)
4407{
4408 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
4409 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004410 if (wpa_s->off_channel_freq == wpa_s->pending_listen_freq) {
4411 p2p_listen_cb(wpa_s->global->p2p, wpa_s->pending_listen_freq,
4412 wpa_s->pending_listen_duration);
4413 wpa_s->pending_listen_freq = 0;
4414 }
4415}
4416
4417
4418static int wpas_p2p_listen_start(struct wpa_supplicant *wpa_s,
4419 unsigned int timeout)
4420{
4421 /* Limit maximum Listen state time based on driver limitation. */
4422 if (timeout > wpa_s->max_remain_on_chan)
4423 timeout = wpa_s->max_remain_on_chan;
4424
4425 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
4426 return wpa_drv_p2p_listen(wpa_s, timeout);
4427
4428 return p2p_listen(wpa_s->global->p2p, timeout);
4429}
4430
4431
4432/**
4433 * wpas_p2p_cancel_remain_on_channel_cb - Remain-on-channel timeout
4434 * @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface()
4435 * @freq: Frequency of the channel in MHz
4436 *
4437 * This callback is called when the driver indicates that a remain-on-channel
4438 * operation has been completed, i.e., the duration on the requested channel
4439 * has timed out.
4440 */
4441void wpas_p2p_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
4442 unsigned int freq)
4443{
4444 wpa_printf(MSG_DEBUG, "P2P: Cancel remain-on-channel callback "
4445 "(p2p_long_listen=%d ms pending_action_tx=%p)",
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004446 wpa_s->p2p_long_listen, offchannel_pending_action_tx(wpa_s));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004447 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
4448 return;
4449 if (p2p_listen_end(wpa_s->global->p2p, freq) > 0)
4450 return; /* P2P module started a new operation */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004451 if (offchannel_pending_action_tx(wpa_s))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004452 return;
4453 if (wpa_s->p2p_long_listen > 0)
4454 wpa_s->p2p_long_listen -= wpa_s->max_remain_on_chan;
4455 if (wpa_s->p2p_long_listen > 0) {
4456 wpa_printf(MSG_DEBUG, "P2P: Continuing long Listen state");
4457 wpas_p2p_listen_start(wpa_s, wpa_s->p2p_long_listen);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07004458 } else {
4459 /*
4460 * When listen duration is over, stop listen & update p2p_state
4461 * to IDLE.
4462 */
4463 p2p_stop_listen(wpa_s->global->p2p);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004464 }
4465}
4466
4467
4468/**
4469 * wpas_p2p_group_remove - Remove a P2P group
4470 * @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface()
4471 * @ifname: Network interface name of the group interface or "*" to remove all
4472 * groups
4473 * Returns: 0 on success, -1 on failure
4474 *
4475 * This function is used to remove a P2P group. This can be used to disconnect
4476 * from a group in which the local end is a P2P Client or to end a P2P Group in
4477 * case the local end is the Group Owner. If a virtual network interface was
4478 * created for this group, that interface will be removed. Otherwise, only the
4479 * configured P2P group network will be removed from the interface.
4480 */
4481int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname)
4482{
4483 struct wpa_global *global = wpa_s->global;
4484
4485 if (os_strcmp(ifname, "*") == 0) {
4486 struct wpa_supplicant *prev;
4487 wpa_s = global->ifaces;
4488 while (wpa_s) {
4489 prev = wpa_s;
4490 wpa_s = wpa_s->next;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004491 if (prev->p2p_group_interface !=
4492 NOT_P2P_GROUP_INTERFACE ||
4493 (prev->current_ssid &&
4494 prev->current_ssid->p2p_group))
4495 wpas_p2p_disconnect(prev);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004496 }
4497 return 0;
4498 }
4499
4500 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
4501 if (os_strcmp(wpa_s->ifname, ifname) == 0)
4502 break;
4503 }
4504
4505 return wpas_p2p_disconnect(wpa_s);
4506}
4507
4508
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07004509static int wpas_p2p_select_go_freq(struct wpa_supplicant *wpa_s, int freq)
4510{
4511 unsigned int r;
4512
4513 if (freq == 2) {
4514 wpa_printf(MSG_DEBUG, "P2P: Request to start GO on 2.4 GHz "
4515 "band");
4516 if (wpa_s->best_24_freq > 0 &&
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004517 p2p_supported_freq_go(wpa_s->global->p2p,
4518 wpa_s->best_24_freq)) {
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07004519 freq = wpa_s->best_24_freq;
4520 wpa_printf(MSG_DEBUG, "P2P: Use best 2.4 GHz band "
4521 "channel: %d MHz", freq);
4522 } else {
4523 os_get_random((u8 *) &r, sizeof(r));
4524 freq = 2412 + (r % 3) * 25;
4525 wpa_printf(MSG_DEBUG, "P2P: Use random 2.4 GHz band "
4526 "channel: %d MHz", freq);
4527 }
4528 }
4529
4530 if (freq == 5) {
4531 wpa_printf(MSG_DEBUG, "P2P: Request to start GO on 5 GHz "
4532 "band");
4533 if (wpa_s->best_5_freq > 0 &&
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004534 p2p_supported_freq_go(wpa_s->global->p2p,
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07004535 wpa_s->best_5_freq)) {
4536 freq = wpa_s->best_5_freq;
4537 wpa_printf(MSG_DEBUG, "P2P: Use best 5 GHz band "
4538 "channel: %d MHz", freq);
4539 } else {
4540 os_get_random((u8 *) &r, sizeof(r));
4541 freq = 5180 + (r % 4) * 20;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004542 if (!p2p_supported_freq_go(wpa_s->global->p2p, freq)) {
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07004543 wpa_printf(MSG_DEBUG, "P2P: Could not select "
4544 "5 GHz channel for P2P group");
4545 return -1;
4546 }
4547 wpa_printf(MSG_DEBUG, "P2P: Use random 5 GHz band "
4548 "channel: %d MHz", freq);
4549 }
4550 }
4551
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004552 if (freq > 0 && !p2p_supported_freq_go(wpa_s->global->p2p, freq)) {
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07004553 wpa_printf(MSG_DEBUG, "P2P: The forced channel for GO "
4554 "(%u MHz) is not supported for P2P uses",
4555 freq);
4556 return -1;
4557 }
4558
4559 return freq;
4560}
4561
4562
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004563static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
4564 struct p2p_go_neg_results *params,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004565 int freq, int ht40, int vht,
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08004566 const struct p2p_channels *channels)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004567{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004568 int res, *freqs;
Dmitry Shmidt44c95782013-05-17 09:51:35 -07004569 unsigned int pref_freq;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004570 unsigned int num, i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004571
4572 os_memset(params, 0, sizeof(*params));
4573 params->role_go = 1;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004574 params->ht40 = ht40;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004575 params->vht = vht;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004576 if (freq) {
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08004577 if (!freq_included(channels, freq)) {
4578 wpa_printf(MSG_DEBUG, "P2P: Forced GO freq %d MHz not "
4579 "accepted", freq);
4580 return -1;
4581 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004582 wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on forced "
4583 "frequency %d MHz", freq);
4584 params->freq = freq;
4585 } else if (wpa_s->conf->p2p_oper_reg_class == 81 &&
4586 wpa_s->conf->p2p_oper_channel >= 1 &&
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08004587 wpa_s->conf->p2p_oper_channel <= 11 &&
4588 freq_included(channels,
4589 2407 + 5 * wpa_s->conf->p2p_oper_channel)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004590 params->freq = 2407 + 5 * wpa_s->conf->p2p_oper_channel;
4591 wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on configured "
4592 "frequency %d MHz", params->freq);
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08004593 } else if ((wpa_s->conf->p2p_oper_reg_class == 115 ||
4594 wpa_s->conf->p2p_oper_reg_class == 116 ||
4595 wpa_s->conf->p2p_oper_reg_class == 117 ||
4596 wpa_s->conf->p2p_oper_reg_class == 124 ||
4597 wpa_s->conf->p2p_oper_reg_class == 126 ||
4598 wpa_s->conf->p2p_oper_reg_class == 127) &&
4599 freq_included(channels,
4600 5000 + 5 * wpa_s->conf->p2p_oper_channel)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004601 params->freq = 5000 + 5 * wpa_s->conf->p2p_oper_channel;
4602 wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on configured "
4603 "frequency %d MHz", params->freq);
4604 } else if (wpa_s->conf->p2p_oper_channel == 0 &&
4605 wpa_s->best_overall_freq > 0 &&
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004606 p2p_supported_freq_go(wpa_s->global->p2p,
4607 wpa_s->best_overall_freq) &&
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08004608 freq_included(channels, wpa_s->best_overall_freq)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004609 params->freq = wpa_s->best_overall_freq;
4610 wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best overall "
4611 "channel %d MHz", params->freq);
4612 } else if (wpa_s->conf->p2p_oper_channel == 0 &&
4613 wpa_s->best_24_freq > 0 &&
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004614 p2p_supported_freq_go(wpa_s->global->p2p,
4615 wpa_s->best_24_freq) &&
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08004616 freq_included(channels, wpa_s->best_24_freq)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004617 params->freq = wpa_s->best_24_freq;
4618 wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best 2.4 GHz "
4619 "channel %d MHz", params->freq);
4620 } else if (wpa_s->conf->p2p_oper_channel == 0 &&
4621 wpa_s->best_5_freq > 0 &&
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004622 p2p_supported_freq_go(wpa_s->global->p2p,
4623 wpa_s->best_5_freq) &&
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08004624 freq_included(channels, wpa_s->best_5_freq)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004625 params->freq = wpa_s->best_5_freq;
4626 wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best 5 GHz "
4627 "channel %d MHz", params->freq);
Dmitry Shmidt44c95782013-05-17 09:51:35 -07004628 } else if ((pref_freq = p2p_get_pref_freq(wpa_s->global->p2p,
4629 channels))) {
4630 params->freq = pref_freq;
4631 wpa_printf(MSG_DEBUG, "P2P: Set GO freq %d MHz from preferred "
4632 "channels", params->freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004633 } else {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004634 int chan;
4635 for (chan = 0; chan < 11; chan++) {
4636 params->freq = 2412 + chan * 5;
4637 if (!wpas_p2p_disallowed_freq(wpa_s->global,
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08004638 params->freq) &&
4639 freq_included(channels, params->freq))
Dmitry Shmidt04949592012-07-19 12:16:46 -07004640 break;
4641 }
4642 if (chan == 11) {
4643 wpa_printf(MSG_DEBUG, "P2P: No 2.4 GHz channel "
4644 "allowed");
4645 return -1;
4646 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004647 wpa_printf(MSG_DEBUG, "P2P: Set GO freq %d MHz (no preference "
4648 "known)", params->freq);
4649 }
4650
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004651 freqs = os_calloc(wpa_s->num_multichan_concurrent, sizeof(int));
4652 if (!freqs)
4653 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004654
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004655 res = wpas_p2p_valid_oper_freqs(wpa_s, freqs,
4656 wpa_s->num_multichan_concurrent);
4657 if (res < 0) {
4658 os_free(freqs);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004659 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004660 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004661 num = res;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004662
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004663 if (!freq) {
4664 for (i = 0; i < num; i++) {
4665 if (freq_included(channels, freqs[i])) {
4666 wpa_printf(MSG_DEBUG, "P2P: Force GO on a channel we are already using (%u MHz)",
4667 freqs[i]);
4668 params->freq = freqs[i];
4669 break;
4670 }
4671 }
4672
4673 if (i == num) {
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004674 if (wpas_p2p_num_unused_channels(wpa_s) <= 0) {
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004675 wpa_printf(MSG_DEBUG, "P2P: Cannot force GO on any of the channels we are already using");
4676 os_free(freqs);
4677 return -1;
4678 } else {
4679 wpa_printf(MSG_DEBUG, "P2P: Cannot force GO on any of the channels we are already using. Use one of the free channels");
4680 }
4681 }
4682 } else {
4683 for (i = 0; i < num; i++) {
4684 if (freqs[i] == freq)
4685 break;
4686 }
4687
4688 if (i == num) {
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004689 if (wpas_p2p_num_unused_channels(wpa_s) <= 0) {
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004690 wpa_printf(MSG_DEBUG, "P2P: Cannot force GO on freq (%u MHz) as all the channels are in use", freq);
4691 os_free(freqs);
4692 return -1;
4693 } else {
4694 wpa_printf(MSG_DEBUG, "P2P: Cannot force GO on any of the channels we are already using. Use one of the free channels");
4695 }
4696 }
4697 }
4698 os_free(freqs);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004699 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004700}
4701
4702
4703static struct wpa_supplicant *
4704wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
4705 int go)
4706{
4707 struct wpa_supplicant *group_wpa_s;
4708
Dmitry Shmidtaa532512012-09-24 10:35:31 -07004709 if (!wpas_p2p_create_iface(wpa_s)) {
4710 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use same interface for group "
4711 "operations");
Dmitry Shmidt56052862013-10-04 10:23:25 -07004712 wpa_s->p2p_first_connection_timeout = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004713 return wpa_s;
Dmitry Shmidtaa532512012-09-24 10:35:31 -07004714 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004715
4716 if (wpas_p2p_add_group_interface(wpa_s, go ? WPA_IF_P2P_GO :
Dmitry Shmidtaa532512012-09-24 10:35:31 -07004717 WPA_IF_P2P_CLIENT) < 0) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004718 wpa_msg_global(wpa_s, MSG_ERROR,
4719 "P2P: Failed to add group interface");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004720 return NULL;
Dmitry Shmidtaa532512012-09-24 10:35:31 -07004721 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004722 group_wpa_s = wpas_p2p_init_group_interface(wpa_s, go);
4723 if (group_wpa_s == NULL) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004724 wpa_msg_global(wpa_s, MSG_ERROR,
4725 "P2P: Failed to initialize group interface");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004726 wpas_p2p_remove_pending_group_interface(wpa_s);
4727 return NULL;
4728 }
4729
Dmitry Shmidtaa532512012-09-24 10:35:31 -07004730 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use separate group interface %s",
4731 group_wpa_s->ifname);
Dmitry Shmidt56052862013-10-04 10:23:25 -07004732 group_wpa_s->p2p_first_connection_timeout = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004733 return group_wpa_s;
4734}
4735
4736
4737/**
4738 * wpas_p2p_group_add - Add a new P2P group with local end as Group Owner
4739 * @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface()
4740 * @persistent_group: Whether to create a persistent group
4741 * @freq: Frequency for the group or 0 to indicate no hardcoding
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004742 * @ht40: Start GO with 40 MHz channel width
4743 * @vht: Start GO with VHT support
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004744 * Returns: 0 on success, -1 on failure
4745 *
4746 * This function creates a new P2P group with the local end as the Group Owner,
4747 * i.e., without using Group Owner Negotiation.
4748 */
4749int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004750 int freq, int ht40, int vht)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004751{
4752 struct p2p_go_neg_results params;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004753
4754 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
4755 return -1;
4756
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07004757 os_free(wpa_s->global->add_psk);
4758 wpa_s->global->add_psk = NULL;
4759
Dmitry Shmidtdca39792011-09-06 11:17:33 -07004760 /* Make sure we are not running find during connection establishment */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004761 wpa_printf(MSG_DEBUG, "P2P: Stop any on-going P2P FIND");
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004762 wpas_p2p_stop_find_oper(wpa_s);
Dmitry Shmidtdca39792011-09-06 11:17:33 -07004763
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07004764 freq = wpas_p2p_select_go_freq(wpa_s, freq);
4765 if (freq < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004766 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004767
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004768 if (wpas_p2p_init_go_params(wpa_s, &params, freq, ht40, vht, NULL))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004769 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004770 if (params.freq &&
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004771 !p2p_supported_freq_go(wpa_s->global->p2p, params.freq)) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004772 wpa_printf(MSG_DEBUG, "P2P: The selected channel for GO "
4773 "(%u MHz) is not supported for P2P uses",
4774 params.freq);
4775 return -1;
4776 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004777 p2p_go_params(wpa_s->global->p2p, &params);
4778 params.persistent_group = persistent_group;
4779
4780 wpa_s = wpas_p2p_get_group_iface(wpa_s, 0, 1);
4781 if (wpa_s == NULL)
4782 return -1;
4783 wpas_start_wps_go(wpa_s, &params, 0);
4784
4785 return 0;
4786}
4787
4788
4789static int wpas_start_p2p_client(struct wpa_supplicant *wpa_s,
4790 struct wpa_ssid *params, int addr_allocated)
4791{
4792 struct wpa_ssid *ssid;
4793
4794 wpa_s = wpas_p2p_get_group_iface(wpa_s, addr_allocated, 0);
4795 if (wpa_s == NULL)
4796 return -1;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07004797 wpa_s->p2p_last_4way_hs_fail = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004798
4799 wpa_supplicant_ap_deinit(wpa_s);
4800
4801 ssid = wpa_config_add_network(wpa_s->conf);
4802 if (ssid == NULL)
4803 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004804 wpa_config_set_network_defaults(ssid);
4805 ssid->temporary = 1;
4806 ssid->proto = WPA_PROTO_RSN;
4807 ssid->pairwise_cipher = WPA_CIPHER_CCMP;
4808 ssid->group_cipher = WPA_CIPHER_CCMP;
4809 ssid->key_mgmt = WPA_KEY_MGMT_PSK;
4810 ssid->ssid = os_malloc(params->ssid_len);
4811 if (ssid->ssid == NULL) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004812 wpa_config_remove_network(wpa_s->conf, ssid->id);
4813 return -1;
4814 }
4815 os_memcpy(ssid->ssid, params->ssid, params->ssid_len);
4816 ssid->ssid_len = params->ssid_len;
4817 ssid->p2p_group = 1;
4818 ssid->export_keys = 1;
4819 if (params->psk_set) {
4820 os_memcpy(ssid->psk, params->psk, 32);
4821 ssid->psk_set = 1;
4822 }
4823 if (params->passphrase)
4824 ssid->passphrase = os_strdup(params->passphrase);
4825
4826 wpa_supplicant_select_network(wpa_s, ssid);
4827
4828 wpa_s->show_group_started = 1;
4829
4830 return 0;
4831}
4832
4833
4834int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
4835 struct wpa_ssid *ssid, int addr_allocated,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004836 int freq, int ht40, int vht,
Dmitry Shmidt56052862013-10-04 10:23:25 -07004837 const struct p2p_channels *channels,
4838 int connection_timeout)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004839{
4840 struct p2p_go_neg_results params;
4841 int go = 0;
4842
4843 if (ssid->disabled != 2 || ssid->ssid == NULL)
4844 return -1;
4845
4846 if (wpas_get_p2p_group(wpa_s, ssid->ssid, ssid->ssid_len, &go) &&
4847 go == (ssid->mode == WPAS_MODE_P2P_GO)) {
4848 wpa_printf(MSG_DEBUG, "P2P: Requested persistent group is "
4849 "already running");
4850 return 0;
4851 }
4852
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07004853 os_free(wpa_s->global->add_psk);
4854 wpa_s->global->add_psk = NULL;
4855
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004856 /* Make sure we are not running find during connection establishment */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004857 wpas_p2p_stop_find_oper(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004858
Dmitry Shmidt04949592012-07-19 12:16:46 -07004859 wpa_s->p2p_fallback_to_go_neg = 0;
4860
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004861 if (ssid->mode == WPAS_MODE_INFRA)
4862 return wpas_start_p2p_client(wpa_s, ssid, addr_allocated);
4863
4864 if (ssid->mode != WPAS_MODE_P2P_GO)
4865 return -1;
4866
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07004867 freq = wpas_p2p_select_go_freq(wpa_s, freq);
4868 if (freq < 0)
4869 return -1;
4870
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004871 if (wpas_p2p_init_go_params(wpa_s, &params, freq, ht40, vht, channels))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004872 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004873
4874 params.role_go = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004875 params.psk_set = ssid->psk_set;
4876 if (params.psk_set)
4877 os_memcpy(params.psk, ssid->psk, sizeof(params.psk));
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004878 if (ssid->passphrase) {
4879 if (os_strlen(ssid->passphrase) >= sizeof(params.passphrase)) {
4880 wpa_printf(MSG_ERROR, "P2P: Invalid passphrase in "
4881 "persistent group");
4882 return -1;
4883 }
4884 os_strlcpy(params.passphrase, ssid->passphrase,
4885 sizeof(params.passphrase));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004886 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004887 os_memcpy(params.ssid, ssid->ssid, ssid->ssid_len);
4888 params.ssid_len = ssid->ssid_len;
4889 params.persistent_group = 1;
4890
4891 wpa_s = wpas_p2p_get_group_iface(wpa_s, addr_allocated, 1);
4892 if (wpa_s == NULL)
4893 return -1;
4894
Dmitry Shmidt56052862013-10-04 10:23:25 -07004895 wpa_s->p2p_first_connection_timeout = connection_timeout;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004896 wpas_start_wps_go(wpa_s, &params, 0);
4897
4898 return 0;
4899}
4900
4901
4902static void wpas_p2p_ie_update(void *ctx, struct wpabuf *beacon_ies,
4903 struct wpabuf *proberesp_ies)
4904{
4905 struct wpa_supplicant *wpa_s = ctx;
4906 if (wpa_s->ap_iface) {
4907 struct hostapd_data *hapd = wpa_s->ap_iface->bss[0];
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004908 if (!(hapd->conf->p2p & P2P_GROUP_OWNER)) {
4909 wpabuf_free(beacon_ies);
4910 wpabuf_free(proberesp_ies);
4911 return;
4912 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004913 if (beacon_ies) {
4914 wpabuf_free(hapd->p2p_beacon_ie);
4915 hapd->p2p_beacon_ie = beacon_ies;
4916 }
4917 wpabuf_free(hapd->p2p_probe_resp_ie);
4918 hapd->p2p_probe_resp_ie = proberesp_ies;
4919 } else {
4920 wpabuf_free(beacon_ies);
4921 wpabuf_free(proberesp_ies);
4922 }
4923 wpa_supplicant_ap_update_beacon(wpa_s);
4924}
4925
4926
4927static void wpas_p2p_idle_update(void *ctx, int idle)
4928{
4929 struct wpa_supplicant *wpa_s = ctx;
4930 if (!wpa_s->ap_iface)
4931 return;
4932 wpa_printf(MSG_DEBUG, "P2P: GO - group %sidle", idle ? "" : "not ");
Dmitry Shmidt04949592012-07-19 12:16:46 -07004933 if (idle)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004934 wpas_p2p_set_group_idle_timeout(wpa_s);
4935 else
4936 eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL);
4937}
4938
4939
4940struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
Dmitry Shmidt04949592012-07-19 12:16:46 -07004941 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004942{
4943 struct p2p_group *group;
4944 struct p2p_group_config *cfg;
4945
4946 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
4947 return NULL;
4948 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
4949 return NULL;
4950
4951 cfg = os_zalloc(sizeof(*cfg));
4952 if (cfg == NULL)
4953 return NULL;
4954
Dmitry Shmidt04949592012-07-19 12:16:46 -07004955 if (ssid->p2p_persistent_group && wpa_s->conf->persistent_reconnect)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004956 cfg->persistent_group = 2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004957 else if (ssid->p2p_persistent_group)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004958 cfg->persistent_group = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004959 os_memcpy(cfg->interface_addr, wpa_s->own_addr, ETH_ALEN);
4960 if (wpa_s->max_stations &&
4961 wpa_s->max_stations < wpa_s->conf->max_num_sta)
4962 cfg->max_clients = wpa_s->max_stations;
4963 else
4964 cfg->max_clients = wpa_s->conf->max_num_sta;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004965 os_memcpy(cfg->ssid, ssid->ssid, ssid->ssid_len);
4966 cfg->ssid_len = ssid->ssid_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004967 cfg->cb_ctx = wpa_s;
4968 cfg->ie_update = wpas_p2p_ie_update;
4969 cfg->idle_update = wpas_p2p_idle_update;
4970
4971 group = p2p_group_init(wpa_s->global->p2p, cfg);
4972 if (group == NULL)
4973 os_free(cfg);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004974 if (ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004975 p2p_group_notif_formation_done(group);
4976 wpa_s->p2p_group = group;
4977 return group;
4978}
4979
4980
4981void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
4982 int registrar)
4983{
Dmitry Shmidt04949592012-07-19 12:16:46 -07004984 struct wpa_ssid *ssid = wpa_s->current_ssid;
4985
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004986 if (!wpa_s->p2p_in_provisioning) {
4987 wpa_printf(MSG_DEBUG, "P2P: Ignore WPS success event - P2P "
4988 "provisioning not in progress");
4989 return;
4990 }
4991
Dmitry Shmidt04949592012-07-19 12:16:46 -07004992 if (ssid && ssid->mode == WPAS_MODE_INFRA) {
4993 u8 go_dev_addr[ETH_ALEN];
4994 os_memcpy(go_dev_addr, wpa_s->bssid, ETH_ALEN);
4995 wpas_p2p_persistent_group(wpa_s, go_dev_addr, ssid->ssid,
4996 ssid->ssid_len);
4997 /* Clear any stored provisioning info */
4998 p2p_clear_provisioning_info(wpa_s->global->p2p, go_dev_addr);
4999 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005000
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005001 eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->parent,
5002 NULL);
Dmitry Shmidt56052862013-10-04 10:23:25 -07005003 wpa_s->p2p_go_group_formation_completed = 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005004 if (ssid && ssid->mode == WPAS_MODE_INFRA) {
5005 /*
5006 * Use a separate timeout for initial data connection to
5007 * complete to allow the group to be removed automatically if
5008 * something goes wrong in this step before the P2P group idle
5009 * timeout mechanism is taken into use.
5010 */
Dmitry Shmidt56052862013-10-04 10:23:25 -07005011 wpa_dbg(wpa_s, MSG_DEBUG,
5012 "P2P: Re-start group formation timeout (%d seconds) as client for initial connection",
5013 P2P_MAX_INITIAL_CONN_WAIT);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005014 eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT, 0,
5015 wpas_p2p_group_formation_timeout,
5016 wpa_s->parent, NULL);
Dmitry Shmidt56052862013-10-04 10:23:25 -07005017 } else if (ssid) {
5018 /*
5019 * Use a separate timeout for initial data connection to
5020 * complete to allow the group to be removed automatically if
5021 * the client does not complete data connection successfully.
5022 */
5023 wpa_dbg(wpa_s, MSG_DEBUG,
5024 "P2P: Re-start group formation timeout (%d seconds) as GO for initial connection",
5025 P2P_MAX_INITIAL_CONN_WAIT_GO);
5026 eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT_GO, 0,
5027 wpas_p2p_group_formation_timeout,
5028 wpa_s->parent, NULL);
5029 /*
5030 * Complete group formation on first successful data connection
5031 */
5032 wpa_s->p2p_go_group_formation_completed = 0;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005033 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005034 if (wpa_s->global->p2p)
5035 p2p_wps_success_cb(wpa_s->global->p2p, peer_addr);
5036 else if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
5037 wpa_drv_wps_success_cb(wpa_s, peer_addr);
5038 wpas_group_formation_completed(wpa_s, 1);
5039}
5040
5041
Jouni Malinen75ecf522011-06-27 15:19:46 -07005042void wpas_p2p_wps_failed(struct wpa_supplicant *wpa_s,
5043 struct wps_event_fail *fail)
5044{
5045 if (!wpa_s->p2p_in_provisioning) {
5046 wpa_printf(MSG_DEBUG, "P2P: Ignore WPS fail event - P2P "
5047 "provisioning not in progress");
5048 return;
5049 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005050
5051 if (wpa_s->go_params) {
5052 p2p_clear_provisioning_info(
5053 wpa_s->global->p2p,
Dmitry Shmidt04949592012-07-19 12:16:46 -07005054 wpa_s->go_params->peer_device_addr);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005055 }
5056
Jouni Malinen75ecf522011-06-27 15:19:46 -07005057 wpas_notify_p2p_wps_failed(wpa_s, fail);
5058}
5059
5060
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005061int wpas_p2p_prov_disc(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
Dmitry Shmidt04949592012-07-19 12:16:46 -07005062 const char *config_method,
5063 enum wpas_p2p_prov_disc_use use)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005064{
5065 u16 config_methods;
5066
Dmitry Shmidt04949592012-07-19 12:16:46 -07005067 wpa_s->p2p_fallback_to_go_neg = 0;
5068 wpa_s->pending_pd_use = NORMAL_PD;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005069 if (os_strncmp(config_method, "display", 7) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005070 config_methods = WPS_CONFIG_DISPLAY;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005071 else if (os_strncmp(config_method, "keypad", 6) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005072 config_methods = WPS_CONFIG_KEYPAD;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005073 else if (os_strncmp(config_method, "pbc", 3) == 0 ||
5074 os_strncmp(config_method, "pushbutton", 10) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005075 config_methods = WPS_CONFIG_PUSHBUTTON;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005076 else {
5077 wpa_printf(MSG_DEBUG, "P2P: Unknown config method");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005078 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005079 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005080
Dmitry Shmidt04949592012-07-19 12:16:46 -07005081 if (use == WPAS_P2P_PD_AUTO) {
5082 os_memcpy(wpa_s->pending_join_dev_addr, peer_addr, ETH_ALEN);
5083 wpa_s->pending_pd_config_methods = config_methods;
5084 wpa_s->p2p_auto_pd = 1;
5085 wpa_s->p2p_auto_join = 0;
5086 wpa_s->pending_pd_before_join = 0;
5087 wpa_s->auto_pd_scan_retry = 0;
5088 wpas_p2p_stop_find(wpa_s);
5089 wpa_s->p2p_join_scan_count = 0;
5090 os_get_time(&wpa_s->p2p_auto_started);
5091 wpa_printf(MSG_DEBUG, "P2P: Auto PD started at %ld.%06ld",
5092 wpa_s->p2p_auto_started.sec,
5093 wpa_s->p2p_auto_started.usec);
5094 wpas_p2p_join_scan(wpa_s, NULL);
5095 return 0;
5096 }
5097
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005098 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
5099 return wpa_drv_p2p_prov_disc_req(wpa_s, peer_addr,
Dmitry Shmidt04949592012-07-19 12:16:46 -07005100 config_methods,
5101 use == WPAS_P2P_PD_FOR_JOIN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005102 }
5103
5104 if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled)
5105 return -1;
5106
5107 return p2p_prov_disc_req(wpa_s->global->p2p, peer_addr,
Dmitry Shmidt04949592012-07-19 12:16:46 -07005108 config_methods, use == WPAS_P2P_PD_FOR_JOIN,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005109 0, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005110}
5111
5112
5113int wpas_p2p_scan_result_text(const u8 *ies, size_t ies_len, char *buf,
5114 char *end)
5115{
5116 return p2p_scan_result_text(ies, ies_len, buf, end);
5117}
5118
5119
5120static void wpas_p2p_clear_pending_action_tx(struct wpa_supplicant *wpa_s)
5121{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005122 if (!offchannel_pending_action_tx(wpa_s))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005123 return;
5124
5125 wpa_printf(MSG_DEBUG, "P2P: Drop pending Action TX due to new "
5126 "operation request");
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005127 offchannel_clear_pending_action_tx(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005128}
5129
5130
5131int wpas_p2p_find(struct wpa_supplicant *wpa_s, unsigned int timeout,
5132 enum p2p_discovery_type type,
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005133 unsigned int num_req_dev_types, const u8 *req_dev_types,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005134 const u8 *dev_id, unsigned int search_delay)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005135{
5136 wpas_p2p_clear_pending_action_tx(wpa_s);
5137 wpa_s->p2p_long_listen = 0;
5138
5139 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
5140 return wpa_drv_p2p_find(wpa_s, timeout, type);
5141
Dmitry Shmidt04949592012-07-19 12:16:46 -07005142 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL ||
5143 wpa_s->p2p_in_provisioning)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005144 return -1;
5145
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005146 wpa_supplicant_cancel_sched_scan(wpa_s);
5147
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005148 return p2p_find(wpa_s->global->p2p, timeout, type,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005149 num_req_dev_types, req_dev_types, dev_id,
5150 search_delay);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005151}
5152
5153
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005154static int wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005155{
5156 wpas_p2p_clear_pending_action_tx(wpa_s);
5157 wpa_s->p2p_long_listen = 0;
5158 eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL);
5159 eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
Jouni Malinendc7b7132012-09-14 12:53:47 -07005160 wpa_s->global->p2p_cb_on_scan_complete = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005161
5162 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
5163 wpa_drv_p2p_stop_find(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005164 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005165 }
5166
5167 if (wpa_s->global->p2p)
5168 p2p_stop_find(wpa_s->global->p2p);
5169
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005170 return 0;
5171}
5172
5173
5174void wpas_p2p_stop_find(struct wpa_supplicant *wpa_s)
5175{
5176 if (wpas_p2p_stop_find_oper(wpa_s) > 0)
5177 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005178 wpas_p2p_remove_pending_group_interface(wpa_s);
5179}
5180
5181
5182static void wpas_p2p_long_listen_timeout(void *eloop_ctx, void *timeout_ctx)
5183{
5184 struct wpa_supplicant *wpa_s = eloop_ctx;
5185 wpa_s->p2p_long_listen = 0;
5186}
5187
5188
5189int wpas_p2p_listen(struct wpa_supplicant *wpa_s, unsigned int timeout)
5190{
5191 int res;
5192
5193 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
5194 return -1;
5195
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005196 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005197 wpas_p2p_clear_pending_action_tx(wpa_s);
5198
5199 if (timeout == 0) {
5200 /*
5201 * This is a request for unlimited Listen state. However, at
5202 * least for now, this is mapped to a Listen state for one
5203 * hour.
5204 */
5205 timeout = 3600;
5206 }
5207 eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL);
5208 wpa_s->p2p_long_listen = 0;
5209
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005210 /*
5211 * Stop previous find/listen operation to avoid trying to request a new
5212 * remain-on-channel operation while the driver is still running the
5213 * previous one.
5214 */
5215 if (wpa_s->global->p2p)
5216 p2p_stop_find(wpa_s->global->p2p);
5217
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005218 res = wpas_p2p_listen_start(wpa_s, timeout * 1000);
5219 if (res == 0 && timeout * 1000 > wpa_s->max_remain_on_chan) {
5220 wpa_s->p2p_long_listen = timeout * 1000;
5221 eloop_register_timeout(timeout, 0,
5222 wpas_p2p_long_listen_timeout,
5223 wpa_s, NULL);
5224 }
5225
5226 return res;
5227}
5228
5229
5230int wpas_p2p_assoc_req_ie(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
5231 u8 *buf, size_t len, int p2p_group)
5232{
5233 struct wpabuf *p2p_ie;
5234 int ret;
5235
5236 if (wpa_s->global->p2p_disabled)
5237 return -1;
5238 if (wpa_s->global->p2p == NULL)
5239 return -1;
5240 if (bss == NULL)
5241 return -1;
5242
5243 p2p_ie = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
5244 ret = p2p_assoc_req_ie(wpa_s->global->p2p, bss->bssid, buf, len,
5245 p2p_group, p2p_ie);
5246 wpabuf_free(p2p_ie);
5247
5248 return ret;
5249}
5250
5251
5252int wpas_p2p_probe_req_rx(struct wpa_supplicant *wpa_s, const u8 *addr,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005253 const u8 *dst, const u8 *bssid,
Dmitry Shmidt04949592012-07-19 12:16:46 -07005254 const u8 *ie, size_t ie_len, int ssi_signal)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005255{
5256 if (wpa_s->global->p2p_disabled)
5257 return 0;
5258 if (wpa_s->global->p2p == NULL)
5259 return 0;
5260
Dmitry Shmidt04949592012-07-19 12:16:46 -07005261 switch (p2p_probe_req_rx(wpa_s->global->p2p, addr, dst, bssid,
5262 ie, ie_len)) {
5263 case P2P_PREQ_NOT_P2P:
5264 wpas_notify_preq(wpa_s, addr, dst, bssid, ie, ie_len,
5265 ssi_signal);
5266 /* fall through */
5267 case P2P_PREQ_MALFORMED:
5268 case P2P_PREQ_NOT_LISTEN:
5269 case P2P_PREQ_NOT_PROCESSED:
5270 default: /* make gcc happy */
5271 return 0;
5272 case P2P_PREQ_PROCESSED:
5273 return 1;
5274 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005275}
5276
5277
5278void wpas_p2p_rx_action(struct wpa_supplicant *wpa_s, const u8 *da,
5279 const u8 *sa, const u8 *bssid,
5280 u8 category, const u8 *data, size_t len, int freq)
5281{
5282 if (wpa_s->global->p2p_disabled)
5283 return;
5284 if (wpa_s->global->p2p == NULL)
5285 return;
5286
5287 p2p_rx_action(wpa_s->global->p2p, da, sa, bssid, category, data, len,
5288 freq);
5289}
5290
5291
5292void wpas_p2p_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ies)
5293{
5294 if (wpa_s->global->p2p_disabled)
5295 return;
5296 if (wpa_s->global->p2p == NULL)
5297 return;
5298
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005299 p2p_scan_ie(wpa_s->global->p2p, ies, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005300}
5301
5302
5303void wpas_p2p_group_deinit(struct wpa_supplicant *wpa_s)
5304{
5305 p2p_group_deinit(wpa_s->p2p_group);
5306 wpa_s->p2p_group = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005307
5308 wpa_s->ap_configured_cb = NULL;
5309 wpa_s->ap_configured_cb_ctx = NULL;
5310 wpa_s->ap_configured_cb_data = NULL;
5311 wpa_s->connect_without_scan = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005312}
5313
5314
5315int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr)
5316{
5317 wpa_s->p2p_long_listen = 0;
5318
5319 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
5320 return wpa_drv_p2p_reject(wpa_s, addr);
5321
5322 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
5323 return -1;
5324
5325 return p2p_reject(wpa_s->global->p2p, addr);
5326}
5327
5328
5329/* Invite to reinvoke a persistent group */
5330int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
Jouni Malinen31be0a42012-08-31 21:20:51 +03005331 struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07005332 int ht40, int vht, int pref_freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005333{
5334 enum p2p_invite_role role;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005335 u8 *bssid = NULL;
5336 int force_freq = 0;
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08005337 int res;
5338
Dmitry Shmidt700a1372013-03-15 14:14:44 -07005339 wpa_s->global->p2p_invite_group = NULL;
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08005340 if (peer_addr)
5341 os_memcpy(wpa_s->p2p_auth_invite, peer_addr, ETH_ALEN);
5342 else
5343 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005344
Jouni Malinen31be0a42012-08-31 21:20:51 +03005345 wpa_s->p2p_persistent_go_freq = freq;
5346 wpa_s->p2p_go_ht40 = !!ht40;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005347 if (ssid->mode == WPAS_MODE_P2P_GO) {
5348 role = P2P_INVITE_ROLE_GO;
5349 if (peer_addr == NULL) {
5350 wpa_printf(MSG_DEBUG, "P2P: Missing peer "
5351 "address in invitation command");
5352 return -1;
5353 }
5354 if (wpas_p2p_create_iface(wpa_s)) {
5355 if (wpas_p2p_add_group_interface(wpa_s,
5356 WPA_IF_P2P_GO) < 0) {
5357 wpa_printf(MSG_ERROR, "P2P: Failed to "
5358 "allocate a new interface for the "
5359 "group");
5360 return -1;
5361 }
5362 bssid = wpa_s->pending_interface_addr;
5363 } else
5364 bssid = wpa_s->own_addr;
5365 } else {
5366 role = P2P_INVITE_ROLE_CLIENT;
5367 peer_addr = ssid->bssid;
5368 }
5369 wpa_s->pending_invite_ssid_id = ssid->id;
5370
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07005371 res = wpas_p2p_setup_freqs(wpa_s, freq, &force_freq, &pref_freq,
5372 role == P2P_INVITE_ROLE_GO);
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08005373 if (res)
5374 return res;
Irfan Sheriffaf84a572012-09-22 16:59:30 -07005375
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005376 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
5377 return wpa_drv_p2p_invite(wpa_s, peer_addr, role, bssid,
5378 ssid->ssid, ssid->ssid_len,
5379 go_dev_addr, 1);
5380
5381 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
5382 return -1;
5383
5384 return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid,
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08005385 ssid->ssid, ssid->ssid_len, force_freq, go_dev_addr,
5386 1, pref_freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005387}
5388
5389
5390/* Invite to join an active group */
5391int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
5392 const u8 *peer_addr, const u8 *go_dev_addr)
5393{
5394 struct wpa_global *global = wpa_s->global;
5395 enum p2p_invite_role role;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005396 u8 *bssid = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005397 struct wpa_ssid *ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005398 int persistent;
Dmitry Shmidt051af732013-10-22 13:52:46 -07005399 int freq = 0, force_freq = 0, pref_freq = 0;
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08005400 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005401
Jouni Malinen31be0a42012-08-31 21:20:51 +03005402 wpa_s->p2p_persistent_go_freq = 0;
5403 wpa_s->p2p_go_ht40 = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07005404 wpa_s->p2p_go_vht = 0;
Jouni Malinen31be0a42012-08-31 21:20:51 +03005405
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005406 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5407 if (os_strcmp(wpa_s->ifname, ifname) == 0)
5408 break;
5409 }
5410 if (wpa_s == NULL) {
5411 wpa_printf(MSG_DEBUG, "P2P: Interface '%s' not found", ifname);
5412 return -1;
5413 }
5414
5415 ssid = wpa_s->current_ssid;
5416 if (ssid == NULL) {
5417 wpa_printf(MSG_DEBUG, "P2P: No current SSID to use for "
5418 "invitation");
5419 return -1;
5420 }
5421
Dmitry Shmidt700a1372013-03-15 14:14:44 -07005422 wpa_s->global->p2p_invite_group = wpa_s;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005423 persistent = ssid->p2p_persistent_group &&
5424 wpas_p2p_get_persistent(wpa_s->parent, peer_addr,
5425 ssid->ssid, ssid->ssid_len);
5426
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005427 if (ssid->mode == WPAS_MODE_P2P_GO) {
5428 role = P2P_INVITE_ROLE_ACTIVE_GO;
5429 bssid = wpa_s->own_addr;
5430 if (go_dev_addr == NULL)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005431 go_dev_addr = wpa_s->global->p2p_dev_addr;
Dmitry Shmidt051af732013-10-22 13:52:46 -07005432 freq = ssid->frequency;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005433 } else {
5434 role = P2P_INVITE_ROLE_CLIENT;
5435 if (wpa_s->wpa_state < WPA_ASSOCIATED) {
5436 wpa_printf(MSG_DEBUG, "P2P: Not associated - cannot "
5437 "invite to current group");
5438 return -1;
5439 }
5440 bssid = wpa_s->bssid;
5441 if (go_dev_addr == NULL &&
5442 !is_zero_ether_addr(wpa_s->go_dev_addr))
5443 go_dev_addr = wpa_s->go_dev_addr;
Dmitry Shmidt051af732013-10-22 13:52:46 -07005444 freq = wpa_s->current_bss ? wpa_s->current_bss->freq :
5445 (int) wpa_s->assoc_freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005446 }
5447 wpa_s->parent->pending_invite_ssid_id = -1;
5448
5449 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
5450 return wpa_drv_p2p_invite(wpa_s, peer_addr, role, bssid,
5451 ssid->ssid, ssid->ssid_len,
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005452 go_dev_addr, persistent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005453
5454 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
5455 return -1;
5456
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07005457 res = wpas_p2p_setup_freqs(wpa_s, freq, &force_freq, &pref_freq,
5458 role == P2P_INVITE_ROLE_ACTIVE_GO);
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08005459 if (res)
5460 return res;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005461 wpas_p2p_set_own_freq_preference(wpa_s, force_freq);
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08005462
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005463 return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid,
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08005464 ssid->ssid, ssid->ssid_len, force_freq,
5465 go_dev_addr, persistent, pref_freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005466}
5467
5468
5469void wpas_p2p_completed(struct wpa_supplicant *wpa_s)
5470{
5471 struct wpa_ssid *ssid = wpa_s->current_ssid;
5472 const char *ssid_txt;
5473 u8 go_dev_addr[ETH_ALEN];
Jouni Malinen75ecf522011-06-27 15:19:46 -07005474 int network_id = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005475 int persistent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005476 int freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005477
Dmitry Shmidt04949592012-07-19 12:16:46 -07005478 if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION) {
5479 eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
5480 wpa_s->parent, NULL);
5481 }
5482
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005483 if (!wpa_s->show_group_started || !ssid)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005484 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005485
5486 wpa_s->show_group_started = 0;
5487
5488 ssid_txt = wpa_ssid_txt(ssid->ssid, ssid->ssid_len);
5489 os_memset(go_dev_addr, 0, ETH_ALEN);
5490 if (ssid->bssid_set)
5491 os_memcpy(go_dev_addr, ssid->bssid, ETH_ALEN);
5492 persistent = wpas_p2p_persistent_group(wpa_s, go_dev_addr, ssid->ssid,
5493 ssid->ssid_len);
5494 os_memcpy(wpa_s->go_dev_addr, go_dev_addr, ETH_ALEN);
5495
5496 if (wpa_s->global->p2p_group_formation == wpa_s)
5497 wpa_s->global->p2p_group_formation = NULL;
5498
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005499 freq = wpa_s->current_bss ? wpa_s->current_bss->freq :
5500 (int) wpa_s->assoc_freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005501 if (ssid->passphrase == NULL && ssid->psk_set) {
5502 char psk[65];
5503 wpa_snprintf_hex(psk, sizeof(psk), ssid->psk, 32);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005504 wpa_msg_global(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
5505 "%s client ssid=\"%s\" freq=%d psk=%s "
5506 "go_dev_addr=" MACSTR "%s",
5507 wpa_s->ifname, ssid_txt, freq, psk,
5508 MAC2STR(go_dev_addr),
5509 persistent ? " [PERSISTENT]" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005510 } else {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005511 wpa_msg_global(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
5512 "%s client ssid=\"%s\" freq=%d "
5513 "passphrase=\"%s\" go_dev_addr=" MACSTR "%s",
5514 wpa_s->ifname, ssid_txt, freq,
5515 ssid->passphrase ? ssid->passphrase : "",
5516 MAC2STR(go_dev_addr),
5517 persistent ? " [PERSISTENT]" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005518 }
5519
5520 if (persistent)
Jouni Malinen75ecf522011-06-27 15:19:46 -07005521 network_id = wpas_p2p_store_persistent_group(wpa_s->parent,
5522 ssid, go_dev_addr);
5523 if (network_id < 0)
5524 network_id = ssid->id;
5525 wpas_notify_p2p_group_started(wpa_s, ssid, network_id, 1);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005526
5527done:
Dmitry Shmidt37d4d6a2013-03-18 13:09:42 -07005528 wpas_p2p_continue_after_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005529}
5530
5531
5532int wpas_p2p_presence_req(struct wpa_supplicant *wpa_s, u32 duration1,
5533 u32 interval1, u32 duration2, u32 interval2)
5534{
5535 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
5536 return -1;
5537 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
5538 return -1;
5539
5540 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
5541 wpa_s->current_ssid == NULL ||
5542 wpa_s->current_ssid->mode != WPAS_MODE_INFRA)
5543 return -1;
5544
5545 return p2p_presence_req(wpa_s->global->p2p, wpa_s->bssid,
5546 wpa_s->own_addr, wpa_s->assoc_freq,
5547 duration1, interval1, duration2, interval2);
5548}
5549
5550
5551int wpas_p2p_ext_listen(struct wpa_supplicant *wpa_s, unsigned int period,
5552 unsigned int interval)
5553{
5554 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
5555 return -1;
5556
5557 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
5558 return -1;
5559
5560 return p2p_ext_listen(wpa_s->global->p2p, period, interval);
5561}
5562
5563
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005564static int wpas_p2p_is_client(struct wpa_supplicant *wpa_s)
5565{
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005566 if (wpa_s->current_ssid == NULL) {
5567 /*
5568 * current_ssid can be cleared when P2P client interface gets
5569 * disconnected, so assume this interface was used as P2P
5570 * client.
5571 */
5572 return 1;
5573 }
5574 return wpa_s->current_ssid->p2p_group &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005575 wpa_s->current_ssid->mode == WPAS_MODE_INFRA;
5576}
5577
5578
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005579static void wpas_p2p_group_idle_timeout(void *eloop_ctx, void *timeout_ctx)
5580{
5581 struct wpa_supplicant *wpa_s = eloop_ctx;
5582
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005583 if (wpa_s->conf->p2p_group_idle == 0 && !wpas_p2p_is_client(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005584 wpa_printf(MSG_DEBUG, "P2P: Ignore group idle timeout - "
5585 "disabled");
5586 return;
5587 }
5588
Dmitry Shmidt04949592012-07-19 12:16:46 -07005589 wpa_printf(MSG_DEBUG, "P2P: Group idle timeout reached - terminate "
5590 "group");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005591 wpas_p2p_group_delete(wpa_s, P2P_GROUP_REMOVAL_IDLE_TIMEOUT);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005592}
5593
5594
5595static void wpas_p2p_set_group_idle_timeout(struct wpa_supplicant *wpa_s)
5596{
Dmitry Shmidt04949592012-07-19 12:16:46 -07005597 int timeout;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005598
Dmitry Shmidt04949592012-07-19 12:16:46 -07005599 if (eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL) > 0)
5600 wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group idle timeout");
5601
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005602 if (wpa_s->current_ssid == NULL || !wpa_s->current_ssid->p2p_group)
5603 return;
5604
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005605 timeout = wpa_s->conf->p2p_group_idle;
5606 if (wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
5607 (timeout == 0 || timeout > P2P_MAX_CLIENT_IDLE))
5608 timeout = P2P_MAX_CLIENT_IDLE;
5609
5610 if (timeout == 0)
5611 return;
5612
Dmitry Shmidt04949592012-07-19 12:16:46 -07005613 if (timeout < 0) {
5614 if (wpa_s->current_ssid->mode == WPAS_MODE_INFRA)
5615 timeout = 0; /* special client mode no-timeout */
5616 else
5617 return;
5618 }
5619
5620 if (wpa_s->p2p_in_provisioning) {
5621 /*
5622 * Use the normal group formation timeout during the
5623 * provisioning phase to avoid terminating this process too
5624 * early due to group idle timeout.
5625 */
5626 wpa_printf(MSG_DEBUG, "P2P: Do not use P2P group idle timeout "
5627 "during provisioning");
5628 return;
5629 }
Deepthi Gowri9e4e8ac2013-04-16 11:57:05 +05305630
Dmitry Shmidt04949592012-07-19 12:16:46 -07005631 if (wpa_s->show_group_started) {
5632 /*
5633 * Use the normal group formation timeout between the end of
5634 * the provisioning phase and completion of 4-way handshake to
5635 * avoid terminating this process too early due to group idle
5636 * timeout.
5637 */
5638 wpa_printf(MSG_DEBUG, "P2P: Do not use P2P group idle timeout "
5639 "while waiting for initial 4-way handshake to "
5640 "complete");
5641 return;
5642 }
5643
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005644 wpa_printf(MSG_DEBUG, "P2P: Set P2P group idle timeout to %u seconds",
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005645 timeout);
5646 eloop_register_timeout(timeout, 0, wpas_p2p_group_idle_timeout,
5647 wpa_s, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005648}
5649
5650
Jouni Malinen2b89da82012-08-31 22:04:41 +03005651/* Returns 1 if the interface was removed */
5652int wpas_p2p_deauth_notif(struct wpa_supplicant *wpa_s, const u8 *bssid,
5653 u16 reason_code, const u8 *ie, size_t ie_len,
5654 int locally_generated)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005655{
5656 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
Jouni Malinen2b89da82012-08-31 22:04:41 +03005657 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005658 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
Jouni Malinen2b89da82012-08-31 22:04:41 +03005659 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005660
Dmitry Shmidt04949592012-07-19 12:16:46 -07005661 if (!locally_generated)
5662 p2p_deauth_notif(wpa_s->global->p2p, bssid, reason_code, ie,
5663 ie_len);
5664
5665 if (reason_code == WLAN_REASON_DEAUTH_LEAVING && !locally_generated &&
5666 wpa_s->current_ssid &&
5667 wpa_s->current_ssid->p2p_group &&
5668 wpa_s->current_ssid->mode == WPAS_MODE_INFRA) {
5669 wpa_printf(MSG_DEBUG, "P2P: GO indicated that the P2P Group "
5670 "session is ending");
Jouni Malinen2b89da82012-08-31 22:04:41 +03005671 if (wpas_p2p_group_delete(wpa_s,
5672 P2P_GROUP_REMOVAL_GO_ENDING_SESSION)
5673 > 0)
5674 return 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005675 }
Jouni Malinen2b89da82012-08-31 22:04:41 +03005676
5677 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005678}
5679
5680
5681void wpas_p2p_disassoc_notif(struct wpa_supplicant *wpa_s, const u8 *bssid,
Dmitry Shmidt04949592012-07-19 12:16:46 -07005682 u16 reason_code, const u8 *ie, size_t ie_len,
5683 int locally_generated)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005684{
5685 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
5686 return;
5687 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
5688 return;
5689
Dmitry Shmidt04949592012-07-19 12:16:46 -07005690 if (!locally_generated)
5691 p2p_disassoc_notif(wpa_s->global->p2p, bssid, reason_code, ie,
5692 ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005693}
5694
5695
5696void wpas_p2p_update_config(struct wpa_supplicant *wpa_s)
5697{
5698 struct p2p_data *p2p = wpa_s->global->p2p;
5699
5700 if (p2p == NULL)
5701 return;
5702
5703 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_CAPABLE))
5704 return;
5705
5706 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DEVICE_NAME)
5707 p2p_set_dev_name(p2p, wpa_s->conf->device_name);
5708
5709 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DEVICE_TYPE)
5710 p2p_set_pri_dev_type(p2p, wpa_s->conf->device_type);
5711
5712 if (wpa_s->wps &&
5713 (wpa_s->conf->changed_parameters & CFG_CHANGED_CONFIG_METHODS))
5714 p2p_set_config_methods(p2p, wpa_s->wps->config_methods);
5715
5716 if (wpa_s->wps && (wpa_s->conf->changed_parameters & CFG_CHANGED_UUID))
5717 p2p_set_uuid(p2p, wpa_s->wps->uuid);
5718
5719 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WPS_STRING) {
5720 p2p_set_manufacturer(p2p, wpa_s->conf->manufacturer);
5721 p2p_set_model_name(p2p, wpa_s->conf->model_name);
5722 p2p_set_model_number(p2p, wpa_s->conf->model_number);
5723 p2p_set_serial_number(p2p, wpa_s->conf->serial_number);
5724 }
5725
5726 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SEC_DEVICE_TYPE)
5727 p2p_set_sec_dev_types(p2p,
5728 (void *) wpa_s->conf->sec_device_type,
5729 wpa_s->conf->num_sec_device_types);
5730
5731 if (wpa_s->conf->changed_parameters & CFG_CHANGED_VENDOR_EXTENSION) {
5732 int i;
5733 p2p_remove_wps_vendor_extensions(p2p);
5734 for (i = 0; i < MAX_WPS_VENDOR_EXT; i++) {
5735 if (wpa_s->conf->wps_vendor_ext[i] == NULL)
5736 continue;
5737 p2p_add_wps_vendor_extension(
5738 p2p, wpa_s->conf->wps_vendor_ext[i]);
5739 }
5740 }
5741
5742 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
5743 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
5744 char country[3];
5745 country[0] = wpa_s->conf->country[0];
5746 country[1] = wpa_s->conf->country[1];
5747 country[2] = 0x04;
5748 p2p_set_country(p2p, country);
5749 }
5750
5751 if (wpa_s->conf->changed_parameters & CFG_CHANGED_P2P_SSID_POSTFIX) {
5752 p2p_set_ssid_postfix(p2p, (u8 *) wpa_s->conf->p2p_ssid_postfix,
5753 wpa_s->conf->p2p_ssid_postfix ?
5754 os_strlen(wpa_s->conf->p2p_ssid_postfix) :
5755 0);
5756 }
5757
5758 if (wpa_s->conf->changed_parameters & CFG_CHANGED_P2P_INTRA_BSS)
5759 p2p_set_intra_bss_dist(p2p, wpa_s->conf->p2p_intra_bss);
Jouni Malinen75ecf522011-06-27 15:19:46 -07005760
5761 if (wpa_s->conf->changed_parameters & CFG_CHANGED_P2P_LISTEN_CHANNEL) {
5762 u8 reg_class, channel;
5763 int ret;
5764 unsigned int r;
5765 if (wpa_s->conf->p2p_listen_reg_class &&
5766 wpa_s->conf->p2p_listen_channel) {
5767 reg_class = wpa_s->conf->p2p_listen_reg_class;
5768 channel = wpa_s->conf->p2p_listen_channel;
5769 } else {
5770 reg_class = 81;
5771 /*
5772 * Pick one of the social channels randomly as the
5773 * listen channel.
5774 */
5775 os_get_random((u8 *) &r, sizeof(r));
5776 channel = 1 + (r % 3) * 5;
5777 }
5778 ret = p2p_set_listen_channel(p2p, reg_class, channel);
5779 if (ret)
5780 wpa_printf(MSG_ERROR, "P2P: Own listen channel update "
5781 "failed: %d", ret);
5782 }
5783 if (wpa_s->conf->changed_parameters & CFG_CHANGED_P2P_OPER_CHANNEL) {
5784 u8 op_reg_class, op_channel, cfg_op_channel;
5785 int ret = 0;
5786 unsigned int r;
5787 if (wpa_s->conf->p2p_oper_reg_class &&
5788 wpa_s->conf->p2p_oper_channel) {
5789 op_reg_class = wpa_s->conf->p2p_oper_reg_class;
5790 op_channel = wpa_s->conf->p2p_oper_channel;
5791 cfg_op_channel = 1;
5792 } else {
5793 op_reg_class = 81;
5794 /*
5795 * Use random operation channel from (1, 6, 11)
5796 *if no other preference is indicated.
5797 */
5798 os_get_random((u8 *) &r, sizeof(r));
5799 op_channel = 1 + (r % 3) * 5;
5800 cfg_op_channel = 0;
5801 }
5802 ret = p2p_set_oper_channel(p2p, op_reg_class, op_channel,
5803 cfg_op_channel);
5804 if (ret)
5805 wpa_printf(MSG_ERROR, "P2P: Own oper channel update "
5806 "failed: %d", ret);
5807 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07005808
5809 if (wpa_s->conf->changed_parameters & CFG_CHANGED_P2P_PREF_CHAN) {
5810 if (p2p_set_pref_chan(p2p, wpa_s->conf->num_p2p_pref_chan,
5811 wpa_s->conf->p2p_pref_chan) < 0) {
5812 wpa_printf(MSG_ERROR, "P2P: Preferred channel list "
5813 "update failed");
5814 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07005815
5816 if (p2p_set_no_go_freq(p2p, &wpa_s->conf->p2p_no_go_freq) < 0) {
5817 wpa_printf(MSG_ERROR, "P2P: No GO channel list "
5818 "update failed");
5819 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07005820 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005821}
5822
5823
5824int wpas_p2p_set_noa(struct wpa_supplicant *wpa_s, u8 count, int start,
5825 int duration)
5826{
5827 if (!wpa_s->ap_iface)
5828 return -1;
5829 return hostapd_p2p_set_noa(wpa_s->ap_iface->bss[0], count, start,
5830 duration);
5831}
5832
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005833
5834int wpas_p2p_set_cross_connect(struct wpa_supplicant *wpa_s, int enabled)
5835{
5836 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
5837 return -1;
5838 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
5839 return -1;
5840
5841 wpa_s->global->cross_connection = enabled;
5842 p2p_set_cross_connect(wpa_s->global->p2p, enabled);
5843
5844 if (!enabled) {
5845 struct wpa_supplicant *iface;
5846
5847 for (iface = wpa_s->global->ifaces; iface; iface = iface->next)
5848 {
5849 if (iface->cross_connect_enabled == 0)
5850 continue;
5851
5852 iface->cross_connect_enabled = 0;
5853 iface->cross_connect_in_use = 0;
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005854 wpa_msg_global(iface->parent, MSG_INFO,
5855 P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
5856 iface->ifname,
5857 iface->cross_connect_uplink);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005858 }
5859 }
5860
5861 return 0;
5862}
5863
5864
5865static void wpas_p2p_enable_cross_connect(struct wpa_supplicant *uplink)
5866{
5867 struct wpa_supplicant *iface;
5868
5869 if (!uplink->global->cross_connection)
5870 return;
5871
5872 for (iface = uplink->global->ifaces; iface; iface = iface->next) {
5873 if (!iface->cross_connect_enabled)
5874 continue;
5875 if (os_strcmp(uplink->ifname, iface->cross_connect_uplink) !=
5876 0)
5877 continue;
5878 if (iface->ap_iface == NULL)
5879 continue;
5880 if (iface->cross_connect_in_use)
5881 continue;
5882
5883 iface->cross_connect_in_use = 1;
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005884 wpa_msg_global(iface->parent, MSG_INFO,
5885 P2P_EVENT_CROSS_CONNECT_ENABLE "%s %s",
5886 iface->ifname, iface->cross_connect_uplink);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005887 }
5888}
5889
5890
5891static void wpas_p2p_disable_cross_connect(struct wpa_supplicant *uplink)
5892{
5893 struct wpa_supplicant *iface;
5894
5895 for (iface = uplink->global->ifaces; iface; iface = iface->next) {
5896 if (!iface->cross_connect_enabled)
5897 continue;
5898 if (os_strcmp(uplink->ifname, iface->cross_connect_uplink) !=
5899 0)
5900 continue;
5901 if (!iface->cross_connect_in_use)
5902 continue;
5903
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005904 wpa_msg_global(iface->parent, MSG_INFO,
5905 P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
5906 iface->ifname, iface->cross_connect_uplink);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005907 iface->cross_connect_in_use = 0;
5908 }
5909}
5910
5911
5912void wpas_p2p_notif_connected(struct wpa_supplicant *wpa_s)
5913{
5914 if (wpa_s->ap_iface || wpa_s->current_ssid == NULL ||
5915 wpa_s->current_ssid->mode != WPAS_MODE_INFRA ||
5916 wpa_s->cross_connect_disallowed)
5917 wpas_p2p_disable_cross_connect(wpa_s);
5918 else
5919 wpas_p2p_enable_cross_connect(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005920 if (!wpa_s->ap_iface &&
5921 eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL) > 0)
5922 wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group idle timeout");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005923}
5924
5925
5926void wpas_p2p_notif_disconnected(struct wpa_supplicant *wpa_s)
5927{
5928 wpas_p2p_disable_cross_connect(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005929 if (!wpa_s->ap_iface &&
5930 !eloop_is_timeout_registered(wpas_p2p_group_idle_timeout,
5931 wpa_s, NULL))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005932 wpas_p2p_set_group_idle_timeout(wpa_s);
5933}
5934
5935
5936static void wpas_p2p_cross_connect_setup(struct wpa_supplicant *wpa_s)
5937{
5938 struct wpa_supplicant *iface;
5939
5940 if (!wpa_s->global->cross_connection)
5941 return;
5942
5943 for (iface = wpa_s->global->ifaces; iface; iface = iface->next) {
5944 if (iface == wpa_s)
5945 continue;
5946 if (iface->drv_flags &
5947 WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)
5948 continue;
5949 if (iface->drv_flags & WPA_DRIVER_FLAGS_P2P_CAPABLE)
5950 continue;
5951
5952 wpa_s->cross_connect_enabled = 1;
5953 os_strlcpy(wpa_s->cross_connect_uplink, iface->ifname,
5954 sizeof(wpa_s->cross_connect_uplink));
5955 wpa_printf(MSG_DEBUG, "P2P: Enable cross connection from "
5956 "%s to %s whenever uplink is available",
5957 wpa_s->ifname, wpa_s->cross_connect_uplink);
5958
5959 if (iface->ap_iface || iface->current_ssid == NULL ||
5960 iface->current_ssid->mode != WPAS_MODE_INFRA ||
5961 iface->cross_connect_disallowed ||
5962 iface->wpa_state != WPA_COMPLETED)
5963 break;
5964
5965 wpa_s->cross_connect_in_use = 1;
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005966 wpa_msg_global(wpa_s->parent, MSG_INFO,
5967 P2P_EVENT_CROSS_CONNECT_ENABLE "%s %s",
5968 wpa_s->ifname, wpa_s->cross_connect_uplink);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005969 break;
5970 }
5971}
5972
5973
5974int wpas_p2p_notif_pbc_overlap(struct wpa_supplicant *wpa_s)
5975{
5976 if (wpa_s->p2p_group_interface != P2P_GROUP_INTERFACE_CLIENT &&
5977 !wpa_s->p2p_in_provisioning)
5978 return 0; /* not P2P client operation */
5979
5980 wpa_printf(MSG_DEBUG, "P2P: Terminate connection due to WPS PBC "
5981 "session overlap");
5982 if (wpa_s != wpa_s->parent)
5983 wpa_msg_ctrl(wpa_s->parent, MSG_INFO, WPS_EVENT_OVERLAP);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005984 wpas_p2p_group_formation_failed(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005985 return 1;
5986}
5987
5988
5989void wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s)
5990{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07005991 struct p2p_channels chan, cli_chan;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005992
5993 if (wpa_s->global == NULL || wpa_s->global->p2p == NULL)
5994 return;
5995
5996 os_memset(&chan, 0, sizeof(chan));
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07005997 os_memset(&cli_chan, 0, sizeof(cli_chan));
5998 if (wpas_p2p_setup_channels(wpa_s, &chan, &cli_chan)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005999 wpa_printf(MSG_ERROR, "P2P: Failed to update supported "
6000 "channel list");
6001 return;
6002 }
6003
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006004 p2p_update_channel_list(wpa_s->global->p2p, &chan, &cli_chan);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006005}
6006
6007
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006008static void wpas_p2p_scan_res_ignore(struct wpa_supplicant *wpa_s,
6009 struct wpa_scan_results *scan_res)
6010{
6011 wpa_printf(MSG_DEBUG, "P2P: Ignore scan results");
6012}
6013
6014
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006015int wpas_p2p_cancel(struct wpa_supplicant *wpa_s)
6016{
6017 struct wpa_global *global = wpa_s->global;
6018 int found = 0;
6019 const u8 *peer;
6020
6021 if (global->p2p == NULL)
6022 return -1;
6023
6024 wpa_printf(MSG_DEBUG, "P2P: Request to cancel group formation");
6025
6026 if (wpa_s->pending_interface_name[0] &&
6027 !is_zero_ether_addr(wpa_s->pending_interface_addr))
6028 found = 1;
6029
6030 peer = p2p_get_go_neg_peer(global->p2p);
6031 if (peer) {
6032 wpa_printf(MSG_DEBUG, "P2P: Unauthorize pending GO Neg peer "
6033 MACSTR, MAC2STR(peer));
6034 p2p_unauthorize(global->p2p, peer);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006035 found = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006036 }
6037
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006038 if (wpa_s->scan_res_handler == wpas_p2p_scan_res_join) {
6039 wpa_printf(MSG_DEBUG, "P2P: Stop pending scan for join");
6040 wpa_s->scan_res_handler = wpas_p2p_scan_res_ignore;
6041 found = 1;
6042 }
6043
6044 if (wpa_s->pending_pd_before_join) {
6045 wpa_printf(MSG_DEBUG, "P2P: Stop pending PD before join");
6046 wpa_s->pending_pd_before_join = 0;
6047 found = 1;
6048 }
6049
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006050 wpas_p2p_stop_find(wpa_s);
6051
6052 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6053 if (wpa_s == global->p2p_group_formation &&
6054 (wpa_s->p2p_in_provisioning ||
6055 wpa_s->parent->pending_interface_type ==
6056 WPA_IF_P2P_CLIENT)) {
6057 wpa_printf(MSG_DEBUG, "P2P: Interface %s in group "
6058 "formation found - cancelling",
6059 wpa_s->ifname);
6060 found = 1;
6061 eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
6062 wpa_s->parent, NULL);
Jouni Malinenadddfc42012-10-03 14:31:41 -07006063 if (wpa_s->p2p_in_provisioning) {
6064 wpas_group_formation_completed(wpa_s, 0);
6065 break;
6066 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006067 wpas_p2p_group_delete(wpa_s,
6068 P2P_GROUP_REMOVAL_REQUESTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006069 break;
6070 }
6071 }
6072
6073 if (!found) {
6074 wpa_printf(MSG_DEBUG, "P2P: No ongoing group formation found");
6075 return -1;
6076 }
6077
6078 return 0;
6079}
6080
6081
6082void wpas_p2p_interface_unavailable(struct wpa_supplicant *wpa_s)
6083{
6084 if (wpa_s->current_ssid == NULL || !wpa_s->current_ssid->p2p_group)
6085 return;
6086
6087 wpa_printf(MSG_DEBUG, "P2P: Remove group due to driver resource not "
6088 "being available anymore");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006089 wpas_p2p_group_delete(wpa_s, P2P_GROUP_REMOVAL_UNAVAILABLE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006090}
6091
6092
6093void wpas_p2p_update_best_channels(struct wpa_supplicant *wpa_s,
6094 int freq_24, int freq_5, int freq_overall)
6095{
6096 struct p2p_data *p2p = wpa_s->global->p2p;
6097 if (p2p == NULL || (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT))
6098 return;
6099 p2p_set_best_channels(p2p, freq_24, freq_5, freq_overall);
6100}
6101
6102
6103int wpas_p2p_unauthorize(struct wpa_supplicant *wpa_s, const char *addr)
6104{
6105 u8 peer[ETH_ALEN];
6106 struct p2p_data *p2p = wpa_s->global->p2p;
6107
6108 if (p2p == NULL || (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT))
6109 return -1;
6110
6111 if (hwaddr_aton(addr, peer))
6112 return -1;
6113
6114 return p2p_unauthorize(p2p, peer);
6115}
6116
6117
6118/**
6119 * wpas_p2p_disconnect - Disconnect from a P2P Group
6120 * @wpa_s: Pointer to wpa_supplicant data
6121 * Returns: 0 on success, -1 on failure
6122 *
6123 * This can be used to disconnect from a group in which the local end is a P2P
6124 * Client or to end a P2P Group in case the local end is the Group Owner. If a
6125 * virtual network interface was created for this group, that interface will be
6126 * removed. Otherwise, only the configured P2P group network will be removed
6127 * from the interface.
6128 */
6129int wpas_p2p_disconnect(struct wpa_supplicant *wpa_s)
6130{
6131
6132 if (wpa_s == NULL)
6133 return -1;
6134
Jouni Malinen2b89da82012-08-31 22:04:41 +03006135 return wpas_p2p_group_delete(wpa_s, P2P_GROUP_REMOVAL_REQUESTED) < 0 ?
6136 -1 : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006137}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006138
6139
6140int wpas_p2p_in_progress(struct wpa_supplicant *wpa_s)
6141{
Dmitry Shmidtf8623282013-02-20 14:34:59 -08006142 int ret;
6143
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006144 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
6145 return 0;
6146
Dmitry Shmidtf8623282013-02-20 14:34:59 -08006147 ret = p2p_in_progress(wpa_s->global->p2p);
6148 if (ret == 0) {
6149 /*
6150 * Check whether there is an ongoing WPS provisioning step (or
6151 * other parts of group formation) on another interface since
6152 * p2p_in_progress() does not report this to avoid issues for
6153 * scans during such provisioning step.
6154 */
6155 if (wpa_s->global->p2p_group_formation &&
6156 wpa_s->global->p2p_group_formation != wpa_s) {
6157 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Another interface (%s) "
6158 "in group formation",
6159 wpa_s->global->p2p_group_formation->ifname);
6160 ret = 1;
6161 }
6162 }
6163
Dmitry Shmidt92c368d2013-08-29 12:37:21 -07006164 if (!ret && wpa_s->global->p2p_go_wait_client.sec) {
6165 struct os_time now;
6166 os_get_time(&now);
6167 if (now.sec > wpa_s->global->p2p_go_wait_client.sec +
6168 P2P_MAX_INITIAL_CONN_WAIT_GO) {
6169 /* Wait for the first client has expired */
6170 wpa_s->global->p2p_go_wait_client.sec = 0;
6171 } else {
6172 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Waiting for initial client connection during group formation");
6173 ret = 1;
6174 }
6175 }
6176
Dmitry Shmidtf8623282013-02-20 14:34:59 -08006177 return ret;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006178}
6179
6180
6181void wpas_p2p_network_removed(struct wpa_supplicant *wpa_s,
6182 struct wpa_ssid *ssid)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006183{
6184 if (wpa_s->p2p_in_provisioning && ssid->p2p_group &&
6185 eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
6186 wpa_s->parent, NULL) > 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07006187 /**
6188 * Remove the network by scheduling the group formation
6189 * timeout to happen immediately. The teardown code
6190 * needs to be scheduled to run asynch later so that we
6191 * don't delete data from under ourselves unexpectedly.
6192 * Calling wpas_p2p_group_formation_timeout directly
6193 * causes a series of crashes in WPS failure scenarios.
6194 */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006195 wpa_printf(MSG_DEBUG, "P2P: Canceled group formation due to "
6196 "P2P group network getting removed");
Dmitry Shmidt04949592012-07-19 12:16:46 -07006197 eloop_register_timeout(0, 0, wpas_p2p_group_formation_timeout,
6198 wpa_s->parent, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006199 }
6200}
6201
6202
6203struct wpa_ssid * wpas_p2p_get_persistent(struct wpa_supplicant *wpa_s,
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006204 const u8 *addr, const u8 *ssid,
6205 size_t ssid_len)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006206{
6207 struct wpa_ssid *s;
6208 size_t i;
6209
6210 for (s = wpa_s->conf->ssid; s; s = s->next) {
6211 if (s->disabled != 2)
6212 continue;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006213 if (ssid &&
6214 (ssid_len != s->ssid_len ||
6215 os_memcmp(ssid, s->ssid, ssid_len) != 0))
6216 continue;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07006217 if (addr == NULL) {
6218 if (s->mode == WPAS_MODE_P2P_GO)
6219 return s;
6220 continue;
6221 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006222 if (os_memcmp(s->bssid, addr, ETH_ALEN) == 0)
6223 return s; /* peer is GO in the persistent group */
6224 if (s->mode != WPAS_MODE_P2P_GO || s->p2p_client_list == NULL)
6225 continue;
6226 for (i = 0; i < s->num_p2p_clients; i++) {
6227 if (os_memcmp(s->p2p_client_list + i * ETH_ALEN,
6228 addr, ETH_ALEN) == 0)
6229 return s; /* peer is P2P client in persistent
6230 * group */
6231 }
6232 }
6233
6234 return NULL;
6235}
6236
6237
6238void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s,
6239 const u8 *addr)
6240{
Dmitry Shmidt56052862013-10-04 10:23:25 -07006241 if (eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
6242 wpa_s->parent, NULL) > 0) {
6243 /*
6244 * This can happen if WPS provisioning step is not terminated
6245 * cleanly (e.g., P2P Client does not send WSC_Done). Since the
6246 * peer was able to connect, there is no need to time out group
6247 * formation after this, though. In addition, this is used with
6248 * the initial connection wait on the GO as a separate formation
6249 * timeout and as such, expected to be hit after the initial WPS
6250 * provisioning step.
6251 */
6252 wpa_printf(MSG_DEBUG, "P2P: Canceled P2P group formation timeout on data connection");
6253 }
6254 if (!wpa_s->p2p_go_group_formation_completed) {
6255 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Marking group formation completed on GO on first data connection");
6256 wpa_s->p2p_go_group_formation_completed = 1;
6257 wpa_s->global->p2p_group_formation = NULL;
6258 wpa_s->p2p_in_provisioning = 0;
6259 }
Dmitry Shmidt92c368d2013-08-29 12:37:21 -07006260 wpa_s->global->p2p_go_wait_client.sec = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006261 if (addr == NULL)
6262 return;
6263 wpas_p2p_add_persistent_group_client(wpa_s, addr);
6264}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006265
Dmitry Shmidt04949592012-07-19 12:16:46 -07006266
6267static void wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
6268 int group_added)
6269{
6270 struct wpa_supplicant *group = wpa_s;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006271 if (wpa_s->global->p2p_group_formation)
6272 group = wpa_s->global->p2p_group_formation;
6273 wpa_s = wpa_s->parent;
6274 offchannel_send_action_done(wpa_s);
6275 if (group_added)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006276 wpas_p2p_group_delete(group, P2P_GROUP_REMOVAL_SILENT);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006277 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Fall back to GO Negotiation");
6278 wpas_p2p_connect(wpa_s, wpa_s->pending_join_dev_addr, wpa_s->p2p_pin,
6279 wpa_s->p2p_wps_method, wpa_s->p2p_persistent_group, 0,
6280 0, 0, wpa_s->p2p_go_intent, wpa_s->p2p_connect_freq,
6281 wpa_s->p2p_persistent_id,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006282 wpa_s->p2p_pd_before_go_neg,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006283 wpa_s->p2p_go_ht40,
6284 wpa_s->p2p_go_vht);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006285}
6286
6287
6288int wpas_p2p_scan_no_go_seen(struct wpa_supplicant *wpa_s)
6289{
6290 if (!wpa_s->p2p_fallback_to_go_neg ||
6291 wpa_s->p2p_in_provisioning <= 5)
6292 return 0;
6293
6294 if (wpas_p2p_peer_go(wpa_s, wpa_s->pending_join_dev_addr) > 0)
6295 return 0; /* peer operating as a GO */
6296
6297 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: GO not found for p2p_connect-auto - "
6298 "fallback to GO Negotiation");
6299 wpas_p2p_fallback_to_go_neg(wpa_s, 1);
6300
6301 return 1;
6302}
6303
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006304
6305unsigned int wpas_p2p_search_delay(struct wpa_supplicant *wpa_s)
6306{
6307 const char *rn, *rn2;
6308 struct wpa_supplicant *ifs;
6309
6310 if (wpa_s->wpa_state > WPA_SCANNING) {
6311 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use %u ms search delay due to "
6312 "concurrent operation",
6313 P2P_CONCURRENT_SEARCH_DELAY);
6314 return P2P_CONCURRENT_SEARCH_DELAY;
6315 }
6316
6317 if (!wpa_s->driver->get_radio_name)
6318 return 0;
6319 rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
6320 if (rn == NULL || rn[0] == '\0')
6321 return 0;
6322
6323 for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
6324 if (ifs == wpa_s || !ifs->driver->get_radio_name)
6325 continue;
6326
6327 rn2 = ifs->driver->get_radio_name(ifs->drv_priv);
6328 if (!rn2 || os_strcmp(rn, rn2) != 0)
6329 continue;
6330 if (ifs->wpa_state > WPA_SCANNING) {
6331 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use %u ms search "
6332 "delay due to concurrent operation on "
6333 "interface %s",
6334 P2P_CONCURRENT_SEARCH_DELAY, ifs->ifname);
6335 return P2P_CONCURRENT_SEARCH_DELAY;
6336 }
6337 }
6338
6339 return 0;
6340}
6341
Dmitry Shmidt37d4d6a2013-03-18 13:09:42 -07006342
6343void wpas_p2p_continue_after_scan(struct wpa_supplicant *wpa_s)
6344{
6345 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Station mode scan operation not "
6346 "pending anymore (sta_scan_pending=%d "
6347 "p2p_cb_on_scan_complete=%d)", wpa_s->sta_scan_pending,
6348 wpa_s->global->p2p_cb_on_scan_complete);
6349 wpa_s->sta_scan_pending = 0;
6350
6351 if (!wpa_s->global->p2p_cb_on_scan_complete)
6352 return;
6353 wpa_s->global->p2p_cb_on_scan_complete = 0;
6354
6355 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
6356 return;
6357
6358 if (p2p_other_scan_completed(wpa_s->global->p2p) == 1) {
6359 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Pending P2P operation "
6360 "continued after successful connection");
6361 p2p_increase_search_delay(wpa_s->global->p2p,
6362 wpas_p2p_search_delay(wpa_s));
6363 }
6364}
6365
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07006366
6367static int wpas_p2p_remove_psk_entry(struct wpa_supplicant *wpa_s,
6368 struct wpa_ssid *s, const u8 *addr,
6369 int iface_addr)
6370{
6371 struct psk_list_entry *psk, *tmp;
6372 int changed = 0;
6373
6374 dl_list_for_each_safe(psk, tmp, &s->psk_list, struct psk_list_entry,
6375 list) {
6376 if ((iface_addr && !psk->p2p &&
6377 os_memcmp(addr, psk->addr, ETH_ALEN) == 0) ||
6378 (!iface_addr && psk->p2p &&
6379 os_memcmp(addr, psk->addr, ETH_ALEN) == 0)) {
6380 wpa_dbg(wpa_s, MSG_DEBUG,
6381 "P2P: Remove persistent group PSK list entry for "
6382 MACSTR " p2p=%u",
6383 MAC2STR(psk->addr), psk->p2p);
6384 dl_list_del(&psk->list);
6385 os_free(psk);
6386 changed++;
6387 }
6388 }
6389
6390 return changed;
6391}
6392
6393
6394void wpas_p2p_new_psk_cb(struct wpa_supplicant *wpa_s, const u8 *mac_addr,
6395 const u8 *p2p_dev_addr,
6396 const u8 *psk, size_t psk_len)
6397{
6398 struct wpa_ssid *ssid = wpa_s->current_ssid;
6399 struct wpa_ssid *persistent;
6400 struct psk_list_entry *p;
6401
6402 if (psk_len != sizeof(p->psk))
6403 return;
6404
6405 if (p2p_dev_addr) {
6406 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: New PSK for addr=" MACSTR
6407 " p2p_dev_addr=" MACSTR,
6408 MAC2STR(mac_addr), MAC2STR(p2p_dev_addr));
6409 if (is_zero_ether_addr(p2p_dev_addr))
6410 p2p_dev_addr = NULL;
6411 } else {
6412 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: New PSK for addr=" MACSTR,
6413 MAC2STR(mac_addr));
6414 }
6415
6416 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
6417 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: new_psk_cb during group formation");
6418 /* To be added to persistent group once created */
6419 if (wpa_s->global->add_psk == NULL) {
6420 wpa_s->global->add_psk = os_zalloc(sizeof(*p));
6421 if (wpa_s->global->add_psk == NULL)
6422 return;
6423 }
6424 p = wpa_s->global->add_psk;
6425 if (p2p_dev_addr) {
6426 p->p2p = 1;
6427 os_memcpy(p->addr, p2p_dev_addr, ETH_ALEN);
6428 } else {
6429 p->p2p = 0;
6430 os_memcpy(p->addr, mac_addr, ETH_ALEN);
6431 }
6432 os_memcpy(p->psk, psk, psk_len);
6433 return;
6434 }
6435
6436 if (ssid->mode != WPAS_MODE_P2P_GO || !ssid->p2p_persistent_group) {
6437 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Ignore new_psk_cb on not-persistent GO");
6438 return;
6439 }
6440
6441 persistent = wpas_p2p_get_persistent(wpa_s->parent, NULL, ssid->ssid,
6442 ssid->ssid_len);
6443 if (!persistent) {
6444 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Could not find persistent group information to store the new PSK");
6445 return;
6446 }
6447
6448 p = os_zalloc(sizeof(*p));
6449 if (p == NULL)
6450 return;
6451 if (p2p_dev_addr) {
6452 p->p2p = 1;
6453 os_memcpy(p->addr, p2p_dev_addr, ETH_ALEN);
6454 } else {
6455 p->p2p = 0;
6456 os_memcpy(p->addr, mac_addr, ETH_ALEN);
6457 }
6458 os_memcpy(p->psk, psk, psk_len);
6459
6460 if (dl_list_len(&persistent->psk_list) > P2P_MAX_STORED_CLIENTS) {
6461 struct psk_list_entry *last;
6462 last = dl_list_last(&persistent->psk_list,
6463 struct psk_list_entry, list);
6464 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Remove oldest PSK entry for "
6465 MACSTR " (p2p=%u) to make room for a new one",
6466 MAC2STR(last->addr), last->p2p);
6467 dl_list_del(&last->list);
6468 os_free(last);
6469 }
6470
6471 wpas_p2p_remove_psk_entry(wpa_s->parent, persistent,
6472 p2p_dev_addr ? p2p_dev_addr : mac_addr,
6473 p2p_dev_addr == NULL);
6474 if (p2p_dev_addr) {
6475 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Add new PSK for p2p_dev_addr="
6476 MACSTR, MAC2STR(p2p_dev_addr));
6477 } else {
6478 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Add new PSK for addr=" MACSTR,
6479 MAC2STR(mac_addr));
6480 }
6481 dl_list_add(&persistent->psk_list, &p->list);
6482
6483#ifndef CONFIG_NO_CONFIG_WRITE
6484 if (wpa_s->parent->conf->update_config &&
6485 wpa_config_write(wpa_s->parent->confname, wpa_s->parent->conf))
6486 wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
6487#endif /* CONFIG_NO_CONFIG_WRITE */
6488}
6489
6490
6491static void wpas_p2p_remove_psk(struct wpa_supplicant *wpa_s,
6492 struct wpa_ssid *s, const u8 *addr,
6493 int iface_addr)
6494{
6495 int res;
6496
6497 res = wpas_p2p_remove_psk_entry(wpa_s, s, addr, iface_addr);
6498 if (res > 0) {
6499#ifndef CONFIG_NO_CONFIG_WRITE
6500 if (wpa_s->conf->update_config &&
6501 wpa_config_write(wpa_s->confname, wpa_s->conf))
6502 wpa_dbg(wpa_s, MSG_DEBUG,
6503 "P2P: Failed to update configuration");
6504#endif /* CONFIG_NO_CONFIG_WRITE */
6505 }
6506}
6507
6508
6509static void wpas_p2p_remove_client_go(struct wpa_supplicant *wpa_s,
6510 const u8 *peer, int iface_addr)
6511{
6512 struct hostapd_data *hapd;
6513 struct hostapd_wpa_psk *psk, *prev, *rem;
6514 struct sta_info *sta;
6515
6516 if (wpa_s->ap_iface == NULL || wpa_s->current_ssid == NULL ||
6517 wpa_s->current_ssid->mode != WPAS_MODE_P2P_GO)
6518 return;
6519
6520 /* Remove per-station PSK entry */
6521 hapd = wpa_s->ap_iface->bss[0];
6522 prev = NULL;
6523 psk = hapd->conf->ssid.wpa_psk;
6524 while (psk) {
6525 if ((iface_addr && os_memcmp(peer, psk->addr, ETH_ALEN) == 0) ||
6526 (!iface_addr &&
6527 os_memcmp(peer, psk->p2p_dev_addr, ETH_ALEN) == 0)) {
6528 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Remove operating group PSK entry for "
6529 MACSTR " iface_addr=%d",
6530 MAC2STR(peer), iface_addr);
6531 if (prev)
6532 prev->next = psk->next;
6533 else
6534 hapd->conf->ssid.wpa_psk = psk->next;
6535 rem = psk;
6536 psk = psk->next;
6537 os_free(rem);
6538 } else {
6539 prev = psk;
6540 psk = psk->next;
6541 }
6542 }
6543
6544 /* Disconnect from group */
6545 if (iface_addr)
6546 sta = ap_get_sta(hapd, peer);
6547 else
6548 sta = ap_get_sta_p2p(hapd, peer);
6549 if (sta) {
6550 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Disconnect peer " MACSTR
6551 " (iface_addr=%d) from group",
6552 MAC2STR(peer), iface_addr);
6553 hostapd_drv_sta_deauth(hapd, sta->addr,
6554 WLAN_REASON_DEAUTH_LEAVING);
6555 ap_sta_deauthenticate(hapd, sta, WLAN_REASON_DEAUTH_LEAVING);
6556 }
6557}
6558
6559
6560void wpas_p2p_remove_client(struct wpa_supplicant *wpa_s, const u8 *peer,
6561 int iface_addr)
6562{
6563 struct wpa_ssid *s;
6564 struct wpa_supplicant *w;
6565
6566 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Remove client " MACSTR, MAC2STR(peer));
6567
6568 /* Remove from any persistent group */
6569 for (s = wpa_s->parent->conf->ssid; s; s = s->next) {
6570 if (s->disabled != 2 || s->mode != WPAS_MODE_P2P_GO)
6571 continue;
6572 if (!iface_addr)
6573 wpas_remove_persistent_peer(wpa_s, s, peer, 0);
6574 wpas_p2p_remove_psk(wpa_s->parent, s, peer, iface_addr);
6575 }
6576
6577 /* Remove from any operating group */
6578 for (w = wpa_s->global->ifaces; w; w = w->next)
6579 wpas_p2p_remove_client_go(w, peer, iface_addr);
6580}
6581
6582
6583static void wpas_p2p_psk_failure_removal(void *eloop_ctx, void *timeout_ctx)
6584{
6585 struct wpa_supplicant *wpa_s = eloop_ctx;
6586 wpas_p2p_group_delete(wpa_s, P2P_GROUP_REMOVAL_PSK_FAILURE);
6587}
6588
6589
6590int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s)
6591{
6592 struct wpa_ssid *ssid = wpa_s->current_ssid;
6593
6594 if (ssid == NULL || !ssid->p2p_group)
6595 return 0;
6596
6597 if (wpa_s->p2p_last_4way_hs_fail &&
6598 wpa_s->p2p_last_4way_hs_fail == ssid) {
6599 u8 go_dev_addr[ETH_ALEN];
6600 struct wpa_ssid *persistent;
6601
6602 if (wpas_p2p_persistent_group(wpa_s, go_dev_addr,
6603 ssid->ssid,
6604 ssid->ssid_len) <= 0) {
6605 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Could not determine whether 4-way handshake failures were for a persistent group");
6606 goto disconnect;
6607 }
6608
6609 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Two 4-way handshake failures for a P2P group - go_dev_addr="
6610 MACSTR, MAC2STR(go_dev_addr));
6611 persistent = wpas_p2p_get_persistent(wpa_s->parent, go_dev_addr,
6612 ssid->ssid,
6613 ssid->ssid_len);
6614 if (persistent == NULL || persistent->mode != WPAS_MODE_INFRA) {
6615 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: No matching persistent group stored");
6616 goto disconnect;
6617 }
6618 wpa_msg_global(wpa_s->parent, MSG_INFO,
6619 P2P_EVENT_PERSISTENT_PSK_FAIL "%d",
6620 persistent->id);
6621 disconnect:
6622 wpa_s->p2p_last_4way_hs_fail = NULL;
6623 /*
6624 * Remove the group from a timeout to avoid issues with caller
6625 * continuing to use the interface if this is on a P2P group
6626 * interface.
6627 */
6628 eloop_register_timeout(0, 0, wpas_p2p_psk_failure_removal,
6629 wpa_s, NULL);
6630 return 1;
6631 }
6632
6633 wpa_s->p2p_last_4way_hs_fail = ssid;
6634 return 0;
6635}
6636
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006637#ifdef ANDROID_P2P
Dmitry Shmidt1cf45732013-04-29 17:36:45 -07006638static void wpas_p2p_group_freq_conflict(void *eloop_ctx, void *timeout_ctx)
6639{
6640 struct wpa_supplicant *wpa_s = eloop_ctx;
6641
6642 wpa_printf(MSG_DEBUG, "P2P: Frequency conflict - terminate group");
6643 wpas_p2p_group_delete(wpa_s, P2P_GROUP_REMOVAL_FREQ_CONFLICT);
6644}
6645
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006646int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s, int freq,
6647 struct wpa_ssid *ssid)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006648{
6649 struct wpa_supplicant *iface = NULL;
6650 struct p2p_data *p2p = wpa_s->global->p2p;
6651
6652 for (iface = wpa_s->global->ifaces; iface; iface = iface->next) {
Jeff Johnson12b1cd92012-10-07 19:34:24 -07006653 if ((iface->current_ssid) &&
6654 (iface->current_ssid->frequency != freq) &&
6655 ((iface->p2p_group_interface) ||
6656 (iface->current_ssid->p2p_group))) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006657
Jeff Johnson12b1cd92012-10-07 19:34:24 -07006658 if ((iface->p2p_group_interface == P2P_GROUP_INTERFACE_GO) ||
6659 (iface->current_ssid->mode == WPAS_MODE_P2P_GO)) {
6660 /* Try to see whether we can move the GO. If it
6661 * is not possible, remove the GO interface
6662 */
6663 if (wpa_drv_switch_channel(iface, freq) == 0) {
6664 wpa_printf(MSG_ERROR, "P2P: GO Moved to freq(%d)", freq);
6665 iface->current_ssid->frequency = freq;
6666 continue;
6667 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006668 }
6669
6670 /* If GO cannot be moved or if the conflicting interface is a
6671 * P2P Client, remove the interface depending up on the connection
6672 * priority */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006673 if(!wpas_is_p2p_prioritized(iface)) {
Dmitry Shmidtf4f5db32012-09-11 14:36:56 -07006674 /* STA connection has priority over existing
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006675 * P2P connection. So remove the interface */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006676 wpa_printf(MSG_DEBUG, "P2P: Removing P2P connection due to Single channel"
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006677 "concurrent mode frequency conflict");
Dmitry Shmidt1cf45732013-04-29 17:36:45 -07006678 eloop_register_timeout(0, 0, wpas_p2p_group_freq_conflict,
6679 iface, NULL);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006680 /* If connection in progress is p2p connection, do not proceed for the connection */
6681 if (wpa_s == iface)
6682 return -1;
6683 else
6684 /* If connection in progress is STA connection, proceed for the connection */
6685 return 0;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006686 } else {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006687 /* P2p connection has priority, disable the STA network*/
6688 wpa_supplicant_disable_network(wpa_s->global->ifaces, ssid);
6689 wpa_msg(wpa_s->global->ifaces, MSG_INFO, WPA_EVENT_FREQ_CONFLICT
6690 " id=%d", ssid->id);
6691 os_memset(wpa_s->global->ifaces->pending_bssid, 0, ETH_ALEN);
6692 if (wpa_s == iface) {
6693 /* p2p connection is in progress, continue connecting...*/
6694 return 0;
6695 }
6696 else {
6697 /* STA connection is in progress, do not allow to continue */
6698 return -1;
6699 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006700 }
6701 }
6702 }
6703 return 0;
6704}
6705#endif