• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * P2P - IE parser
3  * Copyright (c) 2009-2010, Atheros Communications
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "includes.h"
10 
11 #include "common.h"
12 #include "common/ieee802_11_defs.h"
13 #include "common/ieee802_11_common.h"
14 #include "wps/wps_i.h"
15 #include "p2p_i.h"
16 
17 
p2p_copy_filter_devname(char * dst,size_t dst_len,const void * src,size_t src_len)18 void p2p_copy_filter_devname(char *dst, size_t dst_len,
19 			     const void *src, size_t src_len)
20 {
21 	size_t i;
22 
23 	if (src_len >= dst_len)
24 		src_len = dst_len - 1;
25 	os_memcpy(dst, src, src_len);
26 	dst[src_len] = '\0';
27 	for (i = 0; i < src_len; i++) {
28 		if (dst[i] == '\0')
29 			break;
30 		if (is_ctrl_char(dst[i]))
31 			dst[i] = '_';
32 	}
33 }
34 
35 
p2p_parse_attribute(u8 id,const u8 * data,u16 len,struct p2p_message * msg)36 static int p2p_parse_attribute(u8 id, const u8 *data, u16 len,
37 			       struct p2p_message *msg)
38 {
39 	const u8 *pos;
40 	u16 nlen;
41 	char devtype[WPS_DEV_TYPE_BUFSIZE];
42 
43 	switch (id) {
44 	case P2P_ATTR_CAPABILITY:
45 		if (len < 2) {
46 			wpa_printf(MSG_INFO, "P2P: Too short Capability "
47 				   "attribute (length %d)", len);
48 			return -1;
49 		}
50 		msg->capability = data;
51 		wpa_printf(MSG_EXCESSIVE, "P2P: * Device Capability %02x "
52 			   "Group Capability %02x",
53 			   data[0], data[1]);
54 		break;
55 	case P2P_ATTR_DEVICE_ID:
56 		if (len < ETH_ALEN) {
57 			wpa_printf(MSG_INFO, "P2P: Too short Device ID "
58 				   "attribute (length %d)", len);
59 			return -1;
60 		}
61 		msg->device_id = data;
62 		wpa_printf(MSG_EXCESSIVE, "P2P: * Device ID " MACSTR_SEC,
63 			   MAC2STR_SEC(msg->device_id));
64 		break;
65 	case P2P_ATTR_GROUP_OWNER_INTENT:
66 		if (len < 1) {
67 			wpa_printf(MSG_INFO, "P2P: Too short GO Intent "
68 				   "attribute (length %d)", len);
69 			return -1;
70 		}
71 		msg->go_intent = data;
72 		wpa_printf(MSG_WARNING, "P2P: * GO Intent: Intent %u "
73 			   "Tie breaker %u", data[0] >> 1, data[0] & 0x01);
74 		break;
75 	case P2P_ATTR_STATUS:
76 		if (len < 1) {
77 			wpa_printf(MSG_INFO, "P2P: Too short Status "
78 				   "attribute (length %d)", len);
79 			return -1;
80 		}
81 		msg->status = data;
82 		wpa_printf(MSG_EXCESSIVE, "P2P: * Status: %d", data[0]);
83 		break;
84 	case P2P_ATTR_LISTEN_CHANNEL:
85 		if (len == 0) {
86 			wpa_printf(MSG_INFO, "P2P: * Listen Channel: Ignore "
87 				   "null channel");
88 			break;
89 		}
90 		if (len < 5) {
91 			wpa_printf(MSG_INFO, "P2P: Too short Listen Channel "
92 				   "attribute (length %d)", len);
93 			return -1;
94 		}
95 		msg->listen_channel = data;
96 		if (has_ctrl_char(data, 2)) {
97 			wpa_printf(MSG_EXCESSIVE,
98 				   "P2P: * Listen Channel: Country(binary) %02x %02x (0x%02x) Regulatory Class %d Channel Number %d",
99 				   data[0], data[1], data[2], data[3], data[4]);
100 			break;
101 		}
102 		wpa_printf(MSG_EXCESSIVE, "P2P: * Listen Channel: "
103 			   "Country %c%c(0x%02x) Regulatory "
104 			   "Class %d Channel Number %d", data[0], data[1],
105 			   data[2], data[3], data[4]);
106 		break;
107 	case P2P_ATTR_OPERATING_CHANNEL:
108 		if (len == 0) {
109 			wpa_printf(MSG_INFO, "P2P: * Operating Channel: "
110 				   "Ignore null channel");
111 			break;
112 		}
113 		if (len < 5) {
114 			wpa_printf(MSG_INFO, "P2P: Too short Operating "
115 				   "Channel attribute (length %d)", len);
116 			return -1;
117 		}
118 		msg->operating_channel = data;
119 		if (has_ctrl_char(data, 2)) {
120 			wpa_printf(MSG_INFO,
121 				   "P2P: * Operating Channel: Country(binary) ** Regulatory Class %d Channel Number %d",
122 				   data[3], data[4]);
123 			break;
124 		}
125 		wpa_printf(MSG_DEBUG, "P2P: * Operating Channel: "
126 			   "Country ** Regulatory "
127 			   "Class %d Channel Number %d", data[3], data[4]);
128 		break;
129 	case P2P_ATTR_CHANNEL_LIST:
130 		if (len < 3) {
131 			wpa_printf(MSG_INFO, "P2P: Too short Channel List "
132 				   "attribute (length %d)", len);
133 			return -1;
134 		}
135 		msg->channel_list = data;
136 		msg->channel_list_len = len;
137 		if (has_ctrl_char(data, 2)) {
138 			wpa_printf(MSG_INFO,
139 				   "P2P: * Channel List: Country String (binary) ** (0x%02x)",
140 				   data[2]);
141 		} else {
142 			wpa_printf(MSG_INFO,
143 				   "P2P: * Channel List: Country String '**(0x%02x)'",
144 				   data[2]);
145 		}
146 		wpa_hexdump(MSG_MSGDUMP, "P2P: Channel List",
147 			    msg->channel_list, msg->channel_list_len);
148 		break;
149 	case P2P_ATTR_GROUP_INFO:
150 		msg->group_info = data;
151 		msg->group_info_len = len;
152 		wpa_printf(MSG_EXCESSIVE, "P2P: * Group Info");
153 		break;
154 	case P2P_ATTR_DEVICE_INFO:
155 		if (len < ETH_ALEN + 2 + 8 + 1) {
156 			wpa_printf(MSG_INFO, "P2P: Too short Device Info "
157 				   "attribute (length %d)", len);
158 			return -1;
159 		}
160 		msg->p2p_device_info = data;
161 		msg->p2p_device_info_len = len;
162 		pos = data;
163 		msg->p2p_device_addr = pos;
164 		pos += ETH_ALEN;
165 		msg->config_methods = WPA_GET_BE16(pos);
166 		pos += 2;
167 		msg->pri_dev_type = pos;
168 		pos += 8;
169 		msg->num_sec_dev_types = *pos++;
170 		if (msg->num_sec_dev_types * 8 > data + len - pos) {
171 			wpa_printf(MSG_INFO, "P2P: Device Info underflow");
172 			return -1;
173 		}
174 		pos += msg->num_sec_dev_types * 8;
175 		if (data + len - pos < 4) {
176 			wpa_printf(MSG_INFO, "P2P: Invalid Device Name "
177 				   "length %d", (int) (data + len - pos));
178 			return -1;
179 		}
180 		if (WPA_GET_BE16(pos) != ATTR_DEV_NAME) {
181 			wpa_hexdump(MSG_INFO, "P2P: Unexpected Device Name "
182 				    "header", pos, 4);
183 			return -1;
184 		}
185 		pos += 2;
186 		nlen = WPA_GET_BE16(pos);
187 		pos += 2;
188 		if (nlen > data + len - pos || nlen > WPS_DEV_NAME_MAX_LEN) {
189 			wpa_printf(MSG_INFO, "P2P: Invalid Device Name "
190 				   "length %u (buf len %d)", nlen,
191 				   (int) (data + len - pos));
192 			return -1;
193 		}
194 		p2p_copy_filter_devname(msg->device_name,
195 					sizeof(msg->device_name), pos, nlen);
196 		wpa_printf(MSG_INFO, "P2P: * Device Info: addr " MACSTR_SEC
197 			   " primary device type %s device name '%s' "
198 			   "config methods 0x%x",
199 			   MAC2STR_SEC(msg->p2p_device_addr),
200 			   wps_dev_type_bin2str(msg->pri_dev_type, devtype,
201 						sizeof(devtype)),
202 			   anonymize_common(msg->device_name), msg->config_methods);
203 		break;
204 	case P2P_ATTR_CONFIGURATION_TIMEOUT:
205 		if (len < 2) {
206 			wpa_printf(MSG_DEBUG, "P2P: Too short Configuration "
207 				   "Timeout attribute (length %d)", len);
208 			return -1;
209 		}
210 		msg->config_timeout = data;
211 		wpa_printf(MSG_EXCESSIVE, "P2P: * Configuration Timeout");
212 		break;
213 	case P2P_ATTR_INTENDED_INTERFACE_ADDR:
214 		if (len < ETH_ALEN) {
215 			wpa_printf(MSG_DEBUG, "P2P: Too short Intended P2P "
216 				   "Interface Address attribute (length %d)",
217 				   len);
218 			return -1;
219 		}
220 		msg->intended_addr = data;
221 		wpa_printf(MSG_EXCESSIVE, "P2P: * Intended P2P Interface Address: "
222 			   MACSTR_SEC, MAC2STR_SEC(msg->intended_addr));
223 		break;
224 	case P2P_ATTR_GROUP_BSSID:
225 		if (len < ETH_ALEN) {
226 			wpa_printf(MSG_DEBUG, "P2P: Too short P2P Group BSSID "
227 				   "attribute (length %d)", len);
228 			return -1;
229 		}
230 		msg->group_bssid = data;
231 		wpa_printf(MSG_DEBUG, "P2P: * P2P Group BSSID: " MACSTR_SEC,
232 			   MAC2STR_SEC(msg->group_bssid));
233 		break;
234 	case P2P_ATTR_GROUP_ID:
235 		if (len < ETH_ALEN || len > ETH_ALEN + SSID_MAX_LEN) {
236 			wpa_printf(MSG_DEBUG, "P2P: Invalid P2P Group ID "
237 				   "attribute length %d", len);
238 			return -1;
239 		}
240 		msg->group_id = data;
241 		msg->group_id_len = len;
242 		wpa_printf(MSG_EXCESSIVE, "P2P: * P2P Group ID: Device Address "
243 			   MACSTR_SEC, MAC2STR_SEC(msg->group_id));
244 		wpa_hexdump_ascii(MSG_DEBUG, "P2P: * P2P Group ID: SSID",
245 				  msg->group_id + ETH_ALEN,
246 				  msg->group_id_len - ETH_ALEN);
247 		break;
248 	case P2P_ATTR_INVITATION_FLAGS:
249 		if (len < 1) {
250 			wpa_printf(MSG_DEBUG, "P2P: Too short Invitation "
251 				   "Flag attribute (length %d)", len);
252 			return -1;
253 		}
254 		msg->invitation_flags = data;
255 		wpa_printf(MSG_EXCESSIVE, "P2P: * Invitation Flags: bitmap 0x%x",
256 			   data[0]);
257 		break;
258 	case P2P_ATTR_MANAGEABILITY:
259 		if (len < 1) {
260 			wpa_printf(MSG_DEBUG, "P2P: Too short Manageability "
261 				   "attribute (length %d)", len);
262 			return -1;
263 		}
264 		msg->manageability = data;
265 		wpa_printf(MSG_EXCESSIVE, "P2P: * Manageability: bitmap 0x%x",
266 			   data[0]);
267 		break;
268 	case P2P_ATTR_NOTICE_OF_ABSENCE:
269 		if (len < 2) {
270 			wpa_printf(MSG_DEBUG, "P2P: Too short Notice of "
271 				   "Absence attribute (length %d)", len);
272 			return -1;
273 		}
274 		msg->noa = data;
275 		msg->noa_len = len;
276 		wpa_printf(MSG_EXCESSIVE, "P2P: * Notice of Absence");
277 		break;
278 	case P2P_ATTR_EXT_LISTEN_TIMING:
279 		if (len < 4) {
280 			wpa_printf(MSG_DEBUG, "P2P: Too short Extended Listen "
281 				   "Timing attribute (length %d)", len);
282 			return -1;
283 		}
284 		msg->ext_listen_timing = data;
285 		wpa_printf(MSG_EXCESSIVE, "P2P: * Extended Listen Timing "
286 			   "(period %u msec  interval %u msec)",
287 			   WPA_GET_LE16(msg->ext_listen_timing),
288 			   WPA_GET_LE16(msg->ext_listen_timing + 2));
289 		break;
290 	case P2P_ATTR_MINOR_REASON_CODE:
291 		if (len < 1) {
292 			wpa_printf(MSG_DEBUG, "P2P: Too short Minor Reason "
293 				   "Code attribute (length %d)", len);
294 			return -1;
295 		}
296 		msg->minor_reason_code = data;
297 		wpa_printf(MSG_EXCESSIVE, "P2P: * Minor Reason Code: %u",
298 			   *msg->minor_reason_code);
299 		break;
300 	case P2P_ATTR_OOB_GO_NEG_CHANNEL:
301 		if (len < 6) {
302 			wpa_printf(MSG_DEBUG, "P2P: Too short OOB GO Neg "
303 				   "Channel attribute (length %d)", len);
304 			return -1;
305 		}
306 		msg->oob_go_neg_channel = data;
307 		wpa_printf(MSG_DEBUG, "P2P: * OOB GO Neg Channel: "
308 			   "Country **(0x%02x) Operating Class %d "
309 			   "Channel Number %d Role %d",
310 			   data[2], data[3], data[4], data[5]);
311 		break;
312 	case P2P_ATTR_SERVICE_HASH:
313 		if (len < P2PS_HASH_LEN) {
314 			wpa_printf(MSG_DEBUG,
315 				   "P2P: Too short Service Hash (length %u)",
316 				   len);
317 			return -1;
318 		}
319 		msg->service_hash_count = len / P2PS_HASH_LEN;
320 		msg->service_hash = data;
321 		wpa_hexdump(MSG_EXCESSIVE, "P2P: * Service Hash(s)", data, len);
322 		break;
323 	case P2P_ATTR_SESSION_INFORMATION_DATA:
324 		msg->session_info = data;
325 		msg->session_info_len = len;
326 		wpa_printf(MSG_EXCESSIVE, "P2P: * Service Instance: %u bytes - %p",
327 			   len, data);
328 		break;
329 	case P2P_ATTR_CONNECTION_CAPABILITY:
330 		if (len < 1) {
331 			wpa_printf(MSG_DEBUG,
332 				   "P2P: Too short Connection Capability (length %u)",
333 				   len);
334 			return -1;
335 		}
336 		msg->conn_cap = data;
337 		wpa_printf(MSG_EXCESSIVE, "P2P: * Connection Capability: 0x%x",
338 			   *msg->conn_cap);
339 		break;
340 	case P2P_ATTR_ADVERTISEMENT_ID:
341 		if (len < 10) {
342 			wpa_printf(MSG_DEBUG,
343 				   "P2P: Too short Advertisement ID (length %u)",
344 				   len);
345 			return -1;
346 		}
347 		msg->adv_id = data;
348 		msg->adv_mac = &data[sizeof(u32)];
349 		wpa_printf(MSG_EXCESSIVE, "P2P: * Advertisement ID %x",
350 			   WPA_GET_LE32(data));
351 		break;
352 	case P2P_ATTR_ADVERTISED_SERVICE:
353 		if (len < 8) {
354 			wpa_printf(MSG_DEBUG,
355 				   "P2P: Too short Service Instance (length %u)",
356 				   len);
357 			return -1;
358 		}
359 		msg->adv_service_instance = data;
360 		msg->adv_service_instance_len = len;
361 		if (len <= 255 + 8) {
362 			char str[256];
363 			u8 namelen;
364 
365 			namelen = data[6];
366 			if (namelen > len - 7)
367 				break;
368 			os_memcpy(str, &data[7], namelen);
369 			str[namelen] = '\0';
370 			wpa_printf(MSG_DEBUG, "P2P: * Service Instance: %x-%s",
371 				   WPA_GET_LE32(data), str);
372 		} else {
373 			wpa_printf(MSG_DEBUG, "P2P: * Service Instance: %p",
374 				   data);
375 		}
376 		break;
377 	case P2P_ATTR_SESSION_ID:
378 		if (len < sizeof(u32) + ETH_ALEN) {
379 			wpa_printf(MSG_DEBUG,
380 				   "P2P: Too short Session ID Info (length %u)",
381 				   len);
382 			return -1;
383 		}
384 		msg->session_id = data;
385 		msg->session_mac = &data[sizeof(u32)];
386 		wpa_printf(MSG_EXCESSIVE, "P2P: * Session ID: %x " MACSTR_SEC,
387 			   WPA_GET_LE32(data), MAC2STR_SEC(msg->session_mac));
388 		break;
389 	case P2P_ATTR_FEATURE_CAPABILITY:
390 		if (!len) {
391 			wpa_printf(MSG_DEBUG,
392 				   "P2P: Too short Feature Capability (length %u)",
393 				   len);
394 			return -1;
395 		}
396 		msg->feature_cap = data;
397 		msg->feature_cap_len = len;
398 		wpa_printf(MSG_EXCESSIVE, "P2P: * Feature Cap (length=%u)", len);
399 		break;
400 	case P2P_ATTR_PERSISTENT_GROUP:
401 	{
402 		if (len < ETH_ALEN || len > ETH_ALEN + SSID_MAX_LEN) {
403 			wpa_printf(MSG_DEBUG,
404 				   "P2P: Invalid Persistent Group Info (length %u)",
405 				   len);
406 			return -1;
407 		}
408 
409 		msg->persistent_dev = data;
410 		msg->persistent_ssid_len = len - ETH_ALEN;
411 		msg->persistent_ssid = &data[ETH_ALEN];
412 		wpa_printf(MSG_DEBUG, "P2P: * Persistent Group: " MACSTR_SEC " %s",
413 			   MAC2STR_SEC(msg->persistent_dev),
414 			   anonymize_ssid(wpa_ssid_txt(msg->persistent_ssid,
415 					msg->persistent_ssid_len)));
416 		break;
417 	}
418 	default:
419 		wpa_printf(MSG_DEBUG, "P2P: Skipped unknown attribute %d "
420 			   "(length %d)", id, len);
421 		break;
422 	}
423 
424 	return 0;
425 }
426 
427 
428 /**
429  * p2p_parse_p2p_ie - Parse P2P IE
430  * @buf: Concatenated P2P IE(s) payload
431  * @msg: Buffer for returning parsed attributes
432  * Returns: 0 on success, -1 on failure
433  *
434  * Note: Caller is responsible for clearing the msg data structure before
435  * calling this function.
436  */
p2p_parse_p2p_ie(const struct wpabuf * buf,struct p2p_message * msg)437 int p2p_parse_p2p_ie(const struct wpabuf *buf, struct p2p_message *msg)
438 {
439 	const u8 *pos = wpabuf_head_u8(buf);
440 	const u8 *end = pos + wpabuf_len(buf);
441 
442 	wpa_printf(MSG_EXCESSIVE, "P2P: Parsing P2P IE");
443 
444 	while (pos < end) {
445 		u16 attr_len;
446 		u8 id;
447 
448 		if (end - pos < 3) {
449 			wpa_printf(MSG_DEBUG, "P2P: Invalid P2P attribute");
450 			return -1;
451 		}
452 		id = *pos++;
453 		attr_len = WPA_GET_LE16(pos);
454 		pos += 2;
455 		wpa_printf(MSG_EXCESSIVE, "P2P: Attribute %d length %u",
456 			   id, attr_len);
457 		if (attr_len > end - pos) {
458 			wpa_printf(MSG_DEBUG, "P2P: Attribute underflow "
459 				   "(len=%u left=%d)",
460 				   attr_len, (int) (end - pos));
461 			wpa_hexdump(MSG_MSGDUMP, "P2P: Data", pos, end - pos);
462 			return -1;
463 		}
464 		if (p2p_parse_attribute(id, pos, attr_len, msg))
465 			return -1;
466 		pos += attr_len;
467 	}
468 
469 	return 0;
470 }
471 
472 
p2p_parse_wps_ie(const struct wpabuf * buf,struct p2p_message * msg)473 static int p2p_parse_wps_ie(const struct wpabuf *buf, struct p2p_message *msg)
474 {
475 	struct wps_parse_attr attr;
476 	int i;
477 
478 	wpa_printf(MSG_EXCESSIVE, "P2P: Parsing WPS IE");
479 	if (wps_parse_msg(buf, &attr))
480 		return -1;
481 	if (attr.dev_name && attr.dev_name_len < sizeof(msg->device_name) &&
482 	    !msg->device_name[0])
483 		os_memcpy(msg->device_name, attr.dev_name, attr.dev_name_len);
484 	if (attr.config_methods) {
485 		msg->wps_config_methods =
486 			WPA_GET_BE16(attr.config_methods);
487 		wpa_printf(MSG_EXCESSIVE, "P2P: Config Methods (WPS): 0x%x",
488 			   msg->wps_config_methods);
489 	}
490 	if (attr.dev_password_id) {
491 		msg->dev_password_id = WPA_GET_BE16(attr.dev_password_id);
492 		wpa_printf(MSG_DEBUG, "P2P: Device Password ID: %d",
493 			   msg->dev_password_id);
494 		msg->dev_password_id_present = 1;
495 	}
496 	if (attr.primary_dev_type) {
497 		char devtype[WPS_DEV_TYPE_BUFSIZE];
498 		msg->wps_pri_dev_type = attr.primary_dev_type;
499 		wpa_printf(MSG_EXCESSIVE, "P2P: Primary Device Type (WPS): %s",
500 			   wps_dev_type_bin2str(msg->wps_pri_dev_type, devtype,
501 						sizeof(devtype)));
502 	}
503 	if (attr.sec_dev_type_list) {
504 		msg->wps_sec_dev_type_list = attr.sec_dev_type_list;
505 		msg->wps_sec_dev_type_list_len = attr.sec_dev_type_list_len;
506 	}
507 
508 	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
509 		msg->wps_vendor_ext[i] = attr.vendor_ext[i];
510 		msg->wps_vendor_ext_len[i] = attr.vendor_ext_len[i];
511 	}
512 
513 	msg->manufacturer = attr.manufacturer;
514 	msg->manufacturer_len = attr.manufacturer_len;
515 	msg->model_name = attr.model_name;
516 	msg->model_name_len = attr.model_name_len;
517 	msg->model_number = attr.model_number;
518 	msg->model_number_len = attr.model_number_len;
519 	msg->serial_number = attr.serial_number;
520 	msg->serial_number_len = attr.serial_number_len;
521 
522 	msg->oob_dev_password = attr.oob_dev_password;
523 	msg->oob_dev_password_len = attr.oob_dev_password_len;
524 
525 	return 0;
526 }
527 
528 
529 /**
530  * p2p_parse_ies - Parse P2P message IEs (both WPS and P2P IE)
531  * @data: IEs from the message
532  * @len: Length of data buffer in octets
533  * @msg: Buffer for returning parsed attributes
534  * Returns: 0 on success, -1 on failure
535  *
536  * Note: Caller is responsible for clearing the msg data structure before
537  * calling this function.
538  *
539  * Note: Caller must free temporary memory allocations by calling
540  * p2p_parse_free() when the parsed data is not needed anymore.
541  */
p2p_parse_ies(const u8 * data,size_t len,struct p2p_message * msg)542 int p2p_parse_ies(const u8 *data, size_t len, struct p2p_message *msg)
543 {
544 	struct ieee802_11_elems elems;
545 
546 	if (ieee802_11_parse_elems(data, len, &elems, 0) == ParseFailed)
547 		return -1;
548 
549 	if (elems.ds_params)
550 		msg->ds_params = elems.ds_params;
551 	if (elems.ssid)
552 		msg->ssid = elems.ssid - 2;
553 
554 	msg->wps_attributes = ieee802_11_vendor_ie_concat(data, len,
555 							  WPS_DEV_OUI_WFA);
556 	if (msg->wps_attributes &&
557 	    p2p_parse_wps_ie(msg->wps_attributes, msg)) {
558 		p2p_parse_free(msg);
559 		return -1;
560 	}
561 
562 	msg->p2p_attributes = ieee802_11_vendor_ie_concat(data, len,
563 							  P2P_IE_VENDOR_TYPE);
564 	if (msg->p2p_attributes &&
565 	    p2p_parse_p2p_ie(msg->p2p_attributes, msg)) {
566 		wpa_printf(MSG_DEBUG, "P2P: Failed to parse P2P IE data");
567 		if (msg->p2p_attributes)
568 			wpa_hexdump_buf(MSG_MSGDUMP, "P2P: P2P IE data",
569 					msg->p2p_attributes);
570 		p2p_parse_free(msg);
571 		return -1;
572 	}
573 
574 #ifdef CONFIG_WIFI_DISPLAY
575 	if (elems.wfd) {
576 		msg->wfd_subelems = ieee802_11_vendor_ie_concat(
577 			data, len, WFD_IE_VENDOR_TYPE);
578 	}
579 #endif /* CONFIG_WIFI_DISPLAY */
580 
581 	msg->pref_freq_list = elems.pref_freq_list;
582 	msg->pref_freq_list_len = elems.pref_freq_list_len;
583 
584 	return 0;
585 }
586 
587 
588 /**
589  * p2p_parse - Parse a P2P Action frame contents
590  * @data: Action frame payload after Category and Code fields
591  * @len: Length of data buffer in octets
592  * @msg: Buffer for returning parsed attributes
593  * Returns: 0 on success, -1 on failure
594  *
595  * Note: Caller must free temporary memory allocations by calling
596  * p2p_parse_free() when the parsed data is not needed anymore.
597  */
p2p_parse(const u8 * data,size_t len,struct p2p_message * msg)598 int p2p_parse(const u8 *data, size_t len, struct p2p_message *msg)
599 {
600 	os_memset(msg, 0, sizeof(*msg));
601 	wpa_printf(MSG_EXCESSIVE, "P2P: Parsing the received message");
602 	if (len < 1) {
603 		wpa_printf(MSG_DEBUG, "P2P: No Dialog Token in the message");
604 		return -1;
605 	}
606 	msg->dialog_token = data[0];
607 	wpa_printf(MSG_DEBUG, "P2P: * Dialog Token: %d", msg->dialog_token);
608 
609 	return p2p_parse_ies(data + 1, len - 1, msg);
610 }
611 
612 
p2p_parse_ies_separate(const u8 * wsc,size_t wsc_len,const u8 * p2p,size_t p2p_len,struct p2p_message * msg)613 int p2p_parse_ies_separate(const u8 *wsc, size_t wsc_len, const u8 *p2p,
614 			   size_t p2p_len, struct p2p_message *msg)
615 {
616 	os_memset(msg, 0, sizeof(*msg));
617 
618 	msg->wps_attributes = wpabuf_alloc_copy(wsc, wsc_len);
619 	if (msg->wps_attributes &&
620 	    p2p_parse_wps_ie(msg->wps_attributes, msg)) {
621 		p2p_parse_free(msg);
622 		return -1;
623 	}
624 
625 	msg->p2p_attributes = wpabuf_alloc_copy(p2p, p2p_len);
626 	if (msg->p2p_attributes &&
627 	    p2p_parse_p2p_ie(msg->p2p_attributes, msg)) {
628 		wpa_printf(MSG_DEBUG, "P2P: Failed to parse P2P IE data");
629 		if (msg->p2p_attributes)
630 			wpa_hexdump_buf(MSG_MSGDUMP, "P2P: P2P IE data",
631 					msg->p2p_attributes);
632 		p2p_parse_free(msg);
633 		return -1;
634 	}
635 
636 	return 0;
637 }
638 
639 
640 /**
641  * p2p_parse_free - Free temporary data from P2P parsing
642  * @msg: Parsed attributes
643  */
p2p_parse_free(struct p2p_message * msg)644 void p2p_parse_free(struct p2p_message *msg)
645 {
646 	wpabuf_free(msg->p2p_attributes);
647 	msg->p2p_attributes = NULL;
648 	wpabuf_free(msg->wps_attributes);
649 	msg->wps_attributes = NULL;
650 #ifdef CONFIG_WIFI_DISPLAY
651 	wpabuf_free(msg->wfd_subelems);
652 	msg->wfd_subelems = NULL;
653 #endif /* CONFIG_WIFI_DISPLAY */
654 }
655 
656 
p2p_group_info_parse(const u8 * gi,size_t gi_len,struct p2p_group_info * info)657 int p2p_group_info_parse(const u8 *gi, size_t gi_len,
658 			 struct p2p_group_info *info)
659 {
660 	const u8 *g, *gend;
661 
662 	os_memset(info, 0, sizeof(*info));
663 	if (gi == NULL)
664 		return 0;
665 
666 	g = gi;
667 	gend = gi + gi_len;
668 	while (g < gend) {
669 		struct p2p_client_info *cli;
670 		const u8 *cend;
671 		u16 count;
672 		u8 len;
673 
674 		cli = &info->client[info->num_clients];
675 		len = *g++;
676 		if (len > gend - g || len < 2 * ETH_ALEN + 1 + 2 + 8 + 1)
677 			return -1; /* invalid data */
678 		cend = g + len;
679 		/* g at start of P2P Client Info Descriptor */
680 		cli->p2p_device_addr = g;
681 		g += ETH_ALEN;
682 		cli->p2p_interface_addr = g;
683 		g += ETH_ALEN;
684 		cli->dev_capab = *g++;
685 
686 		cli->config_methods = WPA_GET_BE16(g);
687 		g += 2;
688 		cli->pri_dev_type = g;
689 		g += 8;
690 
691 		/* g at Number of Secondary Device Types */
692 		len = *g++;
693 		if (8 * len > cend - g)
694 			return -1; /* invalid data */
695 		cli->num_sec_dev_types = len;
696 		cli->sec_dev_types = g;
697 		g += 8 * len;
698 
699 		/* g at Device Name in WPS TLV format */
700 		if (cend - g < 2 + 2)
701 			return -1; /* invalid data */
702 		if (WPA_GET_BE16(g) != ATTR_DEV_NAME)
703 			return -1; /* invalid Device Name TLV */
704 		g += 2;
705 		count = WPA_GET_BE16(g);
706 		g += 2;
707 		if (count > cend - g)
708 			return -1; /* invalid Device Name TLV */
709 		if (count >= WPS_DEV_NAME_MAX_LEN)
710 			count = WPS_DEV_NAME_MAX_LEN;
711 		cli->dev_name = (const char *) g;
712 		cli->dev_name_len = count;
713 
714 		g = cend;
715 
716 		info->num_clients++;
717 		if (info->num_clients == P2P_MAX_GROUP_ENTRIES)
718 			return -1;
719 	}
720 
721 	return 0;
722 }
723 
724 
p2p_group_info_text(const u8 * gi,size_t gi_len,char * buf,char * end)725 static int p2p_group_info_text(const u8 *gi, size_t gi_len, char *buf,
726 			       char *end)
727 {
728 	char *pos = buf;
729 	int ret;
730 	struct p2p_group_info info;
731 	unsigned int i;
732 
733 	if (p2p_group_info_parse(gi, gi_len, &info) < 0)
734 		return 0;
735 
736 	for (i = 0; i < info.num_clients; i++) {
737 		struct p2p_client_info *cli;
738 		char name[WPS_DEV_NAME_MAX_LEN + 1];
739 		char devtype[WPS_DEV_TYPE_BUFSIZE];
740 		u8 s;
741 		int count;
742 
743 		cli = &info.client[i];
744 		ret = os_snprintf(pos, end - pos, "p2p_group_client: "
745 				  "dev=" MACSTR " iface=" MACSTR,
746 				  MAC2STR(cli->p2p_device_addr),
747 				  MAC2STR(cli->p2p_interface_addr));
748 		if (os_snprintf_error(end - pos, ret))
749 			return pos - buf;
750 		pos += ret;
751 
752 		ret = os_snprintf(pos, end - pos,
753 				  " dev_capab=0x%x config_methods=0x%x "
754 				  "dev_type=%s",
755 				  cli->dev_capab, cli->config_methods,
756 				  wps_dev_type_bin2str(cli->pri_dev_type,
757 						       devtype,
758 						       sizeof(devtype)));
759 		if (os_snprintf_error(end - pos, ret))
760 			return pos - buf;
761 		pos += ret;
762 
763 		for (s = 0; s < cli->num_sec_dev_types; s++) {
764 			ret = os_snprintf(pos, end - pos, " dev_type=%s",
765 					  wps_dev_type_bin2str(
766 						  &cli->sec_dev_types[s * 8],
767 						  devtype, sizeof(devtype)));
768 			if (os_snprintf_error(end - pos, ret))
769 				return pos - buf;
770 			pos += ret;
771 		}
772 
773 		os_memcpy(name, cli->dev_name, cli->dev_name_len);
774 		name[cli->dev_name_len] = '\0';
775 		count = (int) cli->dev_name_len - 1;
776 		while (count >= 0) {
777 			if (is_ctrl_char(name[count]))
778 				name[count] = '_';
779 			count--;
780 		}
781 
782 		ret = os_snprintf(pos, end - pos, " dev_name='%s'\n", name);
783 		if (os_snprintf_error(end - pos, ret))
784 			return pos - buf;
785 		pos += ret;
786 	}
787 
788 	return pos - buf;
789 }
790 
791 
792 /**
793  * p2p_attr_text - Build text format description of P2P IE attributes
794  * @data: P2P IE contents
795  * @buf: Buffer for returning text
796  * @end: Pointer to the end of the buf area
797  * Returns: Number of octets written to the buffer or -1 on faikure
798  *
799  * This function can be used to parse P2P IE contents into text format
800  * field=value lines.
801  */
p2p_attr_text(struct wpabuf * data,char * buf,char * end)802 int p2p_attr_text(struct wpabuf *data, char *buf, char *end)
803 {
804 	struct p2p_message msg;
805 	char *pos = buf;
806 	int ret;
807 
808 	os_memset(&msg, 0, sizeof(msg));
809 	if (p2p_parse_p2p_ie(data, &msg))
810 		return -1;
811 
812 	if (msg.capability) {
813 		ret = os_snprintf(pos, end - pos,
814 				  "p2p_dev_capab=0x%x\n"
815 				  "p2p_group_capab=0x%x\n",
816 				  msg.capability[0], msg.capability[1]);
817 		if (os_snprintf_error(end - pos, ret))
818 			return pos - buf;
819 		pos += ret;
820 	}
821 
822 	if (msg.pri_dev_type) {
823 		char devtype[WPS_DEV_TYPE_BUFSIZE];
824 		ret = os_snprintf(pos, end - pos,
825 				  "p2p_primary_device_type=%s\n",
826 				  wps_dev_type_bin2str(msg.pri_dev_type,
827 						       devtype,
828 						       sizeof(devtype)));
829 		if (os_snprintf_error(end - pos, ret))
830 			return pos - buf;
831 		pos += ret;
832 	}
833 
834 	ret = os_snprintf(pos, end - pos, "p2p_device_name=%s\n",
835 			  msg.device_name);
836 	if (os_snprintf_error(end - pos, ret))
837 		return pos - buf;
838 	pos += ret;
839 
840 	if (msg.p2p_device_addr) {
841 		ret = os_snprintf(pos, end - pos, "p2p_device_addr=" MACSTR
842 				  "\n",
843 				  MAC2STR(msg.p2p_device_addr));
844 		if (os_snprintf_error(end - pos, ret))
845 			return pos - buf;
846 		pos += ret;
847 	}
848 
849 	ret = os_snprintf(pos, end - pos, "p2p_config_methods=0x%x\n",
850 			  msg.config_methods);
851 	if (os_snprintf_error(end - pos, ret))
852 		return pos - buf;
853 	pos += ret;
854 
855 	ret = p2p_group_info_text(msg.group_info, msg.group_info_len,
856 				  pos, end);
857 	if (ret < 0)
858 		return pos - buf;
859 	pos += ret;
860 
861 	return pos - buf;
862 }
863 
864 
p2p_get_cross_connect_disallowed(const struct wpabuf * p2p_ie)865 int p2p_get_cross_connect_disallowed(const struct wpabuf *p2p_ie)
866 {
867 	struct p2p_message msg;
868 
869 	os_memset(&msg, 0, sizeof(msg));
870 	if (p2p_parse_p2p_ie(p2p_ie, &msg))
871 		return 0;
872 
873 	if (!msg.manageability)
874 		return 0;
875 
876 	return !(msg.manageability[0] & P2P_MAN_CROSS_CONNECTION_PERMITTED);
877 }
878 
879 
p2p_get_group_capab(const struct wpabuf * p2p_ie)880 u8 p2p_get_group_capab(const struct wpabuf *p2p_ie)
881 {
882 	struct p2p_message msg;
883 
884 	os_memset(&msg, 0, sizeof(msg));
885 	if (p2p_parse_p2p_ie(p2p_ie, &msg))
886 		return 0;
887 
888 	if (!msg.capability)
889 		return 0;
890 
891 	return msg.capability[1];
892 }
893 
894 
p2p_get_go_dev_addr(const struct wpabuf * p2p_ie)895 const u8 * p2p_get_go_dev_addr(const struct wpabuf *p2p_ie)
896 {
897 	struct p2p_message msg;
898 
899 	os_memset(&msg, 0, sizeof(msg));
900 	if (p2p_parse_p2p_ie(p2p_ie, &msg))
901 		return NULL;
902 
903 	if (msg.p2p_device_addr)
904 		return msg.p2p_device_addr;
905 	if (msg.device_id)
906 		return msg.device_id;
907 
908 	return NULL;
909 }
910