13ff40c12SJohn Marino /*
23ff40c12SJohn Marino  * Wi-Fi Direct - P2P Group Owner Negotiation
33ff40c12SJohn Marino  * Copyright (c) 2009-2010, Atheros Communications
43ff40c12SJohn Marino  *
53ff40c12SJohn Marino  * This software may be distributed under the terms of the BSD license.
63ff40c12SJohn Marino  * See README for more details.
73ff40c12SJohn Marino  */
83ff40c12SJohn Marino 
93ff40c12SJohn Marino #include "includes.h"
103ff40c12SJohn Marino 
113ff40c12SJohn Marino #include "common.h"
12*a1157835SDaniel Fojt #include "utils/eloop.h"
133ff40c12SJohn Marino #include "common/ieee802_11_defs.h"
14*a1157835SDaniel Fojt #include "common/wpa_ctrl.h"
153ff40c12SJohn Marino #include "wps/wps_defs.h"
163ff40c12SJohn Marino #include "p2p_i.h"
173ff40c12SJohn Marino #include "p2p.h"
183ff40c12SJohn Marino 
193ff40c12SJohn Marino 
p2p_go_det(u8 own_intent,u8 peer_value)203ff40c12SJohn Marino static int p2p_go_det(u8 own_intent, u8 peer_value)
213ff40c12SJohn Marino {
223ff40c12SJohn Marino 	u8 peer_intent = peer_value >> 1;
233ff40c12SJohn Marino 	if (own_intent == peer_intent) {
243ff40c12SJohn Marino 		if (own_intent == P2P_MAX_GO_INTENT)
253ff40c12SJohn Marino 			return -1; /* both devices want to become GO */
263ff40c12SJohn Marino 
273ff40c12SJohn Marino 		/* Use tie breaker bit to determine GO */
283ff40c12SJohn Marino 		return (peer_value & 0x01) ? 0 : 1;
293ff40c12SJohn Marino 	}
303ff40c12SJohn Marino 
313ff40c12SJohn Marino 	return own_intent > peer_intent;
323ff40c12SJohn Marino }
333ff40c12SJohn Marino 
343ff40c12SJohn Marino 
p2p_peer_channels_check(struct p2p_data * p2p,struct p2p_channels * own,struct p2p_device * dev,const u8 * channel_list,size_t channel_list_len)353ff40c12SJohn Marino int p2p_peer_channels_check(struct p2p_data *p2p, struct p2p_channels *own,
363ff40c12SJohn Marino 			    struct p2p_device *dev,
373ff40c12SJohn Marino 			    const u8 *channel_list, size_t channel_list_len)
383ff40c12SJohn Marino {
393ff40c12SJohn Marino 	const u8 *pos, *end;
403ff40c12SJohn Marino 	struct p2p_channels *ch;
41*a1157835SDaniel Fojt 	u8 channels;
423ff40c12SJohn Marino 	struct p2p_channels intersection;
433ff40c12SJohn Marino 
443ff40c12SJohn Marino 	ch = &dev->channels;
453ff40c12SJohn Marino 	os_memset(ch, 0, sizeof(*ch));
463ff40c12SJohn Marino 	pos = channel_list;
473ff40c12SJohn Marino 	end = channel_list + channel_list_len;
483ff40c12SJohn Marino 
493ff40c12SJohn Marino 	if (end - pos < 3)
503ff40c12SJohn Marino 		return -1;
513ff40c12SJohn Marino 	os_memcpy(dev->country, pos, 3);
523ff40c12SJohn Marino 	wpa_hexdump_ascii(MSG_DEBUG, "P2P: Peer country", pos, 3);
533ff40c12SJohn Marino 	if (pos[2] != 0x04 && os_memcmp(pos, p2p->cfg->country, 2) != 0) {
543ff40c12SJohn Marino 		p2p_info(p2p, "Mismatching country (ours=%c%c peer's=%c%c)",
553ff40c12SJohn Marino 			p2p->cfg->country[0], p2p->cfg->country[1],
563ff40c12SJohn Marino 			pos[0], pos[1]);
573ff40c12SJohn Marino 		return -1;
583ff40c12SJohn Marino 	}
593ff40c12SJohn Marino 	pos += 3;
603ff40c12SJohn Marino 
61*a1157835SDaniel Fojt 	while (end - pos > 2) {
623ff40c12SJohn Marino 		struct p2p_reg_class *cl = &ch->reg_class[ch->reg_classes];
633ff40c12SJohn Marino 		cl->reg_class = *pos++;
64*a1157835SDaniel Fojt 		channels = *pos++;
65*a1157835SDaniel Fojt 		if (channels > end - pos) {
663ff40c12SJohn Marino 			p2p_info(p2p, "Invalid peer Channel List");
673ff40c12SJohn Marino 			return -1;
683ff40c12SJohn Marino 		}
693ff40c12SJohn Marino 		cl->channels = channels > P2P_MAX_REG_CLASS_CHANNELS ?
703ff40c12SJohn Marino 			P2P_MAX_REG_CLASS_CHANNELS : channels;
713ff40c12SJohn Marino 		os_memcpy(cl->channel, pos, cl->channels);
723ff40c12SJohn Marino 		pos += channels;
733ff40c12SJohn Marino 		ch->reg_classes++;
743ff40c12SJohn Marino 		if (ch->reg_classes == P2P_MAX_REG_CLASSES)
753ff40c12SJohn Marino 			break;
763ff40c12SJohn Marino 	}
773ff40c12SJohn Marino 
783ff40c12SJohn Marino 	p2p_channels_intersect(own, &dev->channels, &intersection);
793ff40c12SJohn Marino 	p2p_dbg(p2p, "Own reg_classes %d peer reg_classes %d intersection reg_classes %d",
803ff40c12SJohn Marino 		(int) own->reg_classes,
813ff40c12SJohn Marino 		(int) dev->channels.reg_classes,
823ff40c12SJohn Marino 		(int) intersection.reg_classes);
833ff40c12SJohn Marino 	if (intersection.reg_classes == 0) {
843ff40c12SJohn Marino 		p2p_info(p2p, "No common channels found");
853ff40c12SJohn Marino 		return -1;
863ff40c12SJohn Marino 	}
873ff40c12SJohn Marino 	return 0;
883ff40c12SJohn Marino }
893ff40c12SJohn Marino 
903ff40c12SJohn Marino 
p2p_peer_channels(struct p2p_data * p2p,struct p2p_device * dev,const u8 * channel_list,size_t channel_list_len)913ff40c12SJohn Marino static int p2p_peer_channels(struct p2p_data *p2p, struct p2p_device *dev,
923ff40c12SJohn Marino 			     const u8 *channel_list, size_t channel_list_len)
933ff40c12SJohn Marino {
943ff40c12SJohn Marino 	return p2p_peer_channels_check(p2p, &p2p->channels, dev,
953ff40c12SJohn Marino 				       channel_list, channel_list_len);
963ff40c12SJohn Marino }
973ff40c12SJohn Marino 
983ff40c12SJohn Marino 
p2p_wps_method_pw_id(enum p2p_wps_method wps_method)993ff40c12SJohn Marino u16 p2p_wps_method_pw_id(enum p2p_wps_method wps_method)
1003ff40c12SJohn Marino {
1013ff40c12SJohn Marino 	switch (wps_method) {
1023ff40c12SJohn Marino 	case WPS_PIN_DISPLAY:
1033ff40c12SJohn Marino 		return DEV_PW_REGISTRAR_SPECIFIED;
1043ff40c12SJohn Marino 	case WPS_PIN_KEYPAD:
1053ff40c12SJohn Marino 		return DEV_PW_USER_SPECIFIED;
1063ff40c12SJohn Marino 	case WPS_PBC:
1073ff40c12SJohn Marino 		return DEV_PW_PUSHBUTTON;
1083ff40c12SJohn Marino 	case WPS_NFC:
1093ff40c12SJohn Marino 		return DEV_PW_NFC_CONNECTION_HANDOVER;
110*a1157835SDaniel Fojt 	case WPS_P2PS:
111*a1157835SDaniel Fojt 		return DEV_PW_P2PS_DEFAULT;
1123ff40c12SJohn Marino 	default:
1133ff40c12SJohn Marino 		return DEV_PW_DEFAULT;
1143ff40c12SJohn Marino 	}
1153ff40c12SJohn Marino }
1163ff40c12SJohn Marino 
1173ff40c12SJohn Marino 
p2p_wps_method_str(enum p2p_wps_method wps_method)1183ff40c12SJohn Marino static const char * p2p_wps_method_str(enum p2p_wps_method wps_method)
1193ff40c12SJohn Marino {
1203ff40c12SJohn Marino 	switch (wps_method) {
1213ff40c12SJohn Marino 	case WPS_PIN_DISPLAY:
1223ff40c12SJohn Marino 		return "Display";
1233ff40c12SJohn Marino 	case WPS_PIN_KEYPAD:
1243ff40c12SJohn Marino 		return "Keypad";
1253ff40c12SJohn Marino 	case WPS_PBC:
1263ff40c12SJohn Marino 		return "PBC";
1273ff40c12SJohn Marino 	case WPS_NFC:
1283ff40c12SJohn Marino 		return "NFC";
129*a1157835SDaniel Fojt 	case WPS_P2PS:
130*a1157835SDaniel Fojt 		return "P2PS";
1313ff40c12SJohn Marino 	default:
1323ff40c12SJohn Marino 		return "??";
1333ff40c12SJohn Marino 	}
1343ff40c12SJohn Marino }
1353ff40c12SJohn Marino 
1363ff40c12SJohn Marino 
p2p_build_go_neg_req(struct p2p_data * p2p,struct p2p_device * peer)1373ff40c12SJohn Marino static struct wpabuf * p2p_build_go_neg_req(struct p2p_data *p2p,
1383ff40c12SJohn Marino 					    struct p2p_device *peer)
1393ff40c12SJohn Marino {
1403ff40c12SJohn Marino 	struct wpabuf *buf;
1413ff40c12SJohn Marino 	u8 *len;
1423ff40c12SJohn Marino 	u8 group_capab;
1433ff40c12SJohn Marino 	size_t extra = 0;
1443ff40c12SJohn Marino 	u16 pw_id;
1453ff40c12SJohn Marino 
1463ff40c12SJohn Marino #ifdef CONFIG_WIFI_DISPLAY
1473ff40c12SJohn Marino 	if (p2p->wfd_ie_go_neg)
1483ff40c12SJohn Marino 		extra = wpabuf_len(p2p->wfd_ie_go_neg);
1493ff40c12SJohn Marino #endif /* CONFIG_WIFI_DISPLAY */
1503ff40c12SJohn Marino 
151*a1157835SDaniel Fojt 	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_REQ])
152*a1157835SDaniel Fojt 		extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_REQ]);
153*a1157835SDaniel Fojt 
1543ff40c12SJohn Marino 	buf = wpabuf_alloc(1000 + extra);
1553ff40c12SJohn Marino 	if (buf == NULL)
1563ff40c12SJohn Marino 		return NULL;
1573ff40c12SJohn Marino 
1583ff40c12SJohn Marino 	p2p_buf_add_public_action_hdr(buf, P2P_GO_NEG_REQ, peer->dialog_token);
1593ff40c12SJohn Marino 
1603ff40c12SJohn Marino 	len = p2p_buf_add_ie_hdr(buf);
1613ff40c12SJohn Marino 	group_capab = 0;
1623ff40c12SJohn Marino 	if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) {
1633ff40c12SJohn Marino 		group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
1643ff40c12SJohn Marino 		if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN)
1653ff40c12SJohn Marino 			group_capab |= P2P_GROUP_CAPAB_PERSISTENT_RECONN;
1663ff40c12SJohn Marino 	}
1673ff40c12SJohn Marino 	if (p2p->cross_connect)
1683ff40c12SJohn Marino 		group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
1693ff40c12SJohn Marino 	if (p2p->cfg->p2p_intra_bss)
1703ff40c12SJohn Marino 		group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST;
1713ff40c12SJohn Marino 	p2p_buf_add_capability(buf, p2p->dev_capab &
1723ff40c12SJohn Marino 			       ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY,
1733ff40c12SJohn Marino 			       group_capab);
1743ff40c12SJohn Marino 	p2p_buf_add_go_intent(buf, (p2p->go_intent << 1) | peer->tie_breaker);
1753ff40c12SJohn Marino 	p2p_buf_add_config_timeout(buf, p2p->go_timeout, p2p->client_timeout);
1763ff40c12SJohn Marino 	p2p_buf_add_listen_channel(buf, p2p->cfg->country, p2p->cfg->reg_class,
1773ff40c12SJohn Marino 				   p2p->cfg->channel);
1783ff40c12SJohn Marino 	if (p2p->ext_listen_interval)
1793ff40c12SJohn Marino 		p2p_buf_add_ext_listen_timing(buf, p2p->ext_listen_period,
1803ff40c12SJohn Marino 					      p2p->ext_listen_interval);
1813ff40c12SJohn Marino 	p2p_buf_add_intended_addr(buf, p2p->intended_addr);
1823ff40c12SJohn Marino 	p2p_buf_add_channel_list(buf, p2p->cfg->country, &p2p->channels);
1833ff40c12SJohn Marino 	p2p_buf_add_device_info(buf, p2p, peer);
1843ff40c12SJohn Marino 	p2p_buf_add_operating_channel(buf, p2p->cfg->country,
1853ff40c12SJohn Marino 				      p2p->op_reg_class, p2p->op_channel);
1863ff40c12SJohn Marino 	p2p_buf_update_ie_hdr(buf, len);
1873ff40c12SJohn Marino 
188*a1157835SDaniel Fojt 	p2p_buf_add_pref_channel_list(buf, p2p->pref_freq_list,
189*a1157835SDaniel Fojt 				      p2p->num_pref_freq);
190*a1157835SDaniel Fojt 
1913ff40c12SJohn Marino 	/* WPS IE with Device Password ID attribute */
1923ff40c12SJohn Marino 	pw_id = p2p_wps_method_pw_id(peer->wps_method);
1933ff40c12SJohn Marino 	if (peer->oob_pw_id)
1943ff40c12SJohn Marino 		pw_id = peer->oob_pw_id;
1953ff40c12SJohn Marino 	if (p2p_build_wps_ie(p2p, buf, pw_id, 0) < 0) {
1963ff40c12SJohn Marino 		p2p_dbg(p2p, "Failed to build WPS IE for GO Negotiation Request");
1973ff40c12SJohn Marino 		wpabuf_free(buf);
1983ff40c12SJohn Marino 		return NULL;
1993ff40c12SJohn Marino 	}
2003ff40c12SJohn Marino 
2013ff40c12SJohn Marino #ifdef CONFIG_WIFI_DISPLAY
2023ff40c12SJohn Marino 	if (p2p->wfd_ie_go_neg)
2033ff40c12SJohn Marino 		wpabuf_put_buf(buf, p2p->wfd_ie_go_neg);
2043ff40c12SJohn Marino #endif /* CONFIG_WIFI_DISPLAY */
2053ff40c12SJohn Marino 
206*a1157835SDaniel Fojt 	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_REQ])
207*a1157835SDaniel Fojt 		wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_REQ]);
208*a1157835SDaniel Fojt 
2093ff40c12SJohn Marino 	return buf;
2103ff40c12SJohn Marino }
2113ff40c12SJohn Marino 
2123ff40c12SJohn Marino 
p2p_connect_send(struct p2p_data * p2p,struct p2p_device * dev)2133ff40c12SJohn Marino int p2p_connect_send(struct p2p_data *p2p, struct p2p_device *dev)
2143ff40c12SJohn Marino {
2153ff40c12SJohn Marino 	struct wpabuf *req;
2163ff40c12SJohn Marino 	int freq;
2173ff40c12SJohn Marino 
2183ff40c12SJohn Marino 	if (dev->flags & P2P_DEV_PD_BEFORE_GO_NEG) {
2193ff40c12SJohn Marino 		u16 config_method;
2203ff40c12SJohn Marino 		p2p_dbg(p2p, "Use PD-before-GO-Neg workaround for " MACSTR,
2213ff40c12SJohn Marino 			MAC2STR(dev->info.p2p_device_addr));
2223ff40c12SJohn Marino 		if (dev->wps_method == WPS_PIN_DISPLAY)
2233ff40c12SJohn Marino 			config_method = WPS_CONFIG_KEYPAD;
2243ff40c12SJohn Marino 		else if (dev->wps_method == WPS_PIN_KEYPAD)
2253ff40c12SJohn Marino 			config_method = WPS_CONFIG_DISPLAY;
2263ff40c12SJohn Marino 		else if (dev->wps_method == WPS_PBC)
2273ff40c12SJohn Marino 			config_method = WPS_CONFIG_PUSHBUTTON;
228*a1157835SDaniel Fojt 		else if (dev->wps_method == WPS_P2PS)
229*a1157835SDaniel Fojt 			config_method = WPS_CONFIG_P2PS;
2303ff40c12SJohn Marino 		else
2313ff40c12SJohn Marino 			return -1;
2323ff40c12SJohn Marino 		return p2p_prov_disc_req(p2p, dev->info.p2p_device_addr,
233*a1157835SDaniel Fojt 					 NULL, config_method, 0, 0, 1);
2343ff40c12SJohn Marino 	}
2353ff40c12SJohn Marino 
2363ff40c12SJohn Marino 	freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq;
2373ff40c12SJohn Marino 	if (dev->oob_go_neg_freq > 0)
2383ff40c12SJohn Marino 		freq = dev->oob_go_neg_freq;
2393ff40c12SJohn Marino 	if (freq <= 0) {
2403ff40c12SJohn Marino 		p2p_dbg(p2p, "No Listen/Operating frequency known for the peer "
2413ff40c12SJohn Marino 			MACSTR " to send GO Negotiation Request",
2423ff40c12SJohn Marino 			MAC2STR(dev->info.p2p_device_addr));
2433ff40c12SJohn Marino 		return -1;
2443ff40c12SJohn Marino 	}
2453ff40c12SJohn Marino 
2463ff40c12SJohn Marino 	req = p2p_build_go_neg_req(p2p, dev);
2473ff40c12SJohn Marino 	if (req == NULL)
2483ff40c12SJohn Marino 		return -1;
2493ff40c12SJohn Marino 	p2p_dbg(p2p, "Sending GO Negotiation Request");
2503ff40c12SJohn Marino 	p2p_set_state(p2p, P2P_CONNECT);
2513ff40c12SJohn Marino 	p2p->pending_action_state = P2P_PENDING_GO_NEG_REQUEST;
2523ff40c12SJohn Marino 	p2p->go_neg_peer = dev;
253*a1157835SDaniel Fojt 	eloop_cancel_timeout(p2p_go_neg_wait_timeout, p2p, NULL);
2543ff40c12SJohn Marino 	dev->flags |= P2P_DEV_WAIT_GO_NEG_RESPONSE;
2553ff40c12SJohn Marino 	dev->connect_reqs++;
2563ff40c12SJohn Marino 	if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr,
2573ff40c12SJohn Marino 			    p2p->cfg->dev_addr, dev->info.p2p_device_addr,
2583ff40c12SJohn Marino 			    wpabuf_head(req), wpabuf_len(req), 500) < 0) {
2593ff40c12SJohn Marino 		p2p_dbg(p2p, "Failed to send Action frame");
2603ff40c12SJohn Marino 		/* Use P2P find to recover and retry */
2613ff40c12SJohn Marino 		p2p_set_timeout(p2p, 0, 0);
2623ff40c12SJohn Marino 	} else
2633ff40c12SJohn Marino 		dev->go_neg_req_sent++;
2643ff40c12SJohn Marino 
2653ff40c12SJohn Marino 	wpabuf_free(req);
2663ff40c12SJohn Marino 
2673ff40c12SJohn Marino 	return 0;
2683ff40c12SJohn Marino }
2693ff40c12SJohn Marino 
2703ff40c12SJohn Marino 
p2p_build_go_neg_resp(struct p2p_data * p2p,struct p2p_device * peer,u8 dialog_token,u8 status,u8 tie_breaker)2713ff40c12SJohn Marino static struct wpabuf * p2p_build_go_neg_resp(struct p2p_data *p2p,
2723ff40c12SJohn Marino 					     struct p2p_device *peer,
2733ff40c12SJohn Marino 					     u8 dialog_token, u8 status,
2743ff40c12SJohn Marino 					     u8 tie_breaker)
2753ff40c12SJohn Marino {
2763ff40c12SJohn Marino 	struct wpabuf *buf;
2773ff40c12SJohn Marino 	u8 *len;
2783ff40c12SJohn Marino 	u8 group_capab;
2793ff40c12SJohn Marino 	size_t extra = 0;
2803ff40c12SJohn Marino 	u16 pw_id;
2813ff40c12SJohn Marino 
2823ff40c12SJohn Marino 	p2p_dbg(p2p, "Building GO Negotiation Response");
2833ff40c12SJohn Marino 
2843ff40c12SJohn Marino #ifdef CONFIG_WIFI_DISPLAY
2853ff40c12SJohn Marino 	if (p2p->wfd_ie_go_neg)
2863ff40c12SJohn Marino 		extra = wpabuf_len(p2p->wfd_ie_go_neg);
2873ff40c12SJohn Marino #endif /* CONFIG_WIFI_DISPLAY */
2883ff40c12SJohn Marino 
289*a1157835SDaniel Fojt 	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_RESP])
290*a1157835SDaniel Fojt 		extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_RESP]);
291*a1157835SDaniel Fojt 
2923ff40c12SJohn Marino 	buf = wpabuf_alloc(1000 + extra);
2933ff40c12SJohn Marino 	if (buf == NULL)
2943ff40c12SJohn Marino 		return NULL;
2953ff40c12SJohn Marino 
2963ff40c12SJohn Marino 	p2p_buf_add_public_action_hdr(buf, P2P_GO_NEG_RESP, dialog_token);
2973ff40c12SJohn Marino 
2983ff40c12SJohn Marino 	len = p2p_buf_add_ie_hdr(buf);
2993ff40c12SJohn Marino 	p2p_buf_add_status(buf, status);
3003ff40c12SJohn Marino 	group_capab = 0;
3013ff40c12SJohn Marino 	if (peer && peer->go_state == LOCAL_GO) {
3023ff40c12SJohn Marino 		if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) {
3033ff40c12SJohn Marino 			group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
3043ff40c12SJohn Marino 			if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN)
3053ff40c12SJohn Marino 				group_capab |=
3063ff40c12SJohn Marino 					P2P_GROUP_CAPAB_PERSISTENT_RECONN;
3073ff40c12SJohn Marino 		}
3083ff40c12SJohn Marino 		if (p2p->cross_connect)
3093ff40c12SJohn Marino 			group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
3103ff40c12SJohn Marino 		if (p2p->cfg->p2p_intra_bss)
3113ff40c12SJohn Marino 			group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST;
3123ff40c12SJohn Marino 	}
3133ff40c12SJohn Marino 	p2p_buf_add_capability(buf, p2p->dev_capab &
3143ff40c12SJohn Marino 			       ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY,
3153ff40c12SJohn Marino 			       group_capab);
3163ff40c12SJohn Marino 	p2p_buf_add_go_intent(buf, (p2p->go_intent << 1) | tie_breaker);
3173ff40c12SJohn Marino 	p2p_buf_add_config_timeout(buf, p2p->go_timeout, p2p->client_timeout);
318*a1157835SDaniel Fojt 	if (p2p->override_pref_op_class) {
319*a1157835SDaniel Fojt 		p2p_dbg(p2p, "Override operating channel preference");
320*a1157835SDaniel Fojt 		p2p_buf_add_operating_channel(buf, p2p->cfg->country,
321*a1157835SDaniel Fojt 					      p2p->override_pref_op_class,
322*a1157835SDaniel Fojt 					      p2p->override_pref_channel);
323*a1157835SDaniel Fojt 	} else if (peer && peer->go_state == REMOTE_GO && !p2p->num_pref_freq) {
3243ff40c12SJohn Marino 		p2p_dbg(p2p, "Omit Operating Channel attribute");
3253ff40c12SJohn Marino 	} else {
3263ff40c12SJohn Marino 		p2p_buf_add_operating_channel(buf, p2p->cfg->country,
3273ff40c12SJohn Marino 					      p2p->op_reg_class,
3283ff40c12SJohn Marino 					      p2p->op_channel);
3293ff40c12SJohn Marino 	}
3303ff40c12SJohn Marino 	p2p_buf_add_intended_addr(buf, p2p->intended_addr);
3313ff40c12SJohn Marino 	if (status || peer == NULL) {
3323ff40c12SJohn Marino 		p2p_buf_add_channel_list(buf, p2p->cfg->country,
3333ff40c12SJohn Marino 					 &p2p->channels);
3343ff40c12SJohn Marino 	} else if (peer->go_state == REMOTE_GO) {
3353ff40c12SJohn Marino 		p2p_buf_add_channel_list(buf, p2p->cfg->country,
3363ff40c12SJohn Marino 					 &p2p->channels);
3373ff40c12SJohn Marino 	} else {
3383ff40c12SJohn Marino 		struct p2p_channels res;
3393ff40c12SJohn Marino 		p2p_channels_intersect(&p2p->channels, &peer->channels,
3403ff40c12SJohn Marino 				       &res);
3413ff40c12SJohn Marino 		p2p_buf_add_channel_list(buf, p2p->cfg->country, &res);
3423ff40c12SJohn Marino 	}
3433ff40c12SJohn Marino 	p2p_buf_add_device_info(buf, p2p, peer);
3443ff40c12SJohn Marino 	if (peer && peer->go_state == LOCAL_GO) {
3453ff40c12SJohn Marino 		p2p_buf_add_group_id(buf, p2p->cfg->dev_addr, p2p->ssid,
3463ff40c12SJohn Marino 				     p2p->ssid_len);
3473ff40c12SJohn Marino 	}
3483ff40c12SJohn Marino 	p2p_buf_update_ie_hdr(buf, len);
3493ff40c12SJohn Marino 
3503ff40c12SJohn Marino 	/* WPS IE with Device Password ID attribute */
3513ff40c12SJohn Marino 	pw_id = p2p_wps_method_pw_id(peer ? peer->wps_method : WPS_NOT_READY);
3523ff40c12SJohn Marino 	if (peer && peer->oob_pw_id)
3533ff40c12SJohn Marino 		pw_id = peer->oob_pw_id;
3543ff40c12SJohn Marino 	if (p2p_build_wps_ie(p2p, buf, pw_id, 0) < 0) {
3553ff40c12SJohn Marino 		p2p_dbg(p2p, "Failed to build WPS IE for GO Negotiation Response");
3563ff40c12SJohn Marino 		wpabuf_free(buf);
3573ff40c12SJohn Marino 		return NULL;
3583ff40c12SJohn Marino 	}
3593ff40c12SJohn Marino 
3603ff40c12SJohn Marino #ifdef CONFIG_WIFI_DISPLAY
3613ff40c12SJohn Marino 	if (p2p->wfd_ie_go_neg)
3623ff40c12SJohn Marino 		wpabuf_put_buf(buf, p2p->wfd_ie_go_neg);
3633ff40c12SJohn Marino #endif /* CONFIG_WIFI_DISPLAY */
3643ff40c12SJohn Marino 
365*a1157835SDaniel Fojt 	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_RESP])
366*a1157835SDaniel Fojt 		wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_RESP]);
3673ff40c12SJohn Marino 
3683ff40c12SJohn Marino 	return buf;
3693ff40c12SJohn Marino }
3703ff40c12SJohn Marino 
3713ff40c12SJohn Marino 
3723ff40c12SJohn Marino /**
3733ff40c12SJohn Marino  * p2p_reselect_channel - Re-select operating channel based on peer information
3743ff40c12SJohn Marino  * @p2p: P2P module context from p2p_init()
3753ff40c12SJohn Marino  * @intersection: Support channel list intersection from local and peer
3763ff40c12SJohn Marino  *
3773ff40c12SJohn Marino  * This function is used to re-select the best channel after having received
3783ff40c12SJohn Marino  * information from the peer to allow supported channel lists to be intersected.
3793ff40c12SJohn Marino  * This can be used to improve initial channel selection done in
3803ff40c12SJohn Marino  * p2p_prepare_channel() prior to the start of GO Negotiation. In addition, this
3813ff40c12SJohn Marino  * can be used for Invitation case.
3823ff40c12SJohn Marino  */
p2p_reselect_channel(struct p2p_data * p2p,struct p2p_channels * intersection)3833ff40c12SJohn Marino void p2p_reselect_channel(struct p2p_data *p2p,
3843ff40c12SJohn Marino 			  struct p2p_channels *intersection)
3853ff40c12SJohn Marino {
3863ff40c12SJohn Marino 	struct p2p_reg_class *cl;
3873ff40c12SJohn Marino 	int freq;
3883ff40c12SJohn Marino 	u8 op_reg_class, op_channel;
3893ff40c12SJohn Marino 	unsigned int i;
390*a1157835SDaniel Fojt 	const int op_classes_5ghz[] = { 124, 125, 115, 0 };
3913ff40c12SJohn Marino 	const int op_classes_ht40[] = { 126, 127, 116, 117, 0 };
392*a1157835SDaniel Fojt 	const int op_classes_vht[] = { 128, 129, 130, 0 };
3933ff40c12SJohn Marino 
3943ff40c12SJohn Marino 	if (p2p->own_freq_preference > 0 &&
3953ff40c12SJohn Marino 	    p2p_freq_to_channel(p2p->own_freq_preference,
3963ff40c12SJohn Marino 				&op_reg_class, &op_channel) == 0 &&
3973ff40c12SJohn Marino 	    p2p_channels_includes(intersection, op_reg_class, op_channel)) {
3983ff40c12SJohn Marino 		p2p_dbg(p2p, "Pick own channel preference (reg_class %u channel %u) from intersection",
3993ff40c12SJohn Marino 			op_reg_class, op_channel);
4003ff40c12SJohn Marino 		p2p->op_reg_class = op_reg_class;
4013ff40c12SJohn Marino 		p2p->op_channel = op_channel;
4023ff40c12SJohn Marino 		return;
4033ff40c12SJohn Marino 	}
4043ff40c12SJohn Marino 
4053ff40c12SJohn Marino 	if (p2p->best_freq_overall > 0 &&
4063ff40c12SJohn Marino 	    p2p_freq_to_channel(p2p->best_freq_overall,
4073ff40c12SJohn Marino 				&op_reg_class, &op_channel) == 0 &&
4083ff40c12SJohn Marino 	    p2p_channels_includes(intersection, op_reg_class, op_channel)) {
4093ff40c12SJohn Marino 		p2p_dbg(p2p, "Pick best overall channel (reg_class %u channel %u) from intersection",
4103ff40c12SJohn Marino 			op_reg_class, op_channel);
4113ff40c12SJohn Marino 		p2p->op_reg_class = op_reg_class;
4123ff40c12SJohn Marino 		p2p->op_channel = op_channel;
4133ff40c12SJohn Marino 		return;
4143ff40c12SJohn Marino 	}
4153ff40c12SJohn Marino 
4163ff40c12SJohn Marino 	/* First, try to pick the best channel from another band */
4173ff40c12SJohn Marino 	freq = p2p_channel_to_freq(p2p->op_reg_class, p2p->op_channel);
4183ff40c12SJohn Marino 	if (freq >= 2400 && freq < 2500 && p2p->best_freq_5 > 0 &&
4193ff40c12SJohn Marino 	    !p2p_channels_includes(intersection, p2p->op_reg_class,
4203ff40c12SJohn Marino 				   p2p->op_channel) &&
4213ff40c12SJohn Marino 	    p2p_freq_to_channel(p2p->best_freq_5,
4223ff40c12SJohn Marino 				&op_reg_class, &op_channel) == 0 &&
4233ff40c12SJohn Marino 	    p2p_channels_includes(intersection, op_reg_class, op_channel)) {
4243ff40c12SJohn Marino 		p2p_dbg(p2p, "Pick best 5 GHz channel (reg_class %u channel %u) from intersection",
4253ff40c12SJohn Marino 			op_reg_class, op_channel);
4263ff40c12SJohn Marino 		p2p->op_reg_class = op_reg_class;
4273ff40c12SJohn Marino 		p2p->op_channel = op_channel;
4283ff40c12SJohn Marino 		return;
4293ff40c12SJohn Marino 	}
4303ff40c12SJohn Marino 
4313ff40c12SJohn Marino 	if (freq >= 4900 && freq < 6000 && p2p->best_freq_24 > 0 &&
4323ff40c12SJohn Marino 	    !p2p_channels_includes(intersection, p2p->op_reg_class,
4333ff40c12SJohn Marino 				   p2p->op_channel) &&
4343ff40c12SJohn Marino 	    p2p_freq_to_channel(p2p->best_freq_24,
4353ff40c12SJohn Marino 				&op_reg_class, &op_channel) == 0 &&
4363ff40c12SJohn Marino 	    p2p_channels_includes(intersection, op_reg_class, op_channel)) {
4373ff40c12SJohn Marino 		p2p_dbg(p2p, "Pick best 2.4 GHz channel (reg_class %u channel %u) from intersection",
4383ff40c12SJohn Marino 			op_reg_class, op_channel);
4393ff40c12SJohn Marino 		p2p->op_reg_class = op_reg_class;
4403ff40c12SJohn Marino 		p2p->op_channel = op_channel;
4413ff40c12SJohn Marino 		return;
4423ff40c12SJohn Marino 	}
4433ff40c12SJohn Marino 
4443ff40c12SJohn Marino 	/* Select channel with highest preference if the peer supports it */
4453ff40c12SJohn Marino 	for (i = 0; p2p->cfg->pref_chan && i < p2p->cfg->num_pref_chan; i++) {
4463ff40c12SJohn Marino 		if (p2p_channels_includes(intersection,
4473ff40c12SJohn Marino 					  p2p->cfg->pref_chan[i].op_class,
4483ff40c12SJohn Marino 					  p2p->cfg->pref_chan[i].chan)) {
4493ff40c12SJohn Marino 			p2p->op_reg_class = p2p->cfg->pref_chan[i].op_class;
4503ff40c12SJohn Marino 			p2p->op_channel = p2p->cfg->pref_chan[i].chan;
4513ff40c12SJohn Marino 			p2p_dbg(p2p, "Pick highest preferred channel (op_class %u channel %u) from intersection",
4523ff40c12SJohn Marino 				p2p->op_reg_class, p2p->op_channel);
4533ff40c12SJohn Marino 			return;
4543ff40c12SJohn Marino 		}
4553ff40c12SJohn Marino 	}
4563ff40c12SJohn Marino 
4573ff40c12SJohn Marino 	/* Try a channel where we might be able to use VHT */
4583ff40c12SJohn Marino 	if (p2p_channel_select(intersection, op_classes_vht,
4593ff40c12SJohn Marino 			       &p2p->op_reg_class, &p2p->op_channel) == 0) {
4603ff40c12SJohn Marino 		p2p_dbg(p2p, "Pick possible VHT channel (op_class %u channel %u) from intersection",
4613ff40c12SJohn Marino 			p2p->op_reg_class, p2p->op_channel);
4623ff40c12SJohn Marino 		return;
4633ff40c12SJohn Marino 	}
4643ff40c12SJohn Marino 
4653ff40c12SJohn Marino 	/* Try a channel where we might be able to use HT40 */
4663ff40c12SJohn Marino 	if (p2p_channel_select(intersection, op_classes_ht40,
4673ff40c12SJohn Marino 			       &p2p->op_reg_class, &p2p->op_channel) == 0) {
4683ff40c12SJohn Marino 		p2p_dbg(p2p, "Pick possible HT40 channel (op_class %u channel %u) from intersection",
4693ff40c12SJohn Marino 			p2p->op_reg_class, p2p->op_channel);
4703ff40c12SJohn Marino 		return;
4713ff40c12SJohn Marino 	}
4723ff40c12SJohn Marino 
4733ff40c12SJohn Marino 	/* Prefer a 5 GHz channel */
4743ff40c12SJohn Marino 	if (p2p_channel_select(intersection, op_classes_5ghz,
4753ff40c12SJohn Marino 			       &p2p->op_reg_class, &p2p->op_channel) == 0) {
4763ff40c12SJohn Marino 		p2p_dbg(p2p, "Pick possible 5 GHz channel (op_class %u channel %u) from intersection",
4773ff40c12SJohn Marino 			p2p->op_reg_class, p2p->op_channel);
4783ff40c12SJohn Marino 		return;
4793ff40c12SJohn Marino 	}
4803ff40c12SJohn Marino 
4813ff40c12SJohn Marino 	/*
4823ff40c12SJohn Marino 	 * Try to see if the original channel is in the intersection. If
4833ff40c12SJohn Marino 	 * so, no need to change anything, as it already contains some
4843ff40c12SJohn Marino 	 * randomness.
4853ff40c12SJohn Marino 	 */
4863ff40c12SJohn Marino 	if (p2p_channels_includes(intersection, p2p->op_reg_class,
4873ff40c12SJohn Marino 				  p2p->op_channel)) {
4883ff40c12SJohn Marino 		p2p_dbg(p2p, "Using original operating class and channel (op_class %u channel %u) from intersection",
4893ff40c12SJohn Marino 			p2p->op_reg_class, p2p->op_channel);
4903ff40c12SJohn Marino 		return;
4913ff40c12SJohn Marino 	}
4923ff40c12SJohn Marino 
4933ff40c12SJohn Marino 	/*
4943ff40c12SJohn Marino 	 * Fall back to whatever is included in the channel intersection since
4953ff40c12SJohn Marino 	 * no better options seems to be available.
4963ff40c12SJohn Marino 	 */
4973ff40c12SJohn Marino 	cl = &intersection->reg_class[0];
4983ff40c12SJohn Marino 	p2p_dbg(p2p, "Pick another channel (reg_class %u channel %u) from intersection",
4993ff40c12SJohn Marino 		cl->reg_class, cl->channel[0]);
5003ff40c12SJohn Marino 	p2p->op_reg_class = cl->reg_class;
5013ff40c12SJohn Marino 	p2p->op_channel = cl->channel[0];
5023ff40c12SJohn Marino }
5033ff40c12SJohn Marino 
5043ff40c12SJohn Marino 
p2p_go_select_channel(struct p2p_data * p2p,struct p2p_device * dev,u8 * status)505*a1157835SDaniel Fojt int p2p_go_select_channel(struct p2p_data *p2p, struct p2p_device *dev,
5063ff40c12SJohn Marino 			  u8 *status)
5073ff40c12SJohn Marino {
5083ff40c12SJohn Marino 	struct p2p_channels tmp, intersection;
5093ff40c12SJohn Marino 
5103ff40c12SJohn Marino 	p2p_channels_dump(p2p, "own channels", &p2p->channels);
5113ff40c12SJohn Marino 	p2p_channels_dump(p2p, "peer channels", &dev->channels);
5123ff40c12SJohn Marino 	p2p_channels_intersect(&p2p->channels, &dev->channels, &tmp);
5133ff40c12SJohn Marino 	p2p_channels_dump(p2p, "intersection", &tmp);
5143ff40c12SJohn Marino 	p2p_channels_remove_freqs(&tmp, &p2p->no_go_freq);
5153ff40c12SJohn Marino 	p2p_channels_dump(p2p, "intersection after no-GO removal", &tmp);
5163ff40c12SJohn Marino 	p2p_channels_intersect(&tmp, &p2p->cfg->channels, &intersection);
5173ff40c12SJohn Marino 	p2p_channels_dump(p2p, "intersection with local channel list",
5183ff40c12SJohn Marino 			  &intersection);
5193ff40c12SJohn Marino 	if (intersection.reg_classes == 0 ||
5203ff40c12SJohn Marino 	    intersection.reg_class[0].channels == 0) {
5213ff40c12SJohn Marino 		*status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
5223ff40c12SJohn Marino 		p2p_dbg(p2p, "No common channels found");
5233ff40c12SJohn Marino 		return -1;
5243ff40c12SJohn Marino 	}
5253ff40c12SJohn Marino 
5263ff40c12SJohn Marino 	if (!p2p_channels_includes(&intersection, p2p->op_reg_class,
5273ff40c12SJohn Marino 				   p2p->op_channel)) {
5283ff40c12SJohn Marino 		if (dev->flags & P2P_DEV_FORCE_FREQ) {
5293ff40c12SJohn Marino 			*status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
5303ff40c12SJohn Marino 			p2p_dbg(p2p, "Peer does not support the forced channel");
5313ff40c12SJohn Marino 			return -1;
5323ff40c12SJohn Marino 		}
5333ff40c12SJohn Marino 
5343ff40c12SJohn Marino 		p2p_dbg(p2p, "Selected operating channel (op_class %u channel %u) not acceptable to the peer",
5353ff40c12SJohn Marino 			p2p->op_reg_class, p2p->op_channel);
5363ff40c12SJohn Marino 		p2p_reselect_channel(p2p, &intersection);
5373ff40c12SJohn Marino 	} else if (!(dev->flags & P2P_DEV_FORCE_FREQ) &&
5383ff40c12SJohn Marino 		   !p2p->cfg->cfg_op_channel) {
5393ff40c12SJohn Marino 		p2p_dbg(p2p, "Try to optimize channel selection with peer information received; previously selected op_class %u channel %u",
5403ff40c12SJohn Marino 			p2p->op_reg_class, p2p->op_channel);
5413ff40c12SJohn Marino 		p2p_reselect_channel(p2p, &intersection);
5423ff40c12SJohn Marino 	}
5433ff40c12SJohn Marino 
5443ff40c12SJohn Marino 	if (!p2p->ssid_set) {
5453ff40c12SJohn Marino 		p2p_build_ssid(p2p, p2p->ssid, &p2p->ssid_len);
5463ff40c12SJohn Marino 		p2p->ssid_set = 1;
5473ff40c12SJohn Marino 	}
5483ff40c12SJohn Marino 
5493ff40c12SJohn Marino 	return 0;
5503ff40c12SJohn Marino }
5513ff40c12SJohn Marino 
5523ff40c12SJohn Marino 
p2p_check_pref_chan_no_recv(struct p2p_data * p2p,int go,struct p2p_device * dev,struct p2p_message * msg,unsigned freq_list[],unsigned int size)553*a1157835SDaniel Fojt static void p2p_check_pref_chan_no_recv(struct p2p_data *p2p, int go,
554*a1157835SDaniel Fojt 					struct p2p_device *dev,
555*a1157835SDaniel Fojt 					struct p2p_message *msg,
556*a1157835SDaniel Fojt 					unsigned freq_list[], unsigned int size)
557*a1157835SDaniel Fojt {
558*a1157835SDaniel Fojt 	u8 op_class, op_channel;
559*a1157835SDaniel Fojt 	unsigned int oper_freq = 0, i, j;
560*a1157835SDaniel Fojt 	int found = 0;
561*a1157835SDaniel Fojt 
562*a1157835SDaniel Fojt 	p2p_dbg(p2p,
563*a1157835SDaniel Fojt 		"Peer didn't provide a preferred frequency list, see if any of our preferred channels are supported by peer device");
564*a1157835SDaniel Fojt 
565*a1157835SDaniel Fojt 	/*
566*a1157835SDaniel Fojt 	 * Search for a common channel in our preferred frequency list which is
567*a1157835SDaniel Fojt 	 * also supported by the peer device.
568*a1157835SDaniel Fojt 	 */
569*a1157835SDaniel Fojt 	for (i = 0; i < size && !found; i++) {
570*a1157835SDaniel Fojt 		/* Make sure that the common frequency is supported by peer. */
571*a1157835SDaniel Fojt 		oper_freq = freq_list[i];
572*a1157835SDaniel Fojt 		if (p2p_freq_to_channel(oper_freq, &op_class,
573*a1157835SDaniel Fojt 					&op_channel) < 0)
574*a1157835SDaniel Fojt 			continue; /* cannot happen due to earlier check */
575*a1157835SDaniel Fojt 		for (j = 0; j < msg->channel_list_len; j++) {
576*a1157835SDaniel Fojt 
577*a1157835SDaniel Fojt 			if (op_channel != msg->channel_list[j])
578*a1157835SDaniel Fojt 				continue;
579*a1157835SDaniel Fojt 
580*a1157835SDaniel Fojt 			p2p->op_reg_class = op_class;
581*a1157835SDaniel Fojt 			p2p->op_channel = op_channel;
582*a1157835SDaniel Fojt 			os_memcpy(&p2p->channels, &p2p->cfg->channels,
583*a1157835SDaniel Fojt 				  sizeof(struct p2p_channels));
584*a1157835SDaniel Fojt 			found = 1;
585*a1157835SDaniel Fojt 			break;
586*a1157835SDaniel Fojt 		}
587*a1157835SDaniel Fojt 	}
588*a1157835SDaniel Fojt 
589*a1157835SDaniel Fojt 	if (found) {
590*a1157835SDaniel Fojt 		p2p_dbg(p2p,
591*a1157835SDaniel Fojt 			"Freq %d MHz is a preferred channel and is also supported by peer, use it as the operating channel",
592*a1157835SDaniel Fojt 			oper_freq);
593*a1157835SDaniel Fojt 	} else {
594*a1157835SDaniel Fojt 		p2p_dbg(p2p,
595*a1157835SDaniel Fojt 			"None of our preferred channels are supported by peer!");
596*a1157835SDaniel Fojt 	}
597*a1157835SDaniel Fojt }
598*a1157835SDaniel Fojt 
599*a1157835SDaniel Fojt 
p2p_check_pref_chan_recv(struct p2p_data * p2p,int go,struct p2p_device * dev,struct p2p_message * msg,unsigned freq_list[],unsigned int size)600*a1157835SDaniel Fojt static void p2p_check_pref_chan_recv(struct p2p_data *p2p, int go,
601*a1157835SDaniel Fojt 				     struct p2p_device *dev,
602*a1157835SDaniel Fojt 				     struct p2p_message *msg,
603*a1157835SDaniel Fojt 				     unsigned freq_list[], unsigned int size)
604*a1157835SDaniel Fojt {
605*a1157835SDaniel Fojt 	u8 op_class, op_channel;
606*a1157835SDaniel Fojt 	unsigned int oper_freq = 0, i, j;
607*a1157835SDaniel Fojt 	int found = 0;
608*a1157835SDaniel Fojt 
609*a1157835SDaniel Fojt 	/*
610*a1157835SDaniel Fojt 	 * Peer device supports a Preferred Frequency List.
611*a1157835SDaniel Fojt 	 * Search for a common channel in the preferred frequency lists
612*a1157835SDaniel Fojt 	 * of both peer and local devices.
613*a1157835SDaniel Fojt 	 */
614*a1157835SDaniel Fojt 	for (i = 0; i < size && !found; i++) {
615*a1157835SDaniel Fojt 		for (j = 2; j < (msg->pref_freq_list_len / 2); j++) {
616*a1157835SDaniel Fojt 			oper_freq = p2p_channel_to_freq(
617*a1157835SDaniel Fojt 				msg->pref_freq_list[2 * j],
618*a1157835SDaniel Fojt 				msg->pref_freq_list[2 * j + 1]);
619*a1157835SDaniel Fojt 			if (freq_list[i] != oper_freq)
620*a1157835SDaniel Fojt 				continue;
621*a1157835SDaniel Fojt 			if (p2p_freq_to_channel(oper_freq, &op_class,
622*a1157835SDaniel Fojt 						&op_channel) < 0)
623*a1157835SDaniel Fojt 				continue; /* cannot happen */
624*a1157835SDaniel Fojt 			p2p->op_reg_class = op_class;
625*a1157835SDaniel Fojt 			p2p->op_channel = op_channel;
626*a1157835SDaniel Fojt 			os_memcpy(&p2p->channels, &p2p->cfg->channels,
627*a1157835SDaniel Fojt 				  sizeof(struct p2p_channels));
628*a1157835SDaniel Fojt 			found = 1;
629*a1157835SDaniel Fojt 			break;
630*a1157835SDaniel Fojt 		}
631*a1157835SDaniel Fojt 	}
632*a1157835SDaniel Fojt 
633*a1157835SDaniel Fojt 	if (found) {
634*a1157835SDaniel Fojt 		p2p_dbg(p2p,
635*a1157835SDaniel Fojt 			"Freq %d MHz is a common preferred channel for both peer and local, use it as operating channel",
636*a1157835SDaniel Fojt 			oper_freq);
637*a1157835SDaniel Fojt 	} else {
638*a1157835SDaniel Fojt 		p2p_dbg(p2p, "No common preferred channels found!");
639*a1157835SDaniel Fojt 	}
640*a1157835SDaniel Fojt }
641*a1157835SDaniel Fojt 
642*a1157835SDaniel Fojt 
p2p_check_pref_chan(struct p2p_data * p2p,int go,struct p2p_device * dev,struct p2p_message * msg)643*a1157835SDaniel Fojt void p2p_check_pref_chan(struct p2p_data *p2p, int go,
644*a1157835SDaniel Fojt 			 struct p2p_device *dev, struct p2p_message *msg)
645*a1157835SDaniel Fojt {
646*a1157835SDaniel Fojt 	unsigned int freq_list[P2P_MAX_PREF_CHANNELS], size;
647*a1157835SDaniel Fojt 	unsigned int i;
648*a1157835SDaniel Fojt 	u8 op_class, op_channel;
649*a1157835SDaniel Fojt 	char txt[100], *pos, *end;
650*a1157835SDaniel Fojt 	int res;
651*a1157835SDaniel Fojt 
652*a1157835SDaniel Fojt 	/*
653*a1157835SDaniel Fojt 	 * Use the preferred channel list from the driver only if there is no
654*a1157835SDaniel Fojt 	 * forced_freq, e.g., P2P_CONNECT freq=..., and no preferred operating
655*a1157835SDaniel Fojt 	 * channel hardcoded in the configuration file.
656*a1157835SDaniel Fojt 	 */
657*a1157835SDaniel Fojt 	if (!p2p->cfg->get_pref_freq_list || p2p->cfg->num_pref_chan ||
658*a1157835SDaniel Fojt 	    (dev->flags & P2P_DEV_FORCE_FREQ) || p2p->cfg->cfg_op_channel)
659*a1157835SDaniel Fojt 		return;
660*a1157835SDaniel Fojt 
661*a1157835SDaniel Fojt 	/* Obtain our preferred frequency list from driver based on P2P role. */
662*a1157835SDaniel Fojt 	size = P2P_MAX_PREF_CHANNELS;
663*a1157835SDaniel Fojt 	if (p2p->cfg->get_pref_freq_list(p2p->cfg->cb_ctx, go, &size,
664*a1157835SDaniel Fojt 					 freq_list))
665*a1157835SDaniel Fojt 		return;
666*a1157835SDaniel Fojt 	/* Filter out frequencies that are not acceptable for P2P use */
667*a1157835SDaniel Fojt 	i = 0;
668*a1157835SDaniel Fojt 	while (i < size) {
669*a1157835SDaniel Fojt 		if (p2p_freq_to_channel(freq_list[i], &op_class,
670*a1157835SDaniel Fojt 					&op_channel) < 0 ||
671*a1157835SDaniel Fojt 		    (!p2p_channels_includes(&p2p->cfg->channels,
672*a1157835SDaniel Fojt 					    op_class, op_channel) &&
673*a1157835SDaniel Fojt 		     (go || !p2p_channels_includes(&p2p->cfg->cli_channels,
674*a1157835SDaniel Fojt 						   op_class, op_channel)))) {
675*a1157835SDaniel Fojt 			p2p_dbg(p2p,
676*a1157835SDaniel Fojt 				"Ignore local driver frequency preference %u MHz since it is not acceptable for P2P use (go=%d)",
677*a1157835SDaniel Fojt 				freq_list[i], go);
678*a1157835SDaniel Fojt 			if (size - i - 1 > 0)
679*a1157835SDaniel Fojt 				os_memmove(&freq_list[i], &freq_list[i + 1],
680*a1157835SDaniel Fojt 					   (size - i - 1) *
681*a1157835SDaniel Fojt 					   sizeof(unsigned int));
682*a1157835SDaniel Fojt 			size--;
683*a1157835SDaniel Fojt 			continue;
684*a1157835SDaniel Fojt 		}
685*a1157835SDaniel Fojt 
686*a1157835SDaniel Fojt 		/* Preferred frequency is acceptable for P2P use */
687*a1157835SDaniel Fojt 		i++;
688*a1157835SDaniel Fojt 	}
689*a1157835SDaniel Fojt 
690*a1157835SDaniel Fojt 	pos = txt;
691*a1157835SDaniel Fojt 	end = pos + sizeof(txt);
692*a1157835SDaniel Fojt 	for (i = 0; i < size; i++) {
693*a1157835SDaniel Fojt 		res = os_snprintf(pos, end - pos, " %u", freq_list[i]);
694*a1157835SDaniel Fojt 		if (os_snprintf_error(end - pos, res))
695*a1157835SDaniel Fojt 			break;
696*a1157835SDaniel Fojt 		pos += res;
697*a1157835SDaniel Fojt 	}
698*a1157835SDaniel Fojt 	*pos = '\0';
699*a1157835SDaniel Fojt 	p2p_dbg(p2p, "Local driver frequency preference (size=%u):%s",
700*a1157835SDaniel Fojt 		size, txt);
701*a1157835SDaniel Fojt 
702*a1157835SDaniel Fojt 	/*
703*a1157835SDaniel Fojt 	 * Check if peer's preference of operating channel is in
704*a1157835SDaniel Fojt 	 * our preferred channel list.
705*a1157835SDaniel Fojt 	 */
706*a1157835SDaniel Fojt 	for (i = 0; i < size; i++) {
707*a1157835SDaniel Fojt 		if (freq_list[i] == (unsigned int) dev->oper_freq)
708*a1157835SDaniel Fojt 			break;
709*a1157835SDaniel Fojt 	}
710*a1157835SDaniel Fojt 	if (i != size &&
711*a1157835SDaniel Fojt 	    p2p_freq_to_channel(freq_list[i], &op_class, &op_channel) == 0) {
712*a1157835SDaniel Fojt 		/* Peer operating channel preference matches our preference */
713*a1157835SDaniel Fojt 		p2p->op_reg_class = op_class;
714*a1157835SDaniel Fojt 		p2p->op_channel = op_channel;
715*a1157835SDaniel Fojt 		os_memcpy(&p2p->channels, &p2p->cfg->channels,
716*a1157835SDaniel Fojt 			  sizeof(struct p2p_channels));
717*a1157835SDaniel Fojt 		return;
718*a1157835SDaniel Fojt 	}
719*a1157835SDaniel Fojt 
720*a1157835SDaniel Fojt 	p2p_dbg(p2p,
721*a1157835SDaniel Fojt 		"Peer operating channel preference: %d MHz is not in our preferred channel list",
722*a1157835SDaniel Fojt 		dev->oper_freq);
723*a1157835SDaniel Fojt 
724*a1157835SDaniel Fojt 	/*
725*a1157835SDaniel Fojt 	  Check if peer's preferred channel list is
726*a1157835SDaniel Fojt 	  * _not_ included in the GO Negotiation Request or Invitation Request.
727*a1157835SDaniel Fojt 	  */
728*a1157835SDaniel Fojt 	if (msg->pref_freq_list_len == 0)
729*a1157835SDaniel Fojt 		p2p_check_pref_chan_no_recv(p2p, go, dev, msg, freq_list, size);
730*a1157835SDaniel Fojt 	else
731*a1157835SDaniel Fojt 		p2p_check_pref_chan_recv(p2p, go, dev, msg, freq_list, size);
732*a1157835SDaniel Fojt }
733*a1157835SDaniel Fojt 
734*a1157835SDaniel Fojt 
p2p_process_go_neg_req(struct p2p_data * p2p,const u8 * sa,const u8 * data,size_t len,int rx_freq)7353ff40c12SJohn Marino void p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa,
7363ff40c12SJohn Marino 			    const u8 *data, size_t len, int rx_freq)
7373ff40c12SJohn Marino {
7383ff40c12SJohn Marino 	struct p2p_device *dev = NULL;
7393ff40c12SJohn Marino 	struct wpabuf *resp;
7403ff40c12SJohn Marino 	struct p2p_message msg;
7413ff40c12SJohn Marino 	u8 status = P2P_SC_FAIL_INVALID_PARAMS;
7423ff40c12SJohn Marino 	int tie_breaker = 0;
7433ff40c12SJohn Marino 	int freq;
7443ff40c12SJohn Marino 
7453ff40c12SJohn Marino 	p2p_dbg(p2p, "Received GO Negotiation Request from " MACSTR "(freq=%d)",
7463ff40c12SJohn Marino 		MAC2STR(sa), rx_freq);
7473ff40c12SJohn Marino 
7483ff40c12SJohn Marino 	if (p2p_parse(data, len, &msg))
7493ff40c12SJohn Marino 		return;
7503ff40c12SJohn Marino 
7513ff40c12SJohn Marino 	if (!msg.capability) {
7523ff40c12SJohn Marino 		p2p_dbg(p2p, "Mandatory Capability attribute missing from GO Negotiation Request");
7533ff40c12SJohn Marino #ifdef CONFIG_P2P_STRICT
7543ff40c12SJohn Marino 		goto fail;
7553ff40c12SJohn Marino #endif /* CONFIG_P2P_STRICT */
7563ff40c12SJohn Marino 	}
7573ff40c12SJohn Marino 
7583ff40c12SJohn Marino 	if (msg.go_intent)
7593ff40c12SJohn Marino 		tie_breaker = *msg.go_intent & 0x01;
7603ff40c12SJohn Marino 	else {
7613ff40c12SJohn Marino 		p2p_dbg(p2p, "Mandatory GO Intent attribute missing from GO Negotiation Request");
7623ff40c12SJohn Marino #ifdef CONFIG_P2P_STRICT
7633ff40c12SJohn Marino 		goto fail;
7643ff40c12SJohn Marino #endif /* CONFIG_P2P_STRICT */
7653ff40c12SJohn Marino 	}
7663ff40c12SJohn Marino 
7673ff40c12SJohn Marino 	if (!msg.config_timeout) {
7683ff40c12SJohn Marino 		p2p_dbg(p2p, "Mandatory Configuration Timeout attribute missing from GO Negotiation Request");
7693ff40c12SJohn Marino #ifdef CONFIG_P2P_STRICT
7703ff40c12SJohn Marino 		goto fail;
7713ff40c12SJohn Marino #endif /* CONFIG_P2P_STRICT */
7723ff40c12SJohn Marino 	}
7733ff40c12SJohn Marino 
7743ff40c12SJohn Marino 	if (!msg.listen_channel) {
7753ff40c12SJohn Marino 		p2p_dbg(p2p, "No Listen Channel attribute received");
7763ff40c12SJohn Marino 		goto fail;
7773ff40c12SJohn Marino 	}
7783ff40c12SJohn Marino 	if (!msg.operating_channel) {
7793ff40c12SJohn Marino 		p2p_dbg(p2p, "No Operating Channel attribute received");
7803ff40c12SJohn Marino 		goto fail;
7813ff40c12SJohn Marino 	}
7823ff40c12SJohn Marino 	if (!msg.channel_list) {
7833ff40c12SJohn Marino 		p2p_dbg(p2p, "No Channel List attribute received");
7843ff40c12SJohn Marino 		goto fail;
7853ff40c12SJohn Marino 	}
7863ff40c12SJohn Marino 	if (!msg.intended_addr) {
7873ff40c12SJohn Marino 		p2p_dbg(p2p, "No Intended P2P Interface Address attribute received");
7883ff40c12SJohn Marino 		goto fail;
7893ff40c12SJohn Marino 	}
7903ff40c12SJohn Marino 	if (!msg.p2p_device_info) {
7913ff40c12SJohn Marino 		p2p_dbg(p2p, "No P2P Device Info attribute received");
7923ff40c12SJohn Marino 		goto fail;
7933ff40c12SJohn Marino 	}
7943ff40c12SJohn Marino 
7953ff40c12SJohn Marino 	if (os_memcmp(msg.p2p_device_addr, sa, ETH_ALEN) != 0) {
7963ff40c12SJohn Marino 		p2p_dbg(p2p, "Unexpected GO Negotiation Request SA=" MACSTR
7973ff40c12SJohn Marino 			" != dev_addr=" MACSTR,
7983ff40c12SJohn Marino 			MAC2STR(sa), MAC2STR(msg.p2p_device_addr));
7993ff40c12SJohn Marino 		goto fail;
8003ff40c12SJohn Marino 	}
8013ff40c12SJohn Marino 
8023ff40c12SJohn Marino 	dev = p2p_get_device(p2p, sa);
8033ff40c12SJohn Marino 
8043ff40c12SJohn Marino 	if (msg.status && *msg.status) {
8053ff40c12SJohn Marino 		p2p_dbg(p2p, "Unexpected Status attribute (%d) in GO Negotiation Request",
8063ff40c12SJohn Marino 			*msg.status);
807*a1157835SDaniel Fojt 		if (dev && p2p->go_neg_peer == dev &&
808*a1157835SDaniel Fojt 		    *msg.status == P2P_SC_FAIL_REJECTED_BY_USER) {
809*a1157835SDaniel Fojt 			/*
810*a1157835SDaniel Fojt 			 * This mechanism for using Status attribute in GO
811*a1157835SDaniel Fojt 			 * Negotiation Request is not compliant with the P2P
812*a1157835SDaniel Fojt 			 * specification, but some deployed devices use it to
813*a1157835SDaniel Fojt 			 * indicate rejection of GO Negotiation in a case where
814*a1157835SDaniel Fojt 			 * they have sent out GO Negotiation Response with
815*a1157835SDaniel Fojt 			 * status 1. The P2P specification explicitly disallows
816*a1157835SDaniel Fojt 			 * this. To avoid unnecessary interoperability issues
817*a1157835SDaniel Fojt 			 * and extra frames, mark the pending negotiation as
818*a1157835SDaniel Fojt 			 * failed and do not reply to this GO Negotiation
819*a1157835SDaniel Fojt 			 * Request frame.
820*a1157835SDaniel Fojt 			 */
821*a1157835SDaniel Fojt 			p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
822*a1157835SDaniel Fojt 			p2p_go_neg_failed(p2p, *msg.status);
823*a1157835SDaniel Fojt 			p2p_parse_free(&msg);
824*a1157835SDaniel Fojt 			return;
825*a1157835SDaniel Fojt 		}
8263ff40c12SJohn Marino 		goto fail;
8273ff40c12SJohn Marino 	}
8283ff40c12SJohn Marino 
8293ff40c12SJohn Marino 	if (dev == NULL)
8303ff40c12SJohn Marino 		dev = p2p_add_dev_from_go_neg_req(p2p, sa, &msg);
831*a1157835SDaniel Fojt 	else if ((dev->flags & P2P_DEV_PROBE_REQ_ONLY) ||
832*a1157835SDaniel Fojt 		  !(dev->flags & P2P_DEV_REPORTED))
8333ff40c12SJohn Marino 		p2p_add_dev_info(p2p, sa, dev, &msg);
8343ff40c12SJohn Marino 	else if (!dev->listen_freq && !dev->oper_freq) {
8353ff40c12SJohn Marino 		/*
8363ff40c12SJohn Marino 		 * This may happen if the peer entry was added based on PD
8373ff40c12SJohn Marino 		 * Request and no Probe Request/Response frame has been received
8383ff40c12SJohn Marino 		 * from this peer (or that information has timed out).
8393ff40c12SJohn Marino 		 */
8403ff40c12SJohn Marino 		p2p_dbg(p2p, "Update peer " MACSTR
8413ff40c12SJohn Marino 			" based on GO Neg Req since listen/oper freq not known",
8423ff40c12SJohn Marino 			MAC2STR(dev->info.p2p_device_addr));
8433ff40c12SJohn Marino 		p2p_add_dev_info(p2p, sa, dev, &msg);
8443ff40c12SJohn Marino 	}
8453ff40c12SJohn Marino 
846*a1157835SDaniel Fojt 	if (p2p->go_neg_peer && p2p->go_neg_peer == dev)
847*a1157835SDaniel Fojt 		eloop_cancel_timeout(p2p_go_neg_wait_timeout, p2p, NULL);
848*a1157835SDaniel Fojt 
8493ff40c12SJohn Marino 	if (dev && dev->flags & P2P_DEV_USER_REJECTED) {
8503ff40c12SJohn Marino 		p2p_dbg(p2p, "User has rejected this peer");
8513ff40c12SJohn Marino 		status = P2P_SC_FAIL_REJECTED_BY_USER;
8523ff40c12SJohn Marino 	} else if (dev == NULL ||
8533ff40c12SJohn Marino 		   (dev->wps_method == WPS_NOT_READY &&
8543ff40c12SJohn Marino 		    (p2p->authorized_oob_dev_pw_id == 0 ||
8553ff40c12SJohn Marino 		     p2p->authorized_oob_dev_pw_id !=
8563ff40c12SJohn Marino 		     msg.dev_password_id))) {
8573ff40c12SJohn Marino 		p2p_dbg(p2p, "Not ready for GO negotiation with " MACSTR,
8583ff40c12SJohn Marino 			MAC2STR(sa));
8593ff40c12SJohn Marino 		status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
8603ff40c12SJohn Marino 		p2p->cfg->go_neg_req_rx(p2p->cfg->cb_ctx, sa,
861*a1157835SDaniel Fojt 					msg.dev_password_id,
862*a1157835SDaniel Fojt 					msg.go_intent ? (*msg.go_intent >> 1) :
863*a1157835SDaniel Fojt 					0);
8643ff40c12SJohn Marino 	} else if (p2p->go_neg_peer && p2p->go_neg_peer != dev) {
8653ff40c12SJohn Marino 		p2p_dbg(p2p, "Already in Group Formation with another peer");
8663ff40c12SJohn Marino 		status = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
8673ff40c12SJohn Marino 	} else {
8683ff40c12SJohn Marino 		int go;
8693ff40c12SJohn Marino 
8703ff40c12SJohn Marino 		if (!p2p->go_neg_peer) {
8713ff40c12SJohn Marino 			p2p_dbg(p2p, "Starting GO Negotiation with previously authorized peer");
8723ff40c12SJohn Marino 			if (!(dev->flags & P2P_DEV_FORCE_FREQ)) {
8733ff40c12SJohn Marino 				p2p_dbg(p2p, "Use default channel settings");
8743ff40c12SJohn Marino 				p2p->op_reg_class = p2p->cfg->op_reg_class;
8753ff40c12SJohn Marino 				p2p->op_channel = p2p->cfg->op_channel;
8763ff40c12SJohn Marino 				os_memcpy(&p2p->channels, &p2p->cfg->channels,
8773ff40c12SJohn Marino 					  sizeof(struct p2p_channels));
8783ff40c12SJohn Marino 			} else {
8793ff40c12SJohn Marino 				p2p_dbg(p2p, "Use previously configured forced channel settings");
8803ff40c12SJohn Marino 			}
8813ff40c12SJohn Marino 		}
8823ff40c12SJohn Marino 
8833ff40c12SJohn Marino 		dev->flags &= ~P2P_DEV_NOT_YET_READY;
8843ff40c12SJohn Marino 
8853ff40c12SJohn Marino 		if (!msg.go_intent) {
8863ff40c12SJohn Marino 			p2p_dbg(p2p, "No GO Intent attribute received");
8873ff40c12SJohn Marino 			goto fail;
8883ff40c12SJohn Marino 		}
8893ff40c12SJohn Marino 		if ((*msg.go_intent >> 1) > P2P_MAX_GO_INTENT) {
8903ff40c12SJohn Marino 			p2p_dbg(p2p, "Invalid GO Intent value (%u) received",
8913ff40c12SJohn Marino 				*msg.go_intent >> 1);
8923ff40c12SJohn Marino 			goto fail;
8933ff40c12SJohn Marino 		}
8943ff40c12SJohn Marino 
8953ff40c12SJohn Marino 		if (dev->go_neg_req_sent &&
8963ff40c12SJohn Marino 		    os_memcmp(sa, p2p->cfg->dev_addr, ETH_ALEN) > 0) {
8973ff40c12SJohn Marino 			p2p_dbg(p2p, "Do not reply since peer has higher address and GO Neg Request already sent");
8983ff40c12SJohn Marino 			p2p_parse_free(&msg);
8993ff40c12SJohn Marino 			return;
9003ff40c12SJohn Marino 		}
9013ff40c12SJohn Marino 
902*a1157835SDaniel Fojt 		if (dev->go_neg_req_sent &&
903*a1157835SDaniel Fojt 		    (dev->flags & P2P_DEV_PEER_WAITING_RESPONSE)) {
904*a1157835SDaniel Fojt 			p2p_dbg(p2p,
905*a1157835SDaniel Fojt 				"Do not reply since peer is waiting for us to start a new GO Negotiation and GO Neg Request already sent");
906*a1157835SDaniel Fojt 			p2p_parse_free(&msg);
907*a1157835SDaniel Fojt 			return;
908*a1157835SDaniel Fojt 		}
909*a1157835SDaniel Fojt 
9103ff40c12SJohn Marino 		go = p2p_go_det(p2p->go_intent, *msg.go_intent);
9113ff40c12SJohn Marino 		if (go < 0) {
9123ff40c12SJohn Marino 			p2p_dbg(p2p, "Incompatible GO Intent");
9133ff40c12SJohn Marino 			status = P2P_SC_FAIL_BOTH_GO_INTENT_15;
9143ff40c12SJohn Marino 			goto fail;
9153ff40c12SJohn Marino 		}
9163ff40c12SJohn Marino 
9173ff40c12SJohn Marino 		if (p2p_peer_channels(p2p, dev, msg.channel_list,
9183ff40c12SJohn Marino 				      msg.channel_list_len) < 0) {
9193ff40c12SJohn Marino 			p2p_dbg(p2p, "No common channels found");
9203ff40c12SJohn Marino 			status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
9213ff40c12SJohn Marino 			goto fail;
9223ff40c12SJohn Marino 		}
9233ff40c12SJohn Marino 
9243ff40c12SJohn Marino 		switch (msg.dev_password_id) {
9253ff40c12SJohn Marino 		case DEV_PW_REGISTRAR_SPECIFIED:
9263ff40c12SJohn Marino 			p2p_dbg(p2p, "PIN from peer Display");
9273ff40c12SJohn Marino 			if (dev->wps_method != WPS_PIN_KEYPAD) {
9283ff40c12SJohn Marino 				p2p_dbg(p2p, "We have wps_method=%s -> incompatible",
9293ff40c12SJohn Marino 					p2p_wps_method_str(dev->wps_method));
9303ff40c12SJohn Marino 				status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
9313ff40c12SJohn Marino 				goto fail;
9323ff40c12SJohn Marino 			}
9333ff40c12SJohn Marino 			break;
9343ff40c12SJohn Marino 		case DEV_PW_USER_SPECIFIED:
9353ff40c12SJohn Marino 			p2p_dbg(p2p, "Peer entered PIN on Keypad");
9363ff40c12SJohn Marino 			if (dev->wps_method != WPS_PIN_DISPLAY) {
9373ff40c12SJohn Marino 				p2p_dbg(p2p, "We have wps_method=%s -> incompatible",
9383ff40c12SJohn Marino 					p2p_wps_method_str(dev->wps_method));
9393ff40c12SJohn Marino 				status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
9403ff40c12SJohn Marino 				goto fail;
9413ff40c12SJohn Marino 			}
9423ff40c12SJohn Marino 			break;
9433ff40c12SJohn Marino 		case DEV_PW_PUSHBUTTON:
9443ff40c12SJohn Marino 			p2p_dbg(p2p, "Peer using pushbutton");
9453ff40c12SJohn Marino 			if (dev->wps_method != WPS_PBC) {
9463ff40c12SJohn Marino 				p2p_dbg(p2p, "We have wps_method=%s -> incompatible",
9473ff40c12SJohn Marino 					p2p_wps_method_str(dev->wps_method));
9483ff40c12SJohn Marino 				status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
9493ff40c12SJohn Marino 				goto fail;
9503ff40c12SJohn Marino 			}
9513ff40c12SJohn Marino 			break;
952*a1157835SDaniel Fojt 		case DEV_PW_P2PS_DEFAULT:
953*a1157835SDaniel Fojt 			p2p_dbg(p2p, "Peer using P2PS pin");
954*a1157835SDaniel Fojt 			if (dev->wps_method != WPS_P2PS) {
955*a1157835SDaniel Fojt 				p2p_dbg(p2p,
956*a1157835SDaniel Fojt 					"We have wps_method=%s -> incompatible",
957*a1157835SDaniel Fojt 					p2p_wps_method_str(dev->wps_method));
958*a1157835SDaniel Fojt 				status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
959*a1157835SDaniel Fojt 				goto fail;
960*a1157835SDaniel Fojt 			}
961*a1157835SDaniel Fojt 			break;
9623ff40c12SJohn Marino 		default:
9633ff40c12SJohn Marino 			if (msg.dev_password_id &&
9643ff40c12SJohn Marino 			    msg.dev_password_id == dev->oob_pw_id) {
9653ff40c12SJohn Marino 				p2p_dbg(p2p, "Peer using NFC");
9663ff40c12SJohn Marino 				if (dev->wps_method != WPS_NFC) {
9673ff40c12SJohn Marino 					p2p_dbg(p2p, "We have wps_method=%s -> incompatible",
9683ff40c12SJohn Marino 						p2p_wps_method_str(
9693ff40c12SJohn Marino 							dev->wps_method));
9703ff40c12SJohn Marino 					status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
9713ff40c12SJohn Marino 					goto fail;
9723ff40c12SJohn Marino 				}
9733ff40c12SJohn Marino 				break;
9743ff40c12SJohn Marino 			}
9753ff40c12SJohn Marino #ifdef CONFIG_WPS_NFC
9763ff40c12SJohn Marino 			if (p2p->authorized_oob_dev_pw_id &&
9773ff40c12SJohn Marino 			    msg.dev_password_id ==
9783ff40c12SJohn Marino 			    p2p->authorized_oob_dev_pw_id) {
9793ff40c12SJohn Marino 				p2p_dbg(p2p, "Using static handover with our device password from NFC Tag");
9803ff40c12SJohn Marino 				dev->wps_method = WPS_NFC;
9813ff40c12SJohn Marino 				dev->oob_pw_id = p2p->authorized_oob_dev_pw_id;
9823ff40c12SJohn Marino 				break;
9833ff40c12SJohn Marino 			}
9843ff40c12SJohn Marino #endif /* CONFIG_WPS_NFC */
9853ff40c12SJohn Marino 			p2p_dbg(p2p, "Unsupported Device Password ID %d",
9863ff40c12SJohn Marino 				msg.dev_password_id);
9873ff40c12SJohn Marino 			status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
9883ff40c12SJohn Marino 			goto fail;
9893ff40c12SJohn Marino 		}
9903ff40c12SJohn Marino 
9913ff40c12SJohn Marino 		if (go && p2p_go_select_channel(p2p, dev, &status) < 0)
9923ff40c12SJohn Marino 			goto fail;
9933ff40c12SJohn Marino 
9943ff40c12SJohn Marino 		dev->go_state = go ? LOCAL_GO : REMOTE_GO;
9953ff40c12SJohn Marino 		dev->oper_freq = p2p_channel_to_freq(msg.operating_channel[3],
9963ff40c12SJohn Marino 						     msg.operating_channel[4]);
9973ff40c12SJohn Marino 		p2p_dbg(p2p, "Peer operating channel preference: %d MHz",
9983ff40c12SJohn Marino 			dev->oper_freq);
9993ff40c12SJohn Marino 
1000*a1157835SDaniel Fojt 		/*
1001*a1157835SDaniel Fojt 		 * Use the driver preferred frequency list extension if
1002*a1157835SDaniel Fojt 		 * supported.
1003*a1157835SDaniel Fojt 		 */
1004*a1157835SDaniel Fojt 		p2p_check_pref_chan(p2p, go, dev, &msg);
1005*a1157835SDaniel Fojt 
10063ff40c12SJohn Marino 		if (msg.config_timeout) {
10073ff40c12SJohn Marino 			dev->go_timeout = msg.config_timeout[0];
10083ff40c12SJohn Marino 			dev->client_timeout = msg.config_timeout[1];
10093ff40c12SJohn Marino 		}
10103ff40c12SJohn Marino 
10113ff40c12SJohn Marino 		p2p_dbg(p2p, "GO Negotiation with " MACSTR, MAC2STR(sa));
10123ff40c12SJohn Marino 		if (p2p->state != P2P_IDLE)
10133ff40c12SJohn Marino 			p2p_stop_find_for_freq(p2p, rx_freq);
10143ff40c12SJohn Marino 		p2p_set_state(p2p, P2P_GO_NEG);
10153ff40c12SJohn Marino 		p2p_clear_timeout(p2p);
10163ff40c12SJohn Marino 		dev->dialog_token = msg.dialog_token;
10173ff40c12SJohn Marino 		os_memcpy(dev->intended_addr, msg.intended_addr, ETH_ALEN);
10183ff40c12SJohn Marino 		p2p->go_neg_peer = dev;
1019*a1157835SDaniel Fojt 		eloop_cancel_timeout(p2p_go_neg_wait_timeout, p2p, NULL);
10203ff40c12SJohn Marino 		status = P2P_SC_SUCCESS;
10213ff40c12SJohn Marino 	}
10223ff40c12SJohn Marino 
10233ff40c12SJohn Marino fail:
10243ff40c12SJohn Marino 	if (dev)
10253ff40c12SJohn Marino 		dev->status = status;
10263ff40c12SJohn Marino 	resp = p2p_build_go_neg_resp(p2p, dev, msg.dialog_token, status,
10273ff40c12SJohn Marino 				     !tie_breaker);
10283ff40c12SJohn Marino 	p2p_parse_free(&msg);
10293ff40c12SJohn Marino 	if (resp == NULL)
10303ff40c12SJohn Marino 		return;
10313ff40c12SJohn Marino 	p2p_dbg(p2p, "Sending GO Negotiation Response");
10323ff40c12SJohn Marino 	if (rx_freq > 0)
10333ff40c12SJohn Marino 		freq = rx_freq;
10343ff40c12SJohn Marino 	else
10353ff40c12SJohn Marino 		freq = p2p_channel_to_freq(p2p->cfg->reg_class,
10363ff40c12SJohn Marino 					   p2p->cfg->channel);
10373ff40c12SJohn Marino 	if (freq < 0) {
10383ff40c12SJohn Marino 		p2p_dbg(p2p, "Unknown regulatory class/channel");
10393ff40c12SJohn Marino 		wpabuf_free(resp);
10403ff40c12SJohn Marino 		return;
10413ff40c12SJohn Marino 	}
10423ff40c12SJohn Marino 	if (status == P2P_SC_SUCCESS) {
10433ff40c12SJohn Marino 		p2p->pending_action_state = P2P_PENDING_GO_NEG_RESPONSE;
10443ff40c12SJohn Marino 		dev->flags |= P2P_DEV_WAIT_GO_NEG_CONFIRM;
10453ff40c12SJohn Marino 		if (os_memcmp(sa, p2p->cfg->dev_addr, ETH_ALEN) < 0) {
10463ff40c12SJohn Marino 			/*
10473ff40c12SJohn Marino 			 * Peer has smaller address, so the GO Negotiation
10483ff40c12SJohn Marino 			 * Response from us is expected to complete
10493ff40c12SJohn Marino 			 * negotiation. Ignore a GO Negotiation Response from
10503ff40c12SJohn Marino 			 * the peer if it happens to be received after this
10513ff40c12SJohn Marino 			 * point due to a race condition in GO Negotiation
10523ff40c12SJohn Marino 			 * Request transmission and processing.
10533ff40c12SJohn Marino 			 */
10543ff40c12SJohn Marino 			dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE;
10553ff40c12SJohn Marino 		}
10563ff40c12SJohn Marino 	} else
10573ff40c12SJohn Marino 		p2p->pending_action_state =
10583ff40c12SJohn Marino 			P2P_PENDING_GO_NEG_RESPONSE_FAILURE;
10593ff40c12SJohn Marino 	if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
10603ff40c12SJohn Marino 			    p2p->cfg->dev_addr,
1061*a1157835SDaniel Fojt 			    wpabuf_head(resp), wpabuf_len(resp), 100) < 0) {
10623ff40c12SJohn Marino 		p2p_dbg(p2p, "Failed to send Action frame");
10633ff40c12SJohn Marino 	}
10643ff40c12SJohn Marino 
10653ff40c12SJohn Marino 	wpabuf_free(resp);
10663ff40c12SJohn Marino }
10673ff40c12SJohn Marino 
10683ff40c12SJohn Marino 
p2p_build_go_neg_conf(struct p2p_data * p2p,struct p2p_device * peer,u8 dialog_token,u8 status,const u8 * resp_chan,int go)10693ff40c12SJohn Marino static struct wpabuf * p2p_build_go_neg_conf(struct p2p_data *p2p,
10703ff40c12SJohn Marino 					     struct p2p_device *peer,
10713ff40c12SJohn Marino 					     u8 dialog_token, u8 status,
10723ff40c12SJohn Marino 					     const u8 *resp_chan, int go)
10733ff40c12SJohn Marino {
10743ff40c12SJohn Marino 	struct wpabuf *buf;
10753ff40c12SJohn Marino 	u8 *len;
10763ff40c12SJohn Marino 	struct p2p_channels res;
10773ff40c12SJohn Marino 	u8 group_capab;
10783ff40c12SJohn Marino 	size_t extra = 0;
10793ff40c12SJohn Marino 
10803ff40c12SJohn Marino 	p2p_dbg(p2p, "Building GO Negotiation Confirm");
10813ff40c12SJohn Marino 
10823ff40c12SJohn Marino #ifdef CONFIG_WIFI_DISPLAY
10833ff40c12SJohn Marino 	if (p2p->wfd_ie_go_neg)
10843ff40c12SJohn Marino 		extra = wpabuf_len(p2p->wfd_ie_go_neg);
10853ff40c12SJohn Marino #endif /* CONFIG_WIFI_DISPLAY */
10863ff40c12SJohn Marino 
1087*a1157835SDaniel Fojt 	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_CONF])
1088*a1157835SDaniel Fojt 		extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_CONF]);
1089*a1157835SDaniel Fojt 
10903ff40c12SJohn Marino 	buf = wpabuf_alloc(1000 + extra);
10913ff40c12SJohn Marino 	if (buf == NULL)
10923ff40c12SJohn Marino 		return NULL;
10933ff40c12SJohn Marino 
10943ff40c12SJohn Marino 	p2p_buf_add_public_action_hdr(buf, P2P_GO_NEG_CONF, dialog_token);
10953ff40c12SJohn Marino 
10963ff40c12SJohn Marino 	len = p2p_buf_add_ie_hdr(buf);
10973ff40c12SJohn Marino 	p2p_buf_add_status(buf, status);
10983ff40c12SJohn Marino 	group_capab = 0;
10993ff40c12SJohn Marino 	if (peer->go_state == LOCAL_GO) {
11003ff40c12SJohn Marino 		if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) {
11013ff40c12SJohn Marino 			group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
11023ff40c12SJohn Marino 			if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN)
11033ff40c12SJohn Marino 				group_capab |=
11043ff40c12SJohn Marino 					P2P_GROUP_CAPAB_PERSISTENT_RECONN;
11053ff40c12SJohn Marino 		}
11063ff40c12SJohn Marino 		if (p2p->cross_connect)
11073ff40c12SJohn Marino 			group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
11083ff40c12SJohn Marino 		if (p2p->cfg->p2p_intra_bss)
11093ff40c12SJohn Marino 			group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST;
11103ff40c12SJohn Marino 	}
11113ff40c12SJohn Marino 	p2p_buf_add_capability(buf, p2p->dev_capab &
11123ff40c12SJohn Marino 			       ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY,
11133ff40c12SJohn Marino 			       group_capab);
11143ff40c12SJohn Marino 	if (go || resp_chan == NULL)
11153ff40c12SJohn Marino 		p2p_buf_add_operating_channel(buf, p2p->cfg->country,
11163ff40c12SJohn Marino 					      p2p->op_reg_class,
11173ff40c12SJohn Marino 					      p2p->op_channel);
11183ff40c12SJohn Marino 	else
11193ff40c12SJohn Marino 		p2p_buf_add_operating_channel(buf, (const char *) resp_chan,
11203ff40c12SJohn Marino 					      resp_chan[3], resp_chan[4]);
11213ff40c12SJohn Marino 	p2p_channels_intersect(&p2p->channels, &peer->channels, &res);
11223ff40c12SJohn Marino 	p2p_buf_add_channel_list(buf, p2p->cfg->country, &res);
11233ff40c12SJohn Marino 	if (go) {
11243ff40c12SJohn Marino 		p2p_buf_add_group_id(buf, p2p->cfg->dev_addr, p2p->ssid,
11253ff40c12SJohn Marino 				     p2p->ssid_len);
11263ff40c12SJohn Marino 	}
11273ff40c12SJohn Marino 	p2p_buf_update_ie_hdr(buf, len);
11283ff40c12SJohn Marino 
11293ff40c12SJohn Marino #ifdef CONFIG_WIFI_DISPLAY
11303ff40c12SJohn Marino 	if (p2p->wfd_ie_go_neg)
11313ff40c12SJohn Marino 		wpabuf_put_buf(buf, p2p->wfd_ie_go_neg);
11323ff40c12SJohn Marino #endif /* CONFIG_WIFI_DISPLAY */
11333ff40c12SJohn Marino 
1134*a1157835SDaniel Fojt 	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_CONF])
1135*a1157835SDaniel Fojt 		wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_CONF]);
1136*a1157835SDaniel Fojt 
11373ff40c12SJohn Marino 	return buf;
11383ff40c12SJohn Marino }
11393ff40c12SJohn Marino 
11403ff40c12SJohn Marino 
p2p_process_go_neg_resp(struct p2p_data * p2p,const u8 * sa,const u8 * data,size_t len,int rx_freq)11413ff40c12SJohn Marino void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa,
11423ff40c12SJohn Marino 			     const u8 *data, size_t len, int rx_freq)
11433ff40c12SJohn Marino {
11443ff40c12SJohn Marino 	struct p2p_device *dev;
11453ff40c12SJohn Marino 	int go = -1;
11463ff40c12SJohn Marino 	struct p2p_message msg;
11473ff40c12SJohn Marino 	u8 status = P2P_SC_SUCCESS;
11483ff40c12SJohn Marino 	int freq;
11493ff40c12SJohn Marino 
11503ff40c12SJohn Marino 	p2p_dbg(p2p, "Received GO Negotiation Response from " MACSTR
11513ff40c12SJohn Marino 		" (freq=%d)", MAC2STR(sa), rx_freq);
11523ff40c12SJohn Marino 	dev = p2p_get_device(p2p, sa);
11533ff40c12SJohn Marino 	if (dev == NULL || dev->wps_method == WPS_NOT_READY ||
11543ff40c12SJohn Marino 	    dev != p2p->go_neg_peer) {
11553ff40c12SJohn Marino 		p2p_dbg(p2p, "Not ready for GO negotiation with " MACSTR,
11563ff40c12SJohn Marino 			MAC2STR(sa));
11573ff40c12SJohn Marino 		return;
11583ff40c12SJohn Marino 	}
11593ff40c12SJohn Marino 
11603ff40c12SJohn Marino 	if (p2p_parse(data, len, &msg))
11613ff40c12SJohn Marino 		return;
11623ff40c12SJohn Marino 
11633ff40c12SJohn Marino 	if (!(dev->flags & P2P_DEV_WAIT_GO_NEG_RESPONSE)) {
11643ff40c12SJohn Marino 		p2p_dbg(p2p, "Was not expecting GO Negotiation Response - ignore");
11653ff40c12SJohn Marino 		p2p_parse_free(&msg);
11663ff40c12SJohn Marino 		return;
11673ff40c12SJohn Marino 	}
11683ff40c12SJohn Marino 	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE;
11693ff40c12SJohn Marino 
11703ff40c12SJohn Marino 	if (msg.dialog_token != dev->dialog_token) {
11713ff40c12SJohn Marino 		p2p_dbg(p2p, "Unexpected Dialog Token %u (expected %u)",
11723ff40c12SJohn Marino 			msg.dialog_token, dev->dialog_token);
11733ff40c12SJohn Marino 		p2p_parse_free(&msg);
11743ff40c12SJohn Marino 		return;
11753ff40c12SJohn Marino 	}
11763ff40c12SJohn Marino 
11773ff40c12SJohn Marino 	if (!msg.status) {
11783ff40c12SJohn Marino 		p2p_dbg(p2p, "No Status attribute received");
11793ff40c12SJohn Marino 		status = P2P_SC_FAIL_INVALID_PARAMS;
11803ff40c12SJohn Marino 		goto fail;
11813ff40c12SJohn Marino 	}
11823ff40c12SJohn Marino 	if (*msg.status) {
11833ff40c12SJohn Marino 		p2p_dbg(p2p, "GO Negotiation rejected: status %d", *msg.status);
11843ff40c12SJohn Marino 		dev->go_neg_req_sent = 0;
11853ff40c12SJohn Marino 		if (*msg.status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) {
11863ff40c12SJohn Marino 			p2p_dbg(p2p, "Wait for the peer to become ready for GO Negotiation");
11873ff40c12SJohn Marino 			dev->flags |= P2P_DEV_NOT_YET_READY;
1188*a1157835SDaniel Fojt 			eloop_cancel_timeout(p2p_go_neg_wait_timeout, p2p,
1189*a1157835SDaniel Fojt 					     NULL);
1190*a1157835SDaniel Fojt 			eloop_register_timeout(120, 0, p2p_go_neg_wait_timeout,
1191*a1157835SDaniel Fojt 					       p2p, NULL);
1192*a1157835SDaniel Fojt 			if (p2p->state == P2P_CONNECT_LISTEN)
1193*a1157835SDaniel Fojt 				p2p_set_state(p2p, P2P_WAIT_PEER_CONNECT);
1194*a1157835SDaniel Fojt 			else
11953ff40c12SJohn Marino 				p2p_set_state(p2p, P2P_WAIT_PEER_IDLE);
11963ff40c12SJohn Marino 			p2p_set_timeout(p2p, 0, 0);
11973ff40c12SJohn Marino 		} else {
11983ff40c12SJohn Marino 			p2p_dbg(p2p, "Stop GO Negotiation attempt");
1199*a1157835SDaniel Fojt 			p2p_go_neg_failed(p2p, *msg.status);
12003ff40c12SJohn Marino 		}
12013ff40c12SJohn Marino 		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
12023ff40c12SJohn Marino 		p2p_parse_free(&msg);
12033ff40c12SJohn Marino 		return;
12043ff40c12SJohn Marino 	}
12053ff40c12SJohn Marino 
12063ff40c12SJohn Marino 	if (!msg.capability) {
12073ff40c12SJohn Marino 		p2p_dbg(p2p, "Mandatory Capability attribute missing from GO Negotiation Response");
12083ff40c12SJohn Marino #ifdef CONFIG_P2P_STRICT
12093ff40c12SJohn Marino 		status = P2P_SC_FAIL_INVALID_PARAMS;
12103ff40c12SJohn Marino 		goto fail;
12113ff40c12SJohn Marino #endif /* CONFIG_P2P_STRICT */
12123ff40c12SJohn Marino 	}
12133ff40c12SJohn Marino 
12143ff40c12SJohn Marino 	if (!msg.p2p_device_info) {
12153ff40c12SJohn Marino 		p2p_dbg(p2p, "Mandatory P2P Device Info attribute missing from GO Negotiation Response");
12163ff40c12SJohn Marino #ifdef CONFIG_P2P_STRICT
12173ff40c12SJohn Marino 		status = P2P_SC_FAIL_INVALID_PARAMS;
12183ff40c12SJohn Marino 		goto fail;
12193ff40c12SJohn Marino #endif /* CONFIG_P2P_STRICT */
12203ff40c12SJohn Marino 	}
12213ff40c12SJohn Marino 
12223ff40c12SJohn Marino 	if (!msg.intended_addr) {
12233ff40c12SJohn Marino 		p2p_dbg(p2p, "No Intended P2P Interface Address attribute received");
12243ff40c12SJohn Marino 		status = P2P_SC_FAIL_INVALID_PARAMS;
12253ff40c12SJohn Marino 		goto fail;
12263ff40c12SJohn Marino 	}
12273ff40c12SJohn Marino 
12283ff40c12SJohn Marino 	if (!msg.go_intent) {
12293ff40c12SJohn Marino 		p2p_dbg(p2p, "No GO Intent attribute received");
12303ff40c12SJohn Marino 		status = P2P_SC_FAIL_INVALID_PARAMS;
12313ff40c12SJohn Marino 		goto fail;
12323ff40c12SJohn Marino 	}
12333ff40c12SJohn Marino 	if ((*msg.go_intent >> 1) > P2P_MAX_GO_INTENT) {
12343ff40c12SJohn Marino 		p2p_dbg(p2p, "Invalid GO Intent value (%u) received",
12353ff40c12SJohn Marino 			*msg.go_intent >> 1);
12363ff40c12SJohn Marino 		status = P2P_SC_FAIL_INVALID_PARAMS;
12373ff40c12SJohn Marino 		goto fail;
12383ff40c12SJohn Marino 	}
12393ff40c12SJohn Marino 
12403ff40c12SJohn Marino 	go = p2p_go_det(p2p->go_intent, *msg.go_intent);
12413ff40c12SJohn Marino 	if (go < 0) {
12423ff40c12SJohn Marino 		p2p_dbg(p2p, "Incompatible GO Intent");
12433ff40c12SJohn Marino 		status = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
12443ff40c12SJohn Marino 		goto fail;
12453ff40c12SJohn Marino 	}
12463ff40c12SJohn Marino 
12473ff40c12SJohn Marino 	if (!go && msg.group_id) {
12483ff40c12SJohn Marino 		/* Store SSID for Provisioning step */
12493ff40c12SJohn Marino 		p2p->ssid_len = msg.group_id_len - ETH_ALEN;
12503ff40c12SJohn Marino 		os_memcpy(p2p->ssid, msg.group_id + ETH_ALEN, p2p->ssid_len);
12513ff40c12SJohn Marino 	} else if (!go) {
12523ff40c12SJohn Marino 		p2p_dbg(p2p, "Mandatory P2P Group ID attribute missing from GO Negotiation Response");
12533ff40c12SJohn Marino 		p2p->ssid_len = 0;
12543ff40c12SJohn Marino 		status = P2P_SC_FAIL_INVALID_PARAMS;
12553ff40c12SJohn Marino 		goto fail;
12563ff40c12SJohn Marino 	}
12573ff40c12SJohn Marino 
12583ff40c12SJohn Marino 	if (!msg.config_timeout) {
12593ff40c12SJohn Marino 		p2p_dbg(p2p, "Mandatory Configuration Timeout attribute missing from GO Negotiation Response");
12603ff40c12SJohn Marino #ifdef CONFIG_P2P_STRICT
12613ff40c12SJohn Marino 		status = P2P_SC_FAIL_INVALID_PARAMS;
12623ff40c12SJohn Marino 		goto fail;
12633ff40c12SJohn Marino #endif /* CONFIG_P2P_STRICT */
12643ff40c12SJohn Marino 	} else {
12653ff40c12SJohn Marino 		dev->go_timeout = msg.config_timeout[0];
12663ff40c12SJohn Marino 		dev->client_timeout = msg.config_timeout[1];
12673ff40c12SJohn Marino 	}
12683ff40c12SJohn Marino 
1269*a1157835SDaniel Fojt 	if (msg.wfd_subelems) {
1270*a1157835SDaniel Fojt 		wpabuf_free(dev->info.wfd_subelems);
1271*a1157835SDaniel Fojt 		dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
1272*a1157835SDaniel Fojt 	}
1273*a1157835SDaniel Fojt 
12743ff40c12SJohn Marino 	if (!msg.operating_channel && !go) {
12753ff40c12SJohn Marino 		/*
12763ff40c12SJohn Marino 		 * Note: P2P Client may omit Operating Channel attribute to
12773ff40c12SJohn Marino 		 * indicate it does not have a preference.
12783ff40c12SJohn Marino 		 */
12793ff40c12SJohn Marino 		p2p_dbg(p2p, "No Operating Channel attribute received");
12803ff40c12SJohn Marino 		status = P2P_SC_FAIL_INVALID_PARAMS;
12813ff40c12SJohn Marino 		goto fail;
12823ff40c12SJohn Marino 	}
12833ff40c12SJohn Marino 	if (!msg.channel_list) {
12843ff40c12SJohn Marino 		p2p_dbg(p2p, "No Channel List attribute received");
12853ff40c12SJohn Marino 		status = P2P_SC_FAIL_INVALID_PARAMS;
12863ff40c12SJohn Marino 		goto fail;
12873ff40c12SJohn Marino 	}
12883ff40c12SJohn Marino 
12893ff40c12SJohn Marino 	if (p2p_peer_channels(p2p, dev, msg.channel_list,
12903ff40c12SJohn Marino 			      msg.channel_list_len) < 0) {
12913ff40c12SJohn Marino 		p2p_dbg(p2p, "No common channels found");
12923ff40c12SJohn Marino 		status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
12933ff40c12SJohn Marino 		goto fail;
12943ff40c12SJohn Marino 	}
12953ff40c12SJohn Marino 
12963ff40c12SJohn Marino 	if (msg.operating_channel) {
12973ff40c12SJohn Marino 		dev->oper_freq = p2p_channel_to_freq(msg.operating_channel[3],
12983ff40c12SJohn Marino 						     msg.operating_channel[4]);
12993ff40c12SJohn Marino 		p2p_dbg(p2p, "Peer operating channel preference: %d MHz",
13003ff40c12SJohn Marino 			dev->oper_freq);
13013ff40c12SJohn Marino 	} else
13023ff40c12SJohn Marino 		dev->oper_freq = 0;
13033ff40c12SJohn Marino 
13043ff40c12SJohn Marino 	switch (msg.dev_password_id) {
13053ff40c12SJohn Marino 	case DEV_PW_REGISTRAR_SPECIFIED:
13063ff40c12SJohn Marino 		p2p_dbg(p2p, "PIN from peer Display");
13073ff40c12SJohn Marino 		if (dev->wps_method != WPS_PIN_KEYPAD) {
13083ff40c12SJohn Marino 			p2p_dbg(p2p, "We have wps_method=%s -> incompatible",
13093ff40c12SJohn Marino 				p2p_wps_method_str(dev->wps_method));
13103ff40c12SJohn Marino 			status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
13113ff40c12SJohn Marino 			goto fail;
13123ff40c12SJohn Marino 		}
13133ff40c12SJohn Marino 		break;
13143ff40c12SJohn Marino 	case DEV_PW_USER_SPECIFIED:
13153ff40c12SJohn Marino 		p2p_dbg(p2p, "Peer entered PIN on Keypad");
13163ff40c12SJohn Marino 		if (dev->wps_method != WPS_PIN_DISPLAY) {
13173ff40c12SJohn Marino 			p2p_dbg(p2p, "We have wps_method=%s -> incompatible",
13183ff40c12SJohn Marino 				p2p_wps_method_str(dev->wps_method));
13193ff40c12SJohn Marino 			status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
13203ff40c12SJohn Marino 			goto fail;
13213ff40c12SJohn Marino 		}
13223ff40c12SJohn Marino 		break;
13233ff40c12SJohn Marino 	case DEV_PW_PUSHBUTTON:
13243ff40c12SJohn Marino 		p2p_dbg(p2p, "Peer using pushbutton");
13253ff40c12SJohn Marino 		if (dev->wps_method != WPS_PBC) {
13263ff40c12SJohn Marino 			p2p_dbg(p2p, "We have wps_method=%s -> incompatible",
13273ff40c12SJohn Marino 				p2p_wps_method_str(dev->wps_method));
13283ff40c12SJohn Marino 			status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
13293ff40c12SJohn Marino 			goto fail;
13303ff40c12SJohn Marino 		}
13313ff40c12SJohn Marino 		break;
1332*a1157835SDaniel Fojt 	case DEV_PW_P2PS_DEFAULT:
1333*a1157835SDaniel Fojt 		p2p_dbg(p2p, "P2P: Peer using P2PS default pin");
1334*a1157835SDaniel Fojt 		if (dev->wps_method != WPS_P2PS) {
1335*a1157835SDaniel Fojt 			p2p_dbg(p2p, "We have wps_method=%s -> incompatible",
1336*a1157835SDaniel Fojt 				p2p_wps_method_str(dev->wps_method));
1337*a1157835SDaniel Fojt 			status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
1338*a1157835SDaniel Fojt 			goto fail;
1339*a1157835SDaniel Fojt 		}
1340*a1157835SDaniel Fojt 		break;
13413ff40c12SJohn Marino 	default:
13423ff40c12SJohn Marino 		if (msg.dev_password_id &&
13433ff40c12SJohn Marino 		    msg.dev_password_id == dev->oob_pw_id) {
13443ff40c12SJohn Marino 			p2p_dbg(p2p, "Peer using NFC");
13453ff40c12SJohn Marino 			if (dev->wps_method != WPS_NFC) {
13463ff40c12SJohn Marino 				p2p_dbg(p2p, "We have wps_method=%s -> incompatible",
13473ff40c12SJohn Marino 					p2p_wps_method_str(dev->wps_method));
13483ff40c12SJohn Marino 				status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
13493ff40c12SJohn Marino 				goto fail;
13503ff40c12SJohn Marino 			}
13513ff40c12SJohn Marino 			break;
13523ff40c12SJohn Marino 		}
13533ff40c12SJohn Marino 		p2p_dbg(p2p, "Unsupported Device Password ID %d",
13543ff40c12SJohn Marino 			msg.dev_password_id);
13553ff40c12SJohn Marino 		status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
13563ff40c12SJohn Marino 		goto fail;
13573ff40c12SJohn Marino 	}
13583ff40c12SJohn Marino 
13593ff40c12SJohn Marino 	if (go && p2p_go_select_channel(p2p, dev, &status) < 0)
13603ff40c12SJohn Marino 		goto fail;
13613ff40c12SJohn Marino 
1362*a1157835SDaniel Fojt 	/*
1363*a1157835SDaniel Fojt 	 * Use the driver preferred frequency list extension if local device is
1364*a1157835SDaniel Fojt 	 * GO.
1365*a1157835SDaniel Fojt 	 */
1366*a1157835SDaniel Fojt 	if (go)
1367*a1157835SDaniel Fojt 		p2p_check_pref_chan(p2p, go, dev, &msg);
1368*a1157835SDaniel Fojt 
13693ff40c12SJohn Marino 	p2p_set_state(p2p, P2P_GO_NEG);
13703ff40c12SJohn Marino 	p2p_clear_timeout(p2p);
13713ff40c12SJohn Marino 
13723ff40c12SJohn Marino 	p2p_dbg(p2p, "GO Negotiation with " MACSTR, MAC2STR(sa));
13733ff40c12SJohn Marino 	os_memcpy(dev->intended_addr, msg.intended_addr, ETH_ALEN);
13743ff40c12SJohn Marino 
13753ff40c12SJohn Marino fail:
1376*a1157835SDaniel Fojt 	/* Store GO Negotiation Confirmation to allow retransmission */
1377*a1157835SDaniel Fojt 	wpabuf_free(dev->go_neg_conf);
1378*a1157835SDaniel Fojt 	dev->go_neg_conf = p2p_build_go_neg_conf(p2p, dev, msg.dialog_token,
1379*a1157835SDaniel Fojt 						 status, msg.operating_channel,
1380*a1157835SDaniel Fojt 						 go);
13813ff40c12SJohn Marino 	p2p_parse_free(&msg);
1382*a1157835SDaniel Fojt 	if (dev->go_neg_conf == NULL)
13833ff40c12SJohn Marino 		return;
13843ff40c12SJohn Marino 	p2p_dbg(p2p, "Sending GO Negotiation Confirm");
13853ff40c12SJohn Marino 	if (status == P2P_SC_SUCCESS) {
13863ff40c12SJohn Marino 		p2p->pending_action_state = P2P_PENDING_GO_NEG_CONFIRM;
13873ff40c12SJohn Marino 		dev->go_state = go ? LOCAL_GO : REMOTE_GO;
13883ff40c12SJohn Marino 	} else
13893ff40c12SJohn Marino 		p2p->pending_action_state = P2P_NO_PENDING_ACTION;
13903ff40c12SJohn Marino 	if (rx_freq > 0)
13913ff40c12SJohn Marino 		freq = rx_freq;
13923ff40c12SJohn Marino 	else
13933ff40c12SJohn Marino 		freq = dev->listen_freq;
1394*a1157835SDaniel Fojt 
1395*a1157835SDaniel Fojt 	dev->go_neg_conf_freq = freq;
1396*a1157835SDaniel Fojt 	dev->go_neg_conf_sent = 0;
1397*a1157835SDaniel Fojt 
13983ff40c12SJohn Marino 	if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, sa,
1399*a1157835SDaniel Fojt 			    wpabuf_head(dev->go_neg_conf),
1400*a1157835SDaniel Fojt 			    wpabuf_len(dev->go_neg_conf), 50) < 0) {
14013ff40c12SJohn Marino 		p2p_dbg(p2p, "Failed to send Action frame");
1402*a1157835SDaniel Fojt 		p2p_go_neg_failed(p2p, -1);
14033ff40c12SJohn Marino 		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
1404*a1157835SDaniel Fojt 	} else
1405*a1157835SDaniel Fojt 		dev->go_neg_conf_sent++;
14063ff40c12SJohn Marino 	if (status != P2P_SC_SUCCESS) {
14073ff40c12SJohn Marino 		p2p_dbg(p2p, "GO Negotiation failed");
1408*a1157835SDaniel Fojt 		p2p_go_neg_failed(p2p, status);
14093ff40c12SJohn Marino 	}
14103ff40c12SJohn Marino }
14113ff40c12SJohn Marino 
14123ff40c12SJohn Marino 
p2p_process_go_neg_conf(struct p2p_data * p2p,const u8 * sa,const u8 * data,size_t len)14133ff40c12SJohn Marino void p2p_process_go_neg_conf(struct p2p_data *p2p, const u8 *sa,
14143ff40c12SJohn Marino 			     const u8 *data, size_t len)
14153ff40c12SJohn Marino {
14163ff40c12SJohn Marino 	struct p2p_device *dev;
14173ff40c12SJohn Marino 	struct p2p_message msg;
14183ff40c12SJohn Marino 
14193ff40c12SJohn Marino 	p2p_dbg(p2p, "Received GO Negotiation Confirm from " MACSTR,
14203ff40c12SJohn Marino 		MAC2STR(sa));
14213ff40c12SJohn Marino 	dev = p2p_get_device(p2p, sa);
14223ff40c12SJohn Marino 	if (dev == NULL || dev->wps_method == WPS_NOT_READY ||
14233ff40c12SJohn Marino 	    dev != p2p->go_neg_peer) {
14243ff40c12SJohn Marino 		p2p_dbg(p2p, "Not ready for GO negotiation with " MACSTR,
14253ff40c12SJohn Marino 			MAC2STR(sa));
14263ff40c12SJohn Marino 		return;
14273ff40c12SJohn Marino 	}
14283ff40c12SJohn Marino 
14293ff40c12SJohn Marino 	if (p2p->pending_action_state == P2P_PENDING_GO_NEG_RESPONSE) {
14303ff40c12SJohn Marino 		p2p_dbg(p2p, "Stopped waiting for TX status on GO Negotiation Response since we already received Confirmation");
14313ff40c12SJohn Marino 		p2p->pending_action_state = P2P_NO_PENDING_ACTION;
14323ff40c12SJohn Marino 	}
14333ff40c12SJohn Marino 
14343ff40c12SJohn Marino 	if (p2p_parse(data, len, &msg))
14353ff40c12SJohn Marino 		return;
14363ff40c12SJohn Marino 
14373ff40c12SJohn Marino 	if (!(dev->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM)) {
14383ff40c12SJohn Marino 		p2p_dbg(p2p, "Was not expecting GO Negotiation Confirm - ignore");
14393ff40c12SJohn Marino 		p2p_parse_free(&msg);
14403ff40c12SJohn Marino 		return;
14413ff40c12SJohn Marino 	}
14423ff40c12SJohn Marino 	dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM;
14433ff40c12SJohn Marino 	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
14443ff40c12SJohn Marino 
14453ff40c12SJohn Marino 	if (msg.dialog_token != dev->dialog_token) {
14463ff40c12SJohn Marino 		p2p_dbg(p2p, "Unexpected Dialog Token %u (expected %u)",
14473ff40c12SJohn Marino 			msg.dialog_token, dev->dialog_token);
14483ff40c12SJohn Marino 		p2p_parse_free(&msg);
14493ff40c12SJohn Marino 		return;
14503ff40c12SJohn Marino 	}
14513ff40c12SJohn Marino 
14523ff40c12SJohn Marino 	if (!msg.status) {
14533ff40c12SJohn Marino 		p2p_dbg(p2p, "No Status attribute received");
14543ff40c12SJohn Marino 		p2p_parse_free(&msg);
14553ff40c12SJohn Marino 		return;
14563ff40c12SJohn Marino 	}
14573ff40c12SJohn Marino 	if (*msg.status) {
14583ff40c12SJohn Marino 		p2p_dbg(p2p, "GO Negotiation rejected: status %d", *msg.status);
1459*a1157835SDaniel Fojt 		p2p_go_neg_failed(p2p, *msg.status);
14603ff40c12SJohn Marino 		p2p_parse_free(&msg);
14613ff40c12SJohn Marino 		return;
14623ff40c12SJohn Marino 	}
14633ff40c12SJohn Marino 
14643ff40c12SJohn Marino 	if (dev->go_state == REMOTE_GO && msg.group_id) {
14653ff40c12SJohn Marino 		/* Store SSID for Provisioning step */
14663ff40c12SJohn Marino 		p2p->ssid_len = msg.group_id_len - ETH_ALEN;
14673ff40c12SJohn Marino 		os_memcpy(p2p->ssid, msg.group_id + ETH_ALEN, p2p->ssid_len);
14683ff40c12SJohn Marino 	} else if (dev->go_state == REMOTE_GO) {
14693ff40c12SJohn Marino 		p2p_dbg(p2p, "Mandatory P2P Group ID attribute missing from GO Negotiation Confirmation");
14703ff40c12SJohn Marino 		p2p->ssid_len = 0;
1471*a1157835SDaniel Fojt 		p2p_go_neg_failed(p2p, P2P_SC_FAIL_INVALID_PARAMS);
14723ff40c12SJohn Marino 		p2p_parse_free(&msg);
14733ff40c12SJohn Marino 		return;
14743ff40c12SJohn Marino 	}
14753ff40c12SJohn Marino 
14763ff40c12SJohn Marino 	if (!msg.operating_channel) {
14773ff40c12SJohn Marino 		p2p_dbg(p2p, "Mandatory Operating Channel attribute missing from GO Negotiation Confirmation");
14783ff40c12SJohn Marino #ifdef CONFIG_P2P_STRICT
14793ff40c12SJohn Marino 		p2p_parse_free(&msg);
14803ff40c12SJohn Marino 		return;
14813ff40c12SJohn Marino #endif /* CONFIG_P2P_STRICT */
14823ff40c12SJohn Marino 	} else if (dev->go_state == REMOTE_GO) {
14833ff40c12SJohn Marino 		int oper_freq = p2p_channel_to_freq(msg.operating_channel[3],
14843ff40c12SJohn Marino 						    msg.operating_channel[4]);
14853ff40c12SJohn Marino 		if (oper_freq != dev->oper_freq) {
14863ff40c12SJohn Marino 			p2p_dbg(p2p, "Updated peer (GO) operating channel preference from %d MHz to %d MHz",
14873ff40c12SJohn Marino 				dev->oper_freq, oper_freq);
14883ff40c12SJohn Marino 			dev->oper_freq = oper_freq;
14893ff40c12SJohn Marino 		}
14903ff40c12SJohn Marino 	}
14913ff40c12SJohn Marino 
14923ff40c12SJohn Marino 	if (!msg.channel_list) {
14933ff40c12SJohn Marino 		p2p_dbg(p2p, "Mandatory Operating Channel attribute missing from GO Negotiation Confirmation");
14943ff40c12SJohn Marino #ifdef CONFIG_P2P_STRICT
14953ff40c12SJohn Marino 		p2p_parse_free(&msg);
14963ff40c12SJohn Marino 		return;
14973ff40c12SJohn Marino #endif /* CONFIG_P2P_STRICT */
14983ff40c12SJohn Marino 	}
14993ff40c12SJohn Marino 
15003ff40c12SJohn Marino 	p2p_parse_free(&msg);
15013ff40c12SJohn Marino 
15023ff40c12SJohn Marino 	if (dev->go_state == UNKNOWN_GO) {
15033ff40c12SJohn Marino 		/*
15043ff40c12SJohn Marino 		 * This should not happen since GO negotiation has already
15053ff40c12SJohn Marino 		 * been completed.
15063ff40c12SJohn Marino 		 */
15073ff40c12SJohn Marino 		p2p_dbg(p2p, "Unexpected GO Neg state - do not know which end becomes GO");
15083ff40c12SJohn Marino 		return;
15093ff40c12SJohn Marino 	}
15103ff40c12SJohn Marino 
15113ff40c12SJohn Marino 	/*
15123ff40c12SJohn Marino 	 * The peer could have missed our ctrl::ack frame for GO Negotiation
15133ff40c12SJohn Marino 	 * Confirm and continue retransmitting the frame. To reduce the
15143ff40c12SJohn Marino 	 * likelihood of the peer not getting successful TX status for the
15153ff40c12SJohn Marino 	 * GO Negotiation Confirm frame, wait a short time here before starting
15163ff40c12SJohn Marino 	 * the group so that we will remain on the current channel to
15173ff40c12SJohn Marino 	 * acknowledge any possible retransmission from the peer.
15183ff40c12SJohn Marino 	 */
15193ff40c12SJohn Marino 	p2p_dbg(p2p, "20 ms wait on current channel before starting group");
15203ff40c12SJohn Marino 	os_sleep(0, 20000);
15213ff40c12SJohn Marino 
15223ff40c12SJohn Marino 	p2p_go_complete(p2p, dev);
15233ff40c12SJohn Marino }
1524