18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * P2P - IE parser
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2009-2010, Atheros Communications
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_common.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps/wps_i.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p_i.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtvoid p2p_copy_filter_devname(char *dst, size_t dst_len,
19d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			     const void *src, size_t src_len)
20d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
21d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	size_t i;
22d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
23d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (src_len >= dst_len)
24d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		src_len = dst_len - 1;
25d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	os_memcpy(dst, src, src_len);
26d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	dst[src_len] = '\0';
27d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	for (i = 0; i < src_len; i++) {
28d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (dst[i] == '\0')
29d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			break;
30d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (is_ctrl_char(dst[i]))
31d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			dst[i] = '_';
32d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
33d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
34d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
35d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_parse_attribute(u8 id, const u8 *data, u16 len,
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       struct p2p_message *msg)
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos;
40d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	u16 nlen;
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char devtype[WPS_DEV_TYPE_BUFSIZE];
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (id) {
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_ATTR_CAPABILITY:
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 2) {
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Too short Capability "
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "attribute (length %d)", len);
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->capability = data;
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: * Device Capability %02x "
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Group Capability %02x",
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   data[0], data[1]);
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_ATTR_DEVICE_ID:
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < ETH_ALEN) {
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Too short Device ID "
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "attribute (length %d)", len);
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->device_id = data;
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: * Device ID " MACSTR,
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   MAC2STR(msg->device_id));
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_ATTR_GROUP_OWNER_INTENT:
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 1) {
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Too short GO Intent "
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "attribute (length %d)", len);
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->go_intent = data;
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: * GO Intent: Intent %u "
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Tie breaker %u", data[0] >> 1, data[0] & 0x01);
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_ATTR_STATUS:
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 1) {
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Too short Status "
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "attribute (length %d)", len);
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->status = data;
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: * Status: %d", data[0]);
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_ATTR_LISTEN_CHANNEL:
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len == 0) {
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: * Listen Channel: Ignore "
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "null channel");
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 5) {
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Too short Listen Channel "
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "attribute (length %d)", len);
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->listen_channel = data;
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: * Listen Channel: "
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Country %c%c(0x%02x) Regulatory "
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Class %d Channel Number %d", data[0], data[1],
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   data[2], data[3], data[4]);
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_ATTR_OPERATING_CHANNEL:
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len == 0) {
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: * Operating Channel: "
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Ignore null channel");
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 5) {
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Too short Operating "
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Channel attribute (length %d)", len);
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->operating_channel = data;
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: * Operating Channel: "
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Country %c%c(0x%02x) Regulatory "
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Class %d Channel Number %d", data[0], data[1],
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   data[2], data[3], data[4]);
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_ATTR_CHANNEL_LIST:
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 3) {
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Too short Channel List "
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "attribute (length %d)", len);
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->channel_list = data;
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->channel_list_len = len;
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: * Channel List: Country String "
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "'%c%c(0x%02x)'", data[0], data[1], data[2]);
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "P2P: Channel List",
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    msg->channel_list, msg->channel_list_len);
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_ATTR_GROUP_INFO:
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->group_info = data;
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->group_info_len = len;
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: * Group Info");
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_ATTR_DEVICE_INFO:
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < ETH_ALEN + 2 + 8 + 1) {
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Too short Device Info "
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "attribute (length %d)", len);
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->p2p_device_info = data;
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->p2p_device_info_len = len;
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = data;
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->p2p_device_addr = pos;
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ETH_ALEN;
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->config_methods = WPA_GET_BE16(pos);
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 2;
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->pri_dev_type = pos;
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 8;
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->num_sec_dev_types = *pos++;
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (msg->num_sec_dev_types * 8 > data + len - pos) {
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Device Info underflow");
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += msg->num_sec_dev_types * 8;
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (data + len - pos < 4) {
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Invalid Device Name "
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "length %d", (int) (data + len - pos));
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (WPA_GET_BE16(pos) != ATTR_DEV_NAME) {
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG, "P2P: Unexpected Device Name "
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    "header", pos, 4);
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 2;
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		nlen = WPA_GET_BE16(pos);
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 2;
170d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (nlen > data + len - pos || nlen > WPS_DEV_NAME_MAX_LEN) {
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Invalid Device Name "
172d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				   "length %u (buf len %d)", nlen,
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (int) (data + len - pos));
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
176d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		p2p_copy_filter_devname(msg->device_name,
177d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt					sizeof(msg->device_name), pos, nlen);
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: * Device Info: addr " MACSTR
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " primary device type %s device name '%s' "
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "config methods 0x%x",
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   MAC2STR(msg->p2p_device_addr),
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   wps_dev_type_bin2str(msg->pri_dev_type, devtype,
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						sizeof(devtype)),
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   msg->device_name, msg->config_methods);
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_ATTR_CONFIGURATION_TIMEOUT:
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 2) {
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Too short Configuration "
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Timeout attribute (length %d)", len);
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->config_timeout = data;
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: * Configuration Timeout");
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_ATTR_INTENDED_INTERFACE_ADDR:
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < ETH_ALEN) {
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Too short Intended P2P "
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Interface Address attribute (length %d)",
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   len);
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->intended_addr = data;
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: * Intended P2P Interface Address: "
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   MACSTR, MAC2STR(msg->intended_addr));
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_ATTR_GROUP_BSSID:
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < ETH_ALEN) {
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Too short P2P Group BSSID "
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "attribute (length %d)", len);
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->group_bssid = data;
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: * P2P Group BSSID: " MACSTR,
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   MAC2STR(msg->group_bssid));
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_ATTR_GROUP_ID:
2179d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt		if (len < ETH_ALEN || len > ETH_ALEN + SSID_MAX_LEN) {
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Invalid P2P Group ID "
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "attribute length %d", len);
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->group_id = data;
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->group_id_len = len;
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: * P2P Group ID: Device Address "
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   MACSTR, MAC2STR(msg->group_id));
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "P2P: * P2P Group ID: SSID",
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  msg->group_id + ETH_ALEN,
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  msg->group_id_len - ETH_ALEN);
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_ATTR_INVITATION_FLAGS:
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 1) {
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Too short Invitation "
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Flag attribute (length %d)", len);
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->invitation_flags = data;
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: * Invitation Flags: bitmap 0x%x",
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   data[0]);
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_ATTR_MANAGEABILITY:
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 1) {
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Too short Manageability "
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "attribute (length %d)", len);
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->manageability = data;
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: * Manageability: bitmap 0x%x",
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   data[0]);
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_ATTR_NOTICE_OF_ABSENCE:
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 2) {
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Too short Notice of "
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Absence attribute (length %d)", len);
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->noa = data;
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->noa_len = len;
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: * Notice of Absence");
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_ATTR_EXT_LISTEN_TIMING:
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 4) {
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Too short Extended Listen "
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Timing attribute (length %d)", len);
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->ext_listen_timing = data;
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: * Extended Listen Timing "
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(period %u msec  interval %u msec)",
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   WPA_GET_LE16(msg->ext_listen_timing),
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   WPA_GET_LE16(msg->ext_listen_timing + 2));
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case P2P_ATTR_MINOR_REASON_CODE:
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < 1) {
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Too short Minor Reason "
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Code attribute (length %d)", len);
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->minor_reason_code = data;
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: * Minor Reason Code: %u",
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   *msg->minor_reason_code);
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
282cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	case P2P_ATTR_OOB_GO_NEG_CHANNEL:
283cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		if (len < 6) {
284cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Too short OOB GO Neg "
285cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				   "Channel attribute (length %d)", len);
286cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			return -1;
287cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		}
288cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		msg->oob_go_neg_channel = data;
289cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: * OOB GO Neg Channel: "
290cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			   "Country %c%c(0x%02x) Operating Class %d "
291cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			   "Channel Number %d Role %d",
292cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			   data[0], data[1], data[2], data[3], data[4],
293cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			   data[5]);
294cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		break;
295216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	case P2P_ATTR_SERVICE_HASH:
296216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (len < P2PS_HASH_LEN) {
297216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			wpa_printf(MSG_DEBUG,
298216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				   "P2P: Too short Service Hash (length %u)",
299216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				   len);
300216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			return -1;
301216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		}
302216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		msg->service_hash_count = len / P2PS_HASH_LEN;
303216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		msg->service_hash = data;
304216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "P2P: * Service Hash(s)", data, len);
305216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		break;
306216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	case P2P_ATTR_SESSION_INFORMATION_DATA:
307216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		msg->session_info = data;
308216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		msg->session_info_len = len;
309216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: * Service Instance: %u bytes - %p",
310216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			   len, data);
311216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		break;
312216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	case P2P_ATTR_CONNECTION_CAPABILITY:
313216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (len < 1) {
314216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			wpa_printf(MSG_DEBUG,
315216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				   "P2P: Too short Connection Capability (length %u)",
316216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				   len);
317216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			return -1;
318216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		}
319216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		msg->conn_cap = data;
320216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: * Connection Capability: 0x%x",
321216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			   *msg->conn_cap);
322216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		break;
323216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	case P2P_ATTR_ADVERTISEMENT_ID:
324216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (len < 10) {
325216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			wpa_printf(MSG_DEBUG,
326216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				   "P2P: Too short Advertisement ID (length %u)",
327216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				   len);
328216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			return -1;
329216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		}
330216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		msg->adv_id = data;
331216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		msg->adv_mac = &data[sizeof(u32)];
332216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: * Advertisement ID %x",
333216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			   WPA_GET_LE32(data));
334216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		break;
335216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	case P2P_ATTR_ADVERTISED_SERVICE:
336216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (len < 8) {
337216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			wpa_printf(MSG_DEBUG,
338216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				   "P2P: Too short Service Instance (length %u)",
339216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				   len);
340216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			return -1;
341216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		}
342216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		msg->adv_service_instance = data;
343216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		msg->adv_service_instance_len = len;
344216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (len <= 255 + 8) {
345216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			char str[256];
346216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			u8 namelen;
347216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
348216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			namelen = data[6];
349216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			if (namelen > len - 7)
350216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				break;
351216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			os_memcpy(str, &data[7], namelen);
352216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			str[namelen] = '\0';
353216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: * Service Instance: %x-%s",
354216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				   WPA_GET_LE32(data), str);
355216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		} else {
356216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: * Service Instance: %p",
357216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				   data);
358216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		}
359216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		break;
360216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	case P2P_ATTR_SESSION_ID:
361216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (len < sizeof(u32) + ETH_ALEN) {
362216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			wpa_printf(MSG_DEBUG,
363216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				   "P2P: Too short Session ID Info (length %u)",
364216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				   len);
365216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			return -1;
366216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		}
367216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		msg->session_id = data;
368216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		msg->session_mac = &data[sizeof(u32)];
369216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: * Session ID: %x " MACSTR,
370216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			   WPA_GET_LE32(data), MAC2STR(msg->session_mac));
371216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		break;
372216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	case P2P_ATTR_FEATURE_CAPABILITY:
373216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		if (!len) {
374216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			wpa_printf(MSG_DEBUG,
375216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				   "P2P: Too short Feature Capability (length %u)",
376216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				   len);
377216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			return -1;
378216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		}
379216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		msg->feature_cap = data;
380216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		msg->feature_cap_len = len;
381216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: * Feature Cap (length=%u)", len);
382216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		break;
383216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	case P2P_ATTR_PERSISTENT_GROUP:
384216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	{
3859d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt		if (len < ETH_ALEN || len > ETH_ALEN + SSID_MAX_LEN) {
386216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			wpa_printf(MSG_DEBUG,
3879d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt				   "P2P: Invalid Persistent Group Info (length %u)",
388216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt				   len);
389216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			return -1;
390216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		}
391216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
392216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		msg->persistent_dev = data;
393216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		msg->persistent_ssid_len = len - ETH_ALEN;
394216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		msg->persistent_ssid = &data[ETH_ALEN];
395216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: * Persistent Group: " MACSTR " %s",
396216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			   MAC2STR(msg->persistent_dev),
397216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			   wpa_ssid_txt(msg->persistent_ssid,
398216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt					msg->persistent_ssid_len));
399216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		break;
400216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	}
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Skipped unknown attribute %d "
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(length %d)", id, len);
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_parse_p2p_ie - Parse P2P IE
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Concatenated P2P IE(s) payload
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @msg: Buffer for returning parsed attributes
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Note: Caller is responsible for clearing the msg data structure before
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * calling this function.
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_parse_p2p_ie(const struct wpabuf *buf, struct p2p_message *msg)
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos = wpabuf_head_u8(buf);
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *end = pos + wpabuf_len(buf);
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Parsing P2P IE");
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos < end) {
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u16 attr_len;
4296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		u8 id;
4306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (end - pos < 3) {
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Invalid P2P attribute");
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		id = *pos++;
4366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		attr_len = WPA_GET_LE16(pos);
4376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		pos += 2;
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Attribute %d length %u",
4396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   id, attr_len);
4406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (attr_len > end - pos) {
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Attribute underflow "
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "(len=%u left=%d)",
4436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				   attr_len, (int) (end - pos));
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_MSGDUMP, "P2P: Data", pos, end - pos);
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (p2p_parse_attribute(id, pos, attr_len, msg))
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
4496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		pos += attr_len;
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_parse_wps_ie(const struct wpabuf *buf, struct p2p_message *msg)
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wps_parse_attr attr;
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Parsing WPS IE");
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wps_parse_msg(buf, &attr))
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (attr.dev_name && attr.dev_name_len < sizeof(msg->device_name) &&
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !msg->device_name[0])
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(msg->device_name, attr.dev_name, attr.dev_name_len);
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (attr.config_methods) {
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->wps_config_methods =
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			WPA_GET_BE16(attr.config_methods);
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Config Methods (WPS): 0x%x",
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   msg->wps_config_methods);
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (attr.dev_password_id) {
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->dev_password_id = WPA_GET_BE16(attr.dev_password_id);
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Device Password ID: %d",
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   msg->dev_password_id);
477cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		msg->dev_password_id_present = 1;
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (attr.primary_dev_type) {
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char devtype[WPS_DEV_TYPE_BUFSIZE];
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->wps_pri_dev_type = attr.primary_dev_type;
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Primary Device Type (WPS): %s",
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   wps_dev_type_bin2str(msg->wps_pri_dev_type, devtype,
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						sizeof(devtype)));
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (attr.sec_dev_type_list) {
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->wps_sec_dev_type_list = attr.sec_dev_type_list;
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->wps_sec_dev_type_list_len = attr.sec_dev_type_list_len;
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->wps_vendor_ext[i] = attr.vendor_ext[i];
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->wps_vendor_ext_len[i] = attr.vendor_ext_len[i];
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg->manufacturer = attr.manufacturer;
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg->manufacturer_len = attr.manufacturer_len;
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg->model_name = attr.model_name;
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg->model_name_len = attr.model_name_len;
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg->model_number = attr.model_number;
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg->model_number_len = attr.model_number_len;
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg->serial_number = attr.serial_number;
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg->serial_number_len = attr.serial_number_len;
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
505cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	msg->oob_dev_password = attr.oob_dev_password;
506cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	msg->oob_dev_password_len = attr.oob_dev_password_len;
507cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_parse_ies - Parse P2P message IEs (both WPS and P2P IE)
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: IEs from the message
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Length of data buffer in octets
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @msg: Buffer for returning parsed attributes
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Note: Caller is responsible for clearing the msg data structure before
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * calling this function.
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Note: Caller must free temporary memory allocations by calling
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_parse_free() when the parsed data is not needed anymore.
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_parse_ies(const u8 *data, size_t len, struct p2p_message *msg)
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ieee802_11_elems elems;
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ieee802_11_parse_elems(data, len, &elems, 0);
5309d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt	if (elems.ds_params)
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->ds_params = elems.ds_params;
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (elems.ssid)
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg->ssid = elems.ssid - 2;
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg->wps_attributes = ieee802_11_vendor_ie_concat(data, len,
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							  WPS_DEV_OUI_WFA);
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->wps_attributes &&
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    p2p_parse_wps_ie(msg->wps_attributes, msg)) {
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(msg);
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg->p2p_attributes = ieee802_11_vendor_ie_concat(data, len,
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							  P2P_IE_VENDOR_TYPE);
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg->p2p_attributes &&
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    p2p_parse_p2p_ie(msg->p2p_attributes, msg)) {
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Failed to parse P2P IE data");
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (msg->p2p_attributes)
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump_buf(MSG_MSGDUMP, "P2P: P2P IE data",
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					msg->p2p_attributes);
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(msg);
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
55561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
55661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (elems.wfd) {
55761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		msg->wfd_subelems = ieee802_11_vendor_ie_concat(
55861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			data, len, WFD_IE_VENDOR_TYPE);
55961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
56061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
56161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
562d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	msg->pref_freq_list = elems.pref_freq_list;
563d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	msg->pref_freq_list_len = elems.pref_freq_list_len;
564d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_parse - Parse a P2P Action frame contents
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Action frame payload after Category and Code fields
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Length of data buffer in octets
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @msg: Buffer for returning parsed attributes
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Note: Caller must free temporary memory allocations by calling
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_parse_free() when the parsed data is not needed anymore.
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_parse(const u8 *data, size_t len, struct p2p_message *msg)
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(msg, 0, sizeof(*msg));
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Parsing the received message");
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1) {
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: No Dialog Token in the message");
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg->dialog_token = data[0];
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: * Dialog Token: %d", msg->dialog_token);
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return p2p_parse_ies(data + 1, len - 1, msg);
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
594cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtint p2p_parse_ies_separate(const u8 *wsc, size_t wsc_len, const u8 *p2p,
595cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			   size_t p2p_len, struct p2p_message *msg)
596cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{
597cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	os_memset(msg, 0, sizeof(*msg));
598cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
599cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	msg->wps_attributes = wpabuf_alloc_copy(wsc, wsc_len);
600cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (msg->wps_attributes &&
601cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	    p2p_parse_wps_ie(msg->wps_attributes, msg)) {
602cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_parse_free(msg);
603cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		return -1;
604cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
605cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
606cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	msg->p2p_attributes = wpabuf_alloc_copy(p2p, p2p_len);
607cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (msg->p2p_attributes &&
608cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	    p2p_parse_p2p_ie(msg->p2p_attributes, msg)) {
609cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Failed to parse P2P IE data");
610cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		if (msg->p2p_attributes)
611cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			wpa_hexdump_buf(MSG_MSGDUMP, "P2P: P2P IE data",
612cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					msg->p2p_attributes);
613cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_parse_free(msg);
614cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		return -1;
615cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
616cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
617cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	return 0;
618cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt}
619cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
620cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_parse_free - Free temporary data from P2P parsing
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @msg: Parsed attributes
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_parse_free(struct p2p_message *msg)
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(msg->p2p_attributes);
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg->p2p_attributes = NULL;
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(msg->wps_attributes);
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg->wps_attributes = NULL;
63161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
63261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(msg->wfd_subelems);
63361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	msg->wfd_subelems = NULL;
63461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_group_info_parse(const u8 *gi, size_t gi_len,
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 struct p2p_group_info *info)
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *g, *gend;
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(info, 0, sizeof(*info));
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gi == NULL)
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	g = gi;
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gend = gi + gi_len;
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (g < gend) {
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct p2p_client_info *cli;
651d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		const u8 *cend;
652d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		u16 count;
653d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		u8 len;
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cli = &info->client[info->num_clients];
656d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		len = *g++;
657d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (len > gend - g || len < 2 * ETH_ALEN + 1 + 2 + 8 + 1)
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1; /* invalid data */
659d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		cend = g + len;
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* g at start of P2P Client Info Descriptor */
661d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		cli->p2p_device_addr = g;
662d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		g += ETH_ALEN;
663d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		cli->p2p_interface_addr = g;
664d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		g += ETH_ALEN;
665d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		cli->dev_capab = *g++;
666d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
667d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		cli->config_methods = WPA_GET_BE16(g);
668d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		g += 2;
669d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		cli->pri_dev_type = g;
670d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		g += 8;
671d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
672d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		/* g at Number of Secondary Device Types */
673d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		len = *g++;
674d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (8 * len > cend - g)
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1; /* invalid data */
676d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		cli->num_sec_dev_types = len;
677d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		cli->sec_dev_types = g;
678d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		g += 8 * len;
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
680d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		/* g at Device Name in WPS TLV format */
681d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (cend - g < 2 + 2)
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1; /* invalid data */
683d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (WPA_GET_BE16(g) != ATTR_DEV_NAME)
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1; /* invalid Device Name TLV */
685d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		g += 2;
686d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		count = WPA_GET_BE16(g);
687d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		g += 2;
688d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (count > cend - g)
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1; /* invalid Device Name TLV */
6909d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt		if (count >= WPS_DEV_NAME_MAX_LEN)
6919d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt			count = WPS_DEV_NAME_MAX_LEN;
692d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		cli->dev_name = (const char *) g;
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cli->dev_name_len = count;
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		g = cend;
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		info->num_clients++;
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (info->num_clients == P2P_MAX_GROUP_ENTRIES)
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_group_info_text(const u8 *gi, size_t gi_len, char *buf,
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       char *end)
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *pos = buf;
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_info info;
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int i;
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_group_info_parse(gi, gi_len, &info) < 0)
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < info.num_clients; i++) {
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct p2p_client_info *cli;
7199d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt		char name[WPS_DEV_NAME_MAX_LEN + 1];
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char devtype[WPS_DEV_TYPE_BUFSIZE];
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 s;
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int count;
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cli = &info.client[i];
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(pos, end - pos, "p2p_group_client: "
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "dev=" MACSTR " iface=" MACSTR,
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  MAC2STR(cli->p2p_device_addr),
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  MAC2STR(cli->p2p_interface_addr));
7296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (os_snprintf_error(end - pos, ret))
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos - buf;
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ret;
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(pos, end - pos,
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  " dev_capab=0x%x config_methods=0x%x "
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "dev_type=%s",
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  cli->dev_capab, cli->config_methods,
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  wps_dev_type_bin2str(cli->pri_dev_type,
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       devtype,
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       sizeof(devtype)));
7406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (os_snprintf_error(end - pos, ret))
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos - buf;
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ret;
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (s = 0; s < cli->num_sec_dev_types; s++) {
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = os_snprintf(pos, end - pos, " dev_type=%s",
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  wps_dev_type_bin2str(
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						  &cli->sec_dev_types[s * 8],
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						  devtype, sizeof(devtype)));
7496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			if (os_snprintf_error(end - pos, ret))
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return pos - buf;
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += ret;
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(name, cli->dev_name, cli->dev_name_len);
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		name[cli->dev_name_len] = '\0';
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		count = (int) cli->dev_name_len - 1;
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (count >= 0) {
7589d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt			if (is_ctrl_char(name[count]))
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				name[count] = '_';
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			count--;
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(pos, end - pos, " dev_name='%s'\n", name);
7646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (os_snprintf_error(end - pos, ret))
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos - buf;
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ret;
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return pos - buf;
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_attr_text - Build text format description of P2P IE attributes
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: P2P IE contents
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Buffer for returning text
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @end: Pointer to the end of the buf area
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Number of octets written to the buffer or -1 on faikure
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function can be used to parse P2P IE contents into text format
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * field=value lines.
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_attr_text(struct wpabuf *data, char *buf, char *end)
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *pos = buf;
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_p2p_ie(data, &msg))
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.capability) {
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(pos, end - pos,
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "p2p_dev_capab=0x%x\n"
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "p2p_group_capab=0x%x\n",
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  msg.capability[0], msg.capability[1]);
7986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (os_snprintf_error(end - pos, ret))
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos - buf;
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ret;
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.pri_dev_type) {
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char devtype[WPS_DEV_TYPE_BUFSIZE];
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(pos, end - pos,
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "p2p_primary_device_type=%s\n",
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  wps_dev_type_bin2str(msg.pri_dev_type,
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       devtype,
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       sizeof(devtype)));
8106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (os_snprintf_error(end - pos, ret))
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos - buf;
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ret;
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = os_snprintf(pos, end - pos, "p2p_device_name=%s\n",
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg.device_name);
8176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_snprintf_error(end - pos, ret))
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return pos - buf;
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += ret;
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.p2p_device_addr) {
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(pos, end - pos, "p2p_device_addr=" MACSTR
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "\n",
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  MAC2STR(msg.p2p_device_addr));
8256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (os_snprintf_error(end - pos, ret))
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos - buf;
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ret;
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = os_snprintf(pos, end - pos, "p2p_config_methods=0x%x\n",
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  msg.config_methods);
8326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_snprintf_error(end - pos, ret))
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return pos - buf;
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += ret;
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = p2p_group_info_text(msg.group_info, msg.group_info_len,
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  pos, end);
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret < 0)
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return pos - buf;
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += ret;
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return pos - buf;
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_get_cross_connect_disallowed(const struct wpabuf *p2p_ie)
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_p2p_ie(p2p_ie, &msg))
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!msg.manageability)
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return !(msg.manageability[0] & P2P_MAN_CROSS_CONNECTION_PERMITTED);
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu8 p2p_get_group_capab(const struct wpabuf *p2p_ie)
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_p2p_ie(p2p_ie, &msg))
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!msg.capability)
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return msg.capability[1];
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * p2p_get_go_dev_addr(const struct wpabuf *p2p_ie)
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_p2p_ie(p2p_ie, &msg))
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.p2p_device_addr)
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return msg.p2p_device_addr;
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.device_id)
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return msg.device_id;
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
891