1 /* 2 * Wi-Fi Direct - P2P provision discovery 3 * Copyright (c) 2009-2010, Atheros Communications 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15 #include "includes.h" 16 17 #include "common.h" 18 #include "common/ieee802_11_defs.h" 19 #include "wps/wps_defs.h" 20 #include "p2p_i.h" 21 #include "p2p.h" 22 23 24 /* 25 * Number of retries to attempt for provision discovery requests during IDLE 26 * state in case the peer is not listening. 27 */ 28 #define MAX_PROV_DISC_REQ_RETRIES 10 29 30 31 static void p2p_build_wps_ie_config_methods(struct wpabuf *buf, 32 u16 config_methods) 33 { 34 u8 *len; 35 wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); 36 len = wpabuf_put(buf, 1); 37 wpabuf_put_be32(buf, WPS_DEV_OUI_WFA); 38 39 /* Config Methods */ 40 wpabuf_put_be16(buf, ATTR_CONFIG_METHODS); 41 wpabuf_put_be16(buf, 2); 42 wpabuf_put_be16(buf, config_methods); 43 44 p2p_buf_update_ie_hdr(buf, len); 45 } 46 47 48 static struct wpabuf * p2p_build_prov_disc_req(struct p2p_data *p2p, 49 u8 dialog_token, 50 u16 config_methods, 51 struct p2p_device *go) 52 { 53 struct wpabuf *buf; 54 u8 *len; 55 56 buf = wpabuf_alloc(1000); 57 if (buf == NULL) 58 return NULL; 59 60 p2p_buf_add_public_action_hdr(buf, P2P_PROV_DISC_REQ, dialog_token); 61 62 len = p2p_buf_add_ie_hdr(buf); 63 p2p_buf_add_capability(buf, p2p->dev_capab, 0); 64 p2p_buf_add_device_info(buf, p2p, NULL); 65 if (go) { 66 p2p_buf_add_group_id(buf, go->info.p2p_device_addr, 67 go->oper_ssid, go->oper_ssid_len); 68 } 69 p2p_buf_update_ie_hdr(buf, len); 70 71 /* WPS IE with Config Methods attribute */ 72 p2p_build_wps_ie_config_methods(buf, config_methods); 73 74 return buf; 75 } 76 77 78 static struct wpabuf * p2p_build_prov_disc_resp(struct p2p_data *p2p, 79 u8 dialog_token, 80 u16 config_methods) 81 { 82 struct wpabuf *buf; 83 84 buf = wpabuf_alloc(100); 85 if (buf == NULL) 86 return NULL; 87 88 p2p_buf_add_public_action_hdr(buf, P2P_PROV_DISC_RESP, dialog_token); 89 90 /* WPS IE with Config Methods attribute */ 91 p2p_build_wps_ie_config_methods(buf, config_methods); 92 93 return buf; 94 } 95 96 97 void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa, 98 const u8 *data, size_t len, int rx_freq) 99 { 100 struct p2p_message msg; 101 struct p2p_device *dev; 102 int freq; 103 int reject = 1; 104 struct wpabuf *resp; 105 106 if (p2p_parse(data, len, &msg)) 107 return; 108 109 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 110 "P2P: Received Provision Discovery Request from " MACSTR 111 " with config methods 0x%x (freq=%d)", 112 MAC2STR(sa), msg.wps_config_methods, rx_freq); 113 114 dev = p2p_get_device(p2p, sa); 115 if (dev == NULL || !(dev->flags & P2P_DEV_PROBE_REQ_ONLY)) { 116 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 117 "P2P: Provision Discovery Request from " 118 "unknown peer " MACSTR, MAC2STR(sa)); 119 if (p2p_add_device(p2p, sa, rx_freq, 0, data + 1, len - 1)) { 120 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 121 "P2P: Provision Discovery Request add device " 122 "failed " MACSTR, MAC2STR(sa)); 123 } 124 } 125 126 if (!(msg.wps_config_methods & 127 (WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD | 128 WPS_CONFIG_PUSHBUTTON))) { 129 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Unsupported " 130 "Config Methods in Provision Discovery Request"); 131 goto out; 132 } 133 134 if (dev) 135 dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY | 136 P2P_DEV_PD_PEER_KEYPAD); 137 if (msg.wps_config_methods & WPS_CONFIG_DISPLAY) { 138 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR 139 " requested us to show a PIN on display", MAC2STR(sa)); 140 if (dev) 141 dev->flags |= P2P_DEV_PD_PEER_KEYPAD; 142 } else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) { 143 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR 144 " requested us to write its PIN using keypad", 145 MAC2STR(sa)); 146 if (dev) 147 dev->flags |= P2P_DEV_PD_PEER_DISPLAY; 148 } 149 150 reject = 0; 151 152 out: 153 resp = p2p_build_prov_disc_resp(p2p, msg.dialog_token, 154 reject ? 0 : msg.wps_config_methods); 155 if (resp == NULL) { 156 p2p_parse_free(&msg); 157 return; 158 } 159 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 160 "P2P: Sending Provision Discovery Response"); 161 if (rx_freq > 0) 162 freq = rx_freq; 163 else 164 freq = p2p_channel_to_freq(p2p->cfg->country, 165 p2p->cfg->reg_class, 166 p2p->cfg->channel); 167 if (freq < 0) { 168 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 169 "P2P: Unknown regulatory class/channel"); 170 wpabuf_free(resp); 171 p2p_parse_free(&msg); 172 return; 173 } 174 p2p->pending_action_state = P2P_NO_PENDING_ACTION; 175 if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, 176 p2p->cfg->dev_addr, 177 wpabuf_head(resp), wpabuf_len(resp), 200) < 0) { 178 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 179 "P2P: Failed to send Action frame"); 180 } 181 182 wpabuf_free(resp); 183 184 if (!reject && p2p->cfg->prov_disc_req) { 185 const u8 *dev_addr = sa; 186 if (msg.p2p_device_addr) 187 dev_addr = msg.p2p_device_addr; 188 p2p->cfg->prov_disc_req(p2p->cfg->cb_ctx, sa, 189 msg.wps_config_methods, 190 dev_addr, msg.pri_dev_type, 191 msg.device_name, msg.config_methods, 192 msg.capability ? msg.capability[0] : 0, 193 msg.capability ? msg.capability[1] : 194 0); 195 196 } 197 p2p_parse_free(&msg); 198 } 199 200 201 void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa, 202 const u8 *data, size_t len) 203 { 204 struct p2p_message msg; 205 struct p2p_device *dev; 206 u16 report_config_methods = 0; 207 208 if (p2p_parse(data, len, &msg)) 209 return; 210 211 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 212 "P2P: Received Provisioning Discovery Response from " MACSTR 213 " with config methods 0x%x", 214 MAC2STR(sa), msg.wps_config_methods); 215 216 dev = p2p_get_device(p2p, sa); 217 if (dev == NULL || !dev->req_config_methods) { 218 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 219 "P2P: Ignore Provisioning Discovery Response from " 220 MACSTR " with no pending request", MAC2STR(sa)); 221 p2p_parse_free(&msg); 222 return; 223 } 224 225 if (p2p->pending_action_state == P2P_PENDING_PD) { 226 os_memset(p2p->pending_pd_devaddr, 0, ETH_ALEN); 227 p2p->pending_action_state = P2P_NO_PENDING_ACTION; 228 } 229 230 if (dev->dialog_token != msg.dialog_token) { 231 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 232 "P2P: Ignore Provisioning Discovery Response with " 233 "unexpected Dialog Token %u (expected %u)", 234 msg.dialog_token, dev->dialog_token); 235 p2p_parse_free(&msg); 236 return; 237 } 238 239 /* 240 * If the response is from the peer to whom a user initiated request 241 * was sent earlier, we reset that state info here. 242 */ 243 if (p2p->user_initiated_pd && 244 os_memcmp(p2p->pending_pd_devaddr, sa, ETH_ALEN) == 0) 245 p2p_reset_pending_pd(p2p); 246 247 if (msg.wps_config_methods != dev->req_config_methods) { 248 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer rejected " 249 "our Provisioning Discovery Request"); 250 if (p2p->cfg->prov_disc_fail) 251 p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx, sa, 252 P2P_PROV_DISC_REJECTED); 253 p2p_parse_free(&msg); 254 goto out; 255 } 256 257 report_config_methods = dev->req_config_methods; 258 dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY | 259 P2P_DEV_PD_PEER_KEYPAD); 260 if (dev->req_config_methods & WPS_CONFIG_DISPLAY) { 261 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR 262 " accepted to show a PIN on display", MAC2STR(sa)); 263 dev->flags |= P2P_DEV_PD_PEER_DISPLAY; 264 } else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) { 265 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR 266 " accepted to write our PIN using keypad", 267 MAC2STR(sa)); 268 dev->flags |= P2P_DEV_PD_PEER_KEYPAD; 269 } 270 p2p_parse_free(&msg); 271 272 out: 273 dev->req_config_methods = 0; 274 p2p->cfg->send_action_done(p2p->cfg->cb_ctx); 275 if (p2p->cfg->prov_disc_resp) 276 p2p->cfg->prov_disc_resp(p2p->cfg->cb_ctx, sa, 277 report_config_methods); 278 } 279 280 281 int p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev, 282 int join) 283 { 284 struct wpabuf *req; 285 int freq; 286 #ifdef ANDROID_BRCM_P2P_PATCH 287 if(dev->go_state == REMOTE_GO) { 288 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 289 "P2P: GO Sending it to oper_freq %d", dev->oper_freq); 290 freq= dev->oper_freq; 291 } 292 else { 293 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 294 "P2P: NOT GO oper_freq %d listen_freq %d", dev->oper_freq, dev->listen_freq); 295 freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq; 296 } 297 #else 298 freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq; 299 #endif 300 301 if (freq <= 0) { 302 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 303 "P2P: No Listen/Operating frequency known for the " 304 "peer " MACSTR " to send Provision Discovery Request", 305 MAC2STR(dev->info.p2p_device_addr)); 306 return -1; 307 } 308 309 if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) { 310 if (!(dev->info.dev_capab & 311 P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) { 312 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 313 "P2P: Cannot use PD with P2P Device " MACSTR 314 " that is in a group and is not discoverable", 315 MAC2STR(dev->info.p2p_device_addr)); 316 return -1; 317 } 318 /* TODO: use device discoverability request through GO */ 319 } 320 321 dev->dialog_token++; 322 if (dev->dialog_token == 0) 323 dev->dialog_token = 1; 324 req = p2p_build_prov_disc_req(p2p, dev->dialog_token, 325 dev->req_config_methods, 326 join ? dev : NULL); 327 if (req == NULL) 328 return -1; 329 330 p2p->pending_action_state = P2P_PENDING_PD; 331 if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr, 332 p2p->cfg->dev_addr, dev->info.p2p_device_addr, 333 wpabuf_head(req), wpabuf_len(req), 200) < 0) { 334 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 335 "P2P: Failed to send Action frame"); 336 wpabuf_free(req); 337 return -1; 338 } 339 340 os_memcpy(p2p->pending_pd_devaddr, dev->info.p2p_device_addr, ETH_ALEN); 341 342 wpabuf_free(req); 343 return 0; 344 } 345 346 347 int p2p_prov_disc_req(struct p2p_data *p2p, const u8 *peer_addr, 348 u16 config_methods, int join) 349 { 350 struct p2p_device *dev; 351 352 dev = p2p_get_device(p2p, peer_addr); 353 if (dev == NULL) 354 dev = p2p_get_device_interface(p2p, peer_addr); 355 if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) { 356 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Provision " 357 "Discovery Request destination " MACSTR 358 " not yet known", MAC2STR(peer_addr)); 359 return -1; 360 } 361 362 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Provision Discovery " 363 "Request with " MACSTR " (config methods 0x%x)", 364 MAC2STR(peer_addr), config_methods); 365 if (config_methods == 0) 366 return -1; 367 368 dev->req_config_methods = config_methods; 369 if (join) 370 dev->flags |= P2P_DEV_PD_FOR_JOIN; 371 else 372 dev->flags &= ~P2P_DEV_PD_FOR_JOIN; 373 374 if (p2p->go_neg_peer || 375 (p2p->state != P2P_IDLE && p2p->state != P2P_SEARCH && 376 p2p->state != P2P_LISTEN_ONLY)) { 377 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Busy with other " 378 "operations; postpone Provision Discovery Request " 379 "with " MACSTR " (config methods 0x%x)", 380 MAC2STR(peer_addr), config_methods); 381 return 0; 382 } 383 384 /* 385 * We use the join param as a cue to differentiate between user 386 * initiated PD request and one issued during finds (internal). 387 */ 388 p2p->user_initiated_pd = !join; 389 390 /* Also set some retries to attempt in case of IDLE state */ 391 if (p2p->user_initiated_pd && p2p->state == P2P_IDLE) 392 p2p->pd_retries = MAX_PROV_DISC_REQ_RETRIES; 393 394 return p2p_send_prov_disc_req(p2p, dev, join); 395 } 396 397 398 void p2p_reset_pending_pd(struct p2p_data *p2p) 399 { 400 p2p->user_initiated_pd = 0; 401 os_memset(p2p->pending_pd_devaddr, 0, ETH_ALEN); 402 p2p->pd_retries = 0; 403 } 404