1f05cddf9SRui Paulo /* 2f05cddf9SRui Paulo * Wi-Fi Direct - P2P Group Owner Negotiation 3f05cddf9SRui Paulo * Copyright (c) 2009-2010, Atheros Communications 4f05cddf9SRui Paulo * 5f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license. 6f05cddf9SRui Paulo * See README for more details. 7f05cddf9SRui Paulo */ 8f05cddf9SRui Paulo 9f05cddf9SRui Paulo #include "includes.h" 10f05cddf9SRui Paulo 11f05cddf9SRui Paulo #include "common.h" 125b9c547cSRui Paulo #include "utils/eloop.h" 13f05cddf9SRui Paulo #include "common/ieee802_11_defs.h" 145b9c547cSRui Paulo #include "common/wpa_ctrl.h" 15f05cddf9SRui Paulo #include "wps/wps_defs.h" 16f05cddf9SRui Paulo #include "p2p_i.h" 17f05cddf9SRui Paulo #include "p2p.h" 18f05cddf9SRui Paulo 19f05cddf9SRui Paulo 20f05cddf9SRui Paulo static int p2p_go_det(u8 own_intent, u8 peer_value) 21f05cddf9SRui Paulo { 22f05cddf9SRui Paulo u8 peer_intent = peer_value >> 1; 23f05cddf9SRui Paulo if (own_intent == peer_intent) { 24f05cddf9SRui Paulo if (own_intent == P2P_MAX_GO_INTENT) 25f05cddf9SRui Paulo return -1; /* both devices want to become GO */ 26f05cddf9SRui Paulo 27f05cddf9SRui Paulo /* Use tie breaker bit to determine GO */ 28f05cddf9SRui Paulo return (peer_value & 0x01) ? 0 : 1; 29f05cddf9SRui Paulo } 30f05cddf9SRui Paulo 31f05cddf9SRui Paulo return own_intent > peer_intent; 32f05cddf9SRui Paulo } 33f05cddf9SRui Paulo 34f05cddf9SRui Paulo 35f05cddf9SRui Paulo int p2p_peer_channels_check(struct p2p_data *p2p, struct p2p_channels *own, 36f05cddf9SRui Paulo struct p2p_device *dev, 37f05cddf9SRui Paulo const u8 *channel_list, size_t channel_list_len) 38f05cddf9SRui Paulo { 39f05cddf9SRui Paulo const u8 *pos, *end; 40f05cddf9SRui Paulo struct p2p_channels *ch; 41f05cddf9SRui Paulo size_t channels; 42f05cddf9SRui Paulo struct p2p_channels intersection; 43f05cddf9SRui Paulo 44f05cddf9SRui Paulo ch = &dev->channels; 45f05cddf9SRui Paulo os_memset(ch, 0, sizeof(*ch)); 46f05cddf9SRui Paulo pos = channel_list; 47f05cddf9SRui Paulo end = channel_list + channel_list_len; 48f05cddf9SRui Paulo 49f05cddf9SRui Paulo if (end - pos < 3) 50f05cddf9SRui Paulo return -1; 51f05cddf9SRui Paulo os_memcpy(dev->country, pos, 3); 52f05cddf9SRui Paulo wpa_hexdump_ascii(MSG_DEBUG, "P2P: Peer country", pos, 3); 53f05cddf9SRui Paulo if (pos[2] != 0x04 && os_memcmp(pos, p2p->cfg->country, 2) != 0) { 545b9c547cSRui Paulo p2p_info(p2p, "Mismatching country (ours=%c%c peer's=%c%c)", 55f05cddf9SRui Paulo p2p->cfg->country[0], p2p->cfg->country[1], 56f05cddf9SRui Paulo pos[0], pos[1]); 57f05cddf9SRui Paulo return -1; 58f05cddf9SRui Paulo } 59f05cddf9SRui Paulo pos += 3; 60f05cddf9SRui Paulo 61f05cddf9SRui Paulo while (pos + 2 < end) { 62f05cddf9SRui Paulo struct p2p_reg_class *cl = &ch->reg_class[ch->reg_classes]; 63f05cddf9SRui Paulo cl->reg_class = *pos++; 64f05cddf9SRui Paulo if (pos + 1 + pos[0] > end) { 655b9c547cSRui Paulo p2p_info(p2p, "Invalid peer Channel List"); 66f05cddf9SRui Paulo return -1; 67f05cddf9SRui Paulo } 68f05cddf9SRui Paulo channels = *pos++; 69f05cddf9SRui Paulo cl->channels = channels > P2P_MAX_REG_CLASS_CHANNELS ? 70f05cddf9SRui Paulo P2P_MAX_REG_CLASS_CHANNELS : channels; 71f05cddf9SRui Paulo os_memcpy(cl->channel, pos, cl->channels); 72f05cddf9SRui Paulo pos += channels; 73f05cddf9SRui Paulo ch->reg_classes++; 74f05cddf9SRui Paulo if (ch->reg_classes == P2P_MAX_REG_CLASSES) 75f05cddf9SRui Paulo break; 76f05cddf9SRui Paulo } 77f05cddf9SRui Paulo 78f05cddf9SRui Paulo p2p_channels_intersect(own, &dev->channels, &intersection); 795b9c547cSRui Paulo p2p_dbg(p2p, "Own reg_classes %d peer reg_classes %d intersection reg_classes %d", 80f05cddf9SRui Paulo (int) own->reg_classes, 81f05cddf9SRui Paulo (int) dev->channels.reg_classes, 82f05cddf9SRui Paulo (int) intersection.reg_classes); 83f05cddf9SRui Paulo if (intersection.reg_classes == 0) { 845b9c547cSRui Paulo p2p_info(p2p, "No common channels found"); 85f05cddf9SRui Paulo return -1; 86f05cddf9SRui Paulo } 87f05cddf9SRui Paulo return 0; 88f05cddf9SRui Paulo } 89f05cddf9SRui Paulo 90f05cddf9SRui Paulo 91f05cddf9SRui Paulo static int p2p_peer_channels(struct p2p_data *p2p, struct p2p_device *dev, 92f05cddf9SRui Paulo const u8 *channel_list, size_t channel_list_len) 93f05cddf9SRui Paulo { 94f05cddf9SRui Paulo return p2p_peer_channels_check(p2p, &p2p->channels, dev, 95f05cddf9SRui Paulo channel_list, channel_list_len); 96f05cddf9SRui Paulo } 97f05cddf9SRui Paulo 98f05cddf9SRui Paulo 99f05cddf9SRui Paulo u16 p2p_wps_method_pw_id(enum p2p_wps_method wps_method) 100f05cddf9SRui Paulo { 101f05cddf9SRui Paulo switch (wps_method) { 102f05cddf9SRui Paulo case WPS_PIN_DISPLAY: 103f05cddf9SRui Paulo return DEV_PW_REGISTRAR_SPECIFIED; 104f05cddf9SRui Paulo case WPS_PIN_KEYPAD: 105f05cddf9SRui Paulo return DEV_PW_USER_SPECIFIED; 106f05cddf9SRui Paulo case WPS_PBC: 107f05cddf9SRui Paulo return DEV_PW_PUSHBUTTON; 1085b9c547cSRui Paulo case WPS_NFC: 1095b9c547cSRui Paulo return DEV_PW_NFC_CONNECTION_HANDOVER; 1105b9c547cSRui Paulo case WPS_P2PS: 1115b9c547cSRui Paulo return DEV_PW_P2PS_DEFAULT; 112f05cddf9SRui Paulo default: 113f05cddf9SRui Paulo return DEV_PW_DEFAULT; 114f05cddf9SRui Paulo } 115f05cddf9SRui Paulo } 116f05cddf9SRui Paulo 117f05cddf9SRui Paulo 118f05cddf9SRui Paulo static const char * p2p_wps_method_str(enum p2p_wps_method wps_method) 119f05cddf9SRui Paulo { 120f05cddf9SRui Paulo switch (wps_method) { 121f05cddf9SRui Paulo case WPS_PIN_DISPLAY: 122f05cddf9SRui Paulo return "Display"; 123f05cddf9SRui Paulo case WPS_PIN_KEYPAD: 124f05cddf9SRui Paulo return "Keypad"; 125f05cddf9SRui Paulo case WPS_PBC: 126f05cddf9SRui Paulo return "PBC"; 1275b9c547cSRui Paulo case WPS_NFC: 1285b9c547cSRui Paulo return "NFC"; 1295b9c547cSRui Paulo case WPS_P2PS: 1305b9c547cSRui Paulo return "P2PS"; 131f05cddf9SRui Paulo default: 132f05cddf9SRui Paulo return "??"; 133f05cddf9SRui Paulo } 134f05cddf9SRui Paulo } 135f05cddf9SRui Paulo 136f05cddf9SRui Paulo 137f05cddf9SRui Paulo static struct wpabuf * p2p_build_go_neg_req(struct p2p_data *p2p, 138f05cddf9SRui Paulo struct p2p_device *peer) 139f05cddf9SRui Paulo { 140f05cddf9SRui Paulo struct wpabuf *buf; 141f05cddf9SRui Paulo u8 *len; 142f05cddf9SRui Paulo u8 group_capab; 143f05cddf9SRui Paulo size_t extra = 0; 1445b9c547cSRui Paulo u16 pw_id; 145f05cddf9SRui Paulo 146f05cddf9SRui Paulo #ifdef CONFIG_WIFI_DISPLAY 147f05cddf9SRui Paulo if (p2p->wfd_ie_go_neg) 148f05cddf9SRui Paulo extra = wpabuf_len(p2p->wfd_ie_go_neg); 149f05cddf9SRui Paulo #endif /* CONFIG_WIFI_DISPLAY */ 150f05cddf9SRui Paulo 1515b9c547cSRui Paulo if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_REQ]) 1525b9c547cSRui Paulo extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_REQ]); 1535b9c547cSRui Paulo 154f05cddf9SRui Paulo buf = wpabuf_alloc(1000 + extra); 155f05cddf9SRui Paulo if (buf == NULL) 156f05cddf9SRui Paulo return NULL; 157f05cddf9SRui Paulo 158f05cddf9SRui Paulo p2p_buf_add_public_action_hdr(buf, P2P_GO_NEG_REQ, peer->dialog_token); 159f05cddf9SRui Paulo 160f05cddf9SRui Paulo len = p2p_buf_add_ie_hdr(buf); 161f05cddf9SRui Paulo group_capab = 0; 162f05cddf9SRui Paulo if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) { 163f05cddf9SRui Paulo group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP; 164f05cddf9SRui Paulo if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN) 165f05cddf9SRui Paulo group_capab |= P2P_GROUP_CAPAB_PERSISTENT_RECONN; 166f05cddf9SRui Paulo } 167f05cddf9SRui Paulo if (p2p->cross_connect) 168f05cddf9SRui Paulo group_capab |= P2P_GROUP_CAPAB_CROSS_CONN; 169f05cddf9SRui Paulo if (p2p->cfg->p2p_intra_bss) 170f05cddf9SRui Paulo group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST; 171f05cddf9SRui Paulo p2p_buf_add_capability(buf, p2p->dev_capab & 172f05cddf9SRui Paulo ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 173f05cddf9SRui Paulo group_capab); 1745b9c547cSRui Paulo p2p_buf_add_go_intent(buf, (p2p->go_intent << 1) | peer->tie_breaker); 175f05cddf9SRui Paulo p2p_buf_add_config_timeout(buf, p2p->go_timeout, p2p->client_timeout); 176f05cddf9SRui Paulo p2p_buf_add_listen_channel(buf, p2p->cfg->country, p2p->cfg->reg_class, 177f05cddf9SRui Paulo p2p->cfg->channel); 178f05cddf9SRui Paulo if (p2p->ext_listen_interval) 179f05cddf9SRui Paulo p2p_buf_add_ext_listen_timing(buf, p2p->ext_listen_period, 180f05cddf9SRui Paulo p2p->ext_listen_interval); 181f05cddf9SRui Paulo p2p_buf_add_intended_addr(buf, p2p->intended_addr); 182f05cddf9SRui Paulo p2p_buf_add_channel_list(buf, p2p->cfg->country, &p2p->channels); 183f05cddf9SRui Paulo p2p_buf_add_device_info(buf, p2p, peer); 184f05cddf9SRui Paulo p2p_buf_add_operating_channel(buf, p2p->cfg->country, 185f05cddf9SRui Paulo p2p->op_reg_class, p2p->op_channel); 186f05cddf9SRui Paulo p2p_buf_update_ie_hdr(buf, len); 187f05cddf9SRui Paulo 188*325151a3SRui Paulo p2p_buf_add_pref_channel_list(buf, p2p->pref_freq_list, 189*325151a3SRui Paulo p2p->num_pref_freq); 190*325151a3SRui Paulo 191f05cddf9SRui Paulo /* WPS IE with Device Password ID attribute */ 1925b9c547cSRui Paulo pw_id = p2p_wps_method_pw_id(peer->wps_method); 1935b9c547cSRui Paulo if (peer->oob_pw_id) 1945b9c547cSRui Paulo pw_id = peer->oob_pw_id; 1955b9c547cSRui Paulo if (p2p_build_wps_ie(p2p, buf, pw_id, 0) < 0) { 1965b9c547cSRui Paulo p2p_dbg(p2p, "Failed to build WPS IE for GO Negotiation Request"); 1975b9c547cSRui Paulo wpabuf_free(buf); 1985b9c547cSRui Paulo return NULL; 1995b9c547cSRui Paulo } 200f05cddf9SRui Paulo 201f05cddf9SRui Paulo #ifdef CONFIG_WIFI_DISPLAY 202f05cddf9SRui Paulo if (p2p->wfd_ie_go_neg) 203f05cddf9SRui Paulo wpabuf_put_buf(buf, p2p->wfd_ie_go_neg); 204f05cddf9SRui Paulo #endif /* CONFIG_WIFI_DISPLAY */ 205f05cddf9SRui Paulo 2065b9c547cSRui Paulo if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_REQ]) 2075b9c547cSRui Paulo wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_REQ]); 2085b9c547cSRui Paulo 209f05cddf9SRui Paulo return buf; 210f05cddf9SRui Paulo } 211f05cddf9SRui Paulo 212f05cddf9SRui Paulo 213f05cddf9SRui Paulo int p2p_connect_send(struct p2p_data *p2p, struct p2p_device *dev) 214f05cddf9SRui Paulo { 215f05cddf9SRui Paulo struct wpabuf *req; 216f05cddf9SRui Paulo int freq; 217f05cddf9SRui Paulo 218f05cddf9SRui Paulo if (dev->flags & P2P_DEV_PD_BEFORE_GO_NEG) { 219f05cddf9SRui Paulo u16 config_method; 2205b9c547cSRui Paulo p2p_dbg(p2p, "Use PD-before-GO-Neg workaround for " MACSTR, 221f05cddf9SRui Paulo MAC2STR(dev->info.p2p_device_addr)); 222f05cddf9SRui Paulo if (dev->wps_method == WPS_PIN_DISPLAY) 223f05cddf9SRui Paulo config_method = WPS_CONFIG_KEYPAD; 224f05cddf9SRui Paulo else if (dev->wps_method == WPS_PIN_KEYPAD) 225f05cddf9SRui Paulo config_method = WPS_CONFIG_DISPLAY; 226f05cddf9SRui Paulo else if (dev->wps_method == WPS_PBC) 227f05cddf9SRui Paulo config_method = WPS_CONFIG_PUSHBUTTON; 2285b9c547cSRui Paulo else if (dev->wps_method == WPS_P2PS) 2295b9c547cSRui Paulo config_method = WPS_CONFIG_P2PS; 230f05cddf9SRui Paulo else 231f05cddf9SRui Paulo return -1; 232f05cddf9SRui Paulo return p2p_prov_disc_req(p2p, dev->info.p2p_device_addr, 2335b9c547cSRui Paulo NULL, config_method, 0, 0, 1); 234f05cddf9SRui Paulo } 235f05cddf9SRui Paulo 236f05cddf9SRui Paulo freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq; 2375b9c547cSRui Paulo if (dev->oob_go_neg_freq > 0) 2385b9c547cSRui Paulo freq = dev->oob_go_neg_freq; 239f05cddf9SRui Paulo if (freq <= 0) { 2405b9c547cSRui Paulo p2p_dbg(p2p, "No Listen/Operating frequency known for the peer " 2415b9c547cSRui Paulo MACSTR " to send GO Negotiation Request", 242f05cddf9SRui Paulo MAC2STR(dev->info.p2p_device_addr)); 243f05cddf9SRui Paulo return -1; 244f05cddf9SRui Paulo } 245f05cddf9SRui Paulo 246f05cddf9SRui Paulo req = p2p_build_go_neg_req(p2p, dev); 247f05cddf9SRui Paulo if (req == NULL) 248f05cddf9SRui Paulo return -1; 2495b9c547cSRui Paulo p2p_dbg(p2p, "Sending GO Negotiation Request"); 250f05cddf9SRui Paulo p2p_set_state(p2p, P2P_CONNECT); 251f05cddf9SRui Paulo p2p->pending_action_state = P2P_PENDING_GO_NEG_REQUEST; 252f05cddf9SRui Paulo p2p->go_neg_peer = dev; 2535b9c547cSRui Paulo eloop_cancel_timeout(p2p_go_neg_wait_timeout, p2p, NULL); 254f05cddf9SRui Paulo dev->flags |= P2P_DEV_WAIT_GO_NEG_RESPONSE; 255f05cddf9SRui Paulo dev->connect_reqs++; 256f05cddf9SRui Paulo if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr, 257f05cddf9SRui Paulo p2p->cfg->dev_addr, dev->info.p2p_device_addr, 2585b9c547cSRui Paulo wpabuf_head(req), wpabuf_len(req), 500) < 0) { 2595b9c547cSRui Paulo p2p_dbg(p2p, "Failed to send Action frame"); 260f05cddf9SRui Paulo /* Use P2P find to recover and retry */ 261f05cddf9SRui Paulo p2p_set_timeout(p2p, 0, 0); 262f05cddf9SRui Paulo } else 263f05cddf9SRui Paulo dev->go_neg_req_sent++; 264f05cddf9SRui Paulo 265f05cddf9SRui Paulo wpabuf_free(req); 266f05cddf9SRui Paulo 267f05cddf9SRui Paulo return 0; 268f05cddf9SRui Paulo } 269f05cddf9SRui Paulo 270f05cddf9SRui Paulo 271f05cddf9SRui Paulo static struct wpabuf * p2p_build_go_neg_resp(struct p2p_data *p2p, 272f05cddf9SRui Paulo struct p2p_device *peer, 273f05cddf9SRui Paulo u8 dialog_token, u8 status, 274f05cddf9SRui Paulo u8 tie_breaker) 275f05cddf9SRui Paulo { 276f05cddf9SRui Paulo struct wpabuf *buf; 277f05cddf9SRui Paulo u8 *len; 278f05cddf9SRui Paulo u8 group_capab; 279f05cddf9SRui Paulo size_t extra = 0; 2805b9c547cSRui Paulo u16 pw_id; 281f05cddf9SRui Paulo 2825b9c547cSRui Paulo p2p_dbg(p2p, "Building GO Negotiation Response"); 283f05cddf9SRui Paulo 284f05cddf9SRui Paulo #ifdef CONFIG_WIFI_DISPLAY 285f05cddf9SRui Paulo if (p2p->wfd_ie_go_neg) 286f05cddf9SRui Paulo extra = wpabuf_len(p2p->wfd_ie_go_neg); 287f05cddf9SRui Paulo #endif /* CONFIG_WIFI_DISPLAY */ 288f05cddf9SRui Paulo 2895b9c547cSRui Paulo if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_RESP]) 2905b9c547cSRui Paulo extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_RESP]); 2915b9c547cSRui Paulo 292f05cddf9SRui Paulo buf = wpabuf_alloc(1000 + extra); 293f05cddf9SRui Paulo if (buf == NULL) 294f05cddf9SRui Paulo return NULL; 295f05cddf9SRui Paulo 296f05cddf9SRui Paulo p2p_buf_add_public_action_hdr(buf, P2P_GO_NEG_RESP, dialog_token); 297f05cddf9SRui Paulo 298f05cddf9SRui Paulo len = p2p_buf_add_ie_hdr(buf); 299f05cddf9SRui Paulo p2p_buf_add_status(buf, status); 300f05cddf9SRui Paulo group_capab = 0; 301f05cddf9SRui Paulo if (peer && peer->go_state == LOCAL_GO) { 302f05cddf9SRui Paulo if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) { 303f05cddf9SRui Paulo group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP; 304f05cddf9SRui Paulo if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN) 305f05cddf9SRui Paulo group_capab |= 306f05cddf9SRui Paulo P2P_GROUP_CAPAB_PERSISTENT_RECONN; 307f05cddf9SRui Paulo } 308f05cddf9SRui Paulo if (p2p->cross_connect) 309f05cddf9SRui Paulo group_capab |= P2P_GROUP_CAPAB_CROSS_CONN; 310f05cddf9SRui Paulo if (p2p->cfg->p2p_intra_bss) 311f05cddf9SRui Paulo group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST; 312f05cddf9SRui Paulo } 313f05cddf9SRui Paulo p2p_buf_add_capability(buf, p2p->dev_capab & 314f05cddf9SRui Paulo ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 315f05cddf9SRui Paulo group_capab); 316f05cddf9SRui Paulo p2p_buf_add_go_intent(buf, (p2p->go_intent << 1) | tie_breaker); 317f05cddf9SRui Paulo p2p_buf_add_config_timeout(buf, p2p->go_timeout, p2p->client_timeout); 318*325151a3SRui Paulo if (peer && peer->go_state == REMOTE_GO && !p2p->num_pref_freq) { 3195b9c547cSRui Paulo p2p_dbg(p2p, "Omit Operating Channel attribute"); 320f05cddf9SRui Paulo } else { 321f05cddf9SRui Paulo p2p_buf_add_operating_channel(buf, p2p->cfg->country, 322f05cddf9SRui Paulo p2p->op_reg_class, 323f05cddf9SRui Paulo p2p->op_channel); 324f05cddf9SRui Paulo } 325f05cddf9SRui Paulo p2p_buf_add_intended_addr(buf, p2p->intended_addr); 326f05cddf9SRui Paulo if (status || peer == NULL) { 327f05cddf9SRui Paulo p2p_buf_add_channel_list(buf, p2p->cfg->country, 328f05cddf9SRui Paulo &p2p->channels); 329f05cddf9SRui Paulo } else if (peer->go_state == REMOTE_GO) { 330f05cddf9SRui Paulo p2p_buf_add_channel_list(buf, p2p->cfg->country, 331f05cddf9SRui Paulo &p2p->channels); 332f05cddf9SRui Paulo } else { 333f05cddf9SRui Paulo struct p2p_channels res; 334f05cddf9SRui Paulo p2p_channels_intersect(&p2p->channels, &peer->channels, 335f05cddf9SRui Paulo &res); 336f05cddf9SRui Paulo p2p_buf_add_channel_list(buf, p2p->cfg->country, &res); 337f05cddf9SRui Paulo } 338f05cddf9SRui Paulo p2p_buf_add_device_info(buf, p2p, peer); 339f05cddf9SRui Paulo if (peer && peer->go_state == LOCAL_GO) { 340f05cddf9SRui Paulo p2p_buf_add_group_id(buf, p2p->cfg->dev_addr, p2p->ssid, 341f05cddf9SRui Paulo p2p->ssid_len); 342f05cddf9SRui Paulo } 343f05cddf9SRui Paulo p2p_buf_update_ie_hdr(buf, len); 344f05cddf9SRui Paulo 345f05cddf9SRui Paulo /* WPS IE with Device Password ID attribute */ 3465b9c547cSRui Paulo pw_id = p2p_wps_method_pw_id(peer ? peer->wps_method : WPS_NOT_READY); 3475b9c547cSRui Paulo if (peer && peer->oob_pw_id) 3485b9c547cSRui Paulo pw_id = peer->oob_pw_id; 3495b9c547cSRui Paulo if (p2p_build_wps_ie(p2p, buf, pw_id, 0) < 0) { 3505b9c547cSRui Paulo p2p_dbg(p2p, "Failed to build WPS IE for GO Negotiation Response"); 3515b9c547cSRui Paulo wpabuf_free(buf); 3525b9c547cSRui Paulo return NULL; 3535b9c547cSRui Paulo } 354f05cddf9SRui Paulo 355f05cddf9SRui Paulo #ifdef CONFIG_WIFI_DISPLAY 356f05cddf9SRui Paulo if (p2p->wfd_ie_go_neg) 357f05cddf9SRui Paulo wpabuf_put_buf(buf, p2p->wfd_ie_go_neg); 358f05cddf9SRui Paulo #endif /* CONFIG_WIFI_DISPLAY */ 359f05cddf9SRui Paulo 3605b9c547cSRui Paulo if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_RESP]) 3615b9c547cSRui Paulo wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_RESP]); 362f05cddf9SRui Paulo 363f05cddf9SRui Paulo return buf; 364f05cddf9SRui Paulo } 365f05cddf9SRui Paulo 366f05cddf9SRui Paulo 367f05cddf9SRui Paulo /** 368f05cddf9SRui Paulo * p2p_reselect_channel - Re-select operating channel based on peer information 369f05cddf9SRui Paulo * @p2p: P2P module context from p2p_init() 370f05cddf9SRui Paulo * @intersection: Support channel list intersection from local and peer 371f05cddf9SRui Paulo * 372f05cddf9SRui Paulo * This function is used to re-select the best channel after having received 373f05cddf9SRui Paulo * information from the peer to allow supported channel lists to be intersected. 374f05cddf9SRui Paulo * This can be used to improve initial channel selection done in 375f05cddf9SRui Paulo * p2p_prepare_channel() prior to the start of GO Negotiation. In addition, this 376f05cddf9SRui Paulo * can be used for Invitation case. 377f05cddf9SRui Paulo */ 378f05cddf9SRui Paulo void p2p_reselect_channel(struct p2p_data *p2p, 379f05cddf9SRui Paulo struct p2p_channels *intersection) 380f05cddf9SRui Paulo { 381f05cddf9SRui Paulo struct p2p_reg_class *cl; 382f05cddf9SRui Paulo int freq; 383f05cddf9SRui Paulo u8 op_reg_class, op_channel; 384f05cddf9SRui Paulo unsigned int i; 385*325151a3SRui Paulo const int op_classes_5ghz[] = { 124, 125, 115, 0 }; 3865b9c547cSRui Paulo const int op_classes_ht40[] = { 126, 127, 116, 117, 0 }; 3875b9c547cSRui Paulo const int op_classes_vht[] = { 128, 0 }; 388f05cddf9SRui Paulo 3895b9c547cSRui Paulo if (p2p->own_freq_preference > 0 && 3905b9c547cSRui Paulo p2p_freq_to_channel(p2p->own_freq_preference, 391f05cddf9SRui Paulo &op_reg_class, &op_channel) == 0 && 392f05cddf9SRui Paulo p2p_channels_includes(intersection, op_reg_class, op_channel)) { 3935b9c547cSRui Paulo p2p_dbg(p2p, "Pick own channel preference (reg_class %u channel %u) from intersection", 3945b9c547cSRui Paulo op_reg_class, op_channel); 3955b9c547cSRui Paulo p2p->op_reg_class = op_reg_class; 3965b9c547cSRui Paulo p2p->op_channel = op_channel; 3975b9c547cSRui Paulo return; 3985b9c547cSRui Paulo } 3995b9c547cSRui Paulo 4005b9c547cSRui Paulo if (p2p->best_freq_overall > 0 && 4015b9c547cSRui Paulo p2p_freq_to_channel(p2p->best_freq_overall, 4025b9c547cSRui Paulo &op_reg_class, &op_channel) == 0 && 4035b9c547cSRui Paulo p2p_channels_includes(intersection, op_reg_class, op_channel)) { 4045b9c547cSRui Paulo p2p_dbg(p2p, "Pick best overall channel (reg_class %u channel %u) from intersection", 4055b9c547cSRui Paulo op_reg_class, op_channel); 4065b9c547cSRui Paulo p2p->op_reg_class = op_reg_class; 4075b9c547cSRui Paulo p2p->op_channel = op_channel; 4085b9c547cSRui Paulo return; 4095b9c547cSRui Paulo } 4105b9c547cSRui Paulo 4115b9c547cSRui Paulo /* First, try to pick the best channel from another band */ 4125b9c547cSRui Paulo freq = p2p_channel_to_freq(p2p->op_reg_class, p2p->op_channel); 4135b9c547cSRui Paulo if (freq >= 2400 && freq < 2500 && p2p->best_freq_5 > 0 && 4145b9c547cSRui Paulo !p2p_channels_includes(intersection, p2p->op_reg_class, 4155b9c547cSRui Paulo p2p->op_channel) && 4165b9c547cSRui Paulo p2p_freq_to_channel(p2p->best_freq_5, 4175b9c547cSRui Paulo &op_reg_class, &op_channel) == 0 && 4185b9c547cSRui Paulo p2p_channels_includes(intersection, op_reg_class, op_channel)) { 4195b9c547cSRui Paulo p2p_dbg(p2p, "Pick best 5 GHz channel (reg_class %u channel %u) from intersection", 420f05cddf9SRui Paulo op_reg_class, op_channel); 421f05cddf9SRui Paulo p2p->op_reg_class = op_reg_class; 422f05cddf9SRui Paulo p2p->op_channel = op_channel; 423f05cddf9SRui Paulo return; 424f05cddf9SRui Paulo } 425f05cddf9SRui Paulo 426f05cddf9SRui Paulo if (freq >= 4900 && freq < 6000 && p2p->best_freq_24 > 0 && 4275b9c547cSRui Paulo !p2p_channels_includes(intersection, p2p->op_reg_class, 4285b9c547cSRui Paulo p2p->op_channel) && 4295b9c547cSRui Paulo p2p_freq_to_channel(p2p->best_freq_24, 430f05cddf9SRui Paulo &op_reg_class, &op_channel) == 0 && 431f05cddf9SRui Paulo p2p_channels_includes(intersection, op_reg_class, op_channel)) { 4325b9c547cSRui Paulo p2p_dbg(p2p, "Pick best 2.4 GHz channel (reg_class %u channel %u) from intersection", 433f05cddf9SRui Paulo op_reg_class, op_channel); 434f05cddf9SRui Paulo p2p->op_reg_class = op_reg_class; 435f05cddf9SRui Paulo p2p->op_channel = op_channel; 436f05cddf9SRui Paulo return; 437f05cddf9SRui Paulo } 438f05cddf9SRui Paulo 439f05cddf9SRui Paulo /* Select channel with highest preference if the peer supports it */ 440f05cddf9SRui Paulo for (i = 0; p2p->cfg->pref_chan && i < p2p->cfg->num_pref_chan; i++) { 441f05cddf9SRui Paulo if (p2p_channels_includes(intersection, 442f05cddf9SRui Paulo p2p->cfg->pref_chan[i].op_class, 443f05cddf9SRui Paulo p2p->cfg->pref_chan[i].chan)) { 444f05cddf9SRui Paulo p2p->op_reg_class = p2p->cfg->pref_chan[i].op_class; 445f05cddf9SRui Paulo p2p->op_channel = p2p->cfg->pref_chan[i].chan; 4465b9c547cSRui Paulo p2p_dbg(p2p, "Pick highest preferred channel (op_class %u channel %u) from intersection", 447f05cddf9SRui Paulo p2p->op_reg_class, p2p->op_channel); 448f05cddf9SRui Paulo return; 449f05cddf9SRui Paulo } 450f05cddf9SRui Paulo } 451f05cddf9SRui Paulo 4525b9c547cSRui Paulo /* Try a channel where we might be able to use VHT */ 4535b9c547cSRui Paulo if (p2p_channel_select(intersection, op_classes_vht, 4545b9c547cSRui Paulo &p2p->op_reg_class, &p2p->op_channel) == 0) { 4555b9c547cSRui Paulo p2p_dbg(p2p, "Pick possible VHT channel (op_class %u channel %u) from intersection", 4565b9c547cSRui Paulo p2p->op_reg_class, p2p->op_channel); 457f05cddf9SRui Paulo return; 458f05cddf9SRui Paulo } 4595b9c547cSRui Paulo 4605b9c547cSRui Paulo /* Try a channel where we might be able to use HT40 */ 4615b9c547cSRui Paulo if (p2p_channel_select(intersection, op_classes_ht40, 4625b9c547cSRui Paulo &p2p->op_reg_class, &p2p->op_channel) == 0) { 4635b9c547cSRui Paulo p2p_dbg(p2p, "Pick possible HT40 channel (op_class %u channel %u) from intersection", 4645b9c547cSRui Paulo p2p->op_reg_class, p2p->op_channel); 4655b9c547cSRui Paulo return; 4665b9c547cSRui Paulo } 4675b9c547cSRui Paulo 4685b9c547cSRui Paulo /* Prefer a 5 GHz channel */ 4695b9c547cSRui Paulo if (p2p_channel_select(intersection, op_classes_5ghz, 4705b9c547cSRui Paulo &p2p->op_reg_class, &p2p->op_channel) == 0) { 4715b9c547cSRui Paulo p2p_dbg(p2p, "Pick possible 5 GHz channel (op_class %u channel %u) from intersection", 4725b9c547cSRui Paulo p2p->op_reg_class, p2p->op_channel); 4735b9c547cSRui Paulo return; 474f05cddf9SRui Paulo } 475f05cddf9SRui Paulo 476f05cddf9SRui Paulo /* 477f05cddf9SRui Paulo * Try to see if the original channel is in the intersection. If 478f05cddf9SRui Paulo * so, no need to change anything, as it already contains some 479f05cddf9SRui Paulo * randomness. 480f05cddf9SRui Paulo */ 481f05cddf9SRui Paulo if (p2p_channels_includes(intersection, p2p->op_reg_class, 482f05cddf9SRui Paulo p2p->op_channel)) { 4835b9c547cSRui Paulo p2p_dbg(p2p, "Using original operating class and channel (op_class %u channel %u) from intersection", 484f05cddf9SRui Paulo p2p->op_reg_class, p2p->op_channel); 485f05cddf9SRui Paulo return; 486f05cddf9SRui Paulo } 487f05cddf9SRui Paulo 488f05cddf9SRui Paulo /* 489f05cddf9SRui Paulo * Fall back to whatever is included in the channel intersection since 490f05cddf9SRui Paulo * no better options seems to be available. 491f05cddf9SRui Paulo */ 492f05cddf9SRui Paulo cl = &intersection->reg_class[0]; 4935b9c547cSRui Paulo p2p_dbg(p2p, "Pick another channel (reg_class %u channel %u) from intersection", 494f05cddf9SRui Paulo cl->reg_class, cl->channel[0]); 495f05cddf9SRui Paulo p2p->op_reg_class = cl->reg_class; 496f05cddf9SRui Paulo p2p->op_channel = cl->channel[0]; 497f05cddf9SRui Paulo } 498f05cddf9SRui Paulo 499f05cddf9SRui Paulo 5005b9c547cSRui Paulo int p2p_go_select_channel(struct p2p_data *p2p, struct p2p_device *dev, 501f05cddf9SRui Paulo u8 *status) 502f05cddf9SRui Paulo { 5035b9c547cSRui Paulo struct p2p_channels tmp, intersection; 504f05cddf9SRui Paulo 5055b9c547cSRui Paulo p2p_channels_dump(p2p, "own channels", &p2p->channels); 5065b9c547cSRui Paulo p2p_channels_dump(p2p, "peer channels", &dev->channels); 5075b9c547cSRui Paulo p2p_channels_intersect(&p2p->channels, &dev->channels, &tmp); 5085b9c547cSRui Paulo p2p_channels_dump(p2p, "intersection", &tmp); 5095b9c547cSRui Paulo p2p_channels_remove_freqs(&tmp, &p2p->no_go_freq); 5105b9c547cSRui Paulo p2p_channels_dump(p2p, "intersection after no-GO removal", &tmp); 5115b9c547cSRui Paulo p2p_channels_intersect(&tmp, &p2p->cfg->channels, &intersection); 5125b9c547cSRui Paulo p2p_channels_dump(p2p, "intersection with local channel list", 5135b9c547cSRui Paulo &intersection); 514f05cddf9SRui Paulo if (intersection.reg_classes == 0 || 515f05cddf9SRui Paulo intersection.reg_class[0].channels == 0) { 516f05cddf9SRui Paulo *status = P2P_SC_FAIL_NO_COMMON_CHANNELS; 5175b9c547cSRui Paulo p2p_dbg(p2p, "No common channels found"); 518f05cddf9SRui Paulo return -1; 519f05cddf9SRui Paulo } 520f05cddf9SRui Paulo 521f05cddf9SRui Paulo if (!p2p_channels_includes(&intersection, p2p->op_reg_class, 522f05cddf9SRui Paulo p2p->op_channel)) { 523f05cddf9SRui Paulo if (dev->flags & P2P_DEV_FORCE_FREQ) { 524f05cddf9SRui Paulo *status = P2P_SC_FAIL_NO_COMMON_CHANNELS; 5255b9c547cSRui Paulo p2p_dbg(p2p, "Peer does not support the forced channel"); 526f05cddf9SRui Paulo return -1; 527f05cddf9SRui Paulo } 528f05cddf9SRui Paulo 5295b9c547cSRui Paulo p2p_dbg(p2p, "Selected operating channel (op_class %u channel %u) not acceptable to the peer", 5305b9c547cSRui Paulo p2p->op_reg_class, p2p->op_channel); 531f05cddf9SRui Paulo p2p_reselect_channel(p2p, &intersection); 532f05cddf9SRui Paulo } else if (!(dev->flags & P2P_DEV_FORCE_FREQ) && 533f05cddf9SRui Paulo !p2p->cfg->cfg_op_channel) { 5345b9c547cSRui Paulo p2p_dbg(p2p, "Try to optimize channel selection with peer information received; previously selected op_class %u channel %u", 535f05cddf9SRui Paulo p2p->op_reg_class, p2p->op_channel); 536f05cddf9SRui Paulo p2p_reselect_channel(p2p, &intersection); 537f05cddf9SRui Paulo } 538f05cddf9SRui Paulo 539f05cddf9SRui Paulo if (!p2p->ssid_set) { 540f05cddf9SRui Paulo p2p_build_ssid(p2p, p2p->ssid, &p2p->ssid_len); 541f05cddf9SRui Paulo p2p->ssid_set = 1; 542f05cddf9SRui Paulo } 543f05cddf9SRui Paulo 544f05cddf9SRui Paulo return 0; 545f05cddf9SRui Paulo } 546f05cddf9SRui Paulo 547f05cddf9SRui Paulo 548*325151a3SRui Paulo static void p2p_check_pref_chan_no_recv(struct p2p_data *p2p, int go, 549*325151a3SRui Paulo struct p2p_device *dev, 550*325151a3SRui Paulo struct p2p_message *msg, 551*325151a3SRui Paulo unsigned freq_list[], unsigned int size) 552*325151a3SRui Paulo { 553*325151a3SRui Paulo u8 op_class, op_channel; 554*325151a3SRui Paulo unsigned int oper_freq = 0, i, j; 555*325151a3SRui Paulo int found = 0; 556*325151a3SRui Paulo 557*325151a3SRui Paulo p2p_dbg(p2p, 558*325151a3SRui Paulo "Peer didn't provide a preferred frequency list, see if any of our preferred channels are supported by peer device"); 559*325151a3SRui Paulo 560*325151a3SRui Paulo /* 561*325151a3SRui Paulo * Search for a common channel in our preferred frequency list which is 562*325151a3SRui Paulo * also supported by the peer device. 563*325151a3SRui Paulo */ 564*325151a3SRui Paulo for (i = 0; i < size && !found; i++) { 565*325151a3SRui Paulo /* 566*325151a3SRui Paulo * Make sure that the common frequency is: 567*325151a3SRui Paulo * 1. Supported by peer 568*325151a3SRui Paulo * 2. Allowed for P2P use. 569*325151a3SRui Paulo */ 570*325151a3SRui Paulo oper_freq = freq_list[i]; 571*325151a3SRui Paulo if (p2p_freq_to_channel(oper_freq, &op_class, 572*325151a3SRui Paulo &op_channel) < 0) { 573*325151a3SRui Paulo p2p_dbg(p2p, "Unsupported frequency %u MHz", oper_freq); 574*325151a3SRui Paulo continue; 575*325151a3SRui Paulo } 576*325151a3SRui Paulo if (!p2p_channels_includes(&p2p->cfg->channels, 577*325151a3SRui Paulo op_class, op_channel) && 578*325151a3SRui Paulo (go || !p2p_channels_includes(&p2p->cfg->cli_channels, 579*325151a3SRui Paulo op_class, op_channel))) { 580*325151a3SRui Paulo p2p_dbg(p2p, 581*325151a3SRui Paulo "Freq %u MHz (oper_class %u channel %u) not allowed for P2P", 582*325151a3SRui Paulo oper_freq, op_class, op_channel); 583*325151a3SRui Paulo break; 584*325151a3SRui Paulo } 585*325151a3SRui Paulo for (j = 0; j < msg->channel_list_len; j++) { 586*325151a3SRui Paulo 587*325151a3SRui Paulo if (op_channel != msg->channel_list[j]) 588*325151a3SRui Paulo continue; 589*325151a3SRui Paulo 590*325151a3SRui Paulo p2p->op_reg_class = op_class; 591*325151a3SRui Paulo p2p->op_channel = op_channel; 592*325151a3SRui Paulo os_memcpy(&p2p->channels, &p2p->cfg->channels, 593*325151a3SRui Paulo sizeof(struct p2p_channels)); 594*325151a3SRui Paulo found = 1; 595*325151a3SRui Paulo break; 596*325151a3SRui Paulo } 597*325151a3SRui Paulo } 598*325151a3SRui Paulo 599*325151a3SRui Paulo if (found) { 600*325151a3SRui Paulo p2p_dbg(p2p, 601*325151a3SRui Paulo "Freq %d MHz is a preferred channel and is also supported by peer, use it as the operating channel", 602*325151a3SRui Paulo oper_freq); 603*325151a3SRui Paulo } else { 604*325151a3SRui Paulo p2p_dbg(p2p, 605*325151a3SRui Paulo "None of our preferred channels are supported by peer!. Use: %d MHz for oper_channel", 606*325151a3SRui Paulo dev->oper_freq); 607*325151a3SRui Paulo } 608*325151a3SRui Paulo } 609*325151a3SRui Paulo 610*325151a3SRui Paulo 611*325151a3SRui Paulo static void p2p_check_pref_chan_recv(struct p2p_data *p2p, int go, 612*325151a3SRui Paulo struct p2p_device *dev, 613*325151a3SRui Paulo struct p2p_message *msg, 614*325151a3SRui Paulo unsigned freq_list[], unsigned int size) 615*325151a3SRui Paulo { 616*325151a3SRui Paulo u8 op_class, op_channel; 617*325151a3SRui Paulo unsigned int oper_freq = 0, i, j; 618*325151a3SRui Paulo int found = 0; 619*325151a3SRui Paulo 620*325151a3SRui Paulo /* 621*325151a3SRui Paulo * Peer device supports a Preferred Frequency List. 622*325151a3SRui Paulo * Search for a common channel in the preferred frequency lists 623*325151a3SRui Paulo * of both peer and local devices. 624*325151a3SRui Paulo */ 625*325151a3SRui Paulo for (i = 0; i < size && !found; i++) { 626*325151a3SRui Paulo for (j = 2; j < (msg->pref_freq_list_len / 2); j++) { 627*325151a3SRui Paulo oper_freq = p2p_channel_to_freq( 628*325151a3SRui Paulo msg->pref_freq_list[2 * j], 629*325151a3SRui Paulo msg->pref_freq_list[2 * j + 1]); 630*325151a3SRui Paulo if (freq_list[i] != oper_freq) 631*325151a3SRui Paulo continue; 632*325151a3SRui Paulo 633*325151a3SRui Paulo /* 634*325151a3SRui Paulo * Make sure that the found frequency is: 635*325151a3SRui Paulo * 1. Supported 636*325151a3SRui Paulo * 2. Allowed for P2P use. 637*325151a3SRui Paulo */ 638*325151a3SRui Paulo if (p2p_freq_to_channel(oper_freq, &op_class, 639*325151a3SRui Paulo &op_channel) < 0) { 640*325151a3SRui Paulo p2p_dbg(p2p, "Unsupported frequency %u MHz", 641*325151a3SRui Paulo oper_freq); 642*325151a3SRui Paulo continue; 643*325151a3SRui Paulo } 644*325151a3SRui Paulo 645*325151a3SRui Paulo if (!p2p_channels_includes(&p2p->cfg->channels, 646*325151a3SRui Paulo op_class, op_channel) && 647*325151a3SRui Paulo (go || 648*325151a3SRui Paulo !p2p_channels_includes(&p2p->cfg->cli_channels, 649*325151a3SRui Paulo op_class, op_channel))) { 650*325151a3SRui Paulo p2p_dbg(p2p, 651*325151a3SRui Paulo "Freq %u MHz (oper_class %u channel %u) not allowed for P2P", 652*325151a3SRui Paulo oper_freq, op_class, op_channel); 653*325151a3SRui Paulo break; 654*325151a3SRui Paulo } 655*325151a3SRui Paulo p2p->op_reg_class = op_class; 656*325151a3SRui Paulo p2p->op_channel = op_channel; 657*325151a3SRui Paulo os_memcpy(&p2p->channels, &p2p->cfg->channels, 658*325151a3SRui Paulo sizeof(struct p2p_channels)); 659*325151a3SRui Paulo found = 1; 660*325151a3SRui Paulo break; 661*325151a3SRui Paulo } 662*325151a3SRui Paulo } 663*325151a3SRui Paulo 664*325151a3SRui Paulo if (found) { 665*325151a3SRui Paulo p2p_dbg(p2p, 666*325151a3SRui Paulo "Freq %d MHz is a common preferred channel for both peer and local, use it as operating channel", 667*325151a3SRui Paulo oper_freq); 668*325151a3SRui Paulo } else { 669*325151a3SRui Paulo p2p_dbg(p2p, 670*325151a3SRui Paulo "No common preferred channels found! Use: %d MHz for oper_channel", 671*325151a3SRui Paulo dev->oper_freq); 672*325151a3SRui Paulo } 673*325151a3SRui Paulo } 674*325151a3SRui Paulo 675*325151a3SRui Paulo 676*325151a3SRui Paulo void p2p_check_pref_chan(struct p2p_data *p2p, int go, 677*325151a3SRui Paulo struct p2p_device *dev, struct p2p_message *msg) 678*325151a3SRui Paulo { 679*325151a3SRui Paulo unsigned int freq_list[P2P_MAX_PREF_CHANNELS], size; 680*325151a3SRui Paulo unsigned int i; 681*325151a3SRui Paulo u8 op_class, op_channel; 682*325151a3SRui Paulo 683*325151a3SRui Paulo /* 684*325151a3SRui Paulo * Use the preferred channel list from the driver only if there is no 685*325151a3SRui Paulo * forced_freq, e.g., P2P_CONNECT freq=..., and no preferred operating 686*325151a3SRui Paulo * channel hardcoded in the configuration file. 687*325151a3SRui Paulo */ 688*325151a3SRui Paulo if (!p2p->cfg->get_pref_freq_list || p2p->cfg->num_pref_chan || 689*325151a3SRui Paulo (dev->flags & P2P_DEV_FORCE_FREQ) || p2p->cfg->cfg_op_channel) 690*325151a3SRui Paulo return; 691*325151a3SRui Paulo 692*325151a3SRui Paulo /* Obtain our preferred frequency list from driver based on P2P role. */ 693*325151a3SRui Paulo size = P2P_MAX_PREF_CHANNELS; 694*325151a3SRui Paulo if (p2p->cfg->get_pref_freq_list(p2p->cfg->cb_ctx, go, &size, 695*325151a3SRui Paulo freq_list)) 696*325151a3SRui Paulo return; 697*325151a3SRui Paulo 698*325151a3SRui Paulo /* 699*325151a3SRui Paulo * Check if peer's preference of operating channel is in 700*325151a3SRui Paulo * our preferred channel list. 701*325151a3SRui Paulo */ 702*325151a3SRui Paulo for (i = 0; i < size; i++) { 703*325151a3SRui Paulo if (freq_list[i] == (unsigned int) dev->oper_freq) 704*325151a3SRui Paulo break; 705*325151a3SRui Paulo } 706*325151a3SRui Paulo if (i != size) { 707*325151a3SRui Paulo /* Peer operating channel preference matches our preference */ 708*325151a3SRui Paulo if (p2p_freq_to_channel(freq_list[i], &op_class, &op_channel) < 709*325151a3SRui Paulo 0) { 710*325151a3SRui Paulo p2p_dbg(p2p, 711*325151a3SRui Paulo "Peer operating channel preference is unsupported frequency %u MHz", 712*325151a3SRui Paulo freq_list[i]); 713*325151a3SRui Paulo } else { 714*325151a3SRui Paulo p2p->op_reg_class = op_class; 715*325151a3SRui Paulo p2p->op_channel = op_channel; 716*325151a3SRui Paulo os_memcpy(&p2p->channels, &p2p->cfg->channels, 717*325151a3SRui Paulo sizeof(struct p2p_channels)); 718*325151a3SRui Paulo return; 719*325151a3SRui Paulo } 720*325151a3SRui Paulo } 721*325151a3SRui Paulo 722*325151a3SRui Paulo p2p_dbg(p2p, 723*325151a3SRui Paulo "Peer operating channel preference: %d MHz is not in our preferred channel list", 724*325151a3SRui Paulo dev->oper_freq); 725*325151a3SRui Paulo 726*325151a3SRui Paulo /* 727*325151a3SRui Paulo Check if peer's preferred channel list is 728*325151a3SRui Paulo * _not_ included in the GO Negotiation Request or Invitation Request. 729*325151a3SRui Paulo */ 730*325151a3SRui Paulo if (msg->pref_freq_list_len == 0) 731*325151a3SRui Paulo p2p_check_pref_chan_no_recv(p2p, go, dev, msg, freq_list, size); 732*325151a3SRui Paulo else 733*325151a3SRui Paulo p2p_check_pref_chan_recv(p2p, go, dev, msg, freq_list, size); 734*325151a3SRui Paulo } 735*325151a3SRui Paulo 736*325151a3SRui Paulo 737f05cddf9SRui Paulo void p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa, 738f05cddf9SRui Paulo const u8 *data, size_t len, int rx_freq) 739f05cddf9SRui Paulo { 740f05cddf9SRui Paulo struct p2p_device *dev = NULL; 741f05cddf9SRui Paulo struct wpabuf *resp; 742f05cddf9SRui Paulo struct p2p_message msg; 743f05cddf9SRui Paulo u8 status = P2P_SC_FAIL_INVALID_PARAMS; 744f05cddf9SRui Paulo int tie_breaker = 0; 745f05cddf9SRui Paulo int freq; 746f05cddf9SRui Paulo 7475b9c547cSRui Paulo p2p_dbg(p2p, "Received GO Negotiation Request from " MACSTR "(freq=%d)", 7485b9c547cSRui Paulo MAC2STR(sa), rx_freq); 749f05cddf9SRui Paulo 750f05cddf9SRui Paulo if (p2p_parse(data, len, &msg)) 751f05cddf9SRui Paulo return; 752f05cddf9SRui Paulo 753f05cddf9SRui Paulo if (!msg.capability) { 7545b9c547cSRui Paulo p2p_dbg(p2p, "Mandatory Capability attribute missing from GO Negotiation Request"); 755f05cddf9SRui Paulo #ifdef CONFIG_P2P_STRICT 756f05cddf9SRui Paulo goto fail; 757f05cddf9SRui Paulo #endif /* CONFIG_P2P_STRICT */ 758f05cddf9SRui Paulo } 759f05cddf9SRui Paulo 760f05cddf9SRui Paulo if (msg.go_intent) 761f05cddf9SRui Paulo tie_breaker = *msg.go_intent & 0x01; 762f05cddf9SRui Paulo else { 7635b9c547cSRui Paulo p2p_dbg(p2p, "Mandatory GO Intent attribute missing from GO Negotiation Request"); 764f05cddf9SRui Paulo #ifdef CONFIG_P2P_STRICT 765f05cddf9SRui Paulo goto fail; 766f05cddf9SRui Paulo #endif /* CONFIG_P2P_STRICT */ 767f05cddf9SRui Paulo } 768f05cddf9SRui Paulo 769f05cddf9SRui Paulo if (!msg.config_timeout) { 7705b9c547cSRui Paulo p2p_dbg(p2p, "Mandatory Configuration Timeout attribute missing from GO Negotiation Request"); 771f05cddf9SRui Paulo #ifdef CONFIG_P2P_STRICT 772f05cddf9SRui Paulo goto fail; 773f05cddf9SRui Paulo #endif /* CONFIG_P2P_STRICT */ 774f05cddf9SRui Paulo } 775f05cddf9SRui Paulo 776f05cddf9SRui Paulo if (!msg.listen_channel) { 7775b9c547cSRui Paulo p2p_dbg(p2p, "No Listen Channel attribute received"); 778f05cddf9SRui Paulo goto fail; 779f05cddf9SRui Paulo } 780f05cddf9SRui Paulo if (!msg.operating_channel) { 7815b9c547cSRui Paulo p2p_dbg(p2p, "No Operating Channel attribute received"); 782f05cddf9SRui Paulo goto fail; 783f05cddf9SRui Paulo } 784f05cddf9SRui Paulo if (!msg.channel_list) { 7855b9c547cSRui Paulo p2p_dbg(p2p, "No Channel List attribute received"); 786f05cddf9SRui Paulo goto fail; 787f05cddf9SRui Paulo } 788f05cddf9SRui Paulo if (!msg.intended_addr) { 7895b9c547cSRui Paulo p2p_dbg(p2p, "No Intended P2P Interface Address attribute received"); 790f05cddf9SRui Paulo goto fail; 791f05cddf9SRui Paulo } 792f05cddf9SRui Paulo if (!msg.p2p_device_info) { 7935b9c547cSRui Paulo p2p_dbg(p2p, "No P2P Device Info attribute received"); 794f05cddf9SRui Paulo goto fail; 795f05cddf9SRui Paulo } 796f05cddf9SRui Paulo 797f05cddf9SRui Paulo if (os_memcmp(msg.p2p_device_addr, sa, ETH_ALEN) != 0) { 7985b9c547cSRui Paulo p2p_dbg(p2p, "Unexpected GO Negotiation Request SA=" MACSTR 799f05cddf9SRui Paulo " != dev_addr=" MACSTR, 800f05cddf9SRui Paulo MAC2STR(sa), MAC2STR(msg.p2p_device_addr)); 801f05cddf9SRui Paulo goto fail; 802f05cddf9SRui Paulo } 803f05cddf9SRui Paulo 804f05cddf9SRui Paulo dev = p2p_get_device(p2p, sa); 805f05cddf9SRui Paulo 806f05cddf9SRui Paulo if (msg.status && *msg.status) { 8075b9c547cSRui Paulo p2p_dbg(p2p, "Unexpected Status attribute (%d) in GO Negotiation Request", 8085b9c547cSRui Paulo *msg.status); 8095b9c547cSRui Paulo if (dev && p2p->go_neg_peer == dev && 8105b9c547cSRui Paulo *msg.status == P2P_SC_FAIL_REJECTED_BY_USER) { 8115b9c547cSRui Paulo /* 8125b9c547cSRui Paulo * This mechanism for using Status attribute in GO 8135b9c547cSRui Paulo * Negotiation Request is not compliant with the P2P 8145b9c547cSRui Paulo * specification, but some deployed devices use it to 8155b9c547cSRui Paulo * indicate rejection of GO Negotiation in a case where 8165b9c547cSRui Paulo * they have sent out GO Negotiation Response with 8175b9c547cSRui Paulo * status 1. The P2P specification explicitly disallows 8185b9c547cSRui Paulo * this. To avoid unnecessary interoperability issues 8195b9c547cSRui Paulo * and extra frames, mark the pending negotiation as 8205b9c547cSRui Paulo * failed and do not reply to this GO Negotiation 8215b9c547cSRui Paulo * Request frame. 8225b9c547cSRui Paulo */ 8235b9c547cSRui Paulo p2p->cfg->send_action_done(p2p->cfg->cb_ctx); 8245b9c547cSRui Paulo p2p_go_neg_failed(p2p, *msg.status); 8255b9c547cSRui Paulo p2p_parse_free(&msg); 8265b9c547cSRui Paulo return; 8275b9c547cSRui Paulo } 828f05cddf9SRui Paulo goto fail; 829f05cddf9SRui Paulo } 830f05cddf9SRui Paulo 831f05cddf9SRui Paulo if (dev == NULL) 832f05cddf9SRui Paulo dev = p2p_add_dev_from_go_neg_req(p2p, sa, &msg); 8335b9c547cSRui Paulo else if ((dev->flags & P2P_DEV_PROBE_REQ_ONLY) || 8345b9c547cSRui Paulo !(dev->flags & P2P_DEV_REPORTED)) 835f05cddf9SRui Paulo p2p_add_dev_info(p2p, sa, dev, &msg); 8365b9c547cSRui Paulo else if (!dev->listen_freq && !dev->oper_freq) { 8375b9c547cSRui Paulo /* 8385b9c547cSRui Paulo * This may happen if the peer entry was added based on PD 8395b9c547cSRui Paulo * Request and no Probe Request/Response frame has been received 8405b9c547cSRui Paulo * from this peer (or that information has timed out). 8415b9c547cSRui Paulo */ 8425b9c547cSRui Paulo p2p_dbg(p2p, "Update peer " MACSTR 8435b9c547cSRui Paulo " based on GO Neg Req since listen/oper freq not known", 8445b9c547cSRui Paulo MAC2STR(dev->info.p2p_device_addr)); 8455b9c547cSRui Paulo p2p_add_dev_info(p2p, sa, dev, &msg); 8465b9c547cSRui Paulo } 8475b9c547cSRui Paulo 8485b9c547cSRui Paulo if (p2p->go_neg_peer && p2p->go_neg_peer == dev) 8495b9c547cSRui Paulo eloop_cancel_timeout(p2p_go_neg_wait_timeout, p2p, NULL); 8505b9c547cSRui Paulo 851f05cddf9SRui Paulo if (dev && dev->flags & P2P_DEV_USER_REJECTED) { 8525b9c547cSRui Paulo p2p_dbg(p2p, "User has rejected this peer"); 853f05cddf9SRui Paulo status = P2P_SC_FAIL_REJECTED_BY_USER; 8545b9c547cSRui Paulo } else if (dev == NULL || 8555b9c547cSRui Paulo (dev->wps_method == WPS_NOT_READY && 8565b9c547cSRui Paulo (p2p->authorized_oob_dev_pw_id == 0 || 8575b9c547cSRui Paulo p2p->authorized_oob_dev_pw_id != 8585b9c547cSRui Paulo msg.dev_password_id))) { 8595b9c547cSRui Paulo p2p_dbg(p2p, "Not ready for GO negotiation with " MACSTR, 860f05cddf9SRui Paulo MAC2STR(sa)); 861f05cddf9SRui Paulo status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE; 862f05cddf9SRui Paulo p2p->cfg->go_neg_req_rx(p2p->cfg->cb_ctx, sa, 863*325151a3SRui Paulo msg.dev_password_id, 864*325151a3SRui Paulo msg.go_intent ? (*msg.go_intent >> 1) : 865*325151a3SRui Paulo 0); 866f05cddf9SRui Paulo } else if (p2p->go_neg_peer && p2p->go_neg_peer != dev) { 8675b9c547cSRui Paulo p2p_dbg(p2p, "Already in Group Formation with another peer"); 868f05cddf9SRui Paulo status = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE; 869f05cddf9SRui Paulo } else { 870f05cddf9SRui Paulo int go; 871f05cddf9SRui Paulo 872f05cddf9SRui Paulo if (!p2p->go_neg_peer) { 8735b9c547cSRui Paulo p2p_dbg(p2p, "Starting GO Negotiation with previously authorized peer"); 874f05cddf9SRui Paulo if (!(dev->flags & P2P_DEV_FORCE_FREQ)) { 8755b9c547cSRui Paulo p2p_dbg(p2p, "Use default channel settings"); 876f05cddf9SRui Paulo p2p->op_reg_class = p2p->cfg->op_reg_class; 877f05cddf9SRui Paulo p2p->op_channel = p2p->cfg->op_channel; 878f05cddf9SRui Paulo os_memcpy(&p2p->channels, &p2p->cfg->channels, 879f05cddf9SRui Paulo sizeof(struct p2p_channels)); 880f05cddf9SRui Paulo } else { 8815b9c547cSRui Paulo p2p_dbg(p2p, "Use previously configured forced channel settings"); 882f05cddf9SRui Paulo } 883f05cddf9SRui Paulo } 884f05cddf9SRui Paulo 885f05cddf9SRui Paulo dev->flags &= ~P2P_DEV_NOT_YET_READY; 886f05cddf9SRui Paulo 887f05cddf9SRui Paulo if (!msg.go_intent) { 8885b9c547cSRui Paulo p2p_dbg(p2p, "No GO Intent attribute received"); 889f05cddf9SRui Paulo goto fail; 890f05cddf9SRui Paulo } 891f05cddf9SRui Paulo if ((*msg.go_intent >> 1) > P2P_MAX_GO_INTENT) { 8925b9c547cSRui Paulo p2p_dbg(p2p, "Invalid GO Intent value (%u) received", 893f05cddf9SRui Paulo *msg.go_intent >> 1); 894f05cddf9SRui Paulo goto fail; 895f05cddf9SRui Paulo } 896f05cddf9SRui Paulo 897f05cddf9SRui Paulo if (dev->go_neg_req_sent && 898f05cddf9SRui Paulo os_memcmp(sa, p2p->cfg->dev_addr, ETH_ALEN) > 0) { 8995b9c547cSRui Paulo p2p_dbg(p2p, "Do not reply since peer has higher address and GO Neg Request already sent"); 900f05cddf9SRui Paulo p2p_parse_free(&msg); 901f05cddf9SRui Paulo return; 902f05cddf9SRui Paulo } 903f05cddf9SRui Paulo 904f05cddf9SRui Paulo go = p2p_go_det(p2p->go_intent, *msg.go_intent); 905f05cddf9SRui Paulo if (go < 0) { 9065b9c547cSRui Paulo p2p_dbg(p2p, "Incompatible GO Intent"); 907f05cddf9SRui Paulo status = P2P_SC_FAIL_BOTH_GO_INTENT_15; 908f05cddf9SRui Paulo goto fail; 909f05cddf9SRui Paulo } 910f05cddf9SRui Paulo 911f05cddf9SRui Paulo if (p2p_peer_channels(p2p, dev, msg.channel_list, 912f05cddf9SRui Paulo msg.channel_list_len) < 0) { 9135b9c547cSRui Paulo p2p_dbg(p2p, "No common channels found"); 914f05cddf9SRui Paulo status = P2P_SC_FAIL_NO_COMMON_CHANNELS; 915f05cddf9SRui Paulo goto fail; 916f05cddf9SRui Paulo } 917f05cddf9SRui Paulo 918f05cddf9SRui Paulo switch (msg.dev_password_id) { 919f05cddf9SRui Paulo case DEV_PW_REGISTRAR_SPECIFIED: 9205b9c547cSRui Paulo p2p_dbg(p2p, "PIN from peer Display"); 921f05cddf9SRui Paulo if (dev->wps_method != WPS_PIN_KEYPAD) { 9225b9c547cSRui Paulo p2p_dbg(p2p, "We have wps_method=%s -> incompatible", 923f05cddf9SRui Paulo p2p_wps_method_str(dev->wps_method)); 924f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 925f05cddf9SRui Paulo goto fail; 926f05cddf9SRui Paulo } 927f05cddf9SRui Paulo break; 928f05cddf9SRui Paulo case DEV_PW_USER_SPECIFIED: 9295b9c547cSRui Paulo p2p_dbg(p2p, "Peer entered PIN on Keypad"); 930f05cddf9SRui Paulo if (dev->wps_method != WPS_PIN_DISPLAY) { 9315b9c547cSRui Paulo p2p_dbg(p2p, "We have wps_method=%s -> incompatible", 932f05cddf9SRui Paulo p2p_wps_method_str(dev->wps_method)); 933f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 934f05cddf9SRui Paulo goto fail; 935f05cddf9SRui Paulo } 936f05cddf9SRui Paulo break; 937f05cddf9SRui Paulo case DEV_PW_PUSHBUTTON: 9385b9c547cSRui Paulo p2p_dbg(p2p, "Peer using pushbutton"); 939f05cddf9SRui Paulo if (dev->wps_method != WPS_PBC) { 9405b9c547cSRui Paulo p2p_dbg(p2p, "We have wps_method=%s -> incompatible", 9415b9c547cSRui Paulo p2p_wps_method_str(dev->wps_method)); 9425b9c547cSRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 9435b9c547cSRui Paulo goto fail; 9445b9c547cSRui Paulo } 9455b9c547cSRui Paulo break; 9465b9c547cSRui Paulo case DEV_PW_P2PS_DEFAULT: 9475b9c547cSRui Paulo p2p_dbg(p2p, "Peer using P2PS pin"); 9485b9c547cSRui Paulo if (dev->wps_method != WPS_P2PS) { 9495b9c547cSRui Paulo p2p_dbg(p2p, 9505b9c547cSRui Paulo "We have wps_method=%s -> incompatible", 951f05cddf9SRui Paulo p2p_wps_method_str(dev->wps_method)); 952f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 953f05cddf9SRui Paulo goto fail; 954f05cddf9SRui Paulo } 955f05cddf9SRui Paulo break; 956f05cddf9SRui Paulo default: 9575b9c547cSRui Paulo if (msg.dev_password_id && 9585b9c547cSRui Paulo msg.dev_password_id == dev->oob_pw_id) { 9595b9c547cSRui Paulo p2p_dbg(p2p, "Peer using NFC"); 9605b9c547cSRui Paulo if (dev->wps_method != WPS_NFC) { 9615b9c547cSRui Paulo p2p_dbg(p2p, "We have wps_method=%s -> incompatible", 9625b9c547cSRui Paulo p2p_wps_method_str( 9635b9c547cSRui Paulo dev->wps_method)); 9645b9c547cSRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 9655b9c547cSRui Paulo goto fail; 9665b9c547cSRui Paulo } 9675b9c547cSRui Paulo break; 9685b9c547cSRui Paulo } 9695b9c547cSRui Paulo #ifdef CONFIG_WPS_NFC 9705b9c547cSRui Paulo if (p2p->authorized_oob_dev_pw_id && 9715b9c547cSRui Paulo msg.dev_password_id == 9725b9c547cSRui Paulo p2p->authorized_oob_dev_pw_id) { 9735b9c547cSRui Paulo p2p_dbg(p2p, "Using static handover with our device password from NFC Tag"); 9745b9c547cSRui Paulo dev->wps_method = WPS_NFC; 9755b9c547cSRui Paulo dev->oob_pw_id = p2p->authorized_oob_dev_pw_id; 9765b9c547cSRui Paulo break; 9775b9c547cSRui Paulo } 9785b9c547cSRui Paulo #endif /* CONFIG_WPS_NFC */ 9795b9c547cSRui Paulo p2p_dbg(p2p, "Unsupported Device Password ID %d", 980f05cddf9SRui Paulo msg.dev_password_id); 981f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 982f05cddf9SRui Paulo goto fail; 983f05cddf9SRui Paulo } 984f05cddf9SRui Paulo 985f05cddf9SRui Paulo if (go && p2p_go_select_channel(p2p, dev, &status) < 0) 986f05cddf9SRui Paulo goto fail; 987f05cddf9SRui Paulo 988f05cddf9SRui Paulo dev->go_state = go ? LOCAL_GO : REMOTE_GO; 9895b9c547cSRui Paulo dev->oper_freq = p2p_channel_to_freq(msg.operating_channel[3], 990f05cddf9SRui Paulo msg.operating_channel[4]); 9915b9c547cSRui Paulo p2p_dbg(p2p, "Peer operating channel preference: %d MHz", 9925b9c547cSRui Paulo dev->oper_freq); 993f05cddf9SRui Paulo 994*325151a3SRui Paulo /* 995*325151a3SRui Paulo * Use the driver preferred frequency list extension if 996*325151a3SRui Paulo * supported. 997*325151a3SRui Paulo */ 998*325151a3SRui Paulo p2p_check_pref_chan(p2p, go, dev, &msg); 999*325151a3SRui Paulo 1000f05cddf9SRui Paulo if (msg.config_timeout) { 1001f05cddf9SRui Paulo dev->go_timeout = msg.config_timeout[0]; 1002f05cddf9SRui Paulo dev->client_timeout = msg.config_timeout[1]; 1003f05cddf9SRui Paulo } 1004f05cddf9SRui Paulo 10055b9c547cSRui Paulo p2p_dbg(p2p, "GO Negotiation with " MACSTR, MAC2STR(sa)); 1006f05cddf9SRui Paulo if (p2p->state != P2P_IDLE) 1007f05cddf9SRui Paulo p2p_stop_find_for_freq(p2p, rx_freq); 1008f05cddf9SRui Paulo p2p_set_state(p2p, P2P_GO_NEG); 1009f05cddf9SRui Paulo p2p_clear_timeout(p2p); 1010f05cddf9SRui Paulo dev->dialog_token = msg.dialog_token; 1011f05cddf9SRui Paulo os_memcpy(dev->intended_addr, msg.intended_addr, ETH_ALEN); 1012f05cddf9SRui Paulo p2p->go_neg_peer = dev; 10135b9c547cSRui Paulo eloop_cancel_timeout(p2p_go_neg_wait_timeout, p2p, NULL); 1014f05cddf9SRui Paulo status = P2P_SC_SUCCESS; 1015f05cddf9SRui Paulo } 1016f05cddf9SRui Paulo 1017f05cddf9SRui Paulo fail: 1018f05cddf9SRui Paulo if (dev) 1019f05cddf9SRui Paulo dev->status = status; 1020f05cddf9SRui Paulo resp = p2p_build_go_neg_resp(p2p, dev, msg.dialog_token, status, 1021f05cddf9SRui Paulo !tie_breaker); 1022f05cddf9SRui Paulo p2p_parse_free(&msg); 1023f05cddf9SRui Paulo if (resp == NULL) 1024f05cddf9SRui Paulo return; 10255b9c547cSRui Paulo p2p_dbg(p2p, "Sending GO Negotiation Response"); 1026f05cddf9SRui Paulo if (rx_freq > 0) 1027f05cddf9SRui Paulo freq = rx_freq; 1028f05cddf9SRui Paulo else 10295b9c547cSRui Paulo freq = p2p_channel_to_freq(p2p->cfg->reg_class, 1030f05cddf9SRui Paulo p2p->cfg->channel); 1031f05cddf9SRui Paulo if (freq < 0) { 10325b9c547cSRui Paulo p2p_dbg(p2p, "Unknown regulatory class/channel"); 1033f05cddf9SRui Paulo wpabuf_free(resp); 1034f05cddf9SRui Paulo return; 1035f05cddf9SRui Paulo } 1036f05cddf9SRui Paulo if (status == P2P_SC_SUCCESS) { 1037f05cddf9SRui Paulo p2p->pending_action_state = P2P_PENDING_GO_NEG_RESPONSE; 1038f05cddf9SRui Paulo dev->flags |= P2P_DEV_WAIT_GO_NEG_CONFIRM; 1039f05cddf9SRui Paulo if (os_memcmp(sa, p2p->cfg->dev_addr, ETH_ALEN) < 0) { 1040f05cddf9SRui Paulo /* 1041f05cddf9SRui Paulo * Peer has smaller address, so the GO Negotiation 1042f05cddf9SRui Paulo * Response from us is expected to complete 1043f05cddf9SRui Paulo * negotiation. Ignore a GO Negotiation Response from 1044f05cddf9SRui Paulo * the peer if it happens to be received after this 1045f05cddf9SRui Paulo * point due to a race condition in GO Negotiation 1046f05cddf9SRui Paulo * Request transmission and processing. 1047f05cddf9SRui Paulo */ 1048f05cddf9SRui Paulo dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE; 1049f05cddf9SRui Paulo } 1050f05cddf9SRui Paulo } else 1051f05cddf9SRui Paulo p2p->pending_action_state = 1052f05cddf9SRui Paulo P2P_PENDING_GO_NEG_RESPONSE_FAILURE; 1053f05cddf9SRui Paulo if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, 1054f05cddf9SRui Paulo p2p->cfg->dev_addr, 10555b9c547cSRui Paulo wpabuf_head(resp), wpabuf_len(resp), 500) < 0) { 10565b9c547cSRui Paulo p2p_dbg(p2p, "Failed to send Action frame"); 1057f05cddf9SRui Paulo } 1058f05cddf9SRui Paulo 1059f05cddf9SRui Paulo wpabuf_free(resp); 1060f05cddf9SRui Paulo } 1061f05cddf9SRui Paulo 1062f05cddf9SRui Paulo 1063f05cddf9SRui Paulo static struct wpabuf * p2p_build_go_neg_conf(struct p2p_data *p2p, 1064f05cddf9SRui Paulo struct p2p_device *peer, 1065f05cddf9SRui Paulo u8 dialog_token, u8 status, 1066f05cddf9SRui Paulo const u8 *resp_chan, int go) 1067f05cddf9SRui Paulo { 1068f05cddf9SRui Paulo struct wpabuf *buf; 1069f05cddf9SRui Paulo u8 *len; 1070f05cddf9SRui Paulo struct p2p_channels res; 1071f05cddf9SRui Paulo u8 group_capab; 1072f05cddf9SRui Paulo size_t extra = 0; 1073f05cddf9SRui Paulo 10745b9c547cSRui Paulo p2p_dbg(p2p, "Building GO Negotiation Confirm"); 1075f05cddf9SRui Paulo 1076f05cddf9SRui Paulo #ifdef CONFIG_WIFI_DISPLAY 1077f05cddf9SRui Paulo if (p2p->wfd_ie_go_neg) 1078f05cddf9SRui Paulo extra = wpabuf_len(p2p->wfd_ie_go_neg); 1079f05cddf9SRui Paulo #endif /* CONFIG_WIFI_DISPLAY */ 1080f05cddf9SRui Paulo 10815b9c547cSRui Paulo if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_CONF]) 10825b9c547cSRui Paulo extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_CONF]); 10835b9c547cSRui Paulo 1084f05cddf9SRui Paulo buf = wpabuf_alloc(1000 + extra); 1085f05cddf9SRui Paulo if (buf == NULL) 1086f05cddf9SRui Paulo return NULL; 1087f05cddf9SRui Paulo 1088f05cddf9SRui Paulo p2p_buf_add_public_action_hdr(buf, P2P_GO_NEG_CONF, dialog_token); 1089f05cddf9SRui Paulo 1090f05cddf9SRui Paulo len = p2p_buf_add_ie_hdr(buf); 1091f05cddf9SRui Paulo p2p_buf_add_status(buf, status); 1092f05cddf9SRui Paulo group_capab = 0; 1093f05cddf9SRui Paulo if (peer->go_state == LOCAL_GO) { 1094f05cddf9SRui Paulo if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) { 1095f05cddf9SRui Paulo group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP; 1096f05cddf9SRui Paulo if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN) 1097f05cddf9SRui Paulo group_capab |= 1098f05cddf9SRui Paulo P2P_GROUP_CAPAB_PERSISTENT_RECONN; 1099f05cddf9SRui Paulo } 1100f05cddf9SRui Paulo if (p2p->cross_connect) 1101f05cddf9SRui Paulo group_capab |= P2P_GROUP_CAPAB_CROSS_CONN; 1102f05cddf9SRui Paulo if (p2p->cfg->p2p_intra_bss) 1103f05cddf9SRui Paulo group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST; 1104f05cddf9SRui Paulo } 1105f05cddf9SRui Paulo p2p_buf_add_capability(buf, p2p->dev_capab & 1106f05cddf9SRui Paulo ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 1107f05cddf9SRui Paulo group_capab); 1108f05cddf9SRui Paulo if (go || resp_chan == NULL) 1109f05cddf9SRui Paulo p2p_buf_add_operating_channel(buf, p2p->cfg->country, 1110f05cddf9SRui Paulo p2p->op_reg_class, 1111f05cddf9SRui Paulo p2p->op_channel); 1112f05cddf9SRui Paulo else 1113f05cddf9SRui Paulo p2p_buf_add_operating_channel(buf, (const char *) resp_chan, 1114f05cddf9SRui Paulo resp_chan[3], resp_chan[4]); 1115f05cddf9SRui Paulo p2p_channels_intersect(&p2p->channels, &peer->channels, &res); 1116f05cddf9SRui Paulo p2p_buf_add_channel_list(buf, p2p->cfg->country, &res); 1117f05cddf9SRui Paulo if (go) { 1118f05cddf9SRui Paulo p2p_buf_add_group_id(buf, p2p->cfg->dev_addr, p2p->ssid, 1119f05cddf9SRui Paulo p2p->ssid_len); 1120f05cddf9SRui Paulo } 1121f05cddf9SRui Paulo p2p_buf_update_ie_hdr(buf, len); 1122f05cddf9SRui Paulo 1123f05cddf9SRui Paulo #ifdef CONFIG_WIFI_DISPLAY 1124f05cddf9SRui Paulo if (p2p->wfd_ie_go_neg) 1125f05cddf9SRui Paulo wpabuf_put_buf(buf, p2p->wfd_ie_go_neg); 1126f05cddf9SRui Paulo #endif /* CONFIG_WIFI_DISPLAY */ 1127f05cddf9SRui Paulo 11285b9c547cSRui Paulo if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_CONF]) 11295b9c547cSRui Paulo wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_CONF]); 11305b9c547cSRui Paulo 1131f05cddf9SRui Paulo return buf; 1132f05cddf9SRui Paulo } 1133f05cddf9SRui Paulo 1134f05cddf9SRui Paulo 1135f05cddf9SRui Paulo void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa, 1136f05cddf9SRui Paulo const u8 *data, size_t len, int rx_freq) 1137f05cddf9SRui Paulo { 1138f05cddf9SRui Paulo struct p2p_device *dev; 1139f05cddf9SRui Paulo int go = -1; 1140f05cddf9SRui Paulo struct p2p_message msg; 1141f05cddf9SRui Paulo u8 status = P2P_SC_SUCCESS; 1142f05cddf9SRui Paulo int freq; 1143f05cddf9SRui Paulo 11445b9c547cSRui Paulo p2p_dbg(p2p, "Received GO Negotiation Response from " MACSTR 1145f05cddf9SRui Paulo " (freq=%d)", MAC2STR(sa), rx_freq); 1146f05cddf9SRui Paulo dev = p2p_get_device(p2p, sa); 1147f05cddf9SRui Paulo if (dev == NULL || dev->wps_method == WPS_NOT_READY || 1148f05cddf9SRui Paulo dev != p2p->go_neg_peer) { 11495b9c547cSRui Paulo p2p_dbg(p2p, "Not ready for GO negotiation with " MACSTR, 1150f05cddf9SRui Paulo MAC2STR(sa)); 1151f05cddf9SRui Paulo return; 1152f05cddf9SRui Paulo } 1153f05cddf9SRui Paulo 1154f05cddf9SRui Paulo if (p2p_parse(data, len, &msg)) 1155f05cddf9SRui Paulo return; 1156f05cddf9SRui Paulo 1157f05cddf9SRui Paulo if (!(dev->flags & P2P_DEV_WAIT_GO_NEG_RESPONSE)) { 11585b9c547cSRui Paulo p2p_dbg(p2p, "Was not expecting GO Negotiation Response - ignore"); 1159f05cddf9SRui Paulo p2p_parse_free(&msg); 1160f05cddf9SRui Paulo return; 1161f05cddf9SRui Paulo } 1162f05cddf9SRui Paulo dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE; 1163f05cddf9SRui Paulo 1164f05cddf9SRui Paulo if (msg.dialog_token != dev->dialog_token) { 11655b9c547cSRui Paulo p2p_dbg(p2p, "Unexpected Dialog Token %u (expected %u)", 1166f05cddf9SRui Paulo msg.dialog_token, dev->dialog_token); 1167f05cddf9SRui Paulo p2p_parse_free(&msg); 1168f05cddf9SRui Paulo return; 1169f05cddf9SRui Paulo } 1170f05cddf9SRui Paulo 1171f05cddf9SRui Paulo if (!msg.status) { 11725b9c547cSRui Paulo p2p_dbg(p2p, "No Status attribute received"); 1173f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 1174f05cddf9SRui Paulo goto fail; 1175f05cddf9SRui Paulo } 1176f05cddf9SRui Paulo if (*msg.status) { 11775b9c547cSRui Paulo p2p_dbg(p2p, "GO Negotiation rejected: status %d", *msg.status); 1178f05cddf9SRui Paulo dev->go_neg_req_sent = 0; 1179f05cddf9SRui Paulo if (*msg.status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) { 11805b9c547cSRui Paulo p2p_dbg(p2p, "Wait for the peer to become ready for GO Negotiation"); 1181f05cddf9SRui Paulo dev->flags |= P2P_DEV_NOT_YET_READY; 11825b9c547cSRui Paulo eloop_cancel_timeout(p2p_go_neg_wait_timeout, p2p, 11835b9c547cSRui Paulo NULL); 11845b9c547cSRui Paulo eloop_register_timeout(120, 0, p2p_go_neg_wait_timeout, 11855b9c547cSRui Paulo p2p, NULL); 11865b9c547cSRui Paulo if (p2p->state == P2P_CONNECT_LISTEN) 11875b9c547cSRui Paulo p2p_set_state(p2p, P2P_WAIT_PEER_CONNECT); 11885b9c547cSRui Paulo else 1189f05cddf9SRui Paulo p2p_set_state(p2p, P2P_WAIT_PEER_IDLE); 1190f05cddf9SRui Paulo p2p_set_timeout(p2p, 0, 0); 1191f05cddf9SRui Paulo } else { 11925b9c547cSRui Paulo p2p_dbg(p2p, "Stop GO Negotiation attempt"); 11935b9c547cSRui Paulo p2p_go_neg_failed(p2p, *msg.status); 1194f05cddf9SRui Paulo } 1195f05cddf9SRui Paulo p2p->cfg->send_action_done(p2p->cfg->cb_ctx); 1196f05cddf9SRui Paulo p2p_parse_free(&msg); 1197f05cddf9SRui Paulo return; 1198f05cddf9SRui Paulo } 1199f05cddf9SRui Paulo 1200f05cddf9SRui Paulo if (!msg.capability) { 12015b9c547cSRui Paulo p2p_dbg(p2p, "Mandatory Capability attribute missing from GO Negotiation Response"); 1202f05cddf9SRui Paulo #ifdef CONFIG_P2P_STRICT 1203f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 1204f05cddf9SRui Paulo goto fail; 1205f05cddf9SRui Paulo #endif /* CONFIG_P2P_STRICT */ 1206f05cddf9SRui Paulo } 1207f05cddf9SRui Paulo 1208f05cddf9SRui Paulo if (!msg.p2p_device_info) { 12095b9c547cSRui Paulo p2p_dbg(p2p, "Mandatory P2P Device Info attribute missing from GO Negotiation Response"); 1210f05cddf9SRui Paulo #ifdef CONFIG_P2P_STRICT 1211f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 1212f05cddf9SRui Paulo goto fail; 1213f05cddf9SRui Paulo #endif /* CONFIG_P2P_STRICT */ 1214f05cddf9SRui Paulo } 1215f05cddf9SRui Paulo 1216f05cddf9SRui Paulo if (!msg.intended_addr) { 12175b9c547cSRui Paulo p2p_dbg(p2p, "No Intended P2P Interface Address attribute received"); 1218f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 1219f05cddf9SRui Paulo goto fail; 1220f05cddf9SRui Paulo } 1221f05cddf9SRui Paulo 1222f05cddf9SRui Paulo if (!msg.go_intent) { 12235b9c547cSRui Paulo p2p_dbg(p2p, "No GO Intent attribute received"); 1224f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 1225f05cddf9SRui Paulo goto fail; 1226f05cddf9SRui Paulo } 1227f05cddf9SRui Paulo if ((*msg.go_intent >> 1) > P2P_MAX_GO_INTENT) { 12285b9c547cSRui Paulo p2p_dbg(p2p, "Invalid GO Intent value (%u) received", 1229f05cddf9SRui Paulo *msg.go_intent >> 1); 1230f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 1231f05cddf9SRui Paulo goto fail; 1232f05cddf9SRui Paulo } 1233f05cddf9SRui Paulo 1234f05cddf9SRui Paulo go = p2p_go_det(p2p->go_intent, *msg.go_intent); 1235f05cddf9SRui Paulo if (go < 0) { 12365b9c547cSRui Paulo p2p_dbg(p2p, "Incompatible GO Intent"); 1237f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PARAMS; 1238f05cddf9SRui Paulo goto fail; 1239f05cddf9SRui Paulo } 1240f05cddf9SRui Paulo 1241f05cddf9SRui Paulo if (!go && msg.group_id) { 1242f05cddf9SRui Paulo /* Store SSID for Provisioning step */ 1243f05cddf9SRui Paulo p2p->ssid_len = msg.group_id_len - ETH_ALEN; 1244f05cddf9SRui Paulo os_memcpy(p2p->ssid, msg.group_id + ETH_ALEN, p2p->ssid_len); 1245f05cddf9SRui Paulo } else if (!go) { 12465b9c547cSRui Paulo p2p_dbg(p2p, "Mandatory P2P Group ID attribute missing from GO Negotiation Response"); 1247f05cddf9SRui Paulo p2p->ssid_len = 0; 1248f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 1249f05cddf9SRui Paulo goto fail; 1250f05cddf9SRui Paulo } 1251f05cddf9SRui Paulo 1252f05cddf9SRui Paulo if (!msg.config_timeout) { 12535b9c547cSRui Paulo p2p_dbg(p2p, "Mandatory Configuration Timeout attribute missing from GO Negotiation Response"); 1254f05cddf9SRui Paulo #ifdef CONFIG_P2P_STRICT 1255f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 1256f05cddf9SRui Paulo goto fail; 1257f05cddf9SRui Paulo #endif /* CONFIG_P2P_STRICT */ 1258f05cddf9SRui Paulo } else { 1259f05cddf9SRui Paulo dev->go_timeout = msg.config_timeout[0]; 1260f05cddf9SRui Paulo dev->client_timeout = msg.config_timeout[1]; 1261f05cddf9SRui Paulo } 1262f05cddf9SRui Paulo 1263f05cddf9SRui Paulo if (!msg.operating_channel && !go) { 1264f05cddf9SRui Paulo /* 1265f05cddf9SRui Paulo * Note: P2P Client may omit Operating Channel attribute to 1266f05cddf9SRui Paulo * indicate it does not have a preference. 1267f05cddf9SRui Paulo */ 12685b9c547cSRui Paulo p2p_dbg(p2p, "No Operating Channel attribute received"); 1269f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 1270f05cddf9SRui Paulo goto fail; 1271f05cddf9SRui Paulo } 1272f05cddf9SRui Paulo if (!msg.channel_list) { 12735b9c547cSRui Paulo p2p_dbg(p2p, "No Channel List attribute received"); 1274f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 1275f05cddf9SRui Paulo goto fail; 1276f05cddf9SRui Paulo } 1277f05cddf9SRui Paulo 1278f05cddf9SRui Paulo if (p2p_peer_channels(p2p, dev, msg.channel_list, 1279f05cddf9SRui Paulo msg.channel_list_len) < 0) { 12805b9c547cSRui Paulo p2p_dbg(p2p, "No common channels found"); 1281f05cddf9SRui Paulo status = P2P_SC_FAIL_NO_COMMON_CHANNELS; 1282f05cddf9SRui Paulo goto fail; 1283f05cddf9SRui Paulo } 1284f05cddf9SRui Paulo 1285f05cddf9SRui Paulo if (msg.operating_channel) { 12865b9c547cSRui Paulo dev->oper_freq = p2p_channel_to_freq(msg.operating_channel[3], 1287f05cddf9SRui Paulo msg.operating_channel[4]); 12885b9c547cSRui Paulo p2p_dbg(p2p, "Peer operating channel preference: %d MHz", 12895b9c547cSRui Paulo dev->oper_freq); 1290f05cddf9SRui Paulo } else 1291f05cddf9SRui Paulo dev->oper_freq = 0; 1292f05cddf9SRui Paulo 1293f05cddf9SRui Paulo switch (msg.dev_password_id) { 1294f05cddf9SRui Paulo case DEV_PW_REGISTRAR_SPECIFIED: 12955b9c547cSRui Paulo p2p_dbg(p2p, "PIN from peer Display"); 1296f05cddf9SRui Paulo if (dev->wps_method != WPS_PIN_KEYPAD) { 12975b9c547cSRui Paulo p2p_dbg(p2p, "We have wps_method=%s -> incompatible", 1298f05cddf9SRui Paulo p2p_wps_method_str(dev->wps_method)); 1299f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 1300f05cddf9SRui Paulo goto fail; 1301f05cddf9SRui Paulo } 1302f05cddf9SRui Paulo break; 1303f05cddf9SRui Paulo case DEV_PW_USER_SPECIFIED: 13045b9c547cSRui Paulo p2p_dbg(p2p, "Peer entered PIN on Keypad"); 1305f05cddf9SRui Paulo if (dev->wps_method != WPS_PIN_DISPLAY) { 13065b9c547cSRui Paulo p2p_dbg(p2p, "We have wps_method=%s -> incompatible", 1307f05cddf9SRui Paulo p2p_wps_method_str(dev->wps_method)); 1308f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 1309f05cddf9SRui Paulo goto fail; 1310f05cddf9SRui Paulo } 1311f05cddf9SRui Paulo break; 1312f05cddf9SRui Paulo case DEV_PW_PUSHBUTTON: 13135b9c547cSRui Paulo p2p_dbg(p2p, "Peer using pushbutton"); 1314f05cddf9SRui Paulo if (dev->wps_method != WPS_PBC) { 13155b9c547cSRui Paulo p2p_dbg(p2p, "We have wps_method=%s -> incompatible", 13165b9c547cSRui Paulo p2p_wps_method_str(dev->wps_method)); 13175b9c547cSRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 13185b9c547cSRui Paulo goto fail; 13195b9c547cSRui Paulo } 13205b9c547cSRui Paulo break; 13215b9c547cSRui Paulo case DEV_PW_P2PS_DEFAULT: 13225b9c547cSRui Paulo p2p_dbg(p2p, "P2P: Peer using P2PS default pin"); 13235b9c547cSRui Paulo if (dev->wps_method != WPS_P2PS) { 13245b9c547cSRui Paulo p2p_dbg(p2p, "We have wps_method=%s -> incompatible", 1325f05cddf9SRui Paulo p2p_wps_method_str(dev->wps_method)); 1326f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 1327f05cddf9SRui Paulo goto fail; 1328f05cddf9SRui Paulo } 1329f05cddf9SRui Paulo break; 1330f05cddf9SRui Paulo default: 13315b9c547cSRui Paulo if (msg.dev_password_id && 13325b9c547cSRui Paulo msg.dev_password_id == dev->oob_pw_id) { 13335b9c547cSRui Paulo p2p_dbg(p2p, "Peer using NFC"); 13345b9c547cSRui Paulo if (dev->wps_method != WPS_NFC) { 13355b9c547cSRui Paulo p2p_dbg(p2p, "We have wps_method=%s -> incompatible", 13365b9c547cSRui Paulo p2p_wps_method_str(dev->wps_method)); 13375b9c547cSRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 13385b9c547cSRui Paulo goto fail; 13395b9c547cSRui Paulo } 13405b9c547cSRui Paulo break; 13415b9c547cSRui Paulo } 13425b9c547cSRui Paulo p2p_dbg(p2p, "Unsupported Device Password ID %d", 1343f05cddf9SRui Paulo msg.dev_password_id); 1344f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 1345f05cddf9SRui Paulo goto fail; 1346f05cddf9SRui Paulo } 1347f05cddf9SRui Paulo 1348f05cddf9SRui Paulo if (go && p2p_go_select_channel(p2p, dev, &status) < 0) 1349f05cddf9SRui Paulo goto fail; 1350f05cddf9SRui Paulo 1351*325151a3SRui Paulo /* 1352*325151a3SRui Paulo * Use the driver preferred frequency list extension if local device is 1353*325151a3SRui Paulo * GO. 1354*325151a3SRui Paulo */ 1355*325151a3SRui Paulo if (go) 1356*325151a3SRui Paulo p2p_check_pref_chan(p2p, go, dev, &msg); 1357*325151a3SRui Paulo 1358f05cddf9SRui Paulo p2p_set_state(p2p, P2P_GO_NEG); 1359f05cddf9SRui Paulo p2p_clear_timeout(p2p); 1360f05cddf9SRui Paulo 13615b9c547cSRui Paulo p2p_dbg(p2p, "GO Negotiation with " MACSTR, MAC2STR(sa)); 1362f05cddf9SRui Paulo os_memcpy(dev->intended_addr, msg.intended_addr, ETH_ALEN); 1363f05cddf9SRui Paulo 1364f05cddf9SRui Paulo fail: 13655b9c547cSRui Paulo /* Store GO Negotiation Confirmation to allow retransmission */ 13665b9c547cSRui Paulo wpabuf_free(dev->go_neg_conf); 13675b9c547cSRui Paulo dev->go_neg_conf = p2p_build_go_neg_conf(p2p, dev, msg.dialog_token, 13685b9c547cSRui Paulo status, msg.operating_channel, 13695b9c547cSRui Paulo go); 1370f05cddf9SRui Paulo p2p_parse_free(&msg); 13715b9c547cSRui Paulo if (dev->go_neg_conf == NULL) 1372f05cddf9SRui Paulo return; 13735b9c547cSRui Paulo p2p_dbg(p2p, "Sending GO Negotiation Confirm"); 1374f05cddf9SRui Paulo if (status == P2P_SC_SUCCESS) { 1375f05cddf9SRui Paulo p2p->pending_action_state = P2P_PENDING_GO_NEG_CONFIRM; 1376f05cddf9SRui Paulo dev->go_state = go ? LOCAL_GO : REMOTE_GO; 1377f05cddf9SRui Paulo } else 1378f05cddf9SRui Paulo p2p->pending_action_state = P2P_NO_PENDING_ACTION; 1379f05cddf9SRui Paulo if (rx_freq > 0) 1380f05cddf9SRui Paulo freq = rx_freq; 1381f05cddf9SRui Paulo else 1382f05cddf9SRui Paulo freq = dev->listen_freq; 13835b9c547cSRui Paulo 13845b9c547cSRui Paulo dev->go_neg_conf_freq = freq; 13855b9c547cSRui Paulo dev->go_neg_conf_sent = 0; 13865b9c547cSRui Paulo 1387f05cddf9SRui Paulo if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, sa, 13885b9c547cSRui Paulo wpabuf_head(dev->go_neg_conf), 13895b9c547cSRui Paulo wpabuf_len(dev->go_neg_conf), 200) < 0) { 13905b9c547cSRui Paulo p2p_dbg(p2p, "Failed to send Action frame"); 13915b9c547cSRui Paulo p2p_go_neg_failed(p2p, -1); 13925b9c547cSRui Paulo p2p->cfg->send_action_done(p2p->cfg->cb_ctx); 13935b9c547cSRui Paulo } else 13945b9c547cSRui Paulo dev->go_neg_conf_sent++; 13955b9c547cSRui Paulo if (status != P2P_SC_SUCCESS) { 13965b9c547cSRui Paulo p2p_dbg(p2p, "GO Negotiation failed"); 13975b9c547cSRui Paulo p2p_go_neg_failed(p2p, status); 1398f05cddf9SRui Paulo } 1399f05cddf9SRui Paulo } 1400f05cddf9SRui Paulo 1401f05cddf9SRui Paulo 1402f05cddf9SRui Paulo void p2p_process_go_neg_conf(struct p2p_data *p2p, const u8 *sa, 1403f05cddf9SRui Paulo const u8 *data, size_t len) 1404f05cddf9SRui Paulo { 1405f05cddf9SRui Paulo struct p2p_device *dev; 1406f05cddf9SRui Paulo struct p2p_message msg; 1407f05cddf9SRui Paulo 14085b9c547cSRui Paulo p2p_dbg(p2p, "Received GO Negotiation Confirm from " MACSTR, 1409f05cddf9SRui Paulo MAC2STR(sa)); 1410f05cddf9SRui Paulo dev = p2p_get_device(p2p, sa); 1411f05cddf9SRui Paulo if (dev == NULL || dev->wps_method == WPS_NOT_READY || 1412f05cddf9SRui Paulo dev != p2p->go_neg_peer) { 14135b9c547cSRui Paulo p2p_dbg(p2p, "Not ready for GO negotiation with " MACSTR, 1414f05cddf9SRui Paulo MAC2STR(sa)); 1415f05cddf9SRui Paulo return; 1416f05cddf9SRui Paulo } 1417f05cddf9SRui Paulo 1418f05cddf9SRui Paulo if (p2p->pending_action_state == P2P_PENDING_GO_NEG_RESPONSE) { 14195b9c547cSRui Paulo p2p_dbg(p2p, "Stopped waiting for TX status on GO Negotiation Response since we already received Confirmation"); 1420f05cddf9SRui Paulo p2p->pending_action_state = P2P_NO_PENDING_ACTION; 1421f05cddf9SRui Paulo } 1422f05cddf9SRui Paulo 1423f05cddf9SRui Paulo if (p2p_parse(data, len, &msg)) 1424f05cddf9SRui Paulo return; 1425f05cddf9SRui Paulo 1426f05cddf9SRui Paulo if (!(dev->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM)) { 14275b9c547cSRui Paulo p2p_dbg(p2p, "Was not expecting GO Negotiation Confirm - ignore"); 14285b9c547cSRui Paulo p2p_parse_free(&msg); 1429f05cddf9SRui Paulo return; 1430f05cddf9SRui Paulo } 1431f05cddf9SRui Paulo dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM; 14325b9c547cSRui Paulo p2p->cfg->send_action_done(p2p->cfg->cb_ctx); 1433f05cddf9SRui Paulo 1434f05cddf9SRui Paulo if (msg.dialog_token != dev->dialog_token) { 14355b9c547cSRui Paulo p2p_dbg(p2p, "Unexpected Dialog Token %u (expected %u)", 1436f05cddf9SRui Paulo msg.dialog_token, dev->dialog_token); 1437f05cddf9SRui Paulo p2p_parse_free(&msg); 1438f05cddf9SRui Paulo return; 1439f05cddf9SRui Paulo } 1440f05cddf9SRui Paulo 1441f05cddf9SRui Paulo if (!msg.status) { 14425b9c547cSRui Paulo p2p_dbg(p2p, "No Status attribute received"); 1443f05cddf9SRui Paulo p2p_parse_free(&msg); 1444f05cddf9SRui Paulo return; 1445f05cddf9SRui Paulo } 1446f05cddf9SRui Paulo if (*msg.status) { 14475b9c547cSRui Paulo p2p_dbg(p2p, "GO Negotiation rejected: status %d", *msg.status); 14485b9c547cSRui Paulo p2p_go_neg_failed(p2p, *msg.status); 1449f05cddf9SRui Paulo p2p_parse_free(&msg); 1450f05cddf9SRui Paulo return; 1451f05cddf9SRui Paulo } 1452f05cddf9SRui Paulo 1453f05cddf9SRui Paulo if (dev->go_state == REMOTE_GO && msg.group_id) { 1454f05cddf9SRui Paulo /* Store SSID for Provisioning step */ 1455f05cddf9SRui Paulo p2p->ssid_len = msg.group_id_len - ETH_ALEN; 1456f05cddf9SRui Paulo os_memcpy(p2p->ssid, msg.group_id + ETH_ALEN, p2p->ssid_len); 1457f05cddf9SRui Paulo } else if (dev->go_state == REMOTE_GO) { 14585b9c547cSRui Paulo p2p_dbg(p2p, "Mandatory P2P Group ID attribute missing from GO Negotiation Confirmation"); 1459f05cddf9SRui Paulo p2p->ssid_len = 0; 14605b9c547cSRui Paulo p2p_go_neg_failed(p2p, P2P_SC_FAIL_INVALID_PARAMS); 1461f05cddf9SRui Paulo p2p_parse_free(&msg); 1462f05cddf9SRui Paulo return; 1463f05cddf9SRui Paulo } 1464f05cddf9SRui Paulo 1465f05cddf9SRui Paulo if (!msg.operating_channel) { 14665b9c547cSRui Paulo p2p_dbg(p2p, "Mandatory Operating Channel attribute missing from GO Negotiation Confirmation"); 1467f05cddf9SRui Paulo #ifdef CONFIG_P2P_STRICT 1468f05cddf9SRui Paulo p2p_parse_free(&msg); 1469f05cddf9SRui Paulo return; 1470f05cddf9SRui Paulo #endif /* CONFIG_P2P_STRICT */ 14715b9c547cSRui Paulo } else if (dev->go_state == REMOTE_GO) { 14725b9c547cSRui Paulo int oper_freq = p2p_channel_to_freq(msg.operating_channel[3], 14735b9c547cSRui Paulo msg.operating_channel[4]); 14745b9c547cSRui Paulo if (oper_freq != dev->oper_freq) { 14755b9c547cSRui Paulo p2p_dbg(p2p, "Updated peer (GO) operating channel preference from %d MHz to %d MHz", 14765b9c547cSRui Paulo dev->oper_freq, oper_freq); 14775b9c547cSRui Paulo dev->oper_freq = oper_freq; 14785b9c547cSRui Paulo } 1479f05cddf9SRui Paulo } 1480f05cddf9SRui Paulo 1481f05cddf9SRui Paulo if (!msg.channel_list) { 14825b9c547cSRui Paulo p2p_dbg(p2p, "Mandatory Operating Channel attribute missing from GO Negotiation Confirmation"); 1483f05cddf9SRui Paulo #ifdef CONFIG_P2P_STRICT 1484f05cddf9SRui Paulo p2p_parse_free(&msg); 1485f05cddf9SRui Paulo return; 1486f05cddf9SRui Paulo #endif /* CONFIG_P2P_STRICT */ 1487f05cddf9SRui Paulo } 1488f05cddf9SRui Paulo 1489f05cddf9SRui Paulo p2p_parse_free(&msg); 1490f05cddf9SRui Paulo 1491f05cddf9SRui Paulo if (dev->go_state == UNKNOWN_GO) { 1492f05cddf9SRui Paulo /* 1493f05cddf9SRui Paulo * This should not happen since GO negotiation has already 1494f05cddf9SRui Paulo * been completed. 1495f05cddf9SRui Paulo */ 14965b9c547cSRui Paulo p2p_dbg(p2p, "Unexpected GO Neg state - do not know which end becomes GO"); 1497f05cddf9SRui Paulo return; 1498f05cddf9SRui Paulo } 1499f05cddf9SRui Paulo 1500f05cddf9SRui Paulo /* 1501f05cddf9SRui Paulo * The peer could have missed our ctrl::ack frame for GO Negotiation 1502f05cddf9SRui Paulo * Confirm and continue retransmitting the frame. To reduce the 1503f05cddf9SRui Paulo * likelihood of the peer not getting successful TX status for the 1504f05cddf9SRui Paulo * GO Negotiation Confirm frame, wait a short time here before starting 1505f05cddf9SRui Paulo * the group so that we will remain on the current channel to 1506f05cddf9SRui Paulo * acknowledge any possible retransmission from the peer. 1507f05cddf9SRui Paulo */ 15085b9c547cSRui Paulo p2p_dbg(p2p, "20 ms wait on current channel before starting group"); 1509f05cddf9SRui Paulo os_sleep(0, 20000); 1510f05cddf9SRui Paulo 1511f05cddf9SRui Paulo p2p_go_complete(p2p, dev); 1512f05cddf9SRui Paulo } 1513