1 /* 2 * P2P - IE builder 3 * Copyright (c) 2009-2010, Atheros Communications 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "includes.h" 10 11 #include "common.h" 12 #include "common/ieee802_11_defs.h" 13 #include "wps/wps_i.h" 14 #include "p2p_i.h" 15 16 17 void p2p_buf_add_action_hdr(struct wpabuf *buf, u8 subtype, u8 dialog_token) 18 { 19 wpabuf_put_u8(buf, WLAN_ACTION_VENDOR_SPECIFIC); 20 wpabuf_put_be32(buf, P2P_IE_VENDOR_TYPE); 21 22 wpabuf_put_u8(buf, subtype); /* OUI Subtype */ 23 wpabuf_put_u8(buf, dialog_token); 24 wpa_printf(MSG_DEBUG, "P2P: * Dialog Token: %d", dialog_token); 25 } 26 27 28 void p2p_buf_add_public_action_hdr(struct wpabuf *buf, u8 subtype, 29 u8 dialog_token) 30 { 31 wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC); 32 wpabuf_put_u8(buf, WLAN_PA_VENDOR_SPECIFIC); 33 wpabuf_put_be32(buf, P2P_IE_VENDOR_TYPE); 34 35 wpabuf_put_u8(buf, subtype); /* OUI Subtype */ 36 wpabuf_put_u8(buf, dialog_token); 37 wpa_printf(MSG_DEBUG, "P2P: * Dialog Token: %d", dialog_token); 38 } 39 40 41 u8 * p2p_buf_add_ie_hdr(struct wpabuf *buf) 42 { 43 u8 *len; 44 45 /* P2P IE header */ 46 wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); 47 len = wpabuf_put(buf, 1); /* IE length to be filled */ 48 wpabuf_put_be32(buf, P2P_IE_VENDOR_TYPE); 49 wpa_printf(MSG_DEBUG, "P2P: * P2P IE header"); 50 return len; 51 } 52 53 54 void p2p_buf_update_ie_hdr(struct wpabuf *buf, u8 *len) 55 { 56 /* Update P2P IE Length */ 57 *len = (u8 *) wpabuf_put(buf, 0) - len - 1; 58 } 59 60 61 void p2p_buf_add_capability(struct wpabuf *buf, u8 dev_capab, u8 group_capab) 62 { 63 /* P2P Capability */ 64 wpabuf_put_u8(buf, P2P_ATTR_CAPABILITY); 65 wpabuf_put_le16(buf, 2); 66 wpabuf_put_u8(buf, dev_capab); /* Device Capabilities */ 67 wpabuf_put_u8(buf, group_capab); /* Group Capabilities */ 68 wpa_printf(MSG_DEBUG, "P2P: * Capability dev=%02x group=%02x", 69 dev_capab, group_capab); 70 } 71 72 73 void p2p_buf_add_go_intent(struct wpabuf *buf, u8 go_intent) 74 { 75 /* Group Owner Intent */ 76 wpabuf_put_u8(buf, P2P_ATTR_GROUP_OWNER_INTENT); 77 wpabuf_put_le16(buf, 1); 78 wpabuf_put_u8(buf, go_intent); 79 wpa_printf(MSG_DEBUG, "P2P: * GO Intent: Intent %u Tie breaker %u", 80 go_intent >> 1, go_intent & 0x01); 81 } 82 83 84 void p2p_buf_add_listen_channel(struct wpabuf *buf, const char *country, 85 u8 reg_class, u8 channel) 86 { 87 /* Listen Channel */ 88 wpabuf_put_u8(buf, P2P_ATTR_LISTEN_CHANNEL); 89 wpabuf_put_le16(buf, 5); 90 wpabuf_put_data(buf, country, 3); 91 wpabuf_put_u8(buf, reg_class); /* Regulatory Class */ 92 wpabuf_put_u8(buf, channel); /* Channel Number */ 93 wpa_printf(MSG_DEBUG, "P2P: * Listen Channel: Regulatory Class %u " 94 "Channel %u", reg_class, channel); 95 } 96 97 98 void p2p_buf_add_operating_channel(struct wpabuf *buf, const char *country, 99 u8 reg_class, u8 channel) 100 { 101 /* Operating Channel */ 102 wpabuf_put_u8(buf, P2P_ATTR_OPERATING_CHANNEL); 103 wpabuf_put_le16(buf, 5); 104 wpabuf_put_data(buf, country, 3); 105 wpabuf_put_u8(buf, reg_class); /* Regulatory Class */ 106 wpabuf_put_u8(buf, channel); /* Channel Number */ 107 wpa_printf(MSG_DEBUG, "P2P: * Operating Channel: Regulatory Class %u " 108 "Channel %u", reg_class, channel); 109 } 110 111 112 void p2p_buf_add_channel_list(struct wpabuf *buf, const char *country, 113 struct p2p_channels *chan) 114 { 115 u8 *len; 116 size_t i; 117 118 /* Channel List */ 119 wpabuf_put_u8(buf, P2P_ATTR_CHANNEL_LIST); 120 len = wpabuf_put(buf, 2); /* IE length to be filled */ 121 wpabuf_put_data(buf, country, 3); /* Country String */ 122 123 for (i = 0; i < chan->reg_classes; i++) { 124 struct p2p_reg_class *c = &chan->reg_class[i]; 125 wpabuf_put_u8(buf, c->reg_class); 126 wpabuf_put_u8(buf, c->channels); 127 wpabuf_put_data(buf, c->channel, c->channels); 128 } 129 130 /* Update attribute length */ 131 WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2); 132 wpa_hexdump(MSG_DEBUG, "P2P: * Channel List", 133 len + 2, (u8 *) wpabuf_put(buf, 0) - len - 2); 134 } 135 136 137 void p2p_buf_add_status(struct wpabuf *buf, u8 status) 138 { 139 /* Status */ 140 wpabuf_put_u8(buf, P2P_ATTR_STATUS); 141 wpabuf_put_le16(buf, 1); 142 wpabuf_put_u8(buf, status); 143 wpa_printf(MSG_DEBUG, "P2P: * Status: %d", status); 144 } 145 146 147 void p2p_buf_add_device_info(struct wpabuf *buf, struct p2p_data *p2p, 148 struct p2p_device *peer) 149 { 150 u8 *len; 151 u16 methods; 152 size_t nlen, i; 153 154 /* P2P Device Info */ 155 wpabuf_put_u8(buf, P2P_ATTR_DEVICE_INFO); 156 len = wpabuf_put(buf, 2); /* IE length to be filled */ 157 158 /* P2P Device address */ 159 wpabuf_put_data(buf, p2p->cfg->dev_addr, ETH_ALEN); 160 161 /* Config Methods */ 162 methods = 0; 163 if (peer && peer->wps_method != WPS_NOT_READY) { 164 if (peer->wps_method == WPS_PBC) 165 methods |= WPS_CONFIG_PUSHBUTTON; 166 else if (peer->wps_method == WPS_PIN_DISPLAY || 167 peer->wps_method == WPS_PIN_KEYPAD) { 168 methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD; 169 methods |= WPS_CONFIG_P2PS; 170 } 171 } else if (p2p->cfg->config_methods) { 172 methods |= p2p->cfg->config_methods & 173 (WPS_CONFIG_PUSHBUTTON | WPS_CONFIG_DISPLAY | 174 WPS_CONFIG_KEYPAD | WPS_CONFIG_P2PS); 175 } else { 176 methods |= WPS_CONFIG_PUSHBUTTON; 177 methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD; 178 methods |= WPS_CONFIG_P2PS; 179 } 180 wpabuf_put_be16(buf, methods); 181 182 /* Primary Device Type */ 183 wpabuf_put_data(buf, p2p->cfg->pri_dev_type, 184 sizeof(p2p->cfg->pri_dev_type)); 185 186 /* Number of Secondary Device Types */ 187 wpabuf_put_u8(buf, p2p->cfg->num_sec_dev_types); 188 189 /* Secondary Device Type List */ 190 for (i = 0; i < p2p->cfg->num_sec_dev_types; i++) 191 wpabuf_put_data(buf, p2p->cfg->sec_dev_type[i], 192 WPS_DEV_TYPE_LEN); 193 194 /* Device Name */ 195 nlen = p2p->cfg->dev_name ? os_strlen(p2p->cfg->dev_name) : 0; 196 wpabuf_put_be16(buf, ATTR_DEV_NAME); 197 wpabuf_put_be16(buf, nlen); 198 wpabuf_put_data(buf, p2p->cfg->dev_name, nlen); 199 200 /* Update attribute length */ 201 WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2); 202 wpa_printf(MSG_DEBUG, "P2P: * Device Info"); 203 } 204 205 206 void p2p_buf_add_device_id(struct wpabuf *buf, const u8 *dev_addr) 207 { 208 /* P2P Device ID */ 209 wpabuf_put_u8(buf, P2P_ATTR_DEVICE_ID); 210 wpabuf_put_le16(buf, ETH_ALEN); 211 wpabuf_put_data(buf, dev_addr, ETH_ALEN); 212 wpa_printf(MSG_DEBUG, "P2P: * Device ID: " MACSTR, MAC2STR(dev_addr)); 213 } 214 215 216 void p2p_buf_add_config_timeout(struct wpabuf *buf, u8 go_timeout, 217 u8 client_timeout) 218 { 219 /* Configuration Timeout */ 220 wpabuf_put_u8(buf, P2P_ATTR_CONFIGURATION_TIMEOUT); 221 wpabuf_put_le16(buf, 2); 222 wpabuf_put_u8(buf, go_timeout); 223 wpabuf_put_u8(buf, client_timeout); 224 wpa_printf(MSG_DEBUG, "P2P: * Configuration Timeout: GO %d (*10ms) " 225 "client %d (*10ms)", go_timeout, client_timeout); 226 } 227 228 229 void p2p_buf_add_intended_addr(struct wpabuf *buf, const u8 *interface_addr) 230 { 231 /* Intended P2P Interface Address */ 232 wpabuf_put_u8(buf, P2P_ATTR_INTENDED_INTERFACE_ADDR); 233 wpabuf_put_le16(buf, ETH_ALEN); 234 wpabuf_put_data(buf, interface_addr, ETH_ALEN); 235 wpa_printf(MSG_DEBUG, "P2P: * Intended P2P Interface Address " MACSTR, 236 MAC2STR(interface_addr)); 237 } 238 239 240 void p2p_buf_add_group_bssid(struct wpabuf *buf, const u8 *bssid) 241 { 242 /* P2P Group BSSID */ 243 wpabuf_put_u8(buf, P2P_ATTR_GROUP_BSSID); 244 wpabuf_put_le16(buf, ETH_ALEN); 245 wpabuf_put_data(buf, bssid, ETH_ALEN); 246 wpa_printf(MSG_DEBUG, "P2P: * P2P Group BSSID " MACSTR, 247 MAC2STR(bssid)); 248 } 249 250 251 void p2p_buf_add_group_id(struct wpabuf *buf, const u8 *dev_addr, 252 const u8 *ssid, size_t ssid_len) 253 { 254 /* P2P Group ID */ 255 wpabuf_put_u8(buf, P2P_ATTR_GROUP_ID); 256 wpabuf_put_le16(buf, ETH_ALEN + ssid_len); 257 wpabuf_put_data(buf, dev_addr, ETH_ALEN); 258 wpabuf_put_data(buf, ssid, ssid_len); 259 wpa_printf(MSG_DEBUG, "P2P: * P2P Group ID " MACSTR, 260 MAC2STR(dev_addr)); 261 wpa_hexdump_ascii(MSG_DEBUG, "P2P: P2P Group ID SSID", ssid, ssid_len); 262 } 263 264 265 void p2p_buf_add_invitation_flags(struct wpabuf *buf, u8 flags) 266 { 267 /* Invitation Flags */ 268 wpabuf_put_u8(buf, P2P_ATTR_INVITATION_FLAGS); 269 wpabuf_put_le16(buf, 1); 270 wpabuf_put_u8(buf, flags); 271 wpa_printf(MSG_DEBUG, "P2P: * Invitation Flags: bitmap 0x%x", flags); 272 } 273 274 275 static void p2p_buf_add_noa_desc(struct wpabuf *buf, struct p2p_noa_desc *desc) 276 { 277 if (desc == NULL) 278 return; 279 280 wpabuf_put_u8(buf, desc->count_type); 281 wpabuf_put_le32(buf, desc->duration); 282 wpabuf_put_le32(buf, desc->interval); 283 wpabuf_put_le32(buf, desc->start_time); 284 } 285 286 287 void p2p_buf_add_noa(struct wpabuf *buf, u8 noa_index, u8 opp_ps, u8 ctwindow, 288 struct p2p_noa_desc *desc1, struct p2p_noa_desc *desc2) 289 { 290 /* Notice of Absence */ 291 wpabuf_put_u8(buf, P2P_ATTR_NOTICE_OF_ABSENCE); 292 wpabuf_put_le16(buf, 2 + (desc1 ? 13 : 0) + (desc2 ? 13 : 0)); 293 wpabuf_put_u8(buf, noa_index); 294 wpabuf_put_u8(buf, (opp_ps ? 0x80 : 0) | (ctwindow & 0x7f)); 295 p2p_buf_add_noa_desc(buf, desc1); 296 p2p_buf_add_noa_desc(buf, desc2); 297 wpa_printf(MSG_DEBUG, "P2P: * Notice of Absence"); 298 } 299 300 301 void p2p_buf_add_ext_listen_timing(struct wpabuf *buf, u16 period, 302 u16 interval) 303 { 304 /* Extended Listen Timing */ 305 wpabuf_put_u8(buf, P2P_ATTR_EXT_LISTEN_TIMING); 306 wpabuf_put_le16(buf, 4); 307 wpabuf_put_le16(buf, period); 308 wpabuf_put_le16(buf, interval); 309 wpa_printf(MSG_DEBUG, "P2P: * Extended Listen Timing (period %u msec " 310 "interval %u msec)", period, interval); 311 } 312 313 314 void p2p_buf_add_p2p_interface(struct wpabuf *buf, struct p2p_data *p2p) 315 { 316 /* P2P Interface */ 317 wpabuf_put_u8(buf, P2P_ATTR_INTERFACE); 318 wpabuf_put_le16(buf, ETH_ALEN + 1 + ETH_ALEN); 319 /* P2P Device address */ 320 wpabuf_put_data(buf, p2p->cfg->dev_addr, ETH_ALEN); 321 /* 322 * FIX: Fetch interface address list from driver. Do not include 323 * the P2P Device address if it is never used as interface address. 324 */ 325 /* P2P Interface Address Count */ 326 wpabuf_put_u8(buf, 1); 327 wpabuf_put_data(buf, p2p->cfg->dev_addr, ETH_ALEN); 328 } 329 330 331 void p2p_buf_add_oob_go_neg_channel(struct wpabuf *buf, const char *country, 332 u8 oper_class, u8 channel, 333 enum p2p_role_indication role) 334 { 335 /* OOB Group Owner Negotiation Channel */ 336 wpabuf_put_u8(buf, P2P_ATTR_OOB_GO_NEG_CHANNEL); 337 wpabuf_put_le16(buf, 6); 338 wpabuf_put_data(buf, country, 3); 339 wpabuf_put_u8(buf, oper_class); /* Operating Class */ 340 wpabuf_put_u8(buf, channel); /* Channel Number */ 341 wpabuf_put_u8(buf, (u8) role); /* Role indication */ 342 wpa_printf(MSG_DEBUG, "P2P: * OOB GO Negotiation Channel: Operating " 343 "Class %u Channel %u Role %d", 344 oper_class, channel, role); 345 } 346 347 348 void p2p_buf_add_service_hash(struct wpabuf *buf, struct p2p_data *p2p) 349 { 350 if (!p2p) 351 return; 352 353 /* Service Hash */ 354 wpabuf_put_u8(buf, P2P_ATTR_SERVICE_HASH); 355 wpabuf_put_le16(buf, p2p->p2ps_seek_count * P2PS_HASH_LEN); 356 wpabuf_put_data(buf, p2p->query_hash, 357 p2p->p2ps_seek_count * P2PS_HASH_LEN); 358 wpa_hexdump(MSG_DEBUG, "P2P: * Service Hash", 359 p2p->query_hash, p2p->p2ps_seek_count * P2PS_HASH_LEN); 360 } 361 362 363 void p2p_buf_add_session_info(struct wpabuf *buf, const char *info) 364 { 365 size_t info_len = 0; 366 367 if (info && info[0]) 368 info_len = os_strlen(info); 369 370 /* Session Information Data Info */ 371 wpabuf_put_u8(buf, P2P_ATTR_SESSION_INFORMATION_DATA); 372 wpabuf_put_le16(buf, (u16) info_len); 373 374 if (info) { 375 wpabuf_put_data(buf, info, info_len); 376 wpa_printf(MSG_DEBUG, "P2P: * Session Info Data (%s)", info); 377 } 378 } 379 380 381 void p2p_buf_add_connection_capability(struct wpabuf *buf, u8 connection_cap) 382 { 383 /* Connection Capability Info */ 384 wpabuf_put_u8(buf, P2P_ATTR_CONNECTION_CAPABILITY); 385 wpabuf_put_le16(buf, 1); 386 wpabuf_put_u8(buf, connection_cap); 387 wpa_printf(MSG_DEBUG, "P2P: * Connection Capability: 0x%x", 388 connection_cap); 389 } 390 391 392 void p2p_buf_add_advertisement_id(struct wpabuf *buf, u32 id, const u8 *mac) 393 { 394 if (!buf || !mac) 395 return; 396 397 /* Advertisement ID Info */ 398 wpabuf_put_u8(buf, P2P_ATTR_ADVERTISEMENT_ID); 399 wpabuf_put_le16(buf, (u16) (sizeof(u32) + ETH_ALEN)); 400 wpabuf_put_le32(buf, id); 401 wpabuf_put_data(buf, mac, ETH_ALEN); 402 wpa_printf(MSG_DEBUG, "P2P: * Advertisement ID (%x) " MACSTR, 403 id, MAC2STR(mac)); 404 } 405 406 407 void p2p_buf_add_service_instance(struct wpabuf *buf, struct p2p_data *p2p, 408 u8 hash_count, const u8 *hash, 409 struct p2ps_advertisement *adv_list) 410 { 411 struct p2ps_advertisement *adv; 412 struct wpabuf *tmp_buf; 413 u8 *tag_len = NULL, *ie_len = NULL; 414 size_t svc_len = 0, remaining = 0, total_len = 0; 415 416 if (!adv_list || !hash) 417 return; 418 419 /* Allocate temp buffer, allowing for overflow of 1 instance */ 420 tmp_buf = wpabuf_alloc(MAX_SVC_ADV_IE_LEN + 256 + P2PS_HASH_LEN); 421 if (!tmp_buf) 422 return; 423 424 for (adv = adv_list; adv && total_len <= MAX_SVC_ADV_LEN; 425 adv = adv->next) { 426 u8 count = hash_count; 427 const u8 *test = hash; 428 429 while (count--) { 430 /* Check for wildcard */ 431 if (os_memcmp(test, p2p->wild_card_hash, 432 P2PS_HASH_LEN) == 0) { 433 total_len = MAX_SVC_ADV_LEN + 1; 434 goto wild_hash; 435 } 436 437 if (os_memcmp(test, adv->hash, P2PS_HASH_LEN) == 0) 438 goto hash_match; 439 440 test += P2PS_HASH_LEN; 441 } 442 443 /* No matches found - Skip this Adv Instance */ 444 continue; 445 446 hash_match: 447 if (!tag_len) { 448 tag_len = p2p_buf_add_ie_hdr(tmp_buf); 449 remaining = 255 - 4; 450 if (!ie_len) { 451 wpabuf_put_u8(tmp_buf, 452 P2P_ATTR_ADVERTISED_SERVICE); 453 ie_len = wpabuf_put(tmp_buf, sizeof(u16)); 454 remaining -= (sizeof(u8) + sizeof(u16)); 455 } 456 } 457 458 svc_len = os_strlen(adv->svc_name); 459 460 if (7 + svc_len + total_len > MAX_SVC_ADV_LEN) { 461 /* Can't fit... return wildcard */ 462 total_len = MAX_SVC_ADV_LEN + 1; 463 break; 464 } 465 466 if (remaining <= (sizeof(adv->id) + 467 sizeof(adv->config_methods))) { 468 size_t front = remaining; 469 size_t back = (sizeof(adv->id) + 470 sizeof(adv->config_methods)) - front; 471 u8 holder[sizeof(adv->id) + 472 sizeof(adv->config_methods)]; 473 474 /* This works even if front or back == 0 */ 475 WPA_PUT_LE32(holder, adv->id); 476 WPA_PUT_BE16(&holder[sizeof(adv->id)], 477 adv->config_methods); 478 wpabuf_put_data(tmp_buf, holder, front); 479 p2p_buf_update_ie_hdr(tmp_buf, tag_len); 480 tag_len = p2p_buf_add_ie_hdr(tmp_buf); 481 wpabuf_put_data(tmp_buf, &holder[front], back); 482 remaining = 255 - (sizeof(adv->id) + 483 sizeof(adv->config_methods)) - back; 484 } else { 485 wpabuf_put_le32(tmp_buf, adv->id); 486 wpabuf_put_be16(tmp_buf, adv->config_methods); 487 remaining -= (sizeof(adv->id) + 488 sizeof(adv->config_methods)); 489 } 490 491 /* We are guaranteed at least one byte for svc_len */ 492 wpabuf_put_u8(tmp_buf, svc_len); 493 remaining -= sizeof(u8); 494 495 if (remaining < svc_len) { 496 size_t front = remaining; 497 size_t back = svc_len - front; 498 499 wpabuf_put_data(tmp_buf, adv->svc_name, front); 500 p2p_buf_update_ie_hdr(tmp_buf, tag_len); 501 tag_len = p2p_buf_add_ie_hdr(tmp_buf); 502 503 /* In rare cases, we must split across 3 attributes */ 504 if (back > 255 - 4) { 505 wpabuf_put_data(tmp_buf, 506 &adv->svc_name[front], 255 - 4); 507 back -= 255 - 4; 508 front += 255 - 4; 509 p2p_buf_update_ie_hdr(tmp_buf, tag_len); 510 tag_len = p2p_buf_add_ie_hdr(tmp_buf); 511 } 512 513 wpabuf_put_data(tmp_buf, &adv->svc_name[front], back); 514 remaining = 255 - 4 - back; 515 } else { 516 wpabuf_put_data(tmp_buf, adv->svc_name, svc_len); 517 remaining -= svc_len; 518 } 519 520 /* adv_id config_methods svc_string */ 521 total_len += sizeof(u32) + sizeof(u16) + sizeof(u8) + svc_len; 522 } 523 524 if (tag_len) 525 p2p_buf_update_ie_hdr(tmp_buf, tag_len); 526 527 if (ie_len) 528 WPA_PUT_LE16(ie_len, (u16) total_len); 529 530 wild_hash: 531 /* If all fit, return matching instances, otherwise the wildcard */ 532 if (total_len <= MAX_SVC_ADV_LEN) { 533 wpabuf_put_buf(buf, tmp_buf); 534 } else { 535 char *wild_card = P2PS_WILD_HASH_STR; 536 u8 wild_len; 537 538 /* Insert wildcard instance */ 539 tag_len = p2p_buf_add_ie_hdr(buf); 540 wpabuf_put_u8(buf, P2P_ATTR_ADVERTISED_SERVICE); 541 ie_len = wpabuf_put(buf, sizeof(u16)); 542 543 wild_len = (u8) os_strlen(wild_card); 544 wpabuf_put_le32(buf, 0); 545 wpabuf_put_be16(buf, 0); 546 wpabuf_put_u8(buf, wild_len); 547 wpabuf_put_data(buf, wild_card, wild_len); 548 549 WPA_PUT_LE16(ie_len, 4 + 2 + 1 + wild_len); 550 p2p_buf_update_ie_hdr(buf, tag_len); 551 } 552 553 wpabuf_free(tmp_buf); 554 } 555 556 557 void p2p_buf_add_session_id(struct wpabuf *buf, u32 id, const u8 *mac) 558 { 559 if (!buf || !mac) 560 return; 561 562 /* Session ID Info */ 563 wpabuf_put_u8(buf, P2P_ATTR_SESSION_ID); 564 wpabuf_put_le16(buf, (u16) (sizeof(u32) + ETH_ALEN)); 565 wpabuf_put_le32(buf, id); 566 wpabuf_put_data(buf, mac, ETH_ALEN); 567 wpa_printf(MSG_DEBUG, "P2P: * Session ID Info (%x) " MACSTR, 568 id, MAC2STR(mac)); 569 } 570 571 572 void p2p_buf_add_feature_capability(struct wpabuf *buf, u16 len, const u8 *mask) 573 { 574 if (!buf || !len || !mask) 575 return; 576 577 /* Feature Capability */ 578 wpabuf_put_u8(buf, P2P_ATTR_FEATURE_CAPABILITY); 579 wpabuf_put_le16(buf, len); 580 wpabuf_put_data(buf, mask, len); 581 wpa_printf(MSG_DEBUG, "P2P: * Feature Capability (%d)", len); 582 } 583 584 585 void p2p_buf_add_persistent_group_info(struct wpabuf *buf, const u8 *dev_addr, 586 const u8 *ssid, size_t ssid_len) 587 { 588 /* P2P Group ID */ 589 wpabuf_put_u8(buf, P2P_ATTR_PERSISTENT_GROUP); 590 wpabuf_put_le16(buf, ETH_ALEN + ssid_len); 591 wpabuf_put_data(buf, dev_addr, ETH_ALEN); 592 wpabuf_put_data(buf, ssid, ssid_len); 593 wpa_printf(MSG_DEBUG, "P2P: * P2P Group ID " MACSTR, 594 MAC2STR(dev_addr)); 595 } 596 597 598 static int p2p_add_wps_string(struct wpabuf *buf, enum wps_attribute attr, 599 const char *val) 600 { 601 size_t len; 602 603 len = val ? os_strlen(val) : 0; 604 if (wpabuf_tailroom(buf) < 4 + len) 605 return -1; 606 wpabuf_put_be16(buf, attr); 607 #ifndef CONFIG_WPS_STRICT 608 if (len == 0) { 609 /* 610 * Some deployed WPS implementations fail to parse zeor-length 611 * attributes. As a workaround, send a space character if the 612 * device attribute string is empty. 613 */ 614 if (wpabuf_tailroom(buf) < 3) 615 return -1; 616 wpabuf_put_be16(buf, 1); 617 wpabuf_put_u8(buf, ' '); 618 return 0; 619 } 620 #endif /* CONFIG_WPS_STRICT */ 621 wpabuf_put_be16(buf, len); 622 if (val) 623 wpabuf_put_data(buf, val, len); 624 return 0; 625 } 626 627 628 int p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id, 629 int all_attr) 630 { 631 u8 *len; 632 int i; 633 634 if (wpabuf_tailroom(buf) < 6) 635 return -1; 636 wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); 637 len = wpabuf_put(buf, 1); 638 wpabuf_put_be32(buf, WPS_DEV_OUI_WFA); 639 640 if (wps_build_version(buf) < 0) 641 return -1; 642 643 if (all_attr) { 644 if (wpabuf_tailroom(buf) < 5) 645 return -1; 646 wpabuf_put_be16(buf, ATTR_WPS_STATE); 647 wpabuf_put_be16(buf, 1); 648 wpabuf_put_u8(buf, WPS_STATE_NOT_CONFIGURED); 649 } 650 651 if (pw_id >= 0) { 652 if (wpabuf_tailroom(buf) < 6) 653 return -1; 654 /* Device Password ID */ 655 wpabuf_put_be16(buf, ATTR_DEV_PASSWORD_ID); 656 wpabuf_put_be16(buf, 2); 657 wpa_printf(MSG_DEBUG, "P2P: WPS IE Device Password ID: %d", 658 pw_id); 659 wpabuf_put_be16(buf, pw_id); 660 } 661 662 if (all_attr) { 663 if (wpabuf_tailroom(buf) < 5) 664 return -1; 665 wpabuf_put_be16(buf, ATTR_RESPONSE_TYPE); 666 wpabuf_put_be16(buf, 1); 667 wpabuf_put_u8(buf, WPS_RESP_ENROLLEE_INFO); 668 669 if (wps_build_uuid_e(buf, p2p->cfg->uuid) < 0 || 670 p2p_add_wps_string(buf, ATTR_MANUFACTURER, 671 p2p->cfg->manufacturer) < 0 || 672 p2p_add_wps_string(buf, ATTR_MODEL_NAME, 673 p2p->cfg->model_name) < 0 || 674 p2p_add_wps_string(buf, ATTR_MODEL_NUMBER, 675 p2p->cfg->model_number) < 0 || 676 p2p_add_wps_string(buf, ATTR_SERIAL_NUMBER, 677 p2p->cfg->serial_number) < 0) 678 return -1; 679 680 if (wpabuf_tailroom(buf) < 4 + WPS_DEV_TYPE_LEN) 681 return -1; 682 wpabuf_put_be16(buf, ATTR_PRIMARY_DEV_TYPE); 683 wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN); 684 wpabuf_put_data(buf, p2p->cfg->pri_dev_type, WPS_DEV_TYPE_LEN); 685 686 if (p2p_add_wps_string(buf, ATTR_DEV_NAME, p2p->cfg->dev_name) 687 < 0) 688 return -1; 689 690 if (wpabuf_tailroom(buf) < 6) 691 return -1; 692 wpabuf_put_be16(buf, ATTR_CONFIG_METHODS); 693 wpabuf_put_be16(buf, 2); 694 wpabuf_put_be16(buf, p2p->cfg->config_methods); 695 } 696 697 if (wps_build_wfa_ext(buf, 0, NULL, 0) < 0) 698 return -1; 699 700 if (all_attr && p2p->cfg->num_sec_dev_types) { 701 if (wpabuf_tailroom(buf) < 702 4 + WPS_DEV_TYPE_LEN * p2p->cfg->num_sec_dev_types) 703 return -1; 704 wpabuf_put_be16(buf, ATTR_SECONDARY_DEV_TYPE_LIST); 705 wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN * 706 p2p->cfg->num_sec_dev_types); 707 wpabuf_put_data(buf, p2p->cfg->sec_dev_type, 708 WPS_DEV_TYPE_LEN * 709 p2p->cfg->num_sec_dev_types); 710 } 711 712 /* Add the WPS vendor extensions */ 713 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) { 714 if (p2p->wps_vendor_ext[i] == NULL) 715 break; 716 if (wpabuf_tailroom(buf) < 717 4 + wpabuf_len(p2p->wps_vendor_ext[i])) 718 continue; 719 wpabuf_put_be16(buf, ATTR_VENDOR_EXT); 720 wpabuf_put_be16(buf, wpabuf_len(p2p->wps_vendor_ext[i])); 721 wpabuf_put_buf(buf, p2p->wps_vendor_ext[i]); 722 } 723 724 p2p_buf_update_ie_hdr(buf, len); 725 726 return 0; 727 } 728