1 /* 2 * P2P - IE parser 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 "common/ieee802_11_common.h" 20 #include "wps/wps_i.h" 21 #include "p2p_i.h" 22 23 24 static int p2p_parse_attribute(u8 id, const u8 *data, u16 len, 25 struct p2p_message *msg) 26 { 27 const u8 *pos; 28 size_t i, nlen; 29 char devtype[WPS_DEV_TYPE_BUFSIZE]; 30 31 switch (id) { 32 case P2P_ATTR_CAPABILITY: 33 if (len < 2) { 34 wpa_printf(MSG_DEBUG, "P2P: Too short Capability " 35 "attribute (length %d)", len); 36 return -1; 37 } 38 msg->capability = data; 39 wpa_printf(MSG_DEBUG, "P2P: * Device Capability %02x " 40 "Group Capability %02x", 41 data[0], data[1]); 42 break; 43 case P2P_ATTR_DEVICE_ID: 44 if (len < ETH_ALEN) { 45 wpa_printf(MSG_DEBUG, "P2P: Too short Device ID " 46 "attribute (length %d)", len); 47 return -1; 48 } 49 msg->device_id = data; 50 wpa_printf(MSG_DEBUG, "P2P: * Device ID " MACSTR, 51 MAC2STR(msg->device_id)); 52 break; 53 case P2P_ATTR_GROUP_OWNER_INTENT: 54 if (len < 1) { 55 wpa_printf(MSG_DEBUG, "P2P: Too short GO Intent " 56 "attribute (length %d)", len); 57 return -1; 58 } 59 msg->go_intent = data; 60 wpa_printf(MSG_DEBUG, "P2P: * GO Intent: Intent %u " 61 "Tie breaker %u", data[0] >> 1, data[0] & 0x01); 62 break; 63 case P2P_ATTR_STATUS: 64 if (len < 1) { 65 wpa_printf(MSG_DEBUG, "P2P: Too short Status " 66 "attribute (length %d)", len); 67 return -1; 68 } 69 msg->status = data; 70 wpa_printf(MSG_DEBUG, "P2P: * Status: %d", data[0]); 71 break; 72 case P2P_ATTR_LISTEN_CHANNEL: 73 if (len == 0) { 74 wpa_printf(MSG_DEBUG, "P2P: * Listen Channel: Ignore " 75 "null channel"); 76 break; 77 } 78 if (len < 5) { 79 wpa_printf(MSG_DEBUG, "P2P: Too short Listen Channel " 80 "attribute (length %d)", len); 81 return -1; 82 } 83 msg->listen_channel = data; 84 wpa_printf(MSG_DEBUG, "P2P: * Listen Channel: " 85 "Country %c%c(0x%02x) Regulatory " 86 "Class %d Channel Number %d", data[0], data[1], 87 data[2], data[3], data[4]); 88 break; 89 case P2P_ATTR_OPERATING_CHANNEL: 90 if (len == 0) { 91 wpa_printf(MSG_DEBUG, "P2P: * Operating Channel: " 92 "Ignore null channel"); 93 break; 94 } 95 if (len < 5) { 96 wpa_printf(MSG_DEBUG, "P2P: Too short Operating " 97 "Channel attribute (length %d)", len); 98 return -1; 99 } 100 msg->operating_channel = data; 101 wpa_printf(MSG_DEBUG, "P2P: * Operating Channel: " 102 "Country %c%c(0x%02x) Regulatory " 103 "Class %d Channel Number %d", data[0], data[1], 104 data[2], data[3], data[4]); 105 break; 106 case P2P_ATTR_CHANNEL_LIST: 107 if (len < 3) { 108 wpa_printf(MSG_DEBUG, "P2P: Too short Channel List " 109 "attribute (length %d)", len); 110 return -1; 111 } 112 msg->channel_list = data; 113 msg->channel_list_len = len; 114 wpa_printf(MSG_DEBUG, "P2P: * Channel List: Country String " 115 "'%c%c(0x%02x)'", data[0], data[1], data[2]); 116 wpa_hexdump(MSG_MSGDUMP, "P2P: Channel List", 117 msg->channel_list, msg->channel_list_len); 118 break; 119 case P2P_ATTR_GROUP_INFO: 120 msg->group_info = data; 121 msg->group_info_len = len; 122 wpa_printf(MSG_DEBUG, "P2P: * Group Info"); 123 break; 124 case P2P_ATTR_DEVICE_INFO: 125 if (len < ETH_ALEN + 2 + 8 + 1) { 126 wpa_printf(MSG_DEBUG, "P2P: Too short Device Info " 127 "attribute (length %d)", len); 128 return -1; 129 } 130 msg->p2p_device_info = data; 131 msg->p2p_device_info_len = len; 132 pos = data; 133 msg->p2p_device_addr = pos; 134 pos += ETH_ALEN; 135 msg->config_methods = WPA_GET_BE16(pos); 136 pos += 2; 137 msg->pri_dev_type = pos; 138 pos += 8; 139 msg->num_sec_dev_types = *pos++; 140 if (msg->num_sec_dev_types * 8 > data + len - pos) { 141 wpa_printf(MSG_DEBUG, "P2P: Device Info underflow"); 142 return -1; 143 } 144 pos += msg->num_sec_dev_types * 8; 145 if (data + len - pos < 4) { 146 wpa_printf(MSG_DEBUG, "P2P: Invalid Device Name " 147 "length %d", (int) (data + len - pos)); 148 return -1; 149 } 150 if (WPA_GET_BE16(pos) != ATTR_DEV_NAME) { 151 wpa_hexdump(MSG_DEBUG, "P2P: Unexpected Device Name " 152 "header", pos, 4); 153 return -1; 154 } 155 pos += 2; 156 nlen = WPA_GET_BE16(pos); 157 pos += 2; 158 if (data + len - pos < (int) nlen || nlen > 32) { 159 wpa_printf(MSG_DEBUG, "P2P: Invalid Device Name " 160 "length %d (buf len %d)", (int) nlen, 161 (int) (data + len - pos)); 162 return -1; 163 } 164 os_memcpy(msg->device_name, pos, nlen); 165 msg->device_name[nlen] = '\0'; 166 for (i = 0; i < nlen; i++) { 167 if (msg->device_name[i] == '\0') 168 break; 169 if (msg->device_name[i] > 0 && 170 msg->device_name[i] < 32) 171 msg->device_name[i] = '_'; 172 } 173 wpa_printf(MSG_DEBUG, "P2P: * Device Info: addr " MACSTR 174 " primary device type %s device name '%s' " 175 "config methods 0x%x", 176 MAC2STR(msg->p2p_device_addr), 177 wps_dev_type_bin2str(msg->pri_dev_type, devtype, 178 sizeof(devtype)), 179 msg->device_name, msg->config_methods); 180 break; 181 case P2P_ATTR_CONFIGURATION_TIMEOUT: 182 if (len < 2) { 183 wpa_printf(MSG_DEBUG, "P2P: Too short Configuration " 184 "Timeout attribute (length %d)", len); 185 return -1; 186 } 187 msg->config_timeout = data; 188 wpa_printf(MSG_DEBUG, "P2P: * Configuration Timeout"); 189 break; 190 case P2P_ATTR_INTENDED_INTERFACE_ADDR: 191 if (len < ETH_ALEN) { 192 wpa_printf(MSG_DEBUG, "P2P: Too short Intended P2P " 193 "Interface Address attribute (length %d)", 194 len); 195 return -1; 196 } 197 msg->intended_addr = data; 198 wpa_printf(MSG_DEBUG, "P2P: * Intended P2P Interface Address: " 199 MACSTR, MAC2STR(msg->intended_addr)); 200 break; 201 case P2P_ATTR_GROUP_BSSID: 202 if (len < ETH_ALEN) { 203 wpa_printf(MSG_DEBUG, "P2P: Too short P2P Group BSSID " 204 "attribute (length %d)", len); 205 return -1; 206 } 207 msg->group_bssid = data; 208 wpa_printf(MSG_DEBUG, "P2P: * P2P Group BSSID: " MACSTR, 209 MAC2STR(msg->group_bssid)); 210 break; 211 case P2P_ATTR_GROUP_ID: 212 if (len < ETH_ALEN || len > ETH_ALEN + 32) { 213 wpa_printf(MSG_DEBUG, "P2P: Invalid P2P Group ID " 214 "attribute length %d", len); 215 return -1; 216 } 217 msg->group_id = data; 218 msg->group_id_len = len; 219 wpa_printf(MSG_DEBUG, "P2P: * P2P Group ID: Device Address " 220 MACSTR, MAC2STR(msg->group_id)); 221 wpa_hexdump_ascii(MSG_DEBUG, "P2P: * P2P Group ID: SSID", 222 msg->group_id + ETH_ALEN, 223 msg->group_id_len - ETH_ALEN); 224 break; 225 case P2P_ATTR_INVITATION_FLAGS: 226 if (len < 1) { 227 wpa_printf(MSG_DEBUG, "P2P: Too short Invitation " 228 "Flag attribute (length %d)", len); 229 return -1; 230 } 231 msg->invitation_flags = data; 232 wpa_printf(MSG_DEBUG, "P2P: * Invitation Flags: bitmap 0x%x", 233 data[0]); 234 break; 235 case P2P_ATTR_MANAGEABILITY: 236 if (len < 1) { 237 wpa_printf(MSG_DEBUG, "P2P: Too short Manageability " 238 "attribute (length %d)", len); 239 return -1; 240 } 241 msg->manageability = data; 242 wpa_printf(MSG_DEBUG, "P2P: * Manageability: bitmap 0x%x", 243 data[0]); 244 break; 245 case P2P_ATTR_NOTICE_OF_ABSENCE: 246 if (len < 2) { 247 wpa_printf(MSG_DEBUG, "P2P: Too short Notice of " 248 "Absence attribute (length %d)", len); 249 return -1; 250 } 251 msg->noa = data; 252 msg->noa_len = len; 253 wpa_printf(MSG_DEBUG, "P2P: * Notice of Absence"); 254 break; 255 case P2P_ATTR_EXT_LISTEN_TIMING: 256 if (len < 4) { 257 wpa_printf(MSG_DEBUG, "P2P: Too short Extended Listen " 258 "Timing attribute (length %d)", len); 259 return -1; 260 } 261 msg->ext_listen_timing = data; 262 wpa_printf(MSG_DEBUG, "P2P: * Extended Listen Timing " 263 "(period %u msec interval %u msec)", 264 WPA_GET_LE16(msg->ext_listen_timing), 265 WPA_GET_LE16(msg->ext_listen_timing + 2)); 266 break; 267 case P2P_ATTR_MINOR_REASON_CODE: 268 if (len < 1) { 269 wpa_printf(MSG_DEBUG, "P2P: Too short Minor Reason " 270 "Code attribute (length %d)", len); 271 return -1; 272 } 273 msg->minor_reason_code = data; 274 wpa_printf(MSG_DEBUG, "P2P: * Minor Reason Code: %u", 275 *msg->minor_reason_code); 276 break; 277 default: 278 wpa_printf(MSG_DEBUG, "P2P: Skipped unknown attribute %d " 279 "(length %d)", id, len); 280 break; 281 } 282 283 return 0; 284 } 285 286 287 /** 288 * p2p_parse_p2p_ie - Parse P2P IE 289 * @buf: Concatenated P2P IE(s) payload 290 * @msg: Buffer for returning parsed attributes 291 * Returns: 0 on success, -1 on failure 292 * 293 * Note: Caller is responsible for clearing the msg data structure before 294 * calling this function. 295 */ 296 int p2p_parse_p2p_ie(const struct wpabuf *buf, struct p2p_message *msg) 297 { 298 const u8 *pos = wpabuf_head_u8(buf); 299 const u8 *end = pos + wpabuf_len(buf); 300 301 wpa_printf(MSG_DEBUG, "P2P: Parsing P2P IE"); 302 303 while (pos < end) { 304 u16 attr_len; 305 if (pos + 2 >= end) { 306 wpa_printf(MSG_DEBUG, "P2P: Invalid P2P attribute"); 307 return -1; 308 } 309 attr_len = WPA_GET_LE16(pos + 1); 310 wpa_printf(MSG_DEBUG, "P2P: Attribute %d length %u", 311 pos[0], attr_len); 312 if (pos + 3 + attr_len > end) { 313 wpa_printf(MSG_DEBUG, "P2P: Attribute underflow " 314 "(len=%u left=%d)", 315 attr_len, (int) (end - pos - 3)); 316 wpa_hexdump(MSG_MSGDUMP, "P2P: Data", pos, end - pos); 317 return -1; 318 } 319 if (p2p_parse_attribute(pos[0], pos + 3, attr_len, msg)) 320 return -1; 321 pos += 3 + attr_len; 322 } 323 324 return 0; 325 } 326 327 328 static int p2p_parse_wps_ie(const struct wpabuf *buf, struct p2p_message *msg) 329 { 330 struct wps_parse_attr attr; 331 int i; 332 333 wpa_printf(MSG_DEBUG, "P2P: Parsing WPS IE"); 334 if (wps_parse_msg(buf, &attr)) 335 return -1; 336 if (attr.dev_name && attr.dev_name_len < sizeof(msg->device_name) && 337 !msg->device_name[0]) 338 os_memcpy(msg->device_name, attr.dev_name, attr.dev_name_len); 339 if (attr.config_methods) { 340 msg->wps_config_methods = 341 WPA_GET_BE16(attr.config_methods); 342 wpa_printf(MSG_DEBUG, "P2P: Config Methods (WPS): 0x%x", 343 msg->wps_config_methods); 344 } 345 if (attr.dev_password_id) { 346 msg->dev_password_id = WPA_GET_BE16(attr.dev_password_id); 347 wpa_printf(MSG_DEBUG, "P2P: Device Password ID: %d", 348 msg->dev_password_id); 349 } 350 if (attr.primary_dev_type) { 351 char devtype[WPS_DEV_TYPE_BUFSIZE]; 352 msg->wps_pri_dev_type = attr.primary_dev_type; 353 wpa_printf(MSG_DEBUG, "P2P: Primary Device Type (WPS): %s", 354 wps_dev_type_bin2str(msg->wps_pri_dev_type, devtype, 355 sizeof(devtype))); 356 } 357 if (attr.sec_dev_type_list) { 358 msg->wps_sec_dev_type_list = attr.sec_dev_type_list; 359 msg->wps_sec_dev_type_list_len = attr.sec_dev_type_list_len; 360 } 361 362 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) { 363 msg->wps_vendor_ext[i] = attr.vendor_ext[i]; 364 msg->wps_vendor_ext_len[i] = attr.vendor_ext_len[i]; 365 } 366 367 msg->manufacturer = attr.manufacturer; 368 msg->manufacturer_len = attr.manufacturer_len; 369 msg->model_name = attr.model_name; 370 msg->model_name_len = attr.model_name_len; 371 msg->model_number = attr.model_number; 372 msg->model_number_len = attr.model_number_len; 373 msg->serial_number = attr.serial_number; 374 msg->serial_number_len = attr.serial_number_len; 375 376 return 0; 377 } 378 379 380 /** 381 * p2p_parse_ies - Parse P2P message IEs (both WPS and P2P IE) 382 * @data: IEs from the message 383 * @len: Length of data buffer in octets 384 * @msg: Buffer for returning parsed attributes 385 * Returns: 0 on success, -1 on failure 386 * 387 * Note: Caller is responsible for clearing the msg data structure before 388 * calling this function. 389 * 390 * Note: Caller must free temporary memory allocations by calling 391 * p2p_parse_free() when the parsed data is not needed anymore. 392 */ 393 int p2p_parse_ies(const u8 *data, size_t len, struct p2p_message *msg) 394 { 395 struct ieee802_11_elems elems; 396 397 ieee802_11_parse_elems(data, len, &elems, 0); 398 if (elems.ds_params && elems.ds_params_len >= 1) 399 msg->ds_params = elems.ds_params; 400 if (elems.ssid) 401 msg->ssid = elems.ssid - 2; 402 403 msg->wps_attributes = ieee802_11_vendor_ie_concat(data, len, 404 WPS_DEV_OUI_WFA); 405 if (msg->wps_attributes && 406 p2p_parse_wps_ie(msg->wps_attributes, msg)) { 407 p2p_parse_free(msg); 408 return -1; 409 } 410 411 msg->p2p_attributes = ieee802_11_vendor_ie_concat(data, len, 412 P2P_IE_VENDOR_TYPE); 413 if (msg->p2p_attributes && 414 p2p_parse_p2p_ie(msg->p2p_attributes, msg)) { 415 wpa_printf(MSG_DEBUG, "P2P: Failed to parse P2P IE data"); 416 if (msg->p2p_attributes) 417 wpa_hexdump_buf(MSG_MSGDUMP, "P2P: P2P IE data", 418 msg->p2p_attributes); 419 p2p_parse_free(msg); 420 return -1; 421 } 422 423 return 0; 424 } 425 426 427 /** 428 * p2p_parse - Parse a P2P Action frame contents 429 * @data: Action frame payload after Category and Code fields 430 * @len: Length of data buffer in octets 431 * @msg: Buffer for returning parsed attributes 432 * Returns: 0 on success, -1 on failure 433 * 434 * Note: Caller must free temporary memory allocations by calling 435 * p2p_parse_free() when the parsed data is not needed anymore. 436 */ 437 int p2p_parse(const u8 *data, size_t len, struct p2p_message *msg) 438 { 439 os_memset(msg, 0, sizeof(*msg)); 440 wpa_printf(MSG_DEBUG, "P2P: Parsing the received message"); 441 if (len < 1) { 442 wpa_printf(MSG_DEBUG, "P2P: No Dialog Token in the message"); 443 return -1; 444 } 445 msg->dialog_token = data[0]; 446 wpa_printf(MSG_DEBUG, "P2P: * Dialog Token: %d", msg->dialog_token); 447 448 return p2p_parse_ies(data + 1, len - 1, msg); 449 } 450 451 452 /** 453 * p2p_parse_free - Free temporary data from P2P parsing 454 * @msg: Parsed attributes 455 */ 456 void p2p_parse_free(struct p2p_message *msg) 457 { 458 wpabuf_free(msg->p2p_attributes); 459 msg->p2p_attributes = NULL; 460 wpabuf_free(msg->wps_attributes); 461 msg->wps_attributes = NULL; 462 } 463 464 465 int p2p_group_info_parse(const u8 *gi, size_t gi_len, 466 struct p2p_group_info *info) 467 { 468 const u8 *g, *gend; 469 470 os_memset(info, 0, sizeof(*info)); 471 if (gi == NULL) 472 return 0; 473 474 g = gi; 475 gend = gi + gi_len; 476 while (g < gend) { 477 struct p2p_client_info *cli; 478 const u8 *t, *cend; 479 int count; 480 481 cli = &info->client[info->num_clients]; 482 cend = g + 1 + g[0]; 483 if (cend > gend) 484 return -1; /* invalid data */ 485 /* g at start of P2P Client Info Descriptor */ 486 /* t at Device Capability Bitmap */ 487 t = g + 1 + 2 * ETH_ALEN; 488 if (t > cend) 489 return -1; /* invalid data */ 490 cli->p2p_device_addr = g + 1; 491 cli->p2p_interface_addr = g + 1 + ETH_ALEN; 492 cli->dev_capab = t[0]; 493 494 if (t + 1 + 2 + 8 + 1 > cend) 495 return -1; /* invalid data */ 496 497 cli->config_methods = WPA_GET_BE16(&t[1]); 498 cli->pri_dev_type = &t[3]; 499 500 t += 1 + 2 + 8; 501 /* t at Number of Secondary Device Types */ 502 cli->num_sec_dev_types = *t++; 503 if (t + 8 * cli->num_sec_dev_types > cend) 504 return -1; /* invalid data */ 505 cli->sec_dev_types = t; 506 t += 8 * cli->num_sec_dev_types; 507 508 /* t at Device Name in WPS TLV format */ 509 if (t + 2 + 2 > cend) 510 return -1; /* invalid data */ 511 if (WPA_GET_BE16(t) != ATTR_DEV_NAME) 512 return -1; /* invalid Device Name TLV */ 513 t += 2; 514 count = WPA_GET_BE16(t); 515 t += 2; 516 if (count > cend - t) 517 return -1; /* invalid Device Name TLV */ 518 if (count >= 32) 519 count = 32; 520 cli->dev_name = (const char *) t; 521 cli->dev_name_len = count; 522 523 g = cend; 524 525 info->num_clients++; 526 if (info->num_clients == P2P_MAX_GROUP_ENTRIES) 527 return -1; 528 } 529 530 return 0; 531 } 532 533 534 static int p2p_group_info_text(const u8 *gi, size_t gi_len, char *buf, 535 char *end) 536 { 537 char *pos = buf; 538 int ret; 539 struct p2p_group_info info; 540 unsigned int i; 541 542 if (p2p_group_info_parse(gi, gi_len, &info) < 0) 543 return 0; 544 545 for (i = 0; i < info.num_clients; i++) { 546 struct p2p_client_info *cli; 547 char name[33]; 548 char devtype[WPS_DEV_TYPE_BUFSIZE]; 549 u8 s; 550 int count; 551 552 cli = &info.client[i]; 553 ret = os_snprintf(pos, end - pos, "p2p_group_client: " 554 "dev=" MACSTR " iface=" MACSTR, 555 MAC2STR(cli->p2p_device_addr), 556 MAC2STR(cli->p2p_interface_addr)); 557 if (ret < 0 || ret >= end - pos) 558 return pos - buf; 559 pos += ret; 560 561 ret = os_snprintf(pos, end - pos, 562 " dev_capab=0x%x config_methods=0x%x " 563 "dev_type=%s", 564 cli->dev_capab, cli->config_methods, 565 wps_dev_type_bin2str(cli->pri_dev_type, 566 devtype, 567 sizeof(devtype))); 568 if (ret < 0 || ret >= end - pos) 569 return pos - buf; 570 pos += ret; 571 572 for (s = 0; s < cli->num_sec_dev_types; s++) { 573 ret = os_snprintf(pos, end - pos, " dev_type=%s", 574 wps_dev_type_bin2str( 575 &cli->sec_dev_types[s * 8], 576 devtype, sizeof(devtype))); 577 if (ret < 0 || ret >= end - pos) 578 return pos - buf; 579 pos += ret; 580 } 581 582 os_memcpy(name, cli->dev_name, cli->dev_name_len); 583 name[cli->dev_name_len] = '\0'; 584 count = (int) cli->dev_name_len - 1; 585 while (count >= 0) { 586 if (name[count] > 0 && name[count] < 32) 587 name[count] = '_'; 588 count--; 589 } 590 591 ret = os_snprintf(pos, end - pos, " dev_name='%s'\n", name); 592 if (ret < 0 || ret >= end - pos) 593 return pos - buf; 594 pos += ret; 595 } 596 597 return pos - buf; 598 } 599 600 601 /** 602 * p2p_attr_text - Build text format description of P2P IE attributes 603 * @data: P2P IE contents 604 * @buf: Buffer for returning text 605 * @end: Pointer to the end of the buf area 606 * Returns: Number of octets written to the buffer or -1 on faikure 607 * 608 * This function can be used to parse P2P IE contents into text format 609 * field=value lines. 610 */ 611 int p2p_attr_text(struct wpabuf *data, char *buf, char *end) 612 { 613 struct p2p_message msg; 614 char *pos = buf; 615 int ret; 616 617 os_memset(&msg, 0, sizeof(msg)); 618 if (p2p_parse_p2p_ie(data, &msg)) 619 return -1; 620 621 if (msg.capability) { 622 ret = os_snprintf(pos, end - pos, 623 "p2p_dev_capab=0x%x\n" 624 "p2p_group_capab=0x%x\n", 625 msg.capability[0], msg.capability[1]); 626 if (ret < 0 || ret >= end - pos) 627 return pos - buf; 628 pos += ret; 629 } 630 631 if (msg.pri_dev_type) { 632 char devtype[WPS_DEV_TYPE_BUFSIZE]; 633 ret = os_snprintf(pos, end - pos, 634 "p2p_primary_device_type=%s\n", 635 wps_dev_type_bin2str(msg.pri_dev_type, 636 devtype, 637 sizeof(devtype))); 638 if (ret < 0 || ret >= end - pos) 639 return pos - buf; 640 pos += ret; 641 } 642 643 ret = os_snprintf(pos, end - pos, "p2p_device_name=%s\n", 644 msg.device_name); 645 if (ret < 0 || ret >= end - pos) 646 return pos - buf; 647 pos += ret; 648 649 if (msg.p2p_device_addr) { 650 ret = os_snprintf(pos, end - pos, "p2p_device_addr=" MACSTR 651 "\n", 652 MAC2STR(msg.p2p_device_addr)); 653 if (ret < 0 || ret >= end - pos) 654 return pos - buf; 655 pos += ret; 656 } 657 658 ret = os_snprintf(pos, end - pos, "p2p_config_methods=0x%x\n", 659 msg.config_methods); 660 if (ret < 0 || ret >= end - pos) 661 return pos - buf; 662 pos += ret; 663 664 ret = p2p_group_info_text(msg.group_info, msg.group_info_len, 665 pos, end); 666 if (ret < 0) 667 return pos - buf; 668 pos += ret; 669 670 return pos - buf; 671 } 672 673 674 int p2p_get_cross_connect_disallowed(const struct wpabuf *p2p_ie) 675 { 676 struct p2p_message msg; 677 678 os_memset(&msg, 0, sizeof(msg)); 679 if (p2p_parse_p2p_ie(p2p_ie, &msg)) 680 return 0; 681 682 if (!msg.manageability) 683 return 0; 684 685 return !(msg.manageability[0] & P2P_MAN_CROSS_CONNECTION_PERMITTED); 686 } 687 688 689 u8 p2p_get_group_capab(const struct wpabuf *p2p_ie) 690 { 691 struct p2p_message msg; 692 693 os_memset(&msg, 0, sizeof(msg)); 694 if (p2p_parse_p2p_ie(p2p_ie, &msg)) 695 return 0; 696 697 if (!msg.capability) 698 return 0; 699 700 return msg.capability[1]; 701 } 702 703 704 const u8 * p2p_get_go_dev_addr(const struct wpabuf *p2p_ie) 705 { 706 struct p2p_message msg; 707 708 os_memset(&msg, 0, sizeof(msg)); 709 if (p2p_parse_p2p_ie(p2p_ie, &msg)) 710 return NULL; 711 712 if (msg.p2p_device_addr) 713 return msg.p2p_device_addr; 714 if (msg.device_id) 715 return msg.device_id; 716 717 return NULL; 718 } 719