18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Wi-Fi Direct - P2P Device Discoverability procedure 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2010, Atheros Communications 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p_i.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_dev_disc_req(struct p2p_data *p2p, 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_device *go, 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *dev_id) 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *len; 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc(100); 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt go->dialog_token++; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (go->dialog_token == 0) 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt go->dialog_token = 1; 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_buf_add_public_action_hdr(buf, P2P_DEV_DISC_REQ, go->dialog_token); 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = p2p_buf_add_ie_hdr(buf); 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_buf_add_device_id(buf, dev_id); 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_buf_add_group_id(buf, go->info.p2p_device_addr, go->oper_ssid, 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt go->oper_ssid_len); 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_buf_update_ie_hdr(buf, len); 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_dev_disc_req_cb(struct p2p_data *p2p, int success) 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 45b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt p2p_dbg(p2p, "Device Discoverability Request TX callback: success=%d", 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt success); 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!success) { 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Use P2P find, if needed, to find the other device or to 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * retry device discoverability. 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_set_state(p2p, P2P_CONNECT); 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_set_timeout(p2p, 0, 100000); 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt p2p_dbg(p2p, "GO acknowledged Device Discoverability Request - wait for response"); 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO: is the remain-on-channel from Action frame TX long enough for 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * most cases or should we try to increase its duration and/or start 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * another remain-on-channel if needed once the previous one expires? 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_send_dev_disc_req(struct p2p_data *p2p, struct p2p_device *dev) 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_device *go; 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *req; 71623d63a3a443027e50efdaaec027befcc3882527Dmitry Shmidt unsigned int wait_time; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt go = p2p_get_device(p2p, dev->member_in_go_dev); 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (go == NULL || dev->oper_freq <= 0) { 75b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt p2p_dbg(p2p, "Could not find peer entry for GO and frequency to send Device Discoverability Request"); 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = p2p_build_dev_disc_req(p2p, go, dev->info.p2p_device_addr); 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req == NULL) 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 83b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt p2p_dbg(p2p, "Sending Device Discoverability Request to GO " MACSTR 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " for client " MACSTR, 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(go->info.p2p_device_addr), 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(dev->info.p2p_device_addr)); 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->pending_client_disc_go = go; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(p2p->pending_client_disc_addr, dev->info.p2p_device_addr, 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ETH_ALEN); 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->pending_action_state = P2P_PENDING_DEV_DISC_REQUEST; 92623d63a3a443027e50efdaaec027befcc3882527Dmitry Shmidt wait_time = 1000; 93623d63a3a443027e50efdaaec027befcc3882527Dmitry Shmidt if (p2p->cfg->max_listen && wait_time > p2p->cfg->max_listen) 94623d63a3a443027e50efdaaec027befcc3882527Dmitry Shmidt wait_time = p2p->cfg->max_listen; 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p2p_send_action(p2p, dev->oper_freq, go->info.p2p_device_addr, 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->cfg->dev_addr, go->info.p2p_device_addr, 97623d63a3a443027e50efdaaec027befcc3882527Dmitry Shmidt wpabuf_head(req), wpabuf_len(req), wait_time) < 0) { 98b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt p2p_dbg(p2p, "Failed to send Action frame"); 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(req); 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: how to recover from failure? */ 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(req); 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_dev_disc_resp(u8 dialog_token, u8 status) 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *len; 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc(100); 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_buf_add_public_action_hdr(buf, P2P_DEV_DISC_RESP, dialog_token); 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = p2p_buf_add_ie_hdr(buf); 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_buf_add_status(buf, status); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_buf_update_ie_hdr(buf, len); 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_dev_disc_resp_cb(struct p2p_data *p2p, int success) 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 131b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt p2p_dbg(p2p, "Device Discoverability Response TX callback: success=%d", 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt success); 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->cfg->send_action_done(p2p->cfg->cb_ctx); 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_send_dev_disc_resp(struct p2p_data *p2p, u8 dialog_token, 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, int freq, u8 status) 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = p2p_build_dev_disc_resp(dialog_token, status); 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 146b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt p2p_dbg(p2p, "Sending Device Discoverability Response to " MACSTR 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " (status %u freq %d)", 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(addr), status, freq); 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->pending_action_state = P2P_PENDING_DEV_DISC_RESPONSE; 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p2p_send_action(p2p, freq, addr, p2p->cfg->dev_addr, 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->cfg->dev_addr, 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(resp), wpabuf_len(resp), 200) < 0) { 154b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt p2p_dbg(p2p, "Failed to send Action frame"); 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(resp); 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_process_dev_disc_req(struct p2p_data *p2p, const u8 *sa, 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *data, size_t len, int rx_freq) 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_message msg; 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t g; 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 167b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt p2p_dbg(p2p, "Received Device Discoverability Request from " MACSTR 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " (freq=%d)", MAC2STR(sa), rx_freq); 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p2p_parse(data, len, &msg)) 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg.dialog_token == 0) { 174b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt p2p_dbg(p2p, "Invalid Dialog Token 0 (must be nonzero) in Device Discoverability Request"); 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_send_dev_disc_resp(p2p, msg.dialog_token, sa, rx_freq, 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt P2P_SC_FAIL_INVALID_PARAMS); 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_parse_free(&msg); 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg.device_id == NULL) { 182b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt p2p_dbg(p2p, "P2P Device ID attribute missing from Device Discoverability Request"); 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_send_dev_disc_resp(p2p, msg.dialog_token, sa, rx_freq, 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt P2P_SC_FAIL_INVALID_PARAMS); 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_parse_free(&msg); 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (g = 0; g < p2p->num_groups; g++) { 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p2p_group_go_discover(p2p->groups[g], msg.device_id, sa, 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rx_freq) == 0) { 192b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt p2p_dbg(p2p, "Scheduled GO Discoverability Request for the target device"); 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * P2P group code will use a callback to indicate TX 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * status, so that we can reply to the request once the 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * target client has acknowledged the request or it has 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * timed out. 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->pending_dev_disc_dialog_token = msg.dialog_token; 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(p2p->pending_dev_disc_addr, sa, ETH_ALEN); 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->pending_dev_disc_freq = rx_freq; 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_parse_free(&msg); 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 207b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt p2p_dbg(p2p, "Requested client was not found in any group or did not support client discoverability"); 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_send_dev_disc_resp(p2p, msg.dialog_token, sa, rx_freq, 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE); 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_parse_free(&msg); 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_process_dev_disc_resp(struct p2p_data *p2p, const u8 *sa, 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *data, size_t len) 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_message msg; 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_device *go; 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 status; 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 221b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt p2p_dbg(p2p, "Received Device Discoverability Response from " MACSTR, 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(sa)); 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt go = p2p->pending_client_disc_go; 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (go == NULL || 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(sa, go->info.p2p_device_addr, ETH_ALEN) != 0) { 227b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt p2p_dbg(p2p, "Ignore unexpected Device Discoverability Response"); 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p2p_parse(data, len, &msg)) 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg.status == NULL) { 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_parse_free(&msg); 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg.dialog_token != go->dialog_token) { 240b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt p2p_dbg(p2p, "Ignore Device Discoverability Response with unexpected dialog token %u (expected %u)", 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg.dialog_token, go->dialog_token); 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_parse_free(&msg); 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = *msg.status; 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_parse_free(&msg); 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 249b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt p2p_dbg(p2p, "Device Discoverability Response status %u", status); 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p2p->go_neg_peer == NULL || 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(p2p->pending_client_disc_addr, 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->go_neg_peer->info.p2p_device_addr, ETH_ALEN) != 0 || 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(p2p->go_neg_peer->member_in_go_dev, 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt go->info.p2p_device_addr, ETH_ALEN) != 0) { 256b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt p2p_dbg(p2p, "No pending operation with the client discoverability peer anymore"); 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (status == 0) { 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Peer is expected to be awake for at least 100 TU; try to 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * connect immediately. 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 265b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt p2p_dbg(p2p, "Client discoverability request succeeded"); 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p2p->state == P2P_CONNECT) { 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Change state to force the timeout to start in 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * P2P_CONNECT again without going through the short 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Listen state. 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_set_state(p2p, P2P_CONNECT_LISTEN); 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->cfg->send_action_done(p2p->cfg->cb_ctx); 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_set_timeout(p2p, 0, 0); 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Client discoverability request failed; try to connect from 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * timeout. 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 281b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt p2p_dbg(p2p, "Client discoverability request failed"); 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_set_timeout(p2p, 0, 500000); 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_go_disc_req_cb(struct p2p_data *p2p, int success) 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 290b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt p2p_dbg(p2p, "GO Discoverability Request TX callback: success=%d", 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt success); 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->cfg->send_action_done(p2p->cfg->cb_ctx); 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p2p->pending_dev_disc_dialog_token == 0) { 295b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt p2p_dbg(p2p, "No pending Device Discoverability Request"); 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_send_dev_disc_resp(p2p, p2p->pending_dev_disc_dialog_token, 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->pending_dev_disc_addr, 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->pending_dev_disc_freq, 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt success ? P2P_SC_SUCCESS : 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE); 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->pending_dev_disc_dialog_token = 0; 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_process_go_disc_req(struct p2p_data *p2p, const u8 *da, const u8 *sa, 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *data, size_t len, int rx_freq) 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int tu; 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *ies; 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 315b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt p2p_dbg(p2p, "Received GO Discoverability Request - remain awake for 100 TU"); 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ies = p2p_build_probe_resp_ies(p2p); 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ies == NULL) 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Remain awake 100 TU on operating channel */ 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->pending_client_disc_freq = rx_freq; 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tu = 100; 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p2p->cfg->start_listen(p2p->cfg->cb_ctx, rx_freq, 1024 * tu / 1000, 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ies) < 0) { 326b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt p2p_dbg(p2p, "Failed to start listen mode for client discoverability"); 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(ies); 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 330