1*f05cddf9SRui Paulo /* 2*f05cddf9SRui Paulo * Wi-Fi Direct - P2P Group Owner Negotiation 3*f05cddf9SRui Paulo * Copyright (c) 2009-2010, Atheros Communications 4*f05cddf9SRui Paulo * 5*f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license. 6*f05cddf9SRui Paulo * See README for more details. 7*f05cddf9SRui Paulo */ 8*f05cddf9SRui Paulo 9*f05cddf9SRui Paulo #include "includes.h" 10*f05cddf9SRui Paulo 11*f05cddf9SRui Paulo #include "common.h" 12*f05cddf9SRui Paulo #include "common/ieee802_11_defs.h" 13*f05cddf9SRui Paulo #include "wps/wps_defs.h" 14*f05cddf9SRui Paulo #include "p2p_i.h" 15*f05cddf9SRui Paulo #include "p2p.h" 16*f05cddf9SRui Paulo 17*f05cddf9SRui Paulo 18*f05cddf9SRui Paulo static int p2p_go_det(u8 own_intent, u8 peer_value) 19*f05cddf9SRui Paulo { 20*f05cddf9SRui Paulo u8 peer_intent = peer_value >> 1; 21*f05cddf9SRui Paulo if (own_intent == peer_intent) { 22*f05cddf9SRui Paulo if (own_intent == P2P_MAX_GO_INTENT) 23*f05cddf9SRui Paulo return -1; /* both devices want to become GO */ 24*f05cddf9SRui Paulo 25*f05cddf9SRui Paulo /* Use tie breaker bit to determine GO */ 26*f05cddf9SRui Paulo return (peer_value & 0x01) ? 0 : 1; 27*f05cddf9SRui Paulo } 28*f05cddf9SRui Paulo 29*f05cddf9SRui Paulo return own_intent > peer_intent; 30*f05cddf9SRui Paulo } 31*f05cddf9SRui Paulo 32*f05cddf9SRui Paulo 33*f05cddf9SRui Paulo int p2p_peer_channels_check(struct p2p_data *p2p, struct p2p_channels *own, 34*f05cddf9SRui Paulo struct p2p_device *dev, 35*f05cddf9SRui Paulo const u8 *channel_list, size_t channel_list_len) 36*f05cddf9SRui Paulo { 37*f05cddf9SRui Paulo const u8 *pos, *end; 38*f05cddf9SRui Paulo struct p2p_channels *ch; 39*f05cddf9SRui Paulo size_t channels; 40*f05cddf9SRui Paulo struct p2p_channels intersection; 41*f05cddf9SRui Paulo 42*f05cddf9SRui Paulo ch = &dev->channels; 43*f05cddf9SRui Paulo os_memset(ch, 0, sizeof(*ch)); 44*f05cddf9SRui Paulo pos = channel_list; 45*f05cddf9SRui Paulo end = channel_list + channel_list_len; 46*f05cddf9SRui Paulo 47*f05cddf9SRui Paulo if (end - pos < 3) 48*f05cddf9SRui Paulo return -1; 49*f05cddf9SRui Paulo os_memcpy(dev->country, pos, 3); 50*f05cddf9SRui Paulo wpa_hexdump_ascii(MSG_DEBUG, "P2P: Peer country", pos, 3); 51*f05cddf9SRui Paulo if (pos[2] != 0x04 && os_memcmp(pos, p2p->cfg->country, 2) != 0) { 52*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, 53*f05cddf9SRui Paulo "P2P: Mismatching country (ours=%c%c peer's=%c%c)", 54*f05cddf9SRui Paulo p2p->cfg->country[0], p2p->cfg->country[1], 55*f05cddf9SRui Paulo pos[0], pos[1]); 56*f05cddf9SRui Paulo return -1; 57*f05cddf9SRui Paulo } 58*f05cddf9SRui Paulo pos += 3; 59*f05cddf9SRui Paulo 60*f05cddf9SRui Paulo while (pos + 2 < end) { 61*f05cddf9SRui Paulo struct p2p_reg_class *cl = &ch->reg_class[ch->reg_classes]; 62*f05cddf9SRui Paulo cl->reg_class = *pos++; 63*f05cddf9SRui Paulo if (pos + 1 + pos[0] > end) { 64*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, 65*f05cddf9SRui Paulo "P2P: Invalid peer Channel List"); 66*f05cddf9SRui Paulo return -1; 67*f05cddf9SRui Paulo } 68*f05cddf9SRui Paulo channels = *pos++; 69*f05cddf9SRui Paulo cl->channels = channels > P2P_MAX_REG_CLASS_CHANNELS ? 70*f05cddf9SRui Paulo P2P_MAX_REG_CLASS_CHANNELS : channels; 71*f05cddf9SRui Paulo os_memcpy(cl->channel, pos, cl->channels); 72*f05cddf9SRui Paulo pos += channels; 73*f05cddf9SRui Paulo ch->reg_classes++; 74*f05cddf9SRui Paulo if (ch->reg_classes == P2P_MAX_REG_CLASSES) 75*f05cddf9SRui Paulo break; 76*f05cddf9SRui Paulo } 77*f05cddf9SRui Paulo 78*f05cddf9SRui Paulo p2p_channels_intersect(own, &dev->channels, &intersection); 79*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Own reg_classes %d " 80*f05cddf9SRui Paulo "peer reg_classes %d intersection reg_classes %d", 81*f05cddf9SRui Paulo (int) own->reg_classes, 82*f05cddf9SRui Paulo (int) dev->channels.reg_classes, 83*f05cddf9SRui Paulo (int) intersection.reg_classes); 84*f05cddf9SRui Paulo if (intersection.reg_classes == 0) { 85*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, 86*f05cddf9SRui Paulo "P2P: No common channels found"); 87*f05cddf9SRui Paulo return -1; 88*f05cddf9SRui Paulo } 89*f05cddf9SRui Paulo return 0; 90*f05cddf9SRui Paulo } 91*f05cddf9SRui Paulo 92*f05cddf9SRui Paulo 93*f05cddf9SRui Paulo static int p2p_peer_channels(struct p2p_data *p2p, struct p2p_device *dev, 94*f05cddf9SRui Paulo const u8 *channel_list, size_t channel_list_len) 95*f05cddf9SRui Paulo { 96*f05cddf9SRui Paulo return p2p_peer_channels_check(p2p, &p2p->channels, dev, 97*f05cddf9SRui Paulo channel_list, channel_list_len); 98*f05cddf9SRui Paulo } 99*f05cddf9SRui Paulo 100*f05cddf9SRui Paulo 101*f05cddf9SRui Paulo u16 p2p_wps_method_pw_id(enum p2p_wps_method wps_method) 102*f05cddf9SRui Paulo { 103*f05cddf9SRui Paulo switch (wps_method) { 104*f05cddf9SRui Paulo case WPS_PIN_DISPLAY: 105*f05cddf9SRui Paulo return DEV_PW_REGISTRAR_SPECIFIED; 106*f05cddf9SRui Paulo case WPS_PIN_KEYPAD: 107*f05cddf9SRui Paulo return DEV_PW_USER_SPECIFIED; 108*f05cddf9SRui Paulo case WPS_PBC: 109*f05cddf9SRui Paulo return DEV_PW_PUSHBUTTON; 110*f05cddf9SRui Paulo default: 111*f05cddf9SRui Paulo return DEV_PW_DEFAULT; 112*f05cddf9SRui Paulo } 113*f05cddf9SRui Paulo } 114*f05cddf9SRui Paulo 115*f05cddf9SRui Paulo 116*f05cddf9SRui Paulo static const char * p2p_wps_method_str(enum p2p_wps_method wps_method) 117*f05cddf9SRui Paulo { 118*f05cddf9SRui Paulo switch (wps_method) { 119*f05cddf9SRui Paulo case WPS_PIN_DISPLAY: 120*f05cddf9SRui Paulo return "Display"; 121*f05cddf9SRui Paulo case WPS_PIN_KEYPAD: 122*f05cddf9SRui Paulo return "Keypad"; 123*f05cddf9SRui Paulo case WPS_PBC: 124*f05cddf9SRui Paulo return "PBC"; 125*f05cddf9SRui Paulo default: 126*f05cddf9SRui Paulo return "??"; 127*f05cddf9SRui Paulo } 128*f05cddf9SRui Paulo } 129*f05cddf9SRui Paulo 130*f05cddf9SRui Paulo 131*f05cddf9SRui Paulo static struct wpabuf * p2p_build_go_neg_req(struct p2p_data *p2p, 132*f05cddf9SRui Paulo struct p2p_device *peer) 133*f05cddf9SRui Paulo { 134*f05cddf9SRui Paulo struct wpabuf *buf; 135*f05cddf9SRui Paulo u8 *len; 136*f05cddf9SRui Paulo u8 group_capab; 137*f05cddf9SRui Paulo size_t extra = 0; 138*f05cddf9SRui Paulo 139*f05cddf9SRui Paulo #ifdef CONFIG_WIFI_DISPLAY 140*f05cddf9SRui Paulo if (p2p->wfd_ie_go_neg) 141*f05cddf9SRui Paulo extra = wpabuf_len(p2p->wfd_ie_go_neg); 142*f05cddf9SRui Paulo #endif /* CONFIG_WIFI_DISPLAY */ 143*f05cddf9SRui Paulo 144*f05cddf9SRui Paulo buf = wpabuf_alloc(1000 + extra); 145*f05cddf9SRui Paulo if (buf == NULL) 146*f05cddf9SRui Paulo return NULL; 147*f05cddf9SRui Paulo 148*f05cddf9SRui Paulo peer->dialog_token++; 149*f05cddf9SRui Paulo if (peer->dialog_token == 0) 150*f05cddf9SRui Paulo peer->dialog_token = 1; 151*f05cddf9SRui Paulo p2p_buf_add_public_action_hdr(buf, P2P_GO_NEG_REQ, peer->dialog_token); 152*f05cddf9SRui Paulo 153*f05cddf9SRui Paulo len = p2p_buf_add_ie_hdr(buf); 154*f05cddf9SRui Paulo group_capab = 0; 155*f05cddf9SRui Paulo if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) { 156*f05cddf9SRui Paulo group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP; 157*f05cddf9SRui Paulo if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN) 158*f05cddf9SRui Paulo group_capab |= P2P_GROUP_CAPAB_PERSISTENT_RECONN; 159*f05cddf9SRui Paulo } 160*f05cddf9SRui Paulo if (p2p->cross_connect) 161*f05cddf9SRui Paulo group_capab |= P2P_GROUP_CAPAB_CROSS_CONN; 162*f05cddf9SRui Paulo if (p2p->cfg->p2p_intra_bss) 163*f05cddf9SRui Paulo group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST; 164*f05cddf9SRui Paulo p2p_buf_add_capability(buf, p2p->dev_capab & 165*f05cddf9SRui Paulo ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 166*f05cddf9SRui Paulo group_capab); 167*f05cddf9SRui Paulo p2p_buf_add_go_intent(buf, (p2p->go_intent << 1) | 168*f05cddf9SRui Paulo p2p->next_tie_breaker); 169*f05cddf9SRui Paulo p2p->next_tie_breaker = !p2p->next_tie_breaker; 170*f05cddf9SRui Paulo p2p_buf_add_config_timeout(buf, p2p->go_timeout, p2p->client_timeout); 171*f05cddf9SRui Paulo p2p_buf_add_listen_channel(buf, p2p->cfg->country, p2p->cfg->reg_class, 172*f05cddf9SRui Paulo p2p->cfg->channel); 173*f05cddf9SRui Paulo if (p2p->ext_listen_interval) 174*f05cddf9SRui Paulo p2p_buf_add_ext_listen_timing(buf, p2p->ext_listen_period, 175*f05cddf9SRui Paulo p2p->ext_listen_interval); 176*f05cddf9SRui Paulo p2p_buf_add_intended_addr(buf, p2p->intended_addr); 177*f05cddf9SRui Paulo p2p_buf_add_channel_list(buf, p2p->cfg->country, &p2p->channels); 178*f05cddf9SRui Paulo p2p_buf_add_device_info(buf, p2p, peer); 179*f05cddf9SRui Paulo p2p_buf_add_operating_channel(buf, p2p->cfg->country, 180*f05cddf9SRui Paulo p2p->op_reg_class, p2p->op_channel); 181*f05cddf9SRui Paulo p2p_buf_update_ie_hdr(buf, len); 182*f05cddf9SRui Paulo 183*f05cddf9SRui Paulo /* WPS IE with Device Password ID attribute */ 184*f05cddf9SRui Paulo p2p_build_wps_ie(p2p, buf, p2p_wps_method_pw_id(peer->wps_method), 0); 185*f05cddf9SRui Paulo 186*f05cddf9SRui Paulo #ifdef CONFIG_WIFI_DISPLAY 187*f05cddf9SRui Paulo if (p2p->wfd_ie_go_neg) 188*f05cddf9SRui Paulo wpabuf_put_buf(buf, p2p->wfd_ie_go_neg); 189*f05cddf9SRui Paulo #endif /* CONFIG_WIFI_DISPLAY */ 190*f05cddf9SRui Paulo 191*f05cddf9SRui Paulo return buf; 192*f05cddf9SRui Paulo } 193*f05cddf9SRui Paulo 194*f05cddf9SRui Paulo 195*f05cddf9SRui Paulo int p2p_connect_send(struct p2p_data *p2p, struct p2p_device *dev) 196*f05cddf9SRui Paulo { 197*f05cddf9SRui Paulo struct wpabuf *req; 198*f05cddf9SRui Paulo int freq; 199*f05cddf9SRui Paulo 200*f05cddf9SRui Paulo if (dev->flags & P2P_DEV_PD_BEFORE_GO_NEG) { 201*f05cddf9SRui Paulo u16 config_method; 202*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 203*f05cddf9SRui Paulo "P2P: Use PD-before-GO-Neg workaround for " MACSTR, 204*f05cddf9SRui Paulo MAC2STR(dev->info.p2p_device_addr)); 205*f05cddf9SRui Paulo if (dev->wps_method == WPS_PIN_DISPLAY) 206*f05cddf9SRui Paulo config_method = WPS_CONFIG_KEYPAD; 207*f05cddf9SRui Paulo else if (dev->wps_method == WPS_PIN_KEYPAD) 208*f05cddf9SRui Paulo config_method = WPS_CONFIG_DISPLAY; 209*f05cddf9SRui Paulo else if (dev->wps_method == WPS_PBC) 210*f05cddf9SRui Paulo config_method = WPS_CONFIG_PUSHBUTTON; 211*f05cddf9SRui Paulo else 212*f05cddf9SRui Paulo return -1; 213*f05cddf9SRui Paulo return p2p_prov_disc_req(p2p, dev->info.p2p_device_addr, 214*f05cddf9SRui Paulo config_method, 0, 0, 1); 215*f05cddf9SRui Paulo } 216*f05cddf9SRui Paulo 217*f05cddf9SRui Paulo freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq; 218*f05cddf9SRui Paulo if (freq <= 0) { 219*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 220*f05cddf9SRui Paulo "P2P: No Listen/Operating frequency known for the " 221*f05cddf9SRui Paulo "peer " MACSTR " to send GO Negotiation Request", 222*f05cddf9SRui Paulo MAC2STR(dev->info.p2p_device_addr)); 223*f05cddf9SRui Paulo return -1; 224*f05cddf9SRui Paulo } 225*f05cddf9SRui Paulo 226*f05cddf9SRui Paulo req = p2p_build_go_neg_req(p2p, dev); 227*f05cddf9SRui Paulo if (req == NULL) 228*f05cddf9SRui Paulo return -1; 229*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 230*f05cddf9SRui Paulo "P2P: Sending GO Negotiation Request"); 231*f05cddf9SRui Paulo p2p_set_state(p2p, P2P_CONNECT); 232*f05cddf9SRui Paulo p2p->pending_action_state = P2P_PENDING_GO_NEG_REQUEST; 233*f05cddf9SRui Paulo p2p->go_neg_peer = dev; 234*f05cddf9SRui Paulo dev->flags |= P2P_DEV_WAIT_GO_NEG_RESPONSE; 235*f05cddf9SRui Paulo dev->connect_reqs++; 236*f05cddf9SRui Paulo if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr, 237*f05cddf9SRui Paulo p2p->cfg->dev_addr, dev->info.p2p_device_addr, 238*f05cddf9SRui Paulo wpabuf_head(req), wpabuf_len(req), 200) < 0) { 239*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 240*f05cddf9SRui Paulo "P2P: Failed to send Action frame"); 241*f05cddf9SRui Paulo /* Use P2P find to recover and retry */ 242*f05cddf9SRui Paulo p2p_set_timeout(p2p, 0, 0); 243*f05cddf9SRui Paulo } else 244*f05cddf9SRui Paulo dev->go_neg_req_sent++; 245*f05cddf9SRui Paulo 246*f05cddf9SRui Paulo wpabuf_free(req); 247*f05cddf9SRui Paulo 248*f05cddf9SRui Paulo return 0; 249*f05cddf9SRui Paulo } 250*f05cddf9SRui Paulo 251*f05cddf9SRui Paulo 252*f05cddf9SRui Paulo static struct wpabuf * p2p_build_go_neg_resp(struct p2p_data *p2p, 253*f05cddf9SRui Paulo struct p2p_device *peer, 254*f05cddf9SRui Paulo u8 dialog_token, u8 status, 255*f05cddf9SRui Paulo u8 tie_breaker) 256*f05cddf9SRui Paulo { 257*f05cddf9SRui Paulo struct wpabuf *buf; 258*f05cddf9SRui Paulo u8 *len; 259*f05cddf9SRui Paulo u8 group_capab; 260*f05cddf9SRui Paulo size_t extra = 0; 261*f05cddf9SRui Paulo 262*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 263*f05cddf9SRui Paulo "P2P: Building GO Negotiation Response"); 264*f05cddf9SRui Paulo 265*f05cddf9SRui Paulo #ifdef CONFIG_WIFI_DISPLAY 266*f05cddf9SRui Paulo if (p2p->wfd_ie_go_neg) 267*f05cddf9SRui Paulo extra = wpabuf_len(p2p->wfd_ie_go_neg); 268*f05cddf9SRui Paulo #endif /* CONFIG_WIFI_DISPLAY */ 269*f05cddf9SRui Paulo 270*f05cddf9SRui Paulo buf = wpabuf_alloc(1000 + extra); 271*f05cddf9SRui Paulo if (buf == NULL) 272*f05cddf9SRui Paulo return NULL; 273*f05cddf9SRui Paulo 274*f05cddf9SRui Paulo p2p_buf_add_public_action_hdr(buf, P2P_GO_NEG_RESP, dialog_token); 275*f05cddf9SRui Paulo 276*f05cddf9SRui Paulo len = p2p_buf_add_ie_hdr(buf); 277*f05cddf9SRui Paulo p2p_buf_add_status(buf, status); 278*f05cddf9SRui Paulo group_capab = 0; 279*f05cddf9SRui Paulo if (peer && peer->go_state == LOCAL_GO) { 280*f05cddf9SRui Paulo if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) { 281*f05cddf9SRui Paulo group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP; 282*f05cddf9SRui Paulo if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN) 283*f05cddf9SRui Paulo group_capab |= 284*f05cddf9SRui Paulo P2P_GROUP_CAPAB_PERSISTENT_RECONN; 285*f05cddf9SRui Paulo } 286*f05cddf9SRui Paulo if (p2p->cross_connect) 287*f05cddf9SRui Paulo group_capab |= P2P_GROUP_CAPAB_CROSS_CONN; 288*f05cddf9SRui Paulo if (p2p->cfg->p2p_intra_bss) 289*f05cddf9SRui Paulo group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST; 290*f05cddf9SRui Paulo } 291*f05cddf9SRui Paulo p2p_buf_add_capability(buf, p2p->dev_capab & 292*f05cddf9SRui Paulo ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 293*f05cddf9SRui Paulo group_capab); 294*f05cddf9SRui Paulo p2p_buf_add_go_intent(buf, (p2p->go_intent << 1) | tie_breaker); 295*f05cddf9SRui Paulo p2p_buf_add_config_timeout(buf, p2p->go_timeout, p2p->client_timeout); 296*f05cddf9SRui Paulo if (peer && peer->go_state == REMOTE_GO) { 297*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Omit Operating " 298*f05cddf9SRui Paulo "Channel attribute"); 299*f05cddf9SRui Paulo } else { 300*f05cddf9SRui Paulo p2p_buf_add_operating_channel(buf, p2p->cfg->country, 301*f05cddf9SRui Paulo p2p->op_reg_class, 302*f05cddf9SRui Paulo p2p->op_channel); 303*f05cddf9SRui Paulo } 304*f05cddf9SRui Paulo p2p_buf_add_intended_addr(buf, p2p->intended_addr); 305*f05cddf9SRui Paulo if (status || peer == NULL) { 306*f05cddf9SRui Paulo p2p_buf_add_channel_list(buf, p2p->cfg->country, 307*f05cddf9SRui Paulo &p2p->channels); 308*f05cddf9SRui Paulo } else if (peer->go_state == REMOTE_GO) { 309*f05cddf9SRui Paulo p2p_buf_add_channel_list(buf, p2p->cfg->country, 310*f05cddf9SRui Paulo &p2p->channels); 311*f05cddf9SRui Paulo } else { 312*f05cddf9SRui Paulo struct p2p_channels res; 313*f05cddf9SRui Paulo p2p_channels_intersect(&p2p->channels, &peer->channels, 314*f05cddf9SRui Paulo &res); 315*f05cddf9SRui Paulo p2p_buf_add_channel_list(buf, p2p->cfg->country, &res); 316*f05cddf9SRui Paulo } 317*f05cddf9SRui Paulo p2p_buf_add_device_info(buf, p2p, peer); 318*f05cddf9SRui Paulo if (peer && peer->go_state == LOCAL_GO) { 319*f05cddf9SRui Paulo p2p_buf_add_group_id(buf, p2p->cfg->dev_addr, p2p->ssid, 320*f05cddf9SRui Paulo p2p->ssid_len); 321*f05cddf9SRui Paulo } 322*f05cddf9SRui Paulo p2p_buf_update_ie_hdr(buf, len); 323*f05cddf9SRui Paulo 324*f05cddf9SRui Paulo /* WPS IE with Device Password ID attribute */ 325*f05cddf9SRui Paulo p2p_build_wps_ie(p2p, buf, 326*f05cddf9SRui Paulo p2p_wps_method_pw_id(peer ? peer->wps_method : 327*f05cddf9SRui Paulo WPS_NOT_READY), 0); 328*f05cddf9SRui Paulo 329*f05cddf9SRui Paulo #ifdef CONFIG_WIFI_DISPLAY 330*f05cddf9SRui Paulo if (p2p->wfd_ie_go_neg) 331*f05cddf9SRui Paulo wpabuf_put_buf(buf, p2p->wfd_ie_go_neg); 332*f05cddf9SRui Paulo #endif /* CONFIG_WIFI_DISPLAY */ 333*f05cddf9SRui Paulo 334*f05cddf9SRui Paulo 335*f05cddf9SRui Paulo return buf; 336*f05cddf9SRui Paulo } 337*f05cddf9SRui Paulo 338*f05cddf9SRui Paulo 339*f05cddf9SRui Paulo /** 340*f05cddf9SRui Paulo * p2p_reselect_channel - Re-select operating channel based on peer information 341*f05cddf9SRui Paulo * @p2p: P2P module context from p2p_init() 342*f05cddf9SRui Paulo * @intersection: Support channel list intersection from local and peer 343*f05cddf9SRui Paulo * 344*f05cddf9SRui Paulo * This function is used to re-select the best channel after having received 345*f05cddf9SRui Paulo * information from the peer to allow supported channel lists to be intersected. 346*f05cddf9SRui Paulo * This can be used to improve initial channel selection done in 347*f05cddf9SRui Paulo * p2p_prepare_channel() prior to the start of GO Negotiation. In addition, this 348*f05cddf9SRui Paulo * can be used for Invitation case. 349*f05cddf9SRui Paulo */ 350*f05cddf9SRui Paulo void p2p_reselect_channel(struct p2p_data *p2p, 351*f05cddf9SRui Paulo struct p2p_channels *intersection) 352*f05cddf9SRui Paulo { 353*f05cddf9SRui Paulo struct p2p_reg_class *cl; 354*f05cddf9SRui Paulo int freq; 355*f05cddf9SRui Paulo u8 op_reg_class, op_channel; 356*f05cddf9SRui Paulo unsigned int i; 357*f05cddf9SRui Paulo 358*f05cddf9SRui Paulo /* First, try to pick the best channel from another band */ 359*f05cddf9SRui Paulo freq = p2p_channel_to_freq(p2p->cfg->country, p2p->op_reg_class, 360*f05cddf9SRui Paulo p2p->op_channel); 361*f05cddf9SRui Paulo if (freq >= 2400 && freq < 2500 && p2p->best_freq_5 > 0 && 362*f05cddf9SRui Paulo p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_5, 363*f05cddf9SRui Paulo &op_reg_class, &op_channel) == 0 && 364*f05cddf9SRui Paulo p2p_channels_includes(intersection, op_reg_class, op_channel)) { 365*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick best 5 GHz " 366*f05cddf9SRui Paulo "channel (reg_class %u channel %u) from intersection", 367*f05cddf9SRui Paulo op_reg_class, op_channel); 368*f05cddf9SRui Paulo p2p->op_reg_class = op_reg_class; 369*f05cddf9SRui Paulo p2p->op_channel = op_channel; 370*f05cddf9SRui Paulo return; 371*f05cddf9SRui Paulo } 372*f05cddf9SRui Paulo 373*f05cddf9SRui Paulo if (freq >= 4900 && freq < 6000 && p2p->best_freq_24 > 0 && 374*f05cddf9SRui Paulo p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_24, 375*f05cddf9SRui Paulo &op_reg_class, &op_channel) == 0 && 376*f05cddf9SRui Paulo p2p_channels_includes(intersection, op_reg_class, op_channel)) { 377*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick best 2.4 GHz " 378*f05cddf9SRui Paulo "channel (reg_class %u channel %u) from intersection", 379*f05cddf9SRui Paulo op_reg_class, op_channel); 380*f05cddf9SRui Paulo p2p->op_reg_class = op_reg_class; 381*f05cddf9SRui Paulo p2p->op_channel = op_channel; 382*f05cddf9SRui Paulo return; 383*f05cddf9SRui Paulo } 384*f05cddf9SRui Paulo 385*f05cddf9SRui Paulo /* Select channel with highest preference if the peer supports it */ 386*f05cddf9SRui Paulo for (i = 0; p2p->cfg->pref_chan && i < p2p->cfg->num_pref_chan; i++) { 387*f05cddf9SRui Paulo if (p2p_channels_includes(intersection, 388*f05cddf9SRui Paulo p2p->cfg->pref_chan[i].op_class, 389*f05cddf9SRui Paulo p2p->cfg->pref_chan[i].chan)) { 390*f05cddf9SRui Paulo p2p->op_reg_class = p2p->cfg->pref_chan[i].op_class; 391*f05cddf9SRui Paulo p2p->op_channel = p2p->cfg->pref_chan[i].chan; 392*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick " 393*f05cddf9SRui Paulo "highest preferred chnnel (op_class %u " 394*f05cddf9SRui Paulo "channel %u) from intersection", 395*f05cddf9SRui Paulo p2p->op_reg_class, p2p->op_channel); 396*f05cddf9SRui Paulo return; 397*f05cddf9SRui Paulo } 398*f05cddf9SRui Paulo } 399*f05cddf9SRui Paulo 400*f05cddf9SRui Paulo /* Try a channel where we might be able to use HT40 */ 401*f05cddf9SRui Paulo for (i = 0; i < intersection->reg_classes; i++) { 402*f05cddf9SRui Paulo struct p2p_reg_class *c = &intersection->reg_class[i]; 403*f05cddf9SRui Paulo if (c->reg_class == 116 || c->reg_class == 117 || 404*f05cddf9SRui Paulo c->reg_class == 126 || c->reg_class == 127) { 405*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 406*f05cddf9SRui Paulo "P2P: Pick possible HT40 channel (reg_class " 407*f05cddf9SRui Paulo "%u channel %u) from intersection", 408*f05cddf9SRui Paulo c->reg_class, c->channel[0]); 409*f05cddf9SRui Paulo p2p->op_reg_class = c->reg_class; 410*f05cddf9SRui Paulo p2p->op_channel = c->channel[0]; 411*f05cddf9SRui Paulo return; 412*f05cddf9SRui Paulo } 413*f05cddf9SRui Paulo } 414*f05cddf9SRui Paulo 415*f05cddf9SRui Paulo /* 416*f05cddf9SRui Paulo * Try to see if the original channel is in the intersection. If 417*f05cddf9SRui Paulo * so, no need to change anything, as it already contains some 418*f05cddf9SRui Paulo * randomness. 419*f05cddf9SRui Paulo */ 420*f05cddf9SRui Paulo if (p2p_channels_includes(intersection, p2p->op_reg_class, 421*f05cddf9SRui Paulo p2p->op_channel)) { 422*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 423*f05cddf9SRui Paulo "P2P: Using original operating class and channel " 424*f05cddf9SRui Paulo "(op_class %u channel %u) from intersection", 425*f05cddf9SRui Paulo p2p->op_reg_class, p2p->op_channel); 426*f05cddf9SRui Paulo return; 427*f05cddf9SRui Paulo } 428*f05cddf9SRui Paulo 429*f05cddf9SRui Paulo /* 430*f05cddf9SRui Paulo * Fall back to whatever is included in the channel intersection since 431*f05cddf9SRui Paulo * no better options seems to be available. 432*f05cddf9SRui Paulo */ 433*f05cddf9SRui Paulo cl = &intersection->reg_class[0]; 434*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick another channel " 435*f05cddf9SRui Paulo "(reg_class %u channel %u) from intersection", 436*f05cddf9SRui Paulo cl->reg_class, cl->channel[0]); 437*f05cddf9SRui Paulo p2p->op_reg_class = cl->reg_class; 438*f05cddf9SRui Paulo p2p->op_channel = cl->channel[0]; 439*f05cddf9SRui Paulo } 440*f05cddf9SRui Paulo 441*f05cddf9SRui Paulo 442*f05cddf9SRui Paulo static int p2p_go_select_channel(struct p2p_data *p2p, struct p2p_device *dev, 443*f05cddf9SRui Paulo u8 *status) 444*f05cddf9SRui Paulo { 445*f05cddf9SRui Paulo struct p2p_channels intersection; 446*f05cddf9SRui Paulo size_t i; 447*f05cddf9SRui Paulo 448*f05cddf9SRui Paulo p2p_channels_intersect(&p2p->channels, &dev->channels, &intersection); 449*f05cddf9SRui Paulo if (intersection.reg_classes == 0 || 450*f05cddf9SRui Paulo intersection.reg_class[0].channels == 0) { 451*f05cddf9SRui Paulo *status = P2P_SC_FAIL_NO_COMMON_CHANNELS; 452*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 453*f05cddf9SRui Paulo "P2P: No common channels found"); 454*f05cddf9SRui Paulo return -1; 455*f05cddf9SRui Paulo } 456*f05cddf9SRui Paulo 457*f05cddf9SRui Paulo for (i = 0; i < intersection.reg_classes; i++) { 458*f05cddf9SRui Paulo struct p2p_reg_class *c; 459*f05cddf9SRui Paulo c = &intersection.reg_class[i]; 460*f05cddf9SRui Paulo wpa_printf(MSG_DEBUG, "P2P: reg_class %u", c->reg_class); 461*f05cddf9SRui Paulo wpa_hexdump(MSG_DEBUG, "P2P: channels", 462*f05cddf9SRui Paulo c->channel, c->channels); 463*f05cddf9SRui Paulo } 464*f05cddf9SRui Paulo 465*f05cddf9SRui Paulo if (!p2p_channels_includes(&intersection, p2p->op_reg_class, 466*f05cddf9SRui Paulo p2p->op_channel)) { 467*f05cddf9SRui Paulo if (dev->flags & P2P_DEV_FORCE_FREQ) { 468*f05cddf9SRui Paulo *status = P2P_SC_FAIL_NO_COMMON_CHANNELS; 469*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer does " 470*f05cddf9SRui Paulo "not support the forced channel"); 471*f05cddf9SRui Paulo return -1; 472*f05cddf9SRui Paulo } 473*f05cddf9SRui Paulo 474*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Selected operating " 475*f05cddf9SRui Paulo "channel (op_class %u channel %u) not acceptable to " 476*f05cddf9SRui Paulo "the peer", p2p->op_reg_class, p2p->op_channel); 477*f05cddf9SRui Paulo p2p_reselect_channel(p2p, &intersection); 478*f05cddf9SRui Paulo } else if (!(dev->flags & P2P_DEV_FORCE_FREQ) && 479*f05cddf9SRui Paulo !p2p->cfg->cfg_op_channel) { 480*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Try to optimize " 481*f05cddf9SRui Paulo "channel selection with peer information received; " 482*f05cddf9SRui Paulo "previously selected op_class %u channel %u", 483*f05cddf9SRui Paulo p2p->op_reg_class, p2p->op_channel); 484*f05cddf9SRui Paulo p2p_reselect_channel(p2p, &intersection); 485*f05cddf9SRui Paulo } 486*f05cddf9SRui Paulo 487*f05cddf9SRui Paulo if (!p2p->ssid_set) { 488*f05cddf9SRui Paulo p2p_build_ssid(p2p, p2p->ssid, &p2p->ssid_len); 489*f05cddf9SRui Paulo p2p->ssid_set = 1; 490*f05cddf9SRui Paulo } 491*f05cddf9SRui Paulo 492*f05cddf9SRui Paulo return 0; 493*f05cddf9SRui Paulo } 494*f05cddf9SRui Paulo 495*f05cddf9SRui Paulo 496*f05cddf9SRui Paulo void p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa, 497*f05cddf9SRui Paulo const u8 *data, size_t len, int rx_freq) 498*f05cddf9SRui Paulo { 499*f05cddf9SRui Paulo struct p2p_device *dev = NULL; 500*f05cddf9SRui Paulo struct wpabuf *resp; 501*f05cddf9SRui Paulo struct p2p_message msg; 502*f05cddf9SRui Paulo u8 status = P2P_SC_FAIL_INVALID_PARAMS; 503*f05cddf9SRui Paulo int tie_breaker = 0; 504*f05cddf9SRui Paulo int freq; 505*f05cddf9SRui Paulo 506*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 507*f05cddf9SRui Paulo "P2P: Received GO Negotiation Request from " MACSTR 508*f05cddf9SRui Paulo "(freq=%d)", MAC2STR(sa), rx_freq); 509*f05cddf9SRui Paulo 510*f05cddf9SRui Paulo if (p2p_parse(data, len, &msg)) 511*f05cddf9SRui Paulo return; 512*f05cddf9SRui Paulo 513*f05cddf9SRui Paulo if (!msg.capability) { 514*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 515*f05cddf9SRui Paulo "P2P: Mandatory Capability attribute missing from GO " 516*f05cddf9SRui Paulo "Negotiation Request"); 517*f05cddf9SRui Paulo #ifdef CONFIG_P2P_STRICT 518*f05cddf9SRui Paulo goto fail; 519*f05cddf9SRui Paulo #endif /* CONFIG_P2P_STRICT */ 520*f05cddf9SRui Paulo } 521*f05cddf9SRui Paulo 522*f05cddf9SRui Paulo if (msg.go_intent) 523*f05cddf9SRui Paulo tie_breaker = *msg.go_intent & 0x01; 524*f05cddf9SRui Paulo else { 525*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 526*f05cddf9SRui Paulo "P2P: Mandatory GO Intent attribute missing from GO " 527*f05cddf9SRui Paulo "Negotiation Request"); 528*f05cddf9SRui Paulo #ifdef CONFIG_P2P_STRICT 529*f05cddf9SRui Paulo goto fail; 530*f05cddf9SRui Paulo #endif /* CONFIG_P2P_STRICT */ 531*f05cddf9SRui Paulo } 532*f05cddf9SRui Paulo 533*f05cddf9SRui Paulo if (!msg.config_timeout) { 534*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 535*f05cddf9SRui Paulo "P2P: Mandatory Configuration Timeout attribute " 536*f05cddf9SRui Paulo "missing from GO Negotiation Request"); 537*f05cddf9SRui Paulo #ifdef CONFIG_P2P_STRICT 538*f05cddf9SRui Paulo goto fail; 539*f05cddf9SRui Paulo #endif /* CONFIG_P2P_STRICT */ 540*f05cddf9SRui Paulo } 541*f05cddf9SRui Paulo 542*f05cddf9SRui Paulo if (!msg.listen_channel) { 543*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 544*f05cddf9SRui Paulo "P2P: No Listen Channel attribute received"); 545*f05cddf9SRui Paulo goto fail; 546*f05cddf9SRui Paulo } 547*f05cddf9SRui Paulo if (!msg.operating_channel) { 548*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 549*f05cddf9SRui Paulo "P2P: No Operating Channel attribute received"); 550*f05cddf9SRui Paulo goto fail; 551*f05cddf9SRui Paulo } 552*f05cddf9SRui Paulo if (!msg.channel_list) { 553*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 554*f05cddf9SRui Paulo "P2P: No Channel List attribute received"); 555*f05cddf9SRui Paulo goto fail; 556*f05cddf9SRui Paulo } 557*f05cddf9SRui Paulo if (!msg.intended_addr) { 558*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 559*f05cddf9SRui Paulo "P2P: No Intended P2P Interface Address attribute " 560*f05cddf9SRui Paulo "received"); 561*f05cddf9SRui Paulo goto fail; 562*f05cddf9SRui Paulo } 563*f05cddf9SRui Paulo if (!msg.p2p_device_info) { 564*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 565*f05cddf9SRui Paulo "P2P: No P2P Device Info attribute received"); 566*f05cddf9SRui Paulo goto fail; 567*f05cddf9SRui Paulo } 568*f05cddf9SRui Paulo 569*f05cddf9SRui Paulo if (os_memcmp(msg.p2p_device_addr, sa, ETH_ALEN) != 0) { 570*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 571*f05cddf9SRui Paulo "P2P: Unexpected GO Negotiation Request SA=" MACSTR 572*f05cddf9SRui Paulo " != dev_addr=" MACSTR, 573*f05cddf9SRui Paulo MAC2STR(sa), MAC2STR(msg.p2p_device_addr)); 574*f05cddf9SRui Paulo goto fail; 575*f05cddf9SRui Paulo } 576*f05cddf9SRui Paulo 577*f05cddf9SRui Paulo dev = p2p_get_device(p2p, sa); 578*f05cddf9SRui Paulo 579*f05cddf9SRui Paulo if (msg.status && *msg.status) { 580*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 581*f05cddf9SRui Paulo "P2P: Unexpected Status attribute (%d) in GO " 582*f05cddf9SRui Paulo "Negotiation Request", *msg.status); 583*f05cddf9SRui Paulo goto fail; 584*f05cddf9SRui Paulo } 585*f05cddf9SRui Paulo 586*f05cddf9SRui Paulo if (dev == NULL) 587*f05cddf9SRui Paulo dev = p2p_add_dev_from_go_neg_req(p2p, sa, &msg); 588*f05cddf9SRui Paulo else if (dev->flags & P2P_DEV_PROBE_REQ_ONLY) 589*f05cddf9SRui Paulo p2p_add_dev_info(p2p, sa, dev, &msg); 590*f05cddf9SRui Paulo if (dev && dev->flags & P2P_DEV_USER_REJECTED) { 591*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 592*f05cddf9SRui Paulo "P2P: User has rejected this peer"); 593*f05cddf9SRui Paulo status = P2P_SC_FAIL_REJECTED_BY_USER; 594*f05cddf9SRui Paulo } else if (dev == NULL || dev->wps_method == WPS_NOT_READY) { 595*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 596*f05cddf9SRui Paulo "P2P: Not ready for GO negotiation with " MACSTR, 597*f05cddf9SRui Paulo MAC2STR(sa)); 598*f05cddf9SRui Paulo status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE; 599*f05cddf9SRui Paulo if (dev) 600*f05cddf9SRui Paulo dev->flags |= P2P_DEV_PEER_WAITING_RESPONSE; 601*f05cddf9SRui Paulo p2p->cfg->go_neg_req_rx(p2p->cfg->cb_ctx, sa, 602*f05cddf9SRui Paulo msg.dev_password_id); 603*f05cddf9SRui Paulo } else if (p2p->go_neg_peer && p2p->go_neg_peer != dev) { 604*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 605*f05cddf9SRui Paulo "P2P: Already in Group Formation with another peer"); 606*f05cddf9SRui Paulo status = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE; 607*f05cddf9SRui Paulo } else { 608*f05cddf9SRui Paulo int go; 609*f05cddf9SRui Paulo 610*f05cddf9SRui Paulo if (!p2p->go_neg_peer) { 611*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting " 612*f05cddf9SRui Paulo "GO Negotiation with previously authorized " 613*f05cddf9SRui Paulo "peer"); 614*f05cddf9SRui Paulo if (!(dev->flags & P2P_DEV_FORCE_FREQ)) { 615*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 616*f05cddf9SRui Paulo "P2P: Use default channel settings"); 617*f05cddf9SRui Paulo p2p->op_reg_class = p2p->cfg->op_reg_class; 618*f05cddf9SRui Paulo p2p->op_channel = p2p->cfg->op_channel; 619*f05cddf9SRui Paulo os_memcpy(&p2p->channels, &p2p->cfg->channels, 620*f05cddf9SRui Paulo sizeof(struct p2p_channels)); 621*f05cddf9SRui Paulo } else { 622*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 623*f05cddf9SRui Paulo "P2P: Use previously configured " 624*f05cddf9SRui Paulo "forced channel settings"); 625*f05cddf9SRui Paulo } 626*f05cddf9SRui Paulo } 627*f05cddf9SRui Paulo 628*f05cddf9SRui Paulo dev->flags &= ~P2P_DEV_NOT_YET_READY; 629*f05cddf9SRui Paulo 630*f05cddf9SRui Paulo if (!msg.go_intent) { 631*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 632*f05cddf9SRui Paulo "P2P: No GO Intent attribute received"); 633*f05cddf9SRui Paulo goto fail; 634*f05cddf9SRui Paulo } 635*f05cddf9SRui Paulo if ((*msg.go_intent >> 1) > P2P_MAX_GO_INTENT) { 636*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 637*f05cddf9SRui Paulo "P2P: Invalid GO Intent value (%u) received", 638*f05cddf9SRui Paulo *msg.go_intent >> 1); 639*f05cddf9SRui Paulo goto fail; 640*f05cddf9SRui Paulo } 641*f05cddf9SRui Paulo 642*f05cddf9SRui Paulo if (dev->go_neg_req_sent && 643*f05cddf9SRui Paulo os_memcmp(sa, p2p->cfg->dev_addr, ETH_ALEN) > 0) { 644*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 645*f05cddf9SRui Paulo "P2P: Do not reply since peer has higher " 646*f05cddf9SRui Paulo "address and GO Neg Request already sent"); 647*f05cddf9SRui Paulo p2p_parse_free(&msg); 648*f05cddf9SRui Paulo return; 649*f05cddf9SRui Paulo } 650*f05cddf9SRui Paulo 651*f05cddf9SRui Paulo go = p2p_go_det(p2p->go_intent, *msg.go_intent); 652*f05cddf9SRui Paulo if (go < 0) { 653*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 654*f05cddf9SRui Paulo "P2P: Incompatible GO Intent"); 655*f05cddf9SRui Paulo status = P2P_SC_FAIL_BOTH_GO_INTENT_15; 656*f05cddf9SRui Paulo goto fail; 657*f05cddf9SRui Paulo } 658*f05cddf9SRui Paulo 659*f05cddf9SRui Paulo if (p2p_peer_channels(p2p, dev, msg.channel_list, 660*f05cddf9SRui Paulo msg.channel_list_len) < 0) { 661*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 662*f05cddf9SRui Paulo "P2P: No common channels found"); 663*f05cddf9SRui Paulo status = P2P_SC_FAIL_NO_COMMON_CHANNELS; 664*f05cddf9SRui Paulo goto fail; 665*f05cddf9SRui Paulo } 666*f05cddf9SRui Paulo 667*f05cddf9SRui Paulo switch (msg.dev_password_id) { 668*f05cddf9SRui Paulo case DEV_PW_REGISTRAR_SPECIFIED: 669*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 670*f05cddf9SRui Paulo "P2P: PIN from peer Display"); 671*f05cddf9SRui Paulo if (dev->wps_method != WPS_PIN_KEYPAD) { 672*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 673*f05cddf9SRui Paulo "P2P: We have wps_method=%s -> " 674*f05cddf9SRui Paulo "incompatible", 675*f05cddf9SRui Paulo p2p_wps_method_str(dev->wps_method)); 676*f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 677*f05cddf9SRui Paulo goto fail; 678*f05cddf9SRui Paulo } 679*f05cddf9SRui Paulo break; 680*f05cddf9SRui Paulo case DEV_PW_USER_SPECIFIED: 681*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 682*f05cddf9SRui Paulo "P2P: Peer entered PIN on Keypad"); 683*f05cddf9SRui Paulo if (dev->wps_method != WPS_PIN_DISPLAY) { 684*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 685*f05cddf9SRui Paulo "P2P: We have wps_method=%s -> " 686*f05cddf9SRui Paulo "incompatible", 687*f05cddf9SRui Paulo p2p_wps_method_str(dev->wps_method)); 688*f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 689*f05cddf9SRui Paulo goto fail; 690*f05cddf9SRui Paulo } 691*f05cddf9SRui Paulo break; 692*f05cddf9SRui Paulo case DEV_PW_PUSHBUTTON: 693*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 694*f05cddf9SRui Paulo "P2P: Peer using pushbutton"); 695*f05cddf9SRui Paulo if (dev->wps_method != WPS_PBC) { 696*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 697*f05cddf9SRui Paulo "P2P: We have wps_method=%s -> " 698*f05cddf9SRui Paulo "incompatible", 699*f05cddf9SRui Paulo p2p_wps_method_str(dev->wps_method)); 700*f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 701*f05cddf9SRui Paulo goto fail; 702*f05cddf9SRui Paulo } 703*f05cddf9SRui Paulo break; 704*f05cddf9SRui Paulo default: 705*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 706*f05cddf9SRui Paulo "P2P: Unsupported Device Password ID %d", 707*f05cddf9SRui Paulo msg.dev_password_id); 708*f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 709*f05cddf9SRui Paulo goto fail; 710*f05cddf9SRui Paulo } 711*f05cddf9SRui Paulo 712*f05cddf9SRui Paulo if (go && p2p_go_select_channel(p2p, dev, &status) < 0) 713*f05cddf9SRui Paulo goto fail; 714*f05cddf9SRui Paulo 715*f05cddf9SRui Paulo dev->go_state = go ? LOCAL_GO : REMOTE_GO; 716*f05cddf9SRui Paulo dev->oper_freq = p2p_channel_to_freq((const char *) 717*f05cddf9SRui Paulo msg.operating_channel, 718*f05cddf9SRui Paulo msg.operating_channel[3], 719*f05cddf9SRui Paulo msg.operating_channel[4]); 720*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer operating " 721*f05cddf9SRui Paulo "channel preference: %d MHz", dev->oper_freq); 722*f05cddf9SRui Paulo 723*f05cddf9SRui Paulo if (msg.config_timeout) { 724*f05cddf9SRui Paulo dev->go_timeout = msg.config_timeout[0]; 725*f05cddf9SRui Paulo dev->client_timeout = msg.config_timeout[1]; 726*f05cddf9SRui Paulo } 727*f05cddf9SRui Paulo 728*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 729*f05cddf9SRui Paulo "P2P: GO Negotiation with " MACSTR, MAC2STR(sa)); 730*f05cddf9SRui Paulo if (p2p->state != P2P_IDLE) 731*f05cddf9SRui Paulo p2p_stop_find_for_freq(p2p, rx_freq); 732*f05cddf9SRui Paulo p2p_set_state(p2p, P2P_GO_NEG); 733*f05cddf9SRui Paulo p2p_clear_timeout(p2p); 734*f05cddf9SRui Paulo dev->dialog_token = msg.dialog_token; 735*f05cddf9SRui Paulo os_memcpy(dev->intended_addr, msg.intended_addr, ETH_ALEN); 736*f05cddf9SRui Paulo p2p->go_neg_peer = dev; 737*f05cddf9SRui Paulo status = P2P_SC_SUCCESS; 738*f05cddf9SRui Paulo } 739*f05cddf9SRui Paulo 740*f05cddf9SRui Paulo fail: 741*f05cddf9SRui Paulo if (dev) 742*f05cddf9SRui Paulo dev->status = status; 743*f05cddf9SRui Paulo resp = p2p_build_go_neg_resp(p2p, dev, msg.dialog_token, status, 744*f05cddf9SRui Paulo !tie_breaker); 745*f05cddf9SRui Paulo p2p_parse_free(&msg); 746*f05cddf9SRui Paulo if (resp == NULL) 747*f05cddf9SRui Paulo return; 748*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 749*f05cddf9SRui Paulo "P2P: Sending GO Negotiation Response"); 750*f05cddf9SRui Paulo if (rx_freq > 0) 751*f05cddf9SRui Paulo freq = rx_freq; 752*f05cddf9SRui Paulo else 753*f05cddf9SRui Paulo freq = p2p_channel_to_freq(p2p->cfg->country, 754*f05cddf9SRui Paulo p2p->cfg->reg_class, 755*f05cddf9SRui Paulo p2p->cfg->channel); 756*f05cddf9SRui Paulo if (freq < 0) { 757*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 758*f05cddf9SRui Paulo "P2P: Unknown regulatory class/channel"); 759*f05cddf9SRui Paulo wpabuf_free(resp); 760*f05cddf9SRui Paulo return; 761*f05cddf9SRui Paulo } 762*f05cddf9SRui Paulo if (status == P2P_SC_SUCCESS) { 763*f05cddf9SRui Paulo p2p->pending_action_state = P2P_PENDING_GO_NEG_RESPONSE; 764*f05cddf9SRui Paulo dev->flags |= P2P_DEV_WAIT_GO_NEG_CONFIRM; 765*f05cddf9SRui Paulo if (os_memcmp(sa, p2p->cfg->dev_addr, ETH_ALEN) < 0) { 766*f05cddf9SRui Paulo /* 767*f05cddf9SRui Paulo * Peer has smaller address, so the GO Negotiation 768*f05cddf9SRui Paulo * Response from us is expected to complete 769*f05cddf9SRui Paulo * negotiation. Ignore a GO Negotiation Response from 770*f05cddf9SRui Paulo * the peer if it happens to be received after this 771*f05cddf9SRui Paulo * point due to a race condition in GO Negotiation 772*f05cddf9SRui Paulo * Request transmission and processing. 773*f05cddf9SRui Paulo */ 774*f05cddf9SRui Paulo dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE; 775*f05cddf9SRui Paulo } 776*f05cddf9SRui Paulo } else 777*f05cddf9SRui Paulo p2p->pending_action_state = 778*f05cddf9SRui Paulo P2P_PENDING_GO_NEG_RESPONSE_FAILURE; 779*f05cddf9SRui Paulo if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, 780*f05cddf9SRui Paulo p2p->cfg->dev_addr, 781*f05cddf9SRui Paulo wpabuf_head(resp), wpabuf_len(resp), 250) < 0) { 782*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 783*f05cddf9SRui Paulo "P2P: Failed to send Action frame"); 784*f05cddf9SRui Paulo } 785*f05cddf9SRui Paulo 786*f05cddf9SRui Paulo wpabuf_free(resp); 787*f05cddf9SRui Paulo } 788*f05cddf9SRui Paulo 789*f05cddf9SRui Paulo 790*f05cddf9SRui Paulo static struct wpabuf * p2p_build_go_neg_conf(struct p2p_data *p2p, 791*f05cddf9SRui Paulo struct p2p_device *peer, 792*f05cddf9SRui Paulo u8 dialog_token, u8 status, 793*f05cddf9SRui Paulo const u8 *resp_chan, int go) 794*f05cddf9SRui Paulo { 795*f05cddf9SRui Paulo struct wpabuf *buf; 796*f05cddf9SRui Paulo u8 *len; 797*f05cddf9SRui Paulo struct p2p_channels res; 798*f05cddf9SRui Paulo u8 group_capab; 799*f05cddf9SRui Paulo size_t extra = 0; 800*f05cddf9SRui Paulo 801*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 802*f05cddf9SRui Paulo "P2P: Building GO Negotiation Confirm"); 803*f05cddf9SRui Paulo 804*f05cddf9SRui Paulo #ifdef CONFIG_WIFI_DISPLAY 805*f05cddf9SRui Paulo if (p2p->wfd_ie_go_neg) 806*f05cddf9SRui Paulo extra = wpabuf_len(p2p->wfd_ie_go_neg); 807*f05cddf9SRui Paulo #endif /* CONFIG_WIFI_DISPLAY */ 808*f05cddf9SRui Paulo 809*f05cddf9SRui Paulo buf = wpabuf_alloc(1000 + extra); 810*f05cddf9SRui Paulo if (buf == NULL) 811*f05cddf9SRui Paulo return NULL; 812*f05cddf9SRui Paulo 813*f05cddf9SRui Paulo p2p_buf_add_public_action_hdr(buf, P2P_GO_NEG_CONF, dialog_token); 814*f05cddf9SRui Paulo 815*f05cddf9SRui Paulo len = p2p_buf_add_ie_hdr(buf); 816*f05cddf9SRui Paulo p2p_buf_add_status(buf, status); 817*f05cddf9SRui Paulo group_capab = 0; 818*f05cddf9SRui Paulo if (peer->go_state == LOCAL_GO) { 819*f05cddf9SRui Paulo if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) { 820*f05cddf9SRui Paulo group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP; 821*f05cddf9SRui Paulo if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN) 822*f05cddf9SRui Paulo group_capab |= 823*f05cddf9SRui Paulo P2P_GROUP_CAPAB_PERSISTENT_RECONN; 824*f05cddf9SRui Paulo } 825*f05cddf9SRui Paulo if (p2p->cross_connect) 826*f05cddf9SRui Paulo group_capab |= P2P_GROUP_CAPAB_CROSS_CONN; 827*f05cddf9SRui Paulo if (p2p->cfg->p2p_intra_bss) 828*f05cddf9SRui Paulo group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST; 829*f05cddf9SRui Paulo } 830*f05cddf9SRui Paulo p2p_buf_add_capability(buf, p2p->dev_capab & 831*f05cddf9SRui Paulo ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 832*f05cddf9SRui Paulo group_capab); 833*f05cddf9SRui Paulo if (go || resp_chan == NULL) 834*f05cddf9SRui Paulo p2p_buf_add_operating_channel(buf, p2p->cfg->country, 835*f05cddf9SRui Paulo p2p->op_reg_class, 836*f05cddf9SRui Paulo p2p->op_channel); 837*f05cddf9SRui Paulo else 838*f05cddf9SRui Paulo p2p_buf_add_operating_channel(buf, (const char *) resp_chan, 839*f05cddf9SRui Paulo resp_chan[3], resp_chan[4]); 840*f05cddf9SRui Paulo p2p_channels_intersect(&p2p->channels, &peer->channels, &res); 841*f05cddf9SRui Paulo p2p_buf_add_channel_list(buf, p2p->cfg->country, &res); 842*f05cddf9SRui Paulo if (go) { 843*f05cddf9SRui Paulo p2p_buf_add_group_id(buf, p2p->cfg->dev_addr, p2p->ssid, 844*f05cddf9SRui Paulo p2p->ssid_len); 845*f05cddf9SRui Paulo } 846*f05cddf9SRui Paulo p2p_buf_update_ie_hdr(buf, len); 847*f05cddf9SRui Paulo 848*f05cddf9SRui Paulo #ifdef CONFIG_WIFI_DISPLAY 849*f05cddf9SRui Paulo if (p2p->wfd_ie_go_neg) 850*f05cddf9SRui Paulo wpabuf_put_buf(buf, p2p->wfd_ie_go_neg); 851*f05cddf9SRui Paulo #endif /* CONFIG_WIFI_DISPLAY */ 852*f05cddf9SRui Paulo 853*f05cddf9SRui Paulo return buf; 854*f05cddf9SRui Paulo } 855*f05cddf9SRui Paulo 856*f05cddf9SRui Paulo 857*f05cddf9SRui Paulo void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa, 858*f05cddf9SRui Paulo const u8 *data, size_t len, int rx_freq) 859*f05cddf9SRui Paulo { 860*f05cddf9SRui Paulo struct p2p_device *dev; 861*f05cddf9SRui Paulo struct wpabuf *conf; 862*f05cddf9SRui Paulo int go = -1; 863*f05cddf9SRui Paulo struct p2p_message msg; 864*f05cddf9SRui Paulo u8 status = P2P_SC_SUCCESS; 865*f05cddf9SRui Paulo int freq; 866*f05cddf9SRui Paulo 867*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 868*f05cddf9SRui Paulo "P2P: Received GO Negotiation Response from " MACSTR 869*f05cddf9SRui Paulo " (freq=%d)", MAC2STR(sa), rx_freq); 870*f05cddf9SRui Paulo dev = p2p_get_device(p2p, sa); 871*f05cddf9SRui Paulo if (dev == NULL || dev->wps_method == WPS_NOT_READY || 872*f05cddf9SRui Paulo dev != p2p->go_neg_peer) { 873*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 874*f05cddf9SRui Paulo "P2P: Not ready for GO negotiation with " MACSTR, 875*f05cddf9SRui Paulo MAC2STR(sa)); 876*f05cddf9SRui Paulo return; 877*f05cddf9SRui Paulo } 878*f05cddf9SRui Paulo 879*f05cddf9SRui Paulo if (p2p_parse(data, len, &msg)) 880*f05cddf9SRui Paulo return; 881*f05cddf9SRui Paulo 882*f05cddf9SRui Paulo if (!(dev->flags & P2P_DEV_WAIT_GO_NEG_RESPONSE)) { 883*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 884*f05cddf9SRui Paulo "P2P: Was not expecting GO Negotiation Response - " 885*f05cddf9SRui Paulo "ignore"); 886*f05cddf9SRui Paulo p2p_parse_free(&msg); 887*f05cddf9SRui Paulo return; 888*f05cddf9SRui Paulo } 889*f05cddf9SRui Paulo dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE; 890*f05cddf9SRui Paulo 891*f05cddf9SRui Paulo if (msg.dialog_token != dev->dialog_token) { 892*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 893*f05cddf9SRui Paulo "P2P: Unexpected Dialog Token %u (expected %u)", 894*f05cddf9SRui Paulo msg.dialog_token, dev->dialog_token); 895*f05cddf9SRui Paulo p2p_parse_free(&msg); 896*f05cddf9SRui Paulo return; 897*f05cddf9SRui Paulo } 898*f05cddf9SRui Paulo 899*f05cddf9SRui Paulo if (!msg.status) { 900*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 901*f05cddf9SRui Paulo "P2P: No Status attribute received"); 902*f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 903*f05cddf9SRui Paulo goto fail; 904*f05cddf9SRui Paulo } 905*f05cddf9SRui Paulo if (*msg.status) { 906*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 907*f05cddf9SRui Paulo "P2P: GO Negotiation rejected: status %d", 908*f05cddf9SRui Paulo *msg.status); 909*f05cddf9SRui Paulo dev->go_neg_req_sent = 0; 910*f05cddf9SRui Paulo if (*msg.status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) { 911*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 912*f05cddf9SRui Paulo "P2P: Wait for the peer to become ready for " 913*f05cddf9SRui Paulo "GO Negotiation"); 914*f05cddf9SRui Paulo dev->flags |= P2P_DEV_NOT_YET_READY; 915*f05cddf9SRui Paulo dev->wait_count = 0; 916*f05cddf9SRui Paulo p2p_set_state(p2p, P2P_WAIT_PEER_IDLE); 917*f05cddf9SRui Paulo p2p_set_timeout(p2p, 0, 0); 918*f05cddf9SRui Paulo } else { 919*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 920*f05cddf9SRui Paulo "P2P: Stop GO Negotiation attempt"); 921*f05cddf9SRui Paulo p2p_go_neg_failed(p2p, dev, *msg.status); 922*f05cddf9SRui Paulo } 923*f05cddf9SRui Paulo p2p->cfg->send_action_done(p2p->cfg->cb_ctx); 924*f05cddf9SRui Paulo p2p_parse_free(&msg); 925*f05cddf9SRui Paulo return; 926*f05cddf9SRui Paulo } 927*f05cddf9SRui Paulo 928*f05cddf9SRui Paulo if (!msg.capability) { 929*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 930*f05cddf9SRui Paulo "P2P: Mandatory Capability attribute missing from GO " 931*f05cddf9SRui Paulo "Negotiation Response"); 932*f05cddf9SRui Paulo #ifdef CONFIG_P2P_STRICT 933*f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 934*f05cddf9SRui Paulo goto fail; 935*f05cddf9SRui Paulo #endif /* CONFIG_P2P_STRICT */ 936*f05cddf9SRui Paulo } 937*f05cddf9SRui Paulo 938*f05cddf9SRui Paulo if (!msg.p2p_device_info) { 939*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 940*f05cddf9SRui Paulo "P2P: Mandatory P2P Device Info attribute missing " 941*f05cddf9SRui Paulo "from GO Negotiation Response"); 942*f05cddf9SRui Paulo #ifdef CONFIG_P2P_STRICT 943*f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 944*f05cddf9SRui Paulo goto fail; 945*f05cddf9SRui Paulo #endif /* CONFIG_P2P_STRICT */ 946*f05cddf9SRui Paulo } 947*f05cddf9SRui Paulo 948*f05cddf9SRui Paulo if (!msg.intended_addr) { 949*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 950*f05cddf9SRui Paulo "P2P: No Intended P2P Interface Address attribute " 951*f05cddf9SRui Paulo "received"); 952*f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 953*f05cddf9SRui Paulo goto fail; 954*f05cddf9SRui Paulo } 955*f05cddf9SRui Paulo 956*f05cddf9SRui Paulo if (!msg.go_intent) { 957*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 958*f05cddf9SRui Paulo "P2P: No GO Intent attribute received"); 959*f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 960*f05cddf9SRui Paulo goto fail; 961*f05cddf9SRui Paulo } 962*f05cddf9SRui Paulo if ((*msg.go_intent >> 1) > P2P_MAX_GO_INTENT) { 963*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 964*f05cddf9SRui Paulo "P2P: Invalid GO Intent value (%u) received", 965*f05cddf9SRui Paulo *msg.go_intent >> 1); 966*f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 967*f05cddf9SRui Paulo goto fail; 968*f05cddf9SRui Paulo } 969*f05cddf9SRui Paulo 970*f05cddf9SRui Paulo go = p2p_go_det(p2p->go_intent, *msg.go_intent); 971*f05cddf9SRui Paulo if (go < 0) { 972*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 973*f05cddf9SRui Paulo "P2P: Incompatible GO Intent"); 974*f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PARAMS; 975*f05cddf9SRui Paulo goto fail; 976*f05cddf9SRui Paulo } 977*f05cddf9SRui Paulo 978*f05cddf9SRui Paulo if (!go && msg.group_id) { 979*f05cddf9SRui Paulo /* Store SSID for Provisioning step */ 980*f05cddf9SRui Paulo p2p->ssid_len = msg.group_id_len - ETH_ALEN; 981*f05cddf9SRui Paulo os_memcpy(p2p->ssid, msg.group_id + ETH_ALEN, p2p->ssid_len); 982*f05cddf9SRui Paulo } else if (!go) { 983*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 984*f05cddf9SRui Paulo "P2P: Mandatory P2P Group ID attribute missing from " 985*f05cddf9SRui Paulo "GO Negotiation Response"); 986*f05cddf9SRui Paulo p2p->ssid_len = 0; 987*f05cddf9SRui Paulo #ifdef CONFIG_P2P_STRICT 988*f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 989*f05cddf9SRui Paulo goto fail; 990*f05cddf9SRui Paulo #endif /* CONFIG_P2P_STRICT */ 991*f05cddf9SRui Paulo } 992*f05cddf9SRui Paulo 993*f05cddf9SRui Paulo if (!msg.config_timeout) { 994*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 995*f05cddf9SRui Paulo "P2P: Mandatory Configuration Timeout attribute " 996*f05cddf9SRui Paulo "missing from GO Negotiation Response"); 997*f05cddf9SRui Paulo #ifdef CONFIG_P2P_STRICT 998*f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 999*f05cddf9SRui Paulo goto fail; 1000*f05cddf9SRui Paulo #endif /* CONFIG_P2P_STRICT */ 1001*f05cddf9SRui Paulo } else { 1002*f05cddf9SRui Paulo dev->go_timeout = msg.config_timeout[0]; 1003*f05cddf9SRui Paulo dev->client_timeout = msg.config_timeout[1]; 1004*f05cddf9SRui Paulo } 1005*f05cddf9SRui Paulo 1006*f05cddf9SRui Paulo if (!msg.operating_channel && !go) { 1007*f05cddf9SRui Paulo /* 1008*f05cddf9SRui Paulo * Note: P2P Client may omit Operating Channel attribute to 1009*f05cddf9SRui Paulo * indicate it does not have a preference. 1010*f05cddf9SRui Paulo */ 1011*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1012*f05cddf9SRui Paulo "P2P: No Operating Channel attribute received"); 1013*f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 1014*f05cddf9SRui Paulo goto fail; 1015*f05cddf9SRui Paulo } 1016*f05cddf9SRui Paulo if (!msg.channel_list) { 1017*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1018*f05cddf9SRui Paulo "P2P: No Channel List attribute received"); 1019*f05cddf9SRui Paulo status = P2P_SC_FAIL_INVALID_PARAMS; 1020*f05cddf9SRui Paulo goto fail; 1021*f05cddf9SRui Paulo } 1022*f05cddf9SRui Paulo 1023*f05cddf9SRui Paulo if (p2p_peer_channels(p2p, dev, msg.channel_list, 1024*f05cddf9SRui Paulo msg.channel_list_len) < 0) { 1025*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1026*f05cddf9SRui Paulo "P2P: No common channels found"); 1027*f05cddf9SRui Paulo status = P2P_SC_FAIL_NO_COMMON_CHANNELS; 1028*f05cddf9SRui Paulo goto fail; 1029*f05cddf9SRui Paulo } 1030*f05cddf9SRui Paulo 1031*f05cddf9SRui Paulo if (msg.operating_channel) { 1032*f05cddf9SRui Paulo dev->oper_freq = p2p_channel_to_freq((const char *) 1033*f05cddf9SRui Paulo msg.operating_channel, 1034*f05cddf9SRui Paulo msg.operating_channel[3], 1035*f05cddf9SRui Paulo msg.operating_channel[4]); 1036*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer operating " 1037*f05cddf9SRui Paulo "channel preference: %d MHz", dev->oper_freq); 1038*f05cddf9SRui Paulo } else 1039*f05cddf9SRui Paulo dev->oper_freq = 0; 1040*f05cddf9SRui Paulo 1041*f05cddf9SRui Paulo switch (msg.dev_password_id) { 1042*f05cddf9SRui Paulo case DEV_PW_REGISTRAR_SPECIFIED: 1043*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1044*f05cddf9SRui Paulo "P2P: PIN from peer Display"); 1045*f05cddf9SRui Paulo if (dev->wps_method != WPS_PIN_KEYPAD) { 1046*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1047*f05cddf9SRui Paulo "P2P: We have wps_method=%s -> " 1048*f05cddf9SRui Paulo "incompatible", 1049*f05cddf9SRui Paulo p2p_wps_method_str(dev->wps_method)); 1050*f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 1051*f05cddf9SRui Paulo goto fail; 1052*f05cddf9SRui Paulo } 1053*f05cddf9SRui Paulo break; 1054*f05cddf9SRui Paulo case DEV_PW_USER_SPECIFIED: 1055*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1056*f05cddf9SRui Paulo "P2P: Peer entered PIN on Keypad"); 1057*f05cddf9SRui Paulo if (dev->wps_method != WPS_PIN_DISPLAY) { 1058*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1059*f05cddf9SRui Paulo "P2P: We have wps_method=%s -> " 1060*f05cddf9SRui Paulo "incompatible", 1061*f05cddf9SRui Paulo p2p_wps_method_str(dev->wps_method)); 1062*f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 1063*f05cddf9SRui Paulo goto fail; 1064*f05cddf9SRui Paulo } 1065*f05cddf9SRui Paulo break; 1066*f05cddf9SRui Paulo case DEV_PW_PUSHBUTTON: 1067*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1068*f05cddf9SRui Paulo "P2P: Peer using pushbutton"); 1069*f05cddf9SRui Paulo if (dev->wps_method != WPS_PBC) { 1070*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1071*f05cddf9SRui Paulo "P2P: We have wps_method=%s -> " 1072*f05cddf9SRui Paulo "incompatible", 1073*f05cddf9SRui Paulo p2p_wps_method_str(dev->wps_method)); 1074*f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 1075*f05cddf9SRui Paulo goto fail; 1076*f05cddf9SRui Paulo } 1077*f05cddf9SRui Paulo break; 1078*f05cddf9SRui Paulo default: 1079*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1080*f05cddf9SRui Paulo "P2P: Unsupported Device Password ID %d", 1081*f05cddf9SRui Paulo msg.dev_password_id); 1082*f05cddf9SRui Paulo status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; 1083*f05cddf9SRui Paulo goto fail; 1084*f05cddf9SRui Paulo } 1085*f05cddf9SRui Paulo 1086*f05cddf9SRui Paulo if (go && p2p_go_select_channel(p2p, dev, &status) < 0) 1087*f05cddf9SRui Paulo goto fail; 1088*f05cddf9SRui Paulo 1089*f05cddf9SRui Paulo p2p_set_state(p2p, P2P_GO_NEG); 1090*f05cddf9SRui Paulo p2p_clear_timeout(p2p); 1091*f05cddf9SRui Paulo 1092*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1093*f05cddf9SRui Paulo "P2P: GO Negotiation with " MACSTR, MAC2STR(sa)); 1094*f05cddf9SRui Paulo os_memcpy(dev->intended_addr, msg.intended_addr, ETH_ALEN); 1095*f05cddf9SRui Paulo 1096*f05cddf9SRui Paulo fail: 1097*f05cddf9SRui Paulo conf = p2p_build_go_neg_conf(p2p, dev, msg.dialog_token, status, 1098*f05cddf9SRui Paulo msg.operating_channel, go); 1099*f05cddf9SRui Paulo p2p_parse_free(&msg); 1100*f05cddf9SRui Paulo if (conf == NULL) 1101*f05cddf9SRui Paulo return; 1102*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1103*f05cddf9SRui Paulo "P2P: Sending GO Negotiation Confirm"); 1104*f05cddf9SRui Paulo if (status == P2P_SC_SUCCESS) { 1105*f05cddf9SRui Paulo p2p->pending_action_state = P2P_PENDING_GO_NEG_CONFIRM; 1106*f05cddf9SRui Paulo dev->go_state = go ? LOCAL_GO : REMOTE_GO; 1107*f05cddf9SRui Paulo } else 1108*f05cddf9SRui Paulo p2p->pending_action_state = P2P_NO_PENDING_ACTION; 1109*f05cddf9SRui Paulo if (rx_freq > 0) 1110*f05cddf9SRui Paulo freq = rx_freq; 1111*f05cddf9SRui Paulo else 1112*f05cddf9SRui Paulo freq = dev->listen_freq; 1113*f05cddf9SRui Paulo if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, sa, 1114*f05cddf9SRui Paulo wpabuf_head(conf), wpabuf_len(conf), 0) < 0) { 1115*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1116*f05cddf9SRui Paulo "P2P: Failed to send Action frame"); 1117*f05cddf9SRui Paulo p2p_go_neg_failed(p2p, dev, -1); 1118*f05cddf9SRui Paulo } 1119*f05cddf9SRui Paulo wpabuf_free(conf); 1120*f05cddf9SRui Paulo } 1121*f05cddf9SRui Paulo 1122*f05cddf9SRui Paulo 1123*f05cddf9SRui Paulo void p2p_process_go_neg_conf(struct p2p_data *p2p, const u8 *sa, 1124*f05cddf9SRui Paulo const u8 *data, size_t len) 1125*f05cddf9SRui Paulo { 1126*f05cddf9SRui Paulo struct p2p_device *dev; 1127*f05cddf9SRui Paulo struct p2p_message msg; 1128*f05cddf9SRui Paulo 1129*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1130*f05cddf9SRui Paulo "P2P: Received GO Negotiation Confirm from " MACSTR, 1131*f05cddf9SRui Paulo MAC2STR(sa)); 1132*f05cddf9SRui Paulo dev = p2p_get_device(p2p, sa); 1133*f05cddf9SRui Paulo if (dev == NULL || dev->wps_method == WPS_NOT_READY || 1134*f05cddf9SRui Paulo dev != p2p->go_neg_peer) { 1135*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1136*f05cddf9SRui Paulo "P2P: Not ready for GO negotiation with " MACSTR, 1137*f05cddf9SRui Paulo MAC2STR(sa)); 1138*f05cddf9SRui Paulo return; 1139*f05cddf9SRui Paulo } 1140*f05cddf9SRui Paulo 1141*f05cddf9SRui Paulo if (p2p->pending_action_state == P2P_PENDING_GO_NEG_RESPONSE) { 1142*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Stopped waiting " 1143*f05cddf9SRui Paulo "for TX status on GO Negotiation Response since we " 1144*f05cddf9SRui Paulo "already received Confirmation"); 1145*f05cddf9SRui Paulo p2p->pending_action_state = P2P_NO_PENDING_ACTION; 1146*f05cddf9SRui Paulo } 1147*f05cddf9SRui Paulo 1148*f05cddf9SRui Paulo if (p2p_parse(data, len, &msg)) 1149*f05cddf9SRui Paulo return; 1150*f05cddf9SRui Paulo 1151*f05cddf9SRui Paulo if (!(dev->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM)) { 1152*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1153*f05cddf9SRui Paulo "P2P: Was not expecting GO Negotiation Confirm - " 1154*f05cddf9SRui Paulo "ignore"); 1155*f05cddf9SRui Paulo return; 1156*f05cddf9SRui Paulo } 1157*f05cddf9SRui Paulo dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM; 1158*f05cddf9SRui Paulo 1159*f05cddf9SRui Paulo if (msg.dialog_token != dev->dialog_token) { 1160*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1161*f05cddf9SRui Paulo "P2P: Unexpected Dialog Token %u (expected %u)", 1162*f05cddf9SRui Paulo msg.dialog_token, dev->dialog_token); 1163*f05cddf9SRui Paulo p2p_parse_free(&msg); 1164*f05cddf9SRui Paulo return; 1165*f05cddf9SRui Paulo } 1166*f05cddf9SRui Paulo 1167*f05cddf9SRui Paulo if (!msg.status) { 1168*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1169*f05cddf9SRui Paulo "P2P: No Status attribute received"); 1170*f05cddf9SRui Paulo p2p_parse_free(&msg); 1171*f05cddf9SRui Paulo return; 1172*f05cddf9SRui Paulo } 1173*f05cddf9SRui Paulo if (*msg.status) { 1174*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1175*f05cddf9SRui Paulo "P2P: GO Negotiation rejected: status %d", 1176*f05cddf9SRui Paulo *msg.status); 1177*f05cddf9SRui Paulo p2p_parse_free(&msg); 1178*f05cddf9SRui Paulo return; 1179*f05cddf9SRui Paulo } 1180*f05cddf9SRui Paulo 1181*f05cddf9SRui Paulo if (dev->go_state == REMOTE_GO && msg.group_id) { 1182*f05cddf9SRui Paulo /* Store SSID for Provisioning step */ 1183*f05cddf9SRui Paulo p2p->ssid_len = msg.group_id_len - ETH_ALEN; 1184*f05cddf9SRui Paulo os_memcpy(p2p->ssid, msg.group_id + ETH_ALEN, p2p->ssid_len); 1185*f05cddf9SRui Paulo } else if (dev->go_state == REMOTE_GO) { 1186*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1187*f05cddf9SRui Paulo "P2P: Mandatory P2P Group ID attribute missing from " 1188*f05cddf9SRui Paulo "GO Negotiation Confirmation"); 1189*f05cddf9SRui Paulo p2p->ssid_len = 0; 1190*f05cddf9SRui Paulo #ifdef CONFIG_P2P_STRICT 1191*f05cddf9SRui Paulo p2p_parse_free(&msg); 1192*f05cddf9SRui Paulo return; 1193*f05cddf9SRui Paulo #endif /* CONFIG_P2P_STRICT */ 1194*f05cddf9SRui Paulo } 1195*f05cddf9SRui Paulo 1196*f05cddf9SRui Paulo if (!msg.operating_channel) { 1197*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1198*f05cddf9SRui Paulo "P2P: Mandatory Operating Channel attribute missing " 1199*f05cddf9SRui Paulo "from GO Negotiation Confirmation"); 1200*f05cddf9SRui Paulo #ifdef CONFIG_P2P_STRICT 1201*f05cddf9SRui Paulo p2p_parse_free(&msg); 1202*f05cddf9SRui Paulo return; 1203*f05cddf9SRui Paulo #endif /* CONFIG_P2P_STRICT */ 1204*f05cddf9SRui Paulo } 1205*f05cddf9SRui Paulo 1206*f05cddf9SRui Paulo if (!msg.channel_list) { 1207*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1208*f05cddf9SRui Paulo "P2P: Mandatory Operating Channel attribute missing " 1209*f05cddf9SRui Paulo "from GO Negotiation Confirmation"); 1210*f05cddf9SRui Paulo #ifdef CONFIG_P2P_STRICT 1211*f05cddf9SRui Paulo p2p_parse_free(&msg); 1212*f05cddf9SRui Paulo return; 1213*f05cddf9SRui Paulo #endif /* CONFIG_P2P_STRICT */ 1214*f05cddf9SRui Paulo } 1215*f05cddf9SRui Paulo 1216*f05cddf9SRui Paulo p2p_parse_free(&msg); 1217*f05cddf9SRui Paulo 1218*f05cddf9SRui Paulo if (dev->go_state == UNKNOWN_GO) { 1219*f05cddf9SRui Paulo /* 1220*f05cddf9SRui Paulo * This should not happen since GO negotiation has already 1221*f05cddf9SRui Paulo * been completed. 1222*f05cddf9SRui Paulo */ 1223*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 1224*f05cddf9SRui Paulo "P2P: Unexpected GO Neg state - do not know which end " 1225*f05cddf9SRui Paulo "becomes GO"); 1226*f05cddf9SRui Paulo return; 1227*f05cddf9SRui Paulo } 1228*f05cddf9SRui Paulo 1229*f05cddf9SRui Paulo /* 1230*f05cddf9SRui Paulo * The peer could have missed our ctrl::ack frame for GO Negotiation 1231*f05cddf9SRui Paulo * Confirm and continue retransmitting the frame. To reduce the 1232*f05cddf9SRui Paulo * likelihood of the peer not getting successful TX status for the 1233*f05cddf9SRui Paulo * GO Negotiation Confirm frame, wait a short time here before starting 1234*f05cddf9SRui Paulo * the group so that we will remain on the current channel to 1235*f05cddf9SRui Paulo * acknowledge any possible retransmission from the peer. 1236*f05cddf9SRui Paulo */ 1237*f05cddf9SRui Paulo wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: 20 ms wait on current " 1238*f05cddf9SRui Paulo "channel before starting group"); 1239*f05cddf9SRui Paulo os_sleep(0, 20000); 1240*f05cddf9SRui Paulo 1241*f05cddf9SRui Paulo p2p_go_complete(p2p, dev); 1242*f05cddf9SRui Paulo } 1243