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; 41780fb4a2SCy Schubert u8 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 61780fb4a2SCy Schubert while (end - pos > 2) { 62f05cddf9SRui Paulo struct p2p_reg_class *cl = &ch->reg_class[ch->reg_classes]; 63f05cddf9SRui Paulo cl->reg_class = *pos++; 64780fb4a2SCy Schubert channels = *pos++; 65780fb4a2SCy Schubert if (channels > end - pos) { 665b9c547cSRui Paulo p2p_info(p2p, "Invalid peer Channel List"); 67f05cddf9SRui Paulo return -1; 68f05cddf9SRui Paulo } 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 188325151a3SRui Paulo p2p_buf_add_pref_channel_list(buf, p2p->pref_freq_list, 189325151a3SRui Paulo p2p->num_pref_freq); 190325151a3SRui 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); 31885732ac8SCy Schubert if (p2p->override_pref_op_class) { 31985732ac8SCy Schubert p2p_dbg(p2p, "Override operating channel preference"); 32085732ac8SCy Schubert p2p_buf_add_operating_channel(buf, p2p->cfg->country, 32185732ac8SCy Schubert p2p->override_pref_op_class, 32285732ac8SCy Schubert p2p->override_pref_channel); 32385732ac8SCy Schubert } else if (peer && peer->go_state == REMOTE_GO && !p2p->num_pref_freq) { 3245b9c547cSRui Paulo p2p_dbg(p2p, "Omit Operating Channel attribute"); 325f05cddf9SRui Paulo } else { 326f05cddf9SRui Paulo p2p_buf_add_operating_channel(buf, p2p->cfg->country, 327f05cddf9SRui Paulo p2p->op_reg_class, 328f05cddf9SRui Paulo p2p->op_channel); 329f05cddf9SRui Paulo } 330f05cddf9SRui Paulo p2p_buf_add_intended_addr(buf, p2p->intended_addr); 331f05cddf9SRui Paulo if (status || peer == NULL) { 332f05cddf9SRui Paulo p2p_buf_add_channel_list(buf, p2p->cfg->country, 333f05cddf9SRui Paulo &p2p->channels); 334f05cddf9SRui Paulo } else if (peer->go_state == REMOTE_GO) { 335f05cddf9SRui Paulo p2p_buf_add_channel_list(buf, p2p->cfg->country, 336f05cddf9SRui Paulo &p2p->channels); 337f05cddf9SRui Paulo } else { 338f05cddf9SRui Paulo struct p2p_channels res; 339f05cddf9SRui Paulo p2p_channels_intersect(&p2p->channels, &peer->channels, 340f05cddf9SRui Paulo &res); 341f05cddf9SRui Paulo p2p_buf_add_channel_list(buf, p2p->cfg->country, &res); 342f05cddf9SRui Paulo } 343f05cddf9SRui Paulo p2p_buf_add_device_info(buf, p2p, peer); 344f05cddf9SRui Paulo if (peer && peer->go_state == LOCAL_GO) { 345f05cddf9SRui Paulo p2p_buf_add_group_id(buf, p2p->cfg->dev_addr, p2p->ssid, 346f05cddf9SRui Paulo p2p->ssid_len); 347f05cddf9SRui Paulo } 348f05cddf9SRui Paulo p2p_buf_update_ie_hdr(buf, len); 349f05cddf9SRui Paulo 350f05cddf9SRui Paulo /* WPS IE with Device Password ID attribute */ 3515b9c547cSRui Paulo pw_id = p2p_wps_method_pw_id(peer ? peer->wps_method : WPS_NOT_READY); 3525b9c547cSRui Paulo if (peer && peer->oob_pw_id) 3535b9c547cSRui Paulo pw_id = peer->oob_pw_id; 3545b9c547cSRui Paulo if (p2p_build_wps_ie(p2p, buf, pw_id, 0) < 0) { 3555b9c547cSRui Paulo p2p_dbg(p2p, "Failed to build WPS IE for GO Negotiation Response"); 3565b9c547cSRui Paulo wpabuf_free(buf); 3575b9c547cSRui Paulo return NULL; 3585b9c547cSRui Paulo } 359f05cddf9SRui Paulo 360f05cddf9SRui Paulo #ifdef CONFIG_WIFI_DISPLAY 361f05cddf9SRui Paulo if (p2p->wfd_ie_go_neg) 362f05cddf9SRui Paulo wpabuf_put_buf(buf, p2p->wfd_ie_go_neg); 363f05cddf9SRui Paulo #endif /* CONFIG_WIFI_DISPLAY */ 364f05cddf9SRui Paulo 3655b9c547cSRui Paulo if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_RESP]) 3665b9c547cSRui Paulo wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_RESP]); 367f05cddf9SRui Paulo 368f05cddf9SRui Paulo return buf; 369f05cddf9SRui Paulo } 370f05cddf9SRui Paulo 371f05cddf9SRui Paulo 372f05cddf9SRui Paulo /** 373f05cddf9SRui Paulo * p2p_reselect_channel - Re-select operating channel based on peer information 374f05cddf9SRui Paulo * @p2p: P2P module context from p2p_init() 375f05cddf9SRui Paulo * @intersection: Support channel list intersection from local and peer 376f05cddf9SRui Paulo * 377f05cddf9SRui Paulo * This function is used to re-select the best channel after having received 378f05cddf9SRui Paulo * information from the peer to allow supported channel lists to be intersected. 379f05cddf9SRui Paulo * This can be used to improve initial channel selection done in 380f05cddf9SRui Paulo * p2p_prepare_channel() prior to the start of GO Negotiation. In addition, this 381f05cddf9SRui Paulo * can be used for Invitation case. 382f05cddf9SRui Paulo */ 383f05cddf9SRui Paulo void p2p_reselect_channel(struct p2p_data *p2p, 384f05cddf9SRui Paulo struct p2p_channels *intersection) 385f05cddf9SRui Paulo { 386f05cddf9SRui Paulo struct p2p_reg_class *cl; 387f05cddf9SRui Paulo int freq; 388f05cddf9SRui Paulo u8 op_reg_class, op_channel; 389f05cddf9SRui Paulo unsigned int i; 390325151a3SRui Paulo const int op_classes_5ghz[] = { 124, 125, 115, 0 }; 3915b9c547cSRui Paulo const int op_classes_ht40[] = { 126, 127, 116, 117, 0 }; 392780fb4a2SCy Schubert const int op_classes_vht[] = { 128, 129, 130, 0 }; 393c1d255d3SCy Schubert const int op_classes_edmg[] = { 181, 182, 183, 0 }; 394f05cddf9SRui Paulo 3955b9c547cSRui Paulo if (p2p->own_freq_preference > 0 && 3965b9c547cSRui Paulo p2p_freq_to_channel(p2p->own_freq_preference, 397f05cddf9SRui Paulo &op_reg_class, &op_channel) == 0 && 398f05cddf9SRui Paulo p2p_channels_includes(intersection, op_reg_class, op_channel)) { 3995b9c547cSRui Paulo p2p_dbg(p2p, "Pick own channel preference (reg_class %u channel %u) from intersection", 4005b9c547cSRui Paulo op_reg_class, op_channel); 4015b9c547cSRui Paulo p2p->op_reg_class = op_reg_class; 4025b9c547cSRui Paulo p2p->op_channel = op_channel; 4035b9c547cSRui Paulo return; 4045b9c547cSRui Paulo } 4055b9c547cSRui Paulo 4065b9c547cSRui Paulo if (p2p->best_freq_overall > 0 && 4075b9c547cSRui Paulo p2p_freq_to_channel(p2p->best_freq_overall, 4085b9c547cSRui Paulo &op_reg_class, &op_channel) == 0 && 4095b9c547cSRui Paulo p2p_channels_includes(intersection, op_reg_class, op_channel)) { 4105b9c547cSRui Paulo p2p_dbg(p2p, "Pick best overall channel (reg_class %u channel %u) from intersection", 4115b9c547cSRui Paulo op_reg_class, op_channel); 4125b9c547cSRui Paulo p2p->op_reg_class = op_reg_class; 4135b9c547cSRui Paulo p2p->op_channel = op_channel; 4145b9c547cSRui Paulo return; 4155b9c547cSRui Paulo } 4165b9c547cSRui Paulo 4175b9c547cSRui Paulo /* First, try to pick the best channel from another band */ 4185b9c547cSRui Paulo freq = p2p_channel_to_freq(p2p->op_reg_class, p2p->op_channel); 4195b9c547cSRui Paulo if (freq >= 2400 && freq < 2500 && p2p->best_freq_5 > 0 && 4205b9c547cSRui Paulo !p2p_channels_includes(intersection, p2p->op_reg_class, 4215b9c547cSRui Paulo p2p->op_channel) && 4225b9c547cSRui Paulo p2p_freq_to_channel(p2p->best_freq_5, 4235b9c547cSRui Paulo &op_reg_class, &op_channel) == 0 && 4245b9c547cSRui Paulo p2p_channels_includes(intersection, op_reg_class, op_channel)) { 4255b9c547cSRui Paulo p2p_dbg(p2p, "Pick best 5 GHz channel (reg_class %u channel %u) from intersection", 426f05cddf9SRui Paulo op_reg_class, op_channel); 427f05cddf9SRui Paulo p2p->op_reg_class = op_reg_class; 428f05cddf9SRui Paulo p2p->op_channel = op_channel; 429f05cddf9SRui Paulo return; 430f05cddf9SRui Paulo } 431f05cddf9SRui Paulo 432f05cddf9SRui Paulo if (freq >= 4900 && freq < 6000 && p2p->best_freq_24 > 0 && 4335b9c547cSRui Paulo !p2p_channels_includes(intersection, p2p->op_reg_class, 4345b9c547cSRui Paulo p2p->op_channel) && 4355b9c547cSRui Paulo p2p_freq_to_channel(p2p->best_freq_24, 436f05cddf9SRui Paulo &op_reg_class, &op_channel) == 0 && 437f05cddf9SRui Paulo p2p_channels_includes(intersection, op_reg_class, op_channel)) { 4385b9c547cSRui Paulo p2p_dbg(p2p, "Pick best 2.4 GHz channel (reg_class %u channel %u) from intersection", 439f05cddf9SRui Paulo op_reg_class, op_channel); 440f05cddf9SRui Paulo p2p->op_reg_class = op_reg_class; 441f05cddf9SRui Paulo p2p->op_channel = op_channel; 442f05cddf9SRui Paulo return; 443f05cddf9SRui Paulo } 444f05cddf9SRui Paulo 445f05cddf9SRui Paulo /* Select channel with highest preference if the peer supports it */ 446f05cddf9SRui Paulo for (i = 0; p2p->cfg->pref_chan && i < p2p->cfg->num_pref_chan; i++) { 447f05cddf9SRui Paulo if (p2p_channels_includes(intersection, 448f05cddf9SRui Paulo p2p->cfg->pref_chan[i].op_class, 449f05cddf9SRui Paulo p2p->cfg->pref_chan[i].chan)) { 450f05cddf9SRui Paulo p2p->op_reg_class = p2p->cfg->pref_chan[i].op_class; 451f05cddf9SRui Paulo p2p->op_channel = p2p->cfg->pref_chan[i].chan; 4525b9c547cSRui Paulo p2p_dbg(p2p, "Pick highest preferred channel (op_class %u channel %u) from intersection", 453f05cddf9SRui Paulo p2p->op_reg_class, p2p->op_channel); 454f05cddf9SRui Paulo return; 455f05cddf9SRui Paulo } 456f05cddf9SRui Paulo } 457f05cddf9SRui Paulo 458c1d255d3SCy Schubert /* Try a channel where we might be able to use EDMG */ 459c1d255d3SCy Schubert if (p2p_channel_select(intersection, op_classes_edmg, 460c1d255d3SCy Schubert &p2p->op_reg_class, &p2p->op_channel) == 0) { 461c1d255d3SCy Schubert p2p_dbg(p2p, "Pick possible EDMG channel (op_class %u channel %u) from intersection", 462c1d255d3SCy Schubert p2p->op_reg_class, p2p->op_channel); 463c1d255d3SCy Schubert return; 464c1d255d3SCy Schubert } 465c1d255d3SCy Schubert 4665b9c547cSRui Paulo /* Try a channel where we might be able to use VHT */ 4675b9c547cSRui Paulo if (p2p_channel_select(intersection, op_classes_vht, 4685b9c547cSRui Paulo &p2p->op_reg_class, &p2p->op_channel) == 0) { 4695b9c547cSRui Paulo p2p_dbg(p2p, "Pick possible VHT channel (op_class %u channel %u) from intersection", 4705b9c547cSRui Paulo p2p->op_reg_class, p2p->op_channel); 471f05cddf9SRui Paulo return; 472f05cddf9SRui Paulo } 4735b9c547cSRui Paulo 4745b9c547cSRui Paulo /* Try a channel where we might be able to use HT40 */ 4755b9c547cSRui Paulo if (p2p_channel_select(intersection, op_classes_ht40, 4765b9c547cSRui Paulo &p2p->op_reg_class, &p2p->op_channel) == 0) { 4775b9c547cSRui Paulo p2p_dbg(p2p, "Pick possible HT40 channel (op_class %u channel %u) from intersection", 4785b9c547cSRui Paulo p2p->op_reg_class, p2p->op_channel); 4795b9c547cSRui Paulo return; 4805b9c547cSRui Paulo } 4815b9c547cSRui Paulo 4825b9c547cSRui Paulo /* Prefer a 5 GHz channel */ 4835b9c547cSRui Paulo if (p2p_channel_select(intersection, op_classes_5ghz, 4845b9c547cSRui Paulo &p2p->op_reg_class, &p2p->op_channel) == 0) { 4855b9c547cSRui Paulo p2p_dbg(p2p, "Pick possible 5 GHz channel (op_class %u channel %u) from intersection", 4865b9c547cSRui Paulo p2p->op_reg_class, p2p->op_channel); 4875b9c547cSRui Paulo return; 488f05cddf9SRui Paulo } 489f05cddf9SRui Paulo 490f05cddf9SRui Paulo /* 491f05cddf9SRui Paulo * Try to see if the original channel is in the intersection. If 492f05cddf9SRui Paulo * so, no need to change anything, as it already contains some 493f05cddf9SRui Paulo * randomness. 494f05cddf9SRui Paulo */ 495f05cddf9SRui Paulo if (p2p_channels_includes(intersection, p2p->op_reg_class, 496f05cddf9SRui Paulo p2p->op_channel)) { 4975b9c547cSRui Paulo p2p_dbg(p2p, "Using original operating class and channel (op_class %u channel %u) from intersection", 498f05cddf9SRui Paulo p2p->op_reg_class, p2p->op_channel); 499f05cddf9SRui Paulo return; 500f05cddf9SRui Paulo } 501f05cddf9SRui Paulo 502f05cddf9SRui Paulo /* 503f05cddf9SRui Paulo * Fall back to whatever is included in the channel intersection since 504f05cddf9SRui Paulo * no better options seems to be available. 505f05cddf9SRui Paulo */ 506f05cddf9SRui Paulo cl = &intersection->reg_class[0]; 5075b9c547cSRui Paulo p2p_dbg(p2p, "Pick another channel (reg_class %u channel %u) from intersection", 508f05cddf9SRui Paulo cl->reg_class, cl->channel[0]); 509f05cddf9SRui Paulo p2p->op_reg_class = cl->reg_class; 510f05cddf9SRui Paulo p2p->op_channel = cl->channel[0]; 511f05cddf9SRui Paulo } 512f05cddf9SRui Paulo 513f05cddf9SRui Paulo 5145b9c547cSRui Paulo int p2p_go_select_channel(struct p2p_data *p2p, struct p2p_device *dev, 515f05cddf9SRui Paulo u8 *status) 516f05cddf9SRui Paulo { 5175b9c547cSRui Paulo struct p2p_channels tmp, intersection; 518f05cddf9SRui Paulo 5195b9c547cSRui Paulo p2p_channels_dump(p2p, "own channels", &p2p->channels); 5205b9c547cSRui Paulo p2p_channels_dump(p2p, "peer channels", &dev->channels); 5215b9c547cSRui Paulo p2p_channels_intersect(&p2p->channels, &dev->channels, &tmp); 5225b9c547cSRui Paulo p2p_channels_dump(p2p, "intersection", &tmp); 5235b9c547cSRui Paulo p2p_channels_remove_freqs(&tmp, &p2p->no_go_freq); 5245b9c547cSRui Paulo p2p_channels_dump(p2p, "intersection after no-GO removal", &tmp); 5255b9c547cSRui Paulo p2p_channels_intersect(&tmp, &p2p->cfg->channels, &intersection); 5265b9c547cSRui Paulo p2p_channels_dump(p2p, "intersection with local channel list", 5275b9c547cSRui Paulo &intersection); 528f05cddf9SRui Paulo if (intersection.reg_classes == 0 || 529f05cddf9SRui Paulo intersection.reg_class[0].channels == 0) { 530f05cddf9SRui Paulo *status = P2P_SC_FAIL_NO_COMMON_CHANNELS; 5315b9c547cSRui Paulo p2p_dbg(p2p, "No common channels found"); 532f05cddf9SRui Paulo return -1; 533f05cddf9SRui Paulo } 534f05cddf9SRui Paulo 535f05cddf9SRui Paulo if (!p2p_channels_includes(&intersection, p2p->op_reg_class, 536f05cddf9SRui Paulo p2p->op_channel)) { 537f05cddf9SRui Paulo if (dev->flags & P2P_DEV_FORCE_FREQ) { 538f05cddf9SRui Paulo *status = P2P_SC_FAIL_NO_COMMON_CHANNELS; 5395b9c547cSRui Paulo p2p_dbg(p2p, "Peer does not support the forced channel"); 540f05cddf9SRui Paulo return -1; 541f05cddf9SRui Paulo } 542f05cddf9SRui Paulo 5435b9c547cSRui Paulo p2p_dbg(p2p, "Selected operating channel (op_class %u channel %u) not acceptable to the peer", 5445b9c547cSRui Paulo p2p->op_reg_class, p2p->op_channel); 545f05cddf9SRui Paulo p2p_reselect_channel(p2p, &intersection); 546f05cddf9SRui Paulo } else if (!(dev->flags & P2P_DEV_FORCE_FREQ) && 547f05cddf9SRui Paulo !p2p->cfg->cfg_op_channel) { 5485b9c547cSRui Paulo p2p_dbg(p2p, "Try to optimize channel selection with peer information received; previously selected op_class %u channel %u", 549f05cddf9SRui Paulo p2p->op_reg_class, p2p->op_channel); 550f05cddf9SRui Paulo p2p_reselect_channel(p2p, &intersection); 551f05cddf9SRui Paulo } 552f05cddf9SRui Paulo 553f05cddf9SRui Paulo if (!p2p->ssid_set) { 554f05cddf9SRui Paulo p2p_build_ssid(p2p, p2p->ssid, &p2p->ssid_len); 555f05cddf9SRui Paulo p2p->ssid_set = 1; 556f05cddf9SRui Paulo } 557f05cddf9SRui Paulo 558f05cddf9SRui Paulo return 0; 559f05cddf9SRui Paulo } 560f05cddf9SRui Paulo 561f05cddf9SRui Paulo 562325151a3SRui Paulo static void p2p_check_pref_chan_no_recv(struct p2p_data *p2p, int go, 563325151a3SRui Paulo struct p2p_device *dev, 564325151a3SRui Paulo struct p2p_message *msg, 565325151a3SRui Paulo unsigned freq_list[], unsigned int size) 566325151a3SRui Paulo { 567325151a3SRui Paulo u8 op_class, op_channel; 568325151a3SRui Paulo unsigned int oper_freq = 0, i, j; 569325151a3SRui Paulo int found = 0; 570325151a3SRui Paulo 571325151a3SRui Paulo p2p_dbg(p2p, 572325151a3SRui Paulo "Peer didn't provide a preferred frequency list, see if any of our preferred channels are supported by peer device"); 573325151a3SRui Paulo 574325151a3SRui Paulo /* 575325151a3SRui Paulo * Search for a common channel in our preferred frequency list which is 576325151a3SRui Paulo * also supported by the peer device. 577325151a3SRui Paulo */ 578325151a3SRui Paulo for (i = 0; i < size && !found; i++) { 57985732ac8SCy Schubert /* Make sure that the common frequency is supported by peer. */ 580325151a3SRui Paulo oper_freq = freq_list[i]; 581325151a3SRui Paulo if (p2p_freq_to_channel(oper_freq, &op_class, 58285732ac8SCy Schubert &op_channel) < 0) 58385732ac8SCy Schubert continue; /* cannot happen due to earlier check */ 584325151a3SRui Paulo for (j = 0; j < msg->channel_list_len; j++) { 585*4b72b91aSCy Schubert if (!msg->channel_list || 586*4b72b91aSCy Schubert op_channel != msg->channel_list[j]) 587325151a3SRui Paulo continue; 588325151a3SRui Paulo 589325151a3SRui Paulo p2p->op_reg_class = op_class; 590325151a3SRui Paulo p2p->op_channel = op_channel; 591325151a3SRui Paulo os_memcpy(&p2p->channels, &p2p->cfg->channels, 592325151a3SRui Paulo sizeof(struct p2p_channels)); 593325151a3SRui Paulo found = 1; 594325151a3SRui Paulo break; 595325151a3SRui Paulo } 596325151a3SRui Paulo } 597325151a3SRui Paulo 598325151a3SRui Paulo if (found) { 599325151a3SRui Paulo p2p_dbg(p2p, 600325151a3SRui Paulo "Freq %d MHz is a preferred channel and is also supported by peer, use it as the operating channel", 601325151a3SRui Paulo oper_freq); 602325151a3SRui Paulo } else { 603325151a3SRui Paulo p2p_dbg(p2p, 60485732ac8SCy Schubert "None of our preferred channels are supported by peer!"); 605325151a3SRui Paulo } 606325151a3SRui Paulo } 607325151a3SRui Paulo 608325151a3SRui Paulo 609325151a3SRui Paulo static void p2p_check_pref_chan_recv(struct p2p_data *p2p, int go, 610325151a3SRui Paulo struct p2p_device *dev, 611325151a3SRui Paulo struct p2p_message *msg, 612325151a3SRui Paulo unsigned freq_list[], unsigned int size) 613325151a3SRui Paulo { 614325151a3SRui Paulo u8 op_class, op_channel; 615325151a3SRui Paulo unsigned int oper_freq = 0, i, j; 616325151a3SRui Paulo int found = 0; 617325151a3SRui Paulo 618325151a3SRui Paulo /* 619325151a3SRui Paulo * Peer device supports a Preferred Frequency List. 620325151a3SRui Paulo * Search for a common channel in the preferred frequency lists 621325151a3SRui Paulo * of both peer and local devices. 622325151a3SRui Paulo */ 623325151a3SRui Paulo for (i = 0; i < size && !found; i++) { 624325151a3SRui Paulo for (j = 2; j < (msg->pref_freq_list_len / 2); j++) { 625325151a3SRui Paulo oper_freq = p2p_channel_to_freq( 626325151a3SRui Paulo msg->pref_freq_list[2 * j], 627325151a3SRui Paulo msg->pref_freq_list[2 * j + 1]); 628325151a3SRui Paulo if (freq_list[i] != oper_freq) 629325151a3SRui Paulo continue; 630325151a3SRui Paulo if (p2p_freq_to_channel(oper_freq, &op_class, 63185732ac8SCy Schubert &op_channel) < 0) 63285732ac8SCy Schubert continue; /* cannot happen */ 633325151a3SRui Paulo p2p->op_reg_class = op_class; 634325151a3SRui Paulo p2p->op_channel = op_channel; 635325151a3SRui Paulo os_memcpy(&p2p->channels, &p2p->cfg->channels, 636325151a3SRui Paulo sizeof(struct p2p_channels)); 637325151a3SRui Paulo found = 1; 638325151a3SRui Paulo break; 639325151a3SRui Paulo } 640325151a3SRui Paulo } 641325151a3SRui Paulo 642325151a3SRui Paulo if (found) { 643325151a3SRui Paulo p2p_dbg(p2p, 644325151a3SRui Paulo "Freq %d MHz is a common preferred channel for both peer and local, use it as operating channel", 645325151a3SRui Paulo oper_freq); 646325151a3SRui Paulo } else { 64785732ac8SCy Schubert p2p_dbg(p2p, "No common preferred channels found!"); 648325151a3SRui Paulo } 649325151a3SRui Paulo } 650325151a3SRui Paulo 651325151a3SRui Paulo 652325151a3SRui Paulo void p2p_check_pref_chan(struct p2p_data *p2p, int go, 653325151a3SRui Paulo struct p2p_device *dev, struct p2p_message *msg) 654325151a3SRui Paulo { 655325151a3SRui Paulo unsigned int freq_list[P2P_MAX_PREF_CHANNELS], size; 656325151a3SRui Paulo unsigned int i; 657325151a3SRui Paulo u8 op_class, op_channel; 65885732ac8SCy Schubert char txt[100], *pos, *end; 65985732ac8SCy Schubert int res; 660325151a3SRui Paulo 661325151a3SRui Paulo /* 662325151a3SRui Paulo * Use the preferred channel list from the driver only if there is no 663325151a3SRui Paulo * forced_freq, e.g., P2P_CONNECT freq=..., and no preferred operating 664325151a3SRui Paulo * channel hardcoded in the configuration file. 665325151a3SRui Paulo */ 666325151a3SRui Paulo if (!p2p->cfg->get_pref_freq_list || p2p->cfg->num_pref_chan || 667325151a3SRui Paulo (dev->flags & P2P_DEV_FORCE_FREQ) || p2p->cfg->cfg_op_channel) 668325151a3SRui Paulo return; 669325151a3SRui Paulo 670325151a3SRui Paulo /* Obtain our preferred frequency list from driver based on P2P role. */ 671325151a3SRui Paulo size = P2P_MAX_PREF_CHANNELS; 672325151a3SRui Paulo if (p2p->cfg->get_pref_freq_list(p2p->cfg->cb_ctx, go, &size, 673325151a3SRui Paulo freq_list)) 674325151a3SRui Paulo return; 67585732ac8SCy Schubert /* Filter out frequencies that are not acceptable for P2P use */ 67685732ac8SCy Schubert i = 0; 67785732ac8SCy Schubert while (i < size) { 67885732ac8SCy Schubert if (p2p_freq_to_channel(freq_list[i], &op_class, 67985732ac8SCy Schubert &op_channel) < 0 || 68085732ac8SCy Schubert (!p2p_channels_includes(&p2p->cfg->channels, 68185732ac8SCy Schubert op_class, op_channel) && 68285732ac8SCy Schubert (go || !p2p_channels_includes(&p2p->cfg->cli_channels, 68385732ac8SCy Schubert op_class, op_channel)))) { 68485732ac8SCy Schubert p2p_dbg(p2p, 68585732ac8SCy Schubert "Ignore local driver frequency preference %u MHz since it is not acceptable for P2P use (go=%d)", 68685732ac8SCy Schubert freq_list[i], go); 68785732ac8SCy Schubert if (size - i - 1 > 0) 688206b73d0SCy Schubert os_memmove(&freq_list[i], &freq_list[i + 1], 689206b73d0SCy Schubert (size - i - 1) * 690206b73d0SCy Schubert sizeof(unsigned int)); 69185732ac8SCy Schubert size--; 69285732ac8SCy Schubert continue; 69385732ac8SCy Schubert } 69485732ac8SCy Schubert 69585732ac8SCy Schubert /* Preferred frequency is acceptable for P2P use */ 69685732ac8SCy Schubert i++; 69785732ac8SCy Schubert } 69885732ac8SCy Schubert 69985732ac8SCy Schubert pos = txt; 70085732ac8SCy Schubert end = pos + sizeof(txt); 70185732ac8SCy Schubert for (i = 0; i < size; i++) { 70285732ac8SCy Schubert res = os_snprintf(pos, end - pos, " %u", freq_list[i]); 70385732ac8SCy Schubert if (os_snprintf_error(end - pos, res)) 70485732ac8SCy Schubert break; 70585732ac8SCy Schubert pos += res; 70685732ac8SCy Schubert } 70785732ac8SCy Schubert *pos = '\0'; 70885732ac8SCy Schubert p2p_dbg(p2p, "Local driver frequency preference (size=%u):%s", 70985732ac8SCy Schubert size, txt); 710325151a3SRui Paulo 711325151a3SRui Paulo /* 712325151a3SRui Paulo * Check if peer's preference of operating channel is in 713325151a3SRui Paulo * our preferred channel list. 714325151a3SRui Paulo */ 715325151a3SRui Paulo for (i = 0; i < size; i++) { 716325151a3SRui Paulo if (freq_list[i] == (unsigned int) dev->oper_freq) 717325151a3SRui Paulo break; 718325151a3SRui Paulo } 71985732ac8SCy Schubert if (i != size && 72085732ac8SCy Schubert p2p_freq_to_channel(freq_list[i], &op_class, &op_channel) == 0) { 721325151a3SRui Paulo /* Peer operating channel preference matches our preference */ 722325151a3SRui Paulo p2p->op_reg_class = op_class; 723325151a3SRui Paulo p2p->op_channel = op_channel; 724325151a3SRui Paulo os_memcpy(&p2p->channels, &p2p->cfg->channels, 725325151a3SRui Paulo sizeof(struct p2p_channels)); 726325151a3SRui Paulo return; 727325151a3SRui Paulo } 728325151a3SRui Paulo 729325151a3SRui Paulo p2p_dbg(p2p, 730325151a3SRui Paulo "Peer operating channel preference: %d MHz is not in our preferred channel list", 731325151a3SRui Paulo dev->oper_freq); 732325151a3SRui Paulo 733325151a3SRui Paulo /* 734325151a3SRui Paulo Check if peer's preferred channel list is 735325151a3SRui Paulo * _not_ included in the GO Negotiation Request or Invitation Request. 736325151a3SRui Paulo */ 737325151a3SRui Paulo if (msg->pref_freq_list_len == 0) 738325151a3SRui Paulo p2p_check_pref_chan_no_recv(p2p, go, dev, msg, freq_list, size); 739325151a3SRui Paulo else 740325151a3SRui Paulo p2p_check_pref_chan_recv(p2p, go, dev, msg, freq_list, size); 741325151a3SRui Paulo } 742325151a3SRui Paulo 743325151a3SRui Paulo 744f05cddf9SRui Paulo void p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa, 745f05cddf9SRui Paulo const u8 *data, size_t len, int rx_freq) 746f05cddf9SRui Paulo { 747f05cddf9SRui Paulo struct p2p_device *dev = NULL; 748f05cddf9SRui Paulo struct wpabuf *resp; 749f05cddf9SRui Paulo struct p2p_message msg; 750f05cddf9SRui Paulo u8 status = P2P_SC_FAIL_INVALID_PARAMS; 751f05cddf9SRui Paulo int tie_breaker = 0; 752f05cddf9SRui Paulo int freq; 753f05cddf9SRui Paulo 7545b9c547cSRui Paulo p2p_dbg(p2p, "Received GO Negotiation Request from " MACSTR "(freq=%d)", 7555b9c547cSRui Paulo MAC2STR(sa), rx_freq); 756f05cddf9SRui Paulo 757f05cddf9SRui Paulo if (p2p_parse(data, len, &msg)) 758f05cddf9SRui Paulo return; 759f05cddf9SRui Paulo 760f05cddf9SRui Paulo if (!msg.capability) { 7615b9c547cSRui Paulo p2p_dbg(p2p, "Mandatory Capability attribute missing from GO Negotiation Request"); 762f05cddf9SRui Paulo #ifdef CONFIG_P2P_STRICT 763f05cddf9SRui Paulo goto fail; 764f05cddf9SRui Paulo #endif /* CONFIG_P2P_STRICT */ 765f05cddf9SRui Paulo } 766f05cddf9SRui Paulo 767f05cddf9SRui Paulo if (msg.go_intent) 768f05cddf9SRui Paulo tie_breaker = *msg.go_intent & 0x01; 769f05cddf9SRui Paulo else { 7705b9c547cSRui Paulo p2p_dbg(p2p, "Mandatory GO Intent 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.config_timeout) { 7775b9c547cSRui Paulo p2p_dbg(p2p, "Mandatory Configuration Timeout attribute missing from GO Negotiation Request"); 778f05cddf9SRui Paulo #ifdef CONFIG_P2P_STRICT 779f05cddf9SRui Paulo goto fail; 780f05cddf9SRui Paulo #endif /* CONFIG_P2P_STRICT */ 781f05cddf9SRui Paulo } 782f05cddf9SRui Paulo 783f05cddf9SRui Paulo if (!msg.listen_channel) { 7845b9c547cSRui Paulo p2p_dbg(p2p, "No Listen Channel attribute received"); 785f05cddf9SRui Paulo goto fail; 786f05cddf9SRui Paulo } 787f05cddf9SRui Paulo if (!msg.operating_channel) { 7885b9c547cSRui Paulo p2p_dbg(p2p, "No Operating Channel attribute received"); 789f05cddf9SRui Paulo goto fail; 790f05cddf9SRui Paulo } 791f05cddf9SRui Paulo if (!msg.channel_list) { 7925b9c547cSRui Paulo p2p_dbg(p2p, "No Channel List attribute received"); 793f05cddf9SRui Paulo goto fail; 794f05cddf9SRui Paulo } 795f05cddf9SRui Paulo if (!msg.intended_addr) { 7965b9c547cSRui Paulo p2p_dbg(p2p, "No Intended P2P Interface Address attribute received"); 797f05cddf9SRui Paulo goto fail; 798f05cddf9SRui Paulo } 799f05cddf9SRui Paulo if (!msg.p2p_device_info) { 8005b9c547cSRui Paulo p2p_dbg(p2p, "No P2P Device Info attribute received"); 801f05cddf9SRui Paulo goto fail; 802f05cddf9SRui Paulo } 803f05cddf9SRui Paulo 804f05cddf9SRui Paulo if (os_memcmp(msg.p2p_device_addr, sa, ETH_ALEN) != 0) { 8055b9c547cSRui Paulo p2p_dbg(p2p, "Unexpected GO Negotiation Request SA=" MACSTR 806f05cddf9SRui Paulo " != dev_addr=" MACSTR, 807f05cddf9SRui Paulo MAC2STR(sa), MAC2STR(msg.p2p_device_addr)); 808f05cddf9SRui Paulo goto fail; 809f05cddf9SRui Paulo } 810f05cddf9SRui Paulo 811f05cddf9SRui Paulo dev = p2p_get_device(p2p, sa); 812f05cddf9SRui Paulo 813f05cddf9SRui Paulo if (msg.status && *msg.status) { 8145b9c547cSRui Paulo p2p_dbg(p2p, "Unexpected Status attribute (%d) in GO Negotiation Request", 8155b9c547cSRui Paulo *msg.status); 8165b9c547cSRui Paulo if (dev && p2p->go_neg_peer == dev && 8175b9c547cSRui Paulo *msg.status == P2P_SC_FAIL_REJECTED_BY_USER) { 8185b9c547cSRui Paulo /* 8195b9c547cSRui Paulo * This mechanism for using Status attribute in GO 8205b9c547cSRui Paulo * Negotiation Request is not compliant with the P2P 8215b9c547cSRui Paulo * specification, but some deployed devices use it to 8225b9c547cSRui Paulo * indicate rejection of GO Negotiation in a case where 8235b9c547cSRui Paulo * they have sent out GO Negotiation Response with 8245b9c547cSRui Paulo * status 1. The P2P specification explicitly disallows 8255b9c547cSRui Paulo * this. To avoid unnecessary interoperability issues 8265b9c547cSRui Paulo * and extra frames, mark the pending negotiation as 8275b9c547cSRui Paulo * failed and do not reply to this GO Negotiation 8285b9c547cSRui Paulo * Request frame. 8295b9c547cSRui Paulo */ 8305b9c547cSRui Paulo p2p->cfg->send_action_done(p2p->cfg->cb_ctx); 8315b9c547cSRui Paulo p2p_go_neg_failed(p2p, *msg.status); 8325b9c547cSRui Paulo p2p_parse_free(&msg); 8335b9c547cSRui Paulo return; 8345b9c547cSRui Paulo } 835f05cddf9SRui Paulo goto fail; 836f05cddf9SRui Paulo } 837f05cddf9SRui Paulo 838f05cddf9SRui Paulo if (dev == NULL) 839f05cddf9SRui Paulo dev = p2p_add_dev_from_go_neg_req(p2p, sa, &msg); 8405b9c547cSRui Paulo else if ((dev->flags & P2P_DEV_PROBE_REQ_ONLY) || 8415b9c547cSRui Paulo !(dev->flags & P2P_DEV_REPORTED)) 842f05cddf9SRui Paulo p2p_add_dev_info(p2p, sa, dev, &msg); 8435b9c547cSRui Paulo else if (!dev->listen_freq && !dev->oper_freq) { 8445b9c547cSRui Paulo /* 8455b9c547cSRui Paulo * This may happen if the peer entry was added based on PD 8465b9c547cSRui Paulo * Request and no Probe Request/Response frame has been received 8475b9c547cSRui Paulo * from this peer (or that information has timed out). 8485b9c547cSRui Paulo */ 8495b9c547cSRui Paulo p2p_dbg(p2p, "Update peer " MACSTR 8505b9c547cSRui Paulo " based on GO Neg Req since listen/oper freq not known", 8515b9c547cSRui Paulo MAC2STR(dev->info.p2p_device_addr)); 8525b9c547cSRui Paulo p2p_add_dev_info(p2p, sa, dev, &msg); 8535b9c547cSRui Paulo } 8545b9c547cSRui Paulo 8555b9c547cSRui Paulo if (p2p->go_neg_peer && p2p->go_neg_peer == dev) 8565b9c547cSRui Paulo eloop_cancel_timeout(p2p_go_neg_wait_timeout, p2p, NULL); 8575b9c547cSRui Paulo 858f05cddf9SRui Paulo if (dev && dev->flags & P2P_DEV_USER_REJECTED) { 8595b9c547cSRui Paulo p2p_dbg(p2p, "User has rejected this peer"); 860f05cddf9SRui Paulo status = P2P_SC_FAIL_REJECTED_BY_USER; 8615b9c547cSRui Paulo } else if (dev == NULL || 8625b9c547cSRui Paulo (dev->wps_method == WPS_NOT_READY && 8635b9c547cSRui Paulo (p2p->authorized_oob_dev_pw_id == 0 || 8645b9c547cSRui Paulo p2p->authorized_oob_dev_pw_id != 8655b9c547cSRui Paulo msg.dev_password_id))) { 8665b9c547cSRui Paulo p2p_dbg(p2p, "Not ready for GO negotiation with " MACSTR, 867f05cddf9SRui Paulo MAC2STR(sa)); 868f05cddf9SRui Paulo status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE; 869f05cddf9SRui Paulo p2p->cfg->go_neg_req_rx(p2p->cfg->cb_ctx, sa, 870325151a3SRui Paulo msg.dev_password_id, 871325151a3SRui Paulo msg.go_intent ? (*msg.go_intent >> 1) : 872325151a3SRui Paulo 0); 873f05cddf9SRui Paulo } else if (p2p->go_neg_peer && p2p->go_neg_peer != dev) { 8745b9c547cSRui Paulo p2p_dbg(p2p, "Already in Group Formation with another peer"); 875f05cddf9SRui Paulo status = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE; 876f05cddf9SRui Paulo } else { 877f05cddf9SRui Paulo int go; 878f05cddf9SRui Paulo 879f05cddf9SRui Paulo if (!p2p->go_neg_peer) { 8805b9c547cSRui Paulo p2p_dbg(p2p, "Starting GO Negotiation with previously authorized peer"); 881f05cddf9SRui Paulo if (!(dev->flags & P2P_DEV_FORCE_FREQ)) { 8825b9c547cSRui Paulo p2p_dbg(p2p, "Use default channel settings"); 883f05cddf9SRui Paulo p2p->op_reg_class = p2p->cfg->op_reg_class; 884f05cddf9SRui Paulo p2p->op_channel = p2p->cfg->op_channel; 885f05cddf9SRui Paulo os_memcpy(&p2p->channels, &p2p->cfg->channels, 886f05cddf9SRui Paulo sizeof(struct p2p_channels)); 887f05cddf9SRui Paulo } else { 8885b9c547cSRui Paulo p2p_dbg(p2p, "Use previously configured forced channel settings"); 889f05cddf9SRui Paulo } 890f05cddf9SRui Paulo } 891f05cddf9SRui Paulo 892f05cddf9SRui Paulo dev->flags &= ~P2P_DEV_NOT_YET_READY; 893f05cddf9SRui Paulo 894f05cddf9SRui Paulo if (!msg.go_intent) { 8955b9c547cSRui Paulo p2p_dbg(p2p, "No GO Intent attribute received"); 896f05cddf9SRui Paulo goto fail; 897f05cddf9SRui Paulo } 898f05cddf9SRui Paulo if ((*msg.go_intent >> 1) > P2P_MAX_GO_INTENT) { 8995b9c547cSRui Paulo p2p_dbg(p2p, "Invalid GO Intent value (%u) received", 900f05cddf9SRui Paulo *msg.go_intent >> 1); 901f05cddf9SRui Paulo goto fail; 902f05cddf9SRui Paulo } 903f05cddf9SRui Paulo 904f05cddf9SRui Paulo if (dev->go_neg_req_sent && 905f05cddf9SRui Paulo os_memcmp(sa, p2p->cfg->dev_addr, ETH_ALEN) > 0) { 9065b9c547cSRui Paulo p2p_dbg(p2p, "Do not reply since peer has higher address and GO Neg Request already sent"); 907f05cddf9SRui Paulo p2p_parse_free(&msg); 908f05cddf9SRui Paulo return; 909f05cddf9SRui Paulo } 910f05cddf9SRui Paulo 911780fb4a2SCy Schubert if (dev->go_neg_req_sent && 912780fb4a2SCy Schubert (dev->flags & P2P_DEV_PEER_WAITING_RESPONSE)) { 913780fb4a2SCy Schubert p2p_dbg(p2p, 914780fb4a2SCy Schubert "Do not reply since peer is waiting for us to start a new GO Negotiation and GO Neg Request already sent"); 915780fb4a2SCy Schubert p2p_parse_free(&msg); 916780fb4a2SCy Schubert return; 917780fb4a2SCy Schubert } 918780fb4a2SCy Schubert 919f05cddf9SRui Paulo go = p2p_go_det(p2p->go_intent, *msg.go_intent); 920f05cddf9SRui Paulo if (go < 0) { 9215b9c547cSRui Paulo p2p_dbg(p2p, "Incompatible GO Intent"); 922f05cddf9SRui Paulo status = P2P_SC_FAIL_BOTH_GO_INTENT_15; 923f05cddf9SRui Paulo goto fail; 924f05cddf9SRui Paulo } 925f05cddf9SRui Paulo 926f05cddf9SRui Paulo if (p2p_peer_channels(p2p, dev, msg.channel_list, 927f05cddf9SRui Paulo msg.channel_list_len) < 0) { 9285b9c547cSRui Paulo p2p_dbg(p2p, "No common channels found"); 929f05cddf9SRui Paulo status = P2P_SC_FAIL_NO_COMMON_CHANNELS; 930f05cddf9SRui Paulo goto fail; 931f05cddf9SRui Paulo } 932f05cddf9SRui Paulo 933f05cddf9SRui Paulo switch (msg.dev_password_id) { 934f05cddf9SRui Paulo case DEV_PW_REGISTRAR_SPECIFIED: 9355b9c547cSRui Paulo p2p_dbg(p2p, "PIN from peer Display"); 936f05cddf9SRui Paulo if (dev->wps_method != WPS_PIN_KEYPAD) { 9375b9c547cSRui Paulo p2p_dbg(p2p, "We have wps_method=%s -> incompatible", 938f05cddf9SRui Paulo p2p_wps_method_str(dev->wps_method)); 939f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 940f05cddf9SRui Paulo goto fail; 941f05cddf9SRui Paulo } 942f05cddf9SRui Paulo break; 943f05cddf9SRui Paulo case DEV_PW_USER_SPECIFIED: 9445b9c547cSRui Paulo p2p_dbg(p2p, "Peer entered PIN on Keypad"); 945f05cddf9SRui Paulo if (dev->wps_method != WPS_PIN_DISPLAY) { 9465b9c547cSRui Paulo p2p_dbg(p2p, "We have wps_method=%s -> incompatible", 947f05cddf9SRui Paulo p2p_wps_method_str(dev->wps_method)); 948f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 949f05cddf9SRui Paulo goto fail; 950f05cddf9SRui Paulo } 951f05cddf9SRui Paulo break; 952f05cddf9SRui Paulo case DEV_PW_PUSHBUTTON: 9535b9c547cSRui Paulo p2p_dbg(p2p, "Peer using pushbutton"); 954f05cddf9SRui Paulo if (dev->wps_method != WPS_PBC) { 9555b9c547cSRui Paulo p2p_dbg(p2p, "We have wps_method=%s -> incompatible", 9565b9c547cSRui Paulo p2p_wps_method_str(dev->wps_method)); 9575b9c547cSRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 9585b9c547cSRui Paulo goto fail; 9595b9c547cSRui Paulo } 9605b9c547cSRui Paulo break; 9615b9c547cSRui Paulo case DEV_PW_P2PS_DEFAULT: 9625b9c547cSRui Paulo p2p_dbg(p2p, "Peer using P2PS pin"); 9635b9c547cSRui Paulo if (dev->wps_method != WPS_P2PS) { 9645b9c547cSRui Paulo p2p_dbg(p2p, 9655b9c547cSRui Paulo "We have wps_method=%s -> incompatible", 966f05cddf9SRui Paulo p2p_wps_method_str(dev->wps_method)); 967f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 968f05cddf9SRui Paulo goto fail; 969f05cddf9SRui Paulo } 970f05cddf9SRui Paulo break; 971f05cddf9SRui Paulo default: 9725b9c547cSRui Paulo if (msg.dev_password_id && 9735b9c547cSRui Paulo msg.dev_password_id == dev->oob_pw_id) { 9745b9c547cSRui Paulo p2p_dbg(p2p, "Peer using NFC"); 9755b9c547cSRui Paulo if (dev->wps_method != WPS_NFC) { 9765b9c547cSRui Paulo p2p_dbg(p2p, "We have wps_method=%s -> incompatible", 9775b9c547cSRui Paulo p2p_wps_method_str( 9785b9c547cSRui Paulo dev->wps_method)); 9795b9c547cSRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 9805b9c547cSRui Paulo goto fail; 9815b9c547cSRui Paulo } 9825b9c547cSRui Paulo break; 9835b9c547cSRui Paulo } 9845b9c547cSRui Paulo #ifdef CONFIG_WPS_NFC 9855b9c547cSRui Paulo if (p2p->authorized_oob_dev_pw_id && 9865b9c547cSRui Paulo msg.dev_password_id == 9875b9c547cSRui Paulo p2p->authorized_oob_dev_pw_id) { 9885b9c547cSRui Paulo p2p_dbg(p2p, "Using static handover with our device password from NFC Tag"); 9895b9c547cSRui Paulo dev->wps_method = WPS_NFC; 9905b9c547cSRui Paulo dev->oob_pw_id = p2p->authorized_oob_dev_pw_id; 9915b9c547cSRui Paulo break; 9925b9c547cSRui Paulo } 9935b9c547cSRui Paulo #endif /* CONFIG_WPS_NFC */ 9945b9c547cSRui Paulo p2p_dbg(p2p, "Unsupported Device Password ID %d", 995f05cddf9SRui Paulo msg.dev_password_id); 996f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 997f05cddf9SRui Paulo goto fail; 998f05cddf9SRui Paulo } 999f05cddf9SRui Paulo 1000f05cddf9SRui Paulo if (go && p2p_go_select_channel(p2p, dev, &status) < 0) 1001f05cddf9SRui Paulo goto fail; 1002f05cddf9SRui Paulo 1003f05cddf9SRui Paulo dev->go_state = go ? LOCAL_GO : REMOTE_GO; 10045b9c547cSRui Paulo dev->oper_freq = p2p_channel_to_freq(msg.operating_channel[3], 1005f05cddf9SRui Paulo msg.operating_channel[4]); 10065b9c547cSRui Paulo p2p_dbg(p2p, "Peer operating channel preference: %d MHz", 10075b9c547cSRui Paulo dev->oper_freq); 1008f05cddf9SRui Paulo 1009325151a3SRui Paulo /* 1010325151a3SRui Paulo * Use the driver preferred frequency list extension if 1011325151a3SRui Paulo * supported. 1012325151a3SRui Paulo */ 1013325151a3SRui Paulo p2p_check_pref_chan(p2p, go, dev, &msg); 1014325151a3SRui Paulo 1015f05cddf9SRui Paulo if (msg.config_timeout) { 1016f05cddf9SRui Paulo dev->go_timeout = msg.config_timeout[0]; 1017f05cddf9SRui Paulo dev->client_timeout = msg.config_timeout[1]; 1018f05cddf9SRui Paulo } 1019f05cddf9SRui Paulo 10205b9c547cSRui Paulo p2p_dbg(p2p, "GO Negotiation with " MACSTR, MAC2STR(sa)); 1021f05cddf9SRui Paulo if (p2p->state != P2P_IDLE) 1022f05cddf9SRui Paulo p2p_stop_find_for_freq(p2p, rx_freq); 1023f05cddf9SRui Paulo p2p_set_state(p2p, P2P_GO_NEG); 1024f05cddf9SRui Paulo p2p_clear_timeout(p2p); 1025f05cddf9SRui Paulo dev->dialog_token = msg.dialog_token; 1026f05cddf9SRui Paulo os_memcpy(dev->intended_addr, msg.intended_addr, ETH_ALEN); 1027f05cddf9SRui Paulo p2p->go_neg_peer = dev; 10285b9c547cSRui Paulo eloop_cancel_timeout(p2p_go_neg_wait_timeout, p2p, NULL); 1029f05cddf9SRui Paulo status = P2P_SC_SUCCESS; 1030f05cddf9SRui Paulo } 1031f05cddf9SRui Paulo 1032f05cddf9SRui Paulo fail: 1033f05cddf9SRui Paulo if (dev) 1034f05cddf9SRui Paulo dev->status = status; 1035f05cddf9SRui Paulo resp = p2p_build_go_neg_resp(p2p, dev, msg.dialog_token, status, 1036f05cddf9SRui Paulo !tie_breaker); 1037f05cddf9SRui Paulo p2p_parse_free(&msg); 1038f05cddf9SRui Paulo if (resp == NULL) 1039f05cddf9SRui Paulo return; 10405b9c547cSRui Paulo p2p_dbg(p2p, "Sending GO Negotiation Response"); 1041f05cddf9SRui Paulo if (rx_freq > 0) 1042f05cddf9SRui Paulo freq = rx_freq; 1043f05cddf9SRui Paulo else 10445b9c547cSRui Paulo freq = p2p_channel_to_freq(p2p->cfg->reg_class, 1045f05cddf9SRui Paulo p2p->cfg->channel); 1046f05cddf9SRui Paulo if (freq < 0) { 10475b9c547cSRui Paulo p2p_dbg(p2p, "Unknown regulatory class/channel"); 1048f05cddf9SRui Paulo wpabuf_free(resp); 1049f05cddf9SRui Paulo return; 1050f05cddf9SRui Paulo } 1051f05cddf9SRui Paulo if (status == P2P_SC_SUCCESS) { 1052f05cddf9SRui Paulo p2p->pending_action_state = P2P_PENDING_GO_NEG_RESPONSE; 1053f05cddf9SRui Paulo dev->flags |= P2P_DEV_WAIT_GO_NEG_CONFIRM; 1054f05cddf9SRui Paulo if (os_memcmp(sa, p2p->cfg->dev_addr, ETH_ALEN) < 0) { 1055f05cddf9SRui Paulo /* 1056f05cddf9SRui Paulo * Peer has smaller address, so the GO Negotiation 1057f05cddf9SRui Paulo * Response from us is expected to complete 1058f05cddf9SRui Paulo * negotiation. Ignore a GO Negotiation Response from 1059f05cddf9SRui Paulo * the peer if it happens to be received after this 1060f05cddf9SRui Paulo * point due to a race condition in GO Negotiation 1061f05cddf9SRui Paulo * Request transmission and processing. 1062f05cddf9SRui Paulo */ 1063f05cddf9SRui Paulo dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE; 1064f05cddf9SRui Paulo } 1065f05cddf9SRui Paulo } else 1066f05cddf9SRui Paulo p2p->pending_action_state = 1067f05cddf9SRui Paulo P2P_PENDING_GO_NEG_RESPONSE_FAILURE; 1068f05cddf9SRui Paulo if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, 1069f05cddf9SRui Paulo p2p->cfg->dev_addr, 1070780fb4a2SCy Schubert wpabuf_head(resp), wpabuf_len(resp), 100) < 0) { 10715b9c547cSRui Paulo p2p_dbg(p2p, "Failed to send Action frame"); 1072f05cddf9SRui Paulo } 1073f05cddf9SRui Paulo 1074f05cddf9SRui Paulo wpabuf_free(resp); 1075f05cddf9SRui Paulo } 1076f05cddf9SRui Paulo 1077f05cddf9SRui Paulo 1078f05cddf9SRui Paulo static struct wpabuf * p2p_build_go_neg_conf(struct p2p_data *p2p, 1079f05cddf9SRui Paulo struct p2p_device *peer, 1080f05cddf9SRui Paulo u8 dialog_token, u8 status, 1081f05cddf9SRui Paulo const u8 *resp_chan, int go) 1082f05cddf9SRui Paulo { 1083f05cddf9SRui Paulo struct wpabuf *buf; 1084f05cddf9SRui Paulo u8 *len; 1085f05cddf9SRui Paulo struct p2p_channels res; 1086f05cddf9SRui Paulo u8 group_capab; 1087f05cddf9SRui Paulo size_t extra = 0; 1088f05cddf9SRui Paulo 10895b9c547cSRui Paulo p2p_dbg(p2p, "Building GO Negotiation Confirm"); 1090f05cddf9SRui Paulo 1091f05cddf9SRui Paulo #ifdef CONFIG_WIFI_DISPLAY 1092f05cddf9SRui Paulo if (p2p->wfd_ie_go_neg) 1093f05cddf9SRui Paulo extra = wpabuf_len(p2p->wfd_ie_go_neg); 1094f05cddf9SRui Paulo #endif /* CONFIG_WIFI_DISPLAY */ 1095f05cddf9SRui Paulo 10965b9c547cSRui Paulo if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_CONF]) 10975b9c547cSRui Paulo extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_CONF]); 10985b9c547cSRui Paulo 1099f05cddf9SRui Paulo buf = wpabuf_alloc(1000 + extra); 1100f05cddf9SRui Paulo if (buf == NULL) 1101f05cddf9SRui Paulo return NULL; 1102f05cddf9SRui Paulo 1103f05cddf9SRui Paulo p2p_buf_add_public_action_hdr(buf, P2P_GO_NEG_CONF, dialog_token); 1104f05cddf9SRui Paulo 1105f05cddf9SRui Paulo len = p2p_buf_add_ie_hdr(buf); 1106f05cddf9SRui Paulo p2p_buf_add_status(buf, status); 1107f05cddf9SRui Paulo group_capab = 0; 1108f05cddf9SRui Paulo if (peer->go_state == LOCAL_GO) { 1109f05cddf9SRui Paulo if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) { 1110f05cddf9SRui Paulo group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP; 1111f05cddf9SRui Paulo if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN) 1112f05cddf9SRui Paulo group_capab |= 1113f05cddf9SRui Paulo P2P_GROUP_CAPAB_PERSISTENT_RECONN; 1114f05cddf9SRui Paulo } 1115f05cddf9SRui Paulo if (p2p->cross_connect) 1116f05cddf9SRui Paulo group_capab |= P2P_GROUP_CAPAB_CROSS_CONN; 1117f05cddf9SRui Paulo if (p2p->cfg->p2p_intra_bss) 1118f05cddf9SRui Paulo group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST; 1119f05cddf9SRui Paulo } 1120f05cddf9SRui Paulo p2p_buf_add_capability(buf, p2p->dev_capab & 1121f05cddf9SRui Paulo ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 1122f05cddf9SRui Paulo group_capab); 1123f05cddf9SRui Paulo if (go || resp_chan == NULL) 1124f05cddf9SRui Paulo p2p_buf_add_operating_channel(buf, p2p->cfg->country, 1125f05cddf9SRui Paulo p2p->op_reg_class, 1126f05cddf9SRui Paulo p2p->op_channel); 1127f05cddf9SRui Paulo else 1128f05cddf9SRui Paulo p2p_buf_add_operating_channel(buf, (const char *) resp_chan, 1129f05cddf9SRui Paulo resp_chan[3], resp_chan[4]); 1130f05cddf9SRui Paulo p2p_channels_intersect(&p2p->channels, &peer->channels, &res); 1131f05cddf9SRui Paulo p2p_buf_add_channel_list(buf, p2p->cfg->country, &res); 1132f05cddf9SRui Paulo if (go) { 1133f05cddf9SRui Paulo p2p_buf_add_group_id(buf, p2p->cfg->dev_addr, p2p->ssid, 1134f05cddf9SRui Paulo p2p->ssid_len); 1135f05cddf9SRui Paulo } 1136f05cddf9SRui Paulo p2p_buf_update_ie_hdr(buf, len); 1137f05cddf9SRui Paulo 1138f05cddf9SRui Paulo #ifdef CONFIG_WIFI_DISPLAY 1139f05cddf9SRui Paulo if (p2p->wfd_ie_go_neg) 1140f05cddf9SRui Paulo wpabuf_put_buf(buf, p2p->wfd_ie_go_neg); 1141f05cddf9SRui Paulo #endif /* CONFIG_WIFI_DISPLAY */ 1142f05cddf9SRui Paulo 11435b9c547cSRui Paulo if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_CONF]) 11445b9c547cSRui Paulo wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_CONF]); 11455b9c547cSRui Paulo 1146f05cddf9SRui Paulo return buf; 1147f05cddf9SRui Paulo } 1148f05cddf9SRui Paulo 1149f05cddf9SRui Paulo 1150f05cddf9SRui Paulo void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa, 1151f05cddf9SRui Paulo const u8 *data, size_t len, int rx_freq) 1152f05cddf9SRui Paulo { 1153f05cddf9SRui Paulo struct p2p_device *dev; 1154f05cddf9SRui Paulo int go = -1; 1155f05cddf9SRui Paulo struct p2p_message msg; 1156f05cddf9SRui Paulo u8 status = P2P_SC_SUCCESS; 1157f05cddf9SRui Paulo int freq; 1158f05cddf9SRui Paulo 11595b9c547cSRui Paulo p2p_dbg(p2p, "Received GO Negotiation Response from " MACSTR 1160f05cddf9SRui Paulo " (freq=%d)", MAC2STR(sa), rx_freq); 1161f05cddf9SRui Paulo dev = p2p_get_device(p2p, sa); 1162f05cddf9SRui Paulo if (dev == NULL || dev->wps_method == WPS_NOT_READY || 1163f05cddf9SRui Paulo dev != p2p->go_neg_peer) { 11645b9c547cSRui Paulo p2p_dbg(p2p, "Not ready for GO negotiation with " MACSTR, 1165f05cddf9SRui Paulo MAC2STR(sa)); 1166f05cddf9SRui Paulo return; 1167f05cddf9SRui Paulo } 1168f05cddf9SRui Paulo 1169f05cddf9SRui Paulo if (p2p_parse(data, len, &msg)) 1170f05cddf9SRui Paulo return; 1171f05cddf9SRui Paulo 1172f05cddf9SRui Paulo if (!(dev->flags & P2P_DEV_WAIT_GO_NEG_RESPONSE)) { 11735b9c547cSRui Paulo p2p_dbg(p2p, "Was not expecting GO Negotiation Response - ignore"); 1174f05cddf9SRui Paulo p2p_parse_free(&msg); 1175f05cddf9SRui Paulo return; 1176f05cddf9SRui Paulo } 1177f05cddf9SRui Paulo dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE; 1178f05cddf9SRui Paulo 1179f05cddf9SRui Paulo if (msg.dialog_token != dev->dialog_token) { 11805b9c547cSRui Paulo p2p_dbg(p2p, "Unexpected Dialog Token %u (expected %u)", 1181f05cddf9SRui Paulo msg.dialog_token, dev->dialog_token); 1182f05cddf9SRui Paulo p2p_parse_free(&msg); 1183f05cddf9SRui Paulo return; 1184f05cddf9SRui Paulo } 1185f05cddf9SRui Paulo 1186f05cddf9SRui Paulo if (!msg.status) { 11875b9c547cSRui Paulo p2p_dbg(p2p, "No Status attribute received"); 1188f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 1189f05cddf9SRui Paulo goto fail; 1190f05cddf9SRui Paulo } 1191f05cddf9SRui Paulo if (*msg.status) { 11925b9c547cSRui Paulo p2p_dbg(p2p, "GO Negotiation rejected: status %d", *msg.status); 1193f05cddf9SRui Paulo dev->go_neg_req_sent = 0; 1194f05cddf9SRui Paulo if (*msg.status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) { 11955b9c547cSRui Paulo p2p_dbg(p2p, "Wait for the peer to become ready for GO Negotiation"); 1196f05cddf9SRui Paulo dev->flags |= P2P_DEV_NOT_YET_READY; 11975b9c547cSRui Paulo eloop_cancel_timeout(p2p_go_neg_wait_timeout, p2p, 11985b9c547cSRui Paulo NULL); 11995b9c547cSRui Paulo eloop_register_timeout(120, 0, p2p_go_neg_wait_timeout, 12005b9c547cSRui Paulo p2p, NULL); 12015b9c547cSRui Paulo if (p2p->state == P2P_CONNECT_LISTEN) 12025b9c547cSRui Paulo p2p_set_state(p2p, P2P_WAIT_PEER_CONNECT); 12035b9c547cSRui Paulo else 1204f05cddf9SRui Paulo p2p_set_state(p2p, P2P_WAIT_PEER_IDLE); 1205f05cddf9SRui Paulo p2p_set_timeout(p2p, 0, 0); 1206f05cddf9SRui Paulo } else { 12075b9c547cSRui Paulo p2p_dbg(p2p, "Stop GO Negotiation attempt"); 12085b9c547cSRui Paulo p2p_go_neg_failed(p2p, *msg.status); 1209f05cddf9SRui Paulo } 1210f05cddf9SRui Paulo p2p->cfg->send_action_done(p2p->cfg->cb_ctx); 1211f05cddf9SRui Paulo p2p_parse_free(&msg); 1212f05cddf9SRui Paulo return; 1213f05cddf9SRui Paulo } 1214f05cddf9SRui Paulo 1215f05cddf9SRui Paulo if (!msg.capability) { 12165b9c547cSRui Paulo p2p_dbg(p2p, "Mandatory Capability attribute missing from GO Negotiation Response"); 1217f05cddf9SRui Paulo #ifdef CONFIG_P2P_STRICT 1218f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 1219f05cddf9SRui Paulo goto fail; 1220f05cddf9SRui Paulo #endif /* CONFIG_P2P_STRICT */ 1221f05cddf9SRui Paulo } 1222f05cddf9SRui Paulo 1223f05cddf9SRui Paulo if (!msg.p2p_device_info) { 12245b9c547cSRui Paulo p2p_dbg(p2p, "Mandatory P2P Device Info attribute missing from GO Negotiation Response"); 1225f05cddf9SRui Paulo #ifdef CONFIG_P2P_STRICT 1226f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 1227f05cddf9SRui Paulo goto fail; 1228f05cddf9SRui Paulo #endif /* CONFIG_P2P_STRICT */ 1229f05cddf9SRui Paulo } 1230f05cddf9SRui Paulo 1231f05cddf9SRui Paulo if (!msg.intended_addr) { 12325b9c547cSRui Paulo p2p_dbg(p2p, "No Intended P2P Interface Address attribute received"); 1233f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 1234f05cddf9SRui Paulo goto fail; 1235f05cddf9SRui Paulo } 1236f05cddf9SRui Paulo 1237f05cddf9SRui Paulo if (!msg.go_intent) { 12385b9c547cSRui Paulo p2p_dbg(p2p, "No GO Intent attribute received"); 1239f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 1240f05cddf9SRui Paulo goto fail; 1241f05cddf9SRui Paulo } 1242f05cddf9SRui Paulo if ((*msg.go_intent >> 1) > P2P_MAX_GO_INTENT) { 12435b9c547cSRui Paulo p2p_dbg(p2p, "Invalid GO Intent value (%u) received", 1244f05cddf9SRui Paulo *msg.go_intent >> 1); 1245f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 1246f05cddf9SRui Paulo goto fail; 1247f05cddf9SRui Paulo } 1248f05cddf9SRui Paulo 1249f05cddf9SRui Paulo go = p2p_go_det(p2p->go_intent, *msg.go_intent); 1250f05cddf9SRui Paulo if (go < 0) { 12515b9c547cSRui Paulo p2p_dbg(p2p, "Incompatible GO Intent"); 1252f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PARAMS; 1253f05cddf9SRui Paulo goto fail; 1254f05cddf9SRui Paulo } 1255f05cddf9SRui Paulo 1256f05cddf9SRui Paulo if (!go && msg.group_id) { 1257f05cddf9SRui Paulo /* Store SSID for Provisioning step */ 1258f05cddf9SRui Paulo p2p->ssid_len = msg.group_id_len - ETH_ALEN; 1259f05cddf9SRui Paulo os_memcpy(p2p->ssid, msg.group_id + ETH_ALEN, p2p->ssid_len); 1260f05cddf9SRui Paulo } else if (!go) { 12615b9c547cSRui Paulo p2p_dbg(p2p, "Mandatory P2P Group ID attribute missing from GO Negotiation Response"); 1262f05cddf9SRui Paulo p2p->ssid_len = 0; 1263f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 1264f05cddf9SRui Paulo goto fail; 1265f05cddf9SRui Paulo } 1266f05cddf9SRui Paulo 1267f05cddf9SRui Paulo if (!msg.config_timeout) { 12685b9c547cSRui Paulo p2p_dbg(p2p, "Mandatory Configuration Timeout attribute missing from GO Negotiation Response"); 1269f05cddf9SRui Paulo #ifdef CONFIG_P2P_STRICT 1270f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 1271f05cddf9SRui Paulo goto fail; 1272f05cddf9SRui Paulo #endif /* CONFIG_P2P_STRICT */ 1273f05cddf9SRui Paulo } else { 1274f05cddf9SRui Paulo dev->go_timeout = msg.config_timeout[0]; 1275f05cddf9SRui Paulo dev->client_timeout = msg.config_timeout[1]; 1276f05cddf9SRui Paulo } 1277f05cddf9SRui Paulo 1278780fb4a2SCy Schubert if (msg.wfd_subelems) { 1279780fb4a2SCy Schubert wpabuf_free(dev->info.wfd_subelems); 1280780fb4a2SCy Schubert dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems); 1281780fb4a2SCy Schubert } 1282780fb4a2SCy Schubert 1283f05cddf9SRui Paulo if (!msg.operating_channel && !go) { 1284f05cddf9SRui Paulo /* 1285f05cddf9SRui Paulo * Note: P2P Client may omit Operating Channel attribute to 1286f05cddf9SRui Paulo * indicate it does not have a preference. 1287f05cddf9SRui Paulo */ 12885b9c547cSRui Paulo p2p_dbg(p2p, "No Operating Channel attribute received"); 1289f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 1290f05cddf9SRui Paulo goto fail; 1291f05cddf9SRui Paulo } 1292f05cddf9SRui Paulo if (!msg.channel_list) { 12935b9c547cSRui Paulo p2p_dbg(p2p, "No Channel List attribute received"); 1294f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 1295f05cddf9SRui Paulo goto fail; 1296f05cddf9SRui Paulo } 1297f05cddf9SRui Paulo 1298f05cddf9SRui Paulo if (p2p_peer_channels(p2p, dev, msg.channel_list, 1299f05cddf9SRui Paulo msg.channel_list_len) < 0) { 13005b9c547cSRui Paulo p2p_dbg(p2p, "No common channels found"); 1301f05cddf9SRui Paulo status = P2P_SC_FAIL_NO_COMMON_CHANNELS; 1302f05cddf9SRui Paulo goto fail; 1303f05cddf9SRui Paulo } 1304f05cddf9SRui Paulo 1305f05cddf9SRui Paulo if (msg.operating_channel) { 13065b9c547cSRui Paulo dev->oper_freq = p2p_channel_to_freq(msg.operating_channel[3], 1307f05cddf9SRui Paulo msg.operating_channel[4]); 13085b9c547cSRui Paulo p2p_dbg(p2p, "Peer operating channel preference: %d MHz", 13095b9c547cSRui Paulo dev->oper_freq); 1310f05cddf9SRui Paulo } else 1311f05cddf9SRui Paulo dev->oper_freq = 0; 1312f05cddf9SRui Paulo 1313f05cddf9SRui Paulo switch (msg.dev_password_id) { 1314f05cddf9SRui Paulo case DEV_PW_REGISTRAR_SPECIFIED: 13155b9c547cSRui Paulo p2p_dbg(p2p, "PIN from peer Display"); 1316f05cddf9SRui Paulo if (dev->wps_method != WPS_PIN_KEYPAD) { 13175b9c547cSRui Paulo p2p_dbg(p2p, "We have wps_method=%s -> incompatible", 1318f05cddf9SRui Paulo p2p_wps_method_str(dev->wps_method)); 1319f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 1320f05cddf9SRui Paulo goto fail; 1321f05cddf9SRui Paulo } 1322f05cddf9SRui Paulo break; 1323f05cddf9SRui Paulo case DEV_PW_USER_SPECIFIED: 13245b9c547cSRui Paulo p2p_dbg(p2p, "Peer entered PIN on Keypad"); 1325f05cddf9SRui Paulo if (dev->wps_method != WPS_PIN_DISPLAY) { 13265b9c547cSRui Paulo p2p_dbg(p2p, "We have wps_method=%s -> incompatible", 1327f05cddf9SRui Paulo p2p_wps_method_str(dev->wps_method)); 1328f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 1329f05cddf9SRui Paulo goto fail; 1330f05cddf9SRui Paulo } 1331f05cddf9SRui Paulo break; 1332f05cddf9SRui Paulo case DEV_PW_PUSHBUTTON: 13335b9c547cSRui Paulo p2p_dbg(p2p, "Peer using pushbutton"); 1334f05cddf9SRui Paulo if (dev->wps_method != WPS_PBC) { 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 case DEV_PW_P2PS_DEFAULT: 13425b9c547cSRui Paulo p2p_dbg(p2p, "P2P: Peer using P2PS default pin"); 13435b9c547cSRui Paulo if (dev->wps_method != WPS_P2PS) { 13445b9c547cSRui Paulo p2p_dbg(p2p, "We have wps_method=%s -> incompatible", 1345f05cddf9SRui Paulo p2p_wps_method_str(dev->wps_method)); 1346f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 1347f05cddf9SRui Paulo goto fail; 1348f05cddf9SRui Paulo } 1349f05cddf9SRui Paulo break; 1350f05cddf9SRui Paulo default: 13515b9c547cSRui Paulo if (msg.dev_password_id && 13525b9c547cSRui Paulo msg.dev_password_id == dev->oob_pw_id) { 13535b9c547cSRui Paulo p2p_dbg(p2p, "Peer using NFC"); 13545b9c547cSRui Paulo if (dev->wps_method != WPS_NFC) { 13555b9c547cSRui Paulo p2p_dbg(p2p, "We have wps_method=%s -> incompatible", 13565b9c547cSRui Paulo p2p_wps_method_str(dev->wps_method)); 13575b9c547cSRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 13585b9c547cSRui Paulo goto fail; 13595b9c547cSRui Paulo } 13605b9c547cSRui Paulo break; 13615b9c547cSRui Paulo } 13625b9c547cSRui Paulo p2p_dbg(p2p, "Unsupported Device Password ID %d", 1363f05cddf9SRui Paulo msg.dev_password_id); 1364f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 1365f05cddf9SRui Paulo goto fail; 1366f05cddf9SRui Paulo } 1367f05cddf9SRui Paulo 1368f05cddf9SRui Paulo if (go && p2p_go_select_channel(p2p, dev, &status) < 0) 1369f05cddf9SRui Paulo goto fail; 1370f05cddf9SRui Paulo 1371325151a3SRui Paulo /* 1372325151a3SRui Paulo * Use the driver preferred frequency list extension if local device is 1373325151a3SRui Paulo * GO. 1374325151a3SRui Paulo */ 1375325151a3SRui Paulo if (go) 1376325151a3SRui Paulo p2p_check_pref_chan(p2p, go, dev, &msg); 1377325151a3SRui Paulo 1378f05cddf9SRui Paulo p2p_set_state(p2p, P2P_GO_NEG); 1379f05cddf9SRui Paulo p2p_clear_timeout(p2p); 1380f05cddf9SRui Paulo 13815b9c547cSRui Paulo p2p_dbg(p2p, "GO Negotiation with " MACSTR, MAC2STR(sa)); 1382f05cddf9SRui Paulo os_memcpy(dev->intended_addr, msg.intended_addr, ETH_ALEN); 1383f05cddf9SRui Paulo 1384f05cddf9SRui Paulo fail: 13855b9c547cSRui Paulo /* Store GO Negotiation Confirmation to allow retransmission */ 13865b9c547cSRui Paulo wpabuf_free(dev->go_neg_conf); 13875b9c547cSRui Paulo dev->go_neg_conf = p2p_build_go_neg_conf(p2p, dev, msg.dialog_token, 13885b9c547cSRui Paulo status, msg.operating_channel, 13895b9c547cSRui Paulo go); 1390f05cddf9SRui Paulo p2p_parse_free(&msg); 13915b9c547cSRui Paulo if (dev->go_neg_conf == NULL) 1392f05cddf9SRui Paulo return; 13935b9c547cSRui Paulo p2p_dbg(p2p, "Sending GO Negotiation Confirm"); 1394f05cddf9SRui Paulo if (status == P2P_SC_SUCCESS) { 1395f05cddf9SRui Paulo p2p->pending_action_state = P2P_PENDING_GO_NEG_CONFIRM; 1396f05cddf9SRui Paulo dev->go_state = go ? LOCAL_GO : REMOTE_GO; 1397f05cddf9SRui Paulo } else 1398f05cddf9SRui Paulo p2p->pending_action_state = P2P_NO_PENDING_ACTION; 1399f05cddf9SRui Paulo if (rx_freq > 0) 1400f05cddf9SRui Paulo freq = rx_freq; 1401f05cddf9SRui Paulo else 1402f05cddf9SRui Paulo freq = dev->listen_freq; 14035b9c547cSRui Paulo 14045b9c547cSRui Paulo dev->go_neg_conf_freq = freq; 14055b9c547cSRui Paulo dev->go_neg_conf_sent = 0; 14065b9c547cSRui Paulo 1407f05cddf9SRui Paulo if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, sa, 14085b9c547cSRui Paulo wpabuf_head(dev->go_neg_conf), 1409780fb4a2SCy Schubert wpabuf_len(dev->go_neg_conf), 50) < 0) { 14105b9c547cSRui Paulo p2p_dbg(p2p, "Failed to send Action frame"); 14115b9c547cSRui Paulo p2p_go_neg_failed(p2p, -1); 14125b9c547cSRui Paulo p2p->cfg->send_action_done(p2p->cfg->cb_ctx); 14135b9c547cSRui Paulo } else 14145b9c547cSRui Paulo dev->go_neg_conf_sent++; 14155b9c547cSRui Paulo if (status != P2P_SC_SUCCESS) { 14165b9c547cSRui Paulo p2p_dbg(p2p, "GO Negotiation failed"); 14175b9c547cSRui Paulo p2p_go_neg_failed(p2p, status); 1418f05cddf9SRui Paulo } 1419f05cddf9SRui Paulo } 1420f05cddf9SRui Paulo 1421f05cddf9SRui Paulo 1422f05cddf9SRui Paulo void p2p_process_go_neg_conf(struct p2p_data *p2p, const u8 *sa, 1423f05cddf9SRui Paulo const u8 *data, size_t len) 1424f05cddf9SRui Paulo { 1425f05cddf9SRui Paulo struct p2p_device *dev; 1426f05cddf9SRui Paulo struct p2p_message msg; 1427f05cddf9SRui Paulo 14285b9c547cSRui Paulo p2p_dbg(p2p, "Received GO Negotiation Confirm from " MACSTR, 1429f05cddf9SRui Paulo MAC2STR(sa)); 1430f05cddf9SRui Paulo dev = p2p_get_device(p2p, sa); 1431f05cddf9SRui Paulo if (dev == NULL || dev->wps_method == WPS_NOT_READY || 1432f05cddf9SRui Paulo dev != p2p->go_neg_peer) { 14335b9c547cSRui Paulo p2p_dbg(p2p, "Not ready for GO negotiation with " MACSTR, 1434f05cddf9SRui Paulo MAC2STR(sa)); 1435f05cddf9SRui Paulo return; 1436f05cddf9SRui Paulo } 1437f05cddf9SRui Paulo 1438f05cddf9SRui Paulo if (p2p->pending_action_state == P2P_PENDING_GO_NEG_RESPONSE) { 14395b9c547cSRui Paulo p2p_dbg(p2p, "Stopped waiting for TX status on GO Negotiation Response since we already received Confirmation"); 1440f05cddf9SRui Paulo p2p->pending_action_state = P2P_NO_PENDING_ACTION; 1441f05cddf9SRui Paulo } 1442f05cddf9SRui Paulo 1443f05cddf9SRui Paulo if (p2p_parse(data, len, &msg)) 1444f05cddf9SRui Paulo return; 1445f05cddf9SRui Paulo 1446f05cddf9SRui Paulo if (!(dev->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM)) { 14475b9c547cSRui Paulo p2p_dbg(p2p, "Was not expecting GO Negotiation Confirm - ignore"); 14485b9c547cSRui Paulo p2p_parse_free(&msg); 1449f05cddf9SRui Paulo return; 1450f05cddf9SRui Paulo } 1451f05cddf9SRui Paulo dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM; 14525b9c547cSRui Paulo p2p->cfg->send_action_done(p2p->cfg->cb_ctx); 1453f05cddf9SRui Paulo 1454f05cddf9SRui Paulo if (msg.dialog_token != dev->dialog_token) { 14555b9c547cSRui Paulo p2p_dbg(p2p, "Unexpected Dialog Token %u (expected %u)", 1456f05cddf9SRui Paulo msg.dialog_token, dev->dialog_token); 1457f05cddf9SRui Paulo p2p_parse_free(&msg); 1458f05cddf9SRui Paulo return; 1459f05cddf9SRui Paulo } 1460f05cddf9SRui Paulo 1461f05cddf9SRui Paulo if (!msg.status) { 14625b9c547cSRui Paulo p2p_dbg(p2p, "No Status attribute received"); 1463f05cddf9SRui Paulo p2p_parse_free(&msg); 1464f05cddf9SRui Paulo return; 1465f05cddf9SRui Paulo } 1466f05cddf9SRui Paulo if (*msg.status) { 14675b9c547cSRui Paulo p2p_dbg(p2p, "GO Negotiation rejected: status %d", *msg.status); 14685b9c547cSRui Paulo p2p_go_neg_failed(p2p, *msg.status); 1469f05cddf9SRui Paulo p2p_parse_free(&msg); 1470f05cddf9SRui Paulo return; 1471f05cddf9SRui Paulo } 1472f05cddf9SRui Paulo 1473f05cddf9SRui Paulo if (dev->go_state == REMOTE_GO && msg.group_id) { 1474f05cddf9SRui Paulo /* Store SSID for Provisioning step */ 1475f05cddf9SRui Paulo p2p->ssid_len = msg.group_id_len - ETH_ALEN; 1476f05cddf9SRui Paulo os_memcpy(p2p->ssid, msg.group_id + ETH_ALEN, p2p->ssid_len); 1477f05cddf9SRui Paulo } else if (dev->go_state == REMOTE_GO) { 14785b9c547cSRui Paulo p2p_dbg(p2p, "Mandatory P2P Group ID attribute missing from GO Negotiation Confirmation"); 1479f05cddf9SRui Paulo p2p->ssid_len = 0; 14805b9c547cSRui Paulo p2p_go_neg_failed(p2p, P2P_SC_FAIL_INVALID_PARAMS); 1481f05cddf9SRui Paulo p2p_parse_free(&msg); 1482f05cddf9SRui Paulo return; 1483f05cddf9SRui Paulo } 1484f05cddf9SRui Paulo 1485f05cddf9SRui Paulo if (!msg.operating_channel) { 14865b9c547cSRui Paulo p2p_dbg(p2p, "Mandatory Operating Channel attribute missing from GO Negotiation Confirmation"); 1487f05cddf9SRui Paulo #ifdef CONFIG_P2P_STRICT 1488f05cddf9SRui Paulo p2p_parse_free(&msg); 1489f05cddf9SRui Paulo return; 1490f05cddf9SRui Paulo #endif /* CONFIG_P2P_STRICT */ 14915b9c547cSRui Paulo } else if (dev->go_state == REMOTE_GO) { 14925b9c547cSRui Paulo int oper_freq = p2p_channel_to_freq(msg.operating_channel[3], 14935b9c547cSRui Paulo msg.operating_channel[4]); 14945b9c547cSRui Paulo if (oper_freq != dev->oper_freq) { 14955b9c547cSRui Paulo p2p_dbg(p2p, "Updated peer (GO) operating channel preference from %d MHz to %d MHz", 14965b9c547cSRui Paulo dev->oper_freq, oper_freq); 14975b9c547cSRui Paulo dev->oper_freq = oper_freq; 14985b9c547cSRui Paulo } 1499f05cddf9SRui Paulo } 1500f05cddf9SRui Paulo 1501f05cddf9SRui Paulo if (!msg.channel_list) { 15025b9c547cSRui Paulo p2p_dbg(p2p, "Mandatory Operating Channel attribute missing from GO Negotiation Confirmation"); 1503f05cddf9SRui Paulo #ifdef CONFIG_P2P_STRICT 1504f05cddf9SRui Paulo p2p_parse_free(&msg); 1505f05cddf9SRui Paulo return; 1506f05cddf9SRui Paulo #endif /* CONFIG_P2P_STRICT */ 1507f05cddf9SRui Paulo } 1508f05cddf9SRui Paulo 1509f05cddf9SRui Paulo p2p_parse_free(&msg); 1510f05cddf9SRui Paulo 1511f05cddf9SRui Paulo if (dev->go_state == UNKNOWN_GO) { 1512f05cddf9SRui Paulo /* 1513f05cddf9SRui Paulo * This should not happen since GO negotiation has already 1514f05cddf9SRui Paulo * been completed. 1515f05cddf9SRui Paulo */ 15165b9c547cSRui Paulo p2p_dbg(p2p, "Unexpected GO Neg state - do not know which end becomes GO"); 1517f05cddf9SRui Paulo return; 1518f05cddf9SRui Paulo } 1519f05cddf9SRui Paulo 1520f05cddf9SRui Paulo /* 1521f05cddf9SRui Paulo * The peer could have missed our ctrl::ack frame for GO Negotiation 1522f05cddf9SRui Paulo * Confirm and continue retransmitting the frame. To reduce the 1523f05cddf9SRui Paulo * likelihood of the peer not getting successful TX status for the 1524f05cddf9SRui Paulo * GO Negotiation Confirm frame, wait a short time here before starting 1525f05cddf9SRui Paulo * the group so that we will remain on the current channel to 1526f05cddf9SRui Paulo * acknowledge any possible retransmission from the peer. 1527f05cddf9SRui Paulo */ 15285b9c547cSRui Paulo p2p_dbg(p2p, "20 ms wait on current channel before starting group"); 1529f05cddf9SRui Paulo os_sleep(0, 20000); 1530f05cddf9SRui Paulo 1531f05cddf9SRui Paulo p2p_go_complete(p2p, dev); 1532f05cddf9SRui Paulo } 1533