18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Wi-Fi Direct - P2P provision discovery 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2009-2010, Atheros Communications 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This program is free software; you can redistribute it and/or modify 68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * published by the Free Software Foundation. 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * license. 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See README and COPYING for more details. 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps/wps_defs.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p_i.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen/* 2575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen * Number of retries to attempt for provision discovery requests during IDLE 2675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen * state in case the peer is not listening. 2775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen */ 2875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen#define MAX_PROV_DISC_REQ_RETRIES 10 2975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 3075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_build_wps_ie_config_methods(struct wpabuf *buf, 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 config_methods) 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *len; 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = wpabuf_put(buf, 1); 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be32(buf, WPS_DEV_OUI_WFA); 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Config Methods */ 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(buf, ATTR_CONFIG_METHODS); 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(buf, 2); 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(buf, config_methods); 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_buf_update_ie_hdr(buf, len); 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_prov_disc_req(struct p2p_data *p2p, 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dialog_token, 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 config_methods, 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_device *go) 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *len; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc(1000); 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_buf_add_public_action_hdr(buf, P2P_PROV_DISC_REQ, dialog_token); 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = p2p_buf_add_ie_hdr(buf); 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_buf_add_capability(buf, p2p->dev_capab, 0); 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_buf_add_device_info(buf, p2p, NULL); 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (go) { 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_buf_add_group_id(buf, go->info.p2p_device_addr, 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt go->oper_ssid, go->oper_ssid_len); 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_buf_update_ie_hdr(buf, len); 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* WPS IE with Config Methods attribute */ 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_build_wps_ie_config_methods(buf, config_methods); 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_prov_disc_resp(struct p2p_data *p2p, 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dialog_token, 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 config_methods) 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc(100); 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_buf_add_public_action_hdr(buf, P2P_PROV_DISC_RESP, dialog_token); 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* WPS IE with Config Methods attribute */ 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_build_wps_ie_config_methods(buf, config_methods); 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa, 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *data, size_t len, int rx_freq) 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_message msg; 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_device *dev; 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int freq; 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int reject = 1; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p2p_parse(data, len, &msg)) 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "P2P: Received Provision Discovery Request from " MACSTR 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " with config methods 0x%x (freq=%d)", 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(sa), msg.wps_config_methods, rx_freq); 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev = p2p_get_device(p2p, sa); 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dev == NULL || !(dev->flags & P2P_DEV_PROBE_REQ_ONLY)) { 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "P2P: Provision Discovery Request from " 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unknown peer " MACSTR, MAC2STR(sa)); 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p2p_add_device(p2p, sa, rx_freq, 0, data + 1, len - 1)) { 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "P2P: Provision Discovery Request add device " 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "failed " MACSTR, MAC2STR(sa)); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(msg.wps_config_methods & 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD | 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPS_CONFIG_PUSHBUTTON))) { 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Unsupported " 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Config Methods in Provision Discovery Request"); 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dev) 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY | 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt P2P_DEV_PD_PEER_KEYPAD); 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg.wps_config_methods & WPS_CONFIG_DISPLAY) { 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " requested us to show a PIN on display", MAC2STR(sa)); 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dev) 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev->flags |= P2P_DEV_PD_PEER_KEYPAD; 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) { 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " requested us to write its PIN using keypad", 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(sa)); 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dev) 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev->flags |= P2P_DEV_PD_PEER_DISPLAY; 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reject = 0; 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtout: 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = p2p_build_prov_disc_resp(p2p, msg.dialog_token, 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reject ? 0 : msg.wps_config_methods); 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) { 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_parse_free(&msg); 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "P2P: Sending Provision Discovery Response"); 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rx_freq > 0) 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt freq = rx_freq; 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt freq = p2p_channel_to_freq(p2p->cfg->country, 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->cfg->reg_class, 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->cfg->channel); 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (freq < 0) { 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "P2P: Unknown regulatory class/channel"); 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(resp); 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_parse_free(&msg); 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->pending_action_state = P2P_NO_PENDING_ACTION; 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->cfg->dev_addr, 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(resp), wpabuf_len(resp), 200) < 0) { 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "P2P: Failed to send Action frame"); 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(resp); 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!reject && p2p->cfg->prov_disc_req) { 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *dev_addr = sa; 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg.p2p_device_addr) 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev_addr = msg.p2p_device_addr; 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->cfg->prov_disc_req(p2p->cfg->cb_ctx, sa, 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg.wps_config_methods, 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev_addr, msg.pri_dev_type, 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg.device_name, msg.config_methods, 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg.capability ? msg.capability[0] : 0, 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg.capability ? msg.capability[1] : 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0); 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_parse_free(&msg); 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa, 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *data, size_t len) 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_message msg; 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_device *dev; 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 report_config_methods = 0; 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p2p_parse(data, len, &msg)) 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "P2P: Received Provisioning Discovery Response from " MACSTR 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " with config methods 0x%x", 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(sa), msg.wps_config_methods); 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev = p2p_get_device(p2p, sa); 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dev == NULL || !dev->req_config_methods) { 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "P2P: Ignore Provisioning Discovery Response from " 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " with no pending request", MAC2STR(sa)); 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_parse_free(&msg); 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (p2p->pending_action_state == P2P_PENDING_PD) { 22675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen os_memset(p2p->pending_pd_devaddr, 0, ETH_ALEN); 22775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen p2p->pending_action_state = P2P_NO_PENDING_ACTION; 22875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen } 22975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dev->dialog_token != msg.dialog_token) { 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "P2P: Ignore Provisioning Discovery Response with " 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unexpected Dialog Token %u (expected %u)", 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg.dialog_token, dev->dialog_token); 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_parse_free(&msg); 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen /* 24075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen * If the response is from the peer to whom a user initiated request 24175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen * was sent earlier, we reset that state info here. 24275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen */ 24375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (p2p->user_initiated_pd && 24475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen os_memcmp(p2p->pending_pd_devaddr, sa, ETH_ALEN) == 0) 24575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen p2p_reset_pending_pd(p2p); 24675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg.wps_config_methods != dev->req_config_methods) { 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer rejected " 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "our Provisioning Discovery Request"); 25075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (p2p->cfg->prov_disc_fail) 25175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx, sa, 25275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen P2P_PROV_DISC_REJECTED); 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_parse_free(&msg); 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt report_config_methods = dev->req_config_methods; 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY | 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt P2P_DEV_PD_PEER_KEYPAD); 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dev->req_config_methods & WPS_CONFIG_DISPLAY) { 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " accepted to show a PIN on display", MAC2STR(sa)); 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev->flags |= P2P_DEV_PD_PEER_DISPLAY; 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) { 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " accepted to write our PIN using keypad", 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(sa)); 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev->flags |= P2P_DEV_PD_PEER_KEYPAD; 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_parse_free(&msg); 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtout: 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev->req_config_methods = 0; 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->cfg->send_action_done(p2p->cfg->cb_ctx); 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p2p->cfg->prov_disc_resp) 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->cfg->prov_disc_resp(p2p->cfg->cb_ctx, sa, 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt report_config_methods); 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev, 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int join) 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *req; 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int freq; 286497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt#ifdef ANDROID_BRCM_P2P_PATCH 287497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt if(dev->go_state == REMOTE_GO) { 288497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 289497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt "P2P: GO Sending it to oper_freq %d", dev->oper_freq); 290497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt freq= dev->oper_freq; 291497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt } 292497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt else { 293497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 294497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt "P2P: NOT GO oper_freq %d listen_freq %d", dev->oper_freq, dev->listen_freq); 295497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq; 296497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt } 297497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt#else 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq; 299497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt#endif 300497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (freq <= 0) { 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "P2P: No Listen/Operating frequency known for the " 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "peer " MACSTR " to send Provision Discovery Request", 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(dev->info.p2p_device_addr)); 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) { 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(dev->info.dev_capab & 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) { 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "P2P: Cannot use PD with P2P Device " MACSTR 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " that is in a group and is not discoverable", 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(dev->info.p2p_device_addr)); 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: use device discoverability request through GO */ 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev->dialog_token++; 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dev->dialog_token == 0) 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev->dialog_token = 1; 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = p2p_build_prov_disc_req(p2p, dev->dialog_token, 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev->req_config_methods, 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt join ? dev : NULL); 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req == NULL) 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->pending_action_state = P2P_PENDING_PD; 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr, 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->cfg->dev_addr, dev->info.p2p_device_addr, 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(req), wpabuf_len(req), 200) < 0) { 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "P2P: Failed to send Action frame"); 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(req); 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen os_memcpy(p2p->pending_pd_devaddr, dev->info.p2p_device_addr, ETH_ALEN); 34175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(req); 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_prov_disc_req(struct p2p_data *p2p, const u8 *peer_addr, 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 config_methods, int join) 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_device *dev; 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev = p2p_get_device(p2p, peer_addr); 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dev == NULL) 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev = p2p_get_device_interface(p2p, peer_addr); 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) { 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Provision " 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Discovery Request destination " MACSTR 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " not yet known", MAC2STR(peer_addr)); 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Provision Discovery " 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Request with " MACSTR " (config methods 0x%x)", 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peer_addr), config_methods); 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (config_methods == 0) 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev->req_config_methods = config_methods; 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (join) 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev->flags |= P2P_DEV_PD_FOR_JOIN; 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev->flags &= ~P2P_DEV_PD_FOR_JOIN; 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p2p->go_neg_peer || 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (p2p->state != P2P_IDLE && p2p->state != P2P_SEARCH && 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->state != P2P_LISTEN_ONLY)) { 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Busy with other " 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "operations; postpone Provision Discovery Request " 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "with " MACSTR " (config methods 0x%x)", 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peer_addr), config_methods); 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen /* 38575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen * We use the join param as a cue to differentiate between user 38675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen * initiated PD request and one issued during finds (internal). 38775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen */ 38875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen p2p->user_initiated_pd = !join; 38975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 39075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen /* Also set some retries to attempt in case of IDLE state */ 39175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (p2p->user_initiated_pd && p2p->state == P2P_IDLE) 39275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen p2p->pd_retries = MAX_PROV_DISC_REQ_RETRIES; 39375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return p2p_send_prov_disc_req(p2p, dev, join); 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 39675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 39775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 39875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenvoid p2p_reset_pending_pd(struct p2p_data *p2p) 39975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{ 40075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen p2p->user_initiated_pd = 0; 40175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen os_memset(p2p->pending_pd_devaddr, 0, ETH_ALEN); 40275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen p2p->pd_retries = 0; 40375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen} 404