3 * Copyright (c) 2009-2010, Atheros Communications
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
18 #include "common/ieee802_11_defs.h"
19 #include "common/ieee802_11_common.h"
20 #include "wps/wps_i.h"
24 static int p2p_parse_attribute(u8 id
, const u8
*data
, u16 len
,
25 struct p2p_message
*msg
)
29 char devtype
[WPS_DEV_TYPE_BUFSIZE
];
32 case P2P_ATTR_CAPABILITY
:
34 wpa_printf(MSG_DEBUG
, "P2P: Too short Capability "
35 "attribute (length %d)", len
);
38 msg
->capability
= data
;
39 wpa_printf(MSG_DEBUG
, "P2P: * Device Capability %02x "
40 "Group Capability %02x",
43 case P2P_ATTR_DEVICE_ID
:
45 wpa_printf(MSG_DEBUG
, "P2P: Too short Device ID "
46 "attribute (length %d)", len
);
49 msg
->device_id
= data
;
50 wpa_printf(MSG_DEBUG
, "P2P: * Device ID " MACSTR
,
51 MAC2STR(msg
->device_id
));
53 case P2P_ATTR_GROUP_OWNER_INTENT
:
55 wpa_printf(MSG_DEBUG
, "P2P: Too short GO Intent "
56 "attribute (length %d)", len
);
59 msg
->go_intent
= data
;
60 wpa_printf(MSG_DEBUG
, "P2P: * GO Intent: Intent %u "
61 "Tie breaker %u", data
[0] >> 1, data
[0] & 0x01);
65 wpa_printf(MSG_DEBUG
, "P2P: Too short Status "
66 "attribute (length %d)", len
);
70 wpa_printf(MSG_DEBUG
, "P2P: * Status: %d", data
[0]);
72 case P2P_ATTR_LISTEN_CHANNEL
:
74 wpa_printf(MSG_DEBUG
, "P2P: * Listen Channel: Ignore "
79 wpa_printf(MSG_DEBUG
, "P2P: Too short Listen Channel "
80 "attribute (length %d)", len
);
83 msg
->listen_channel
= data
;
84 wpa_printf(MSG_DEBUG
, "P2P: * Listen Channel: "
85 "Country %c%c(0x%02x) Regulatory "
86 "Class %d Channel Number %d", data
[0], data
[1],
87 data
[2], data
[3], data
[4]);
89 case P2P_ATTR_OPERATING_CHANNEL
:
91 wpa_printf(MSG_DEBUG
, "P2P: * Operating Channel: "
92 "Ignore null channel");
96 wpa_printf(MSG_DEBUG
, "P2P: Too short Operating "
97 "Channel attribute (length %d)", len
);
100 msg
->operating_channel
= data
;
101 wpa_printf(MSG_DEBUG
, "P2P: * Operating Channel: "
102 "Country %c%c(0x%02x) Regulatory "
103 "Class %d Channel Number %d", data
[0], data
[1],
104 data
[2], data
[3], data
[4]);
106 case P2P_ATTR_CHANNEL_LIST
:
108 wpa_printf(MSG_DEBUG
, "P2P: Too short Channel List "
109 "attribute (length %d)", len
);
112 msg
->channel_list
= data
;
113 msg
->channel_list_len
= len
;
114 wpa_printf(MSG_DEBUG
, "P2P: * Channel List: Country String "
115 "'%c%c(0x%02x)'", data
[0], data
[1], data
[2]);
116 wpa_hexdump(MSG_MSGDUMP
, "P2P: Channel List",
117 msg
->channel_list
, msg
->channel_list_len
);
119 case P2P_ATTR_GROUP_INFO
:
120 msg
->group_info
= data
;
121 msg
->group_info_len
= len
;
122 wpa_printf(MSG_DEBUG
, "P2P: * Group Info");
124 case P2P_ATTR_DEVICE_INFO
:
125 if (len
< ETH_ALEN
+ 2 + 8 + 1) {
126 wpa_printf(MSG_DEBUG
, "P2P: Too short Device Info "
127 "attribute (length %d)", len
);
130 msg
->p2p_device_info
= data
;
131 msg
->p2p_device_info_len
= len
;
133 msg
->p2p_device_addr
= pos
;
135 msg
->config_methods
= WPA_GET_BE16(pos
);
137 msg
->pri_dev_type
= pos
;
139 msg
->num_sec_dev_types
= *pos
++;
140 if (msg
->num_sec_dev_types
* 8 > data
+ len
- pos
) {
141 wpa_printf(MSG_DEBUG
, "P2P: Device Info underflow");
144 pos
+= msg
->num_sec_dev_types
* 8;
145 if (data
+ len
- pos
< 4) {
146 wpa_printf(MSG_DEBUG
, "P2P: Invalid Device Name "
147 "length %d", (int) (data
+ len
- pos
));
150 if (WPA_GET_BE16(pos
) != ATTR_DEV_NAME
) {
151 wpa_hexdump(MSG_DEBUG
, "P2P: Unexpected Device Name "
156 nlen
= WPA_GET_BE16(pos
);
158 if (data
+ len
- pos
< (int) nlen
|| nlen
> 32) {
159 wpa_printf(MSG_DEBUG
, "P2P: Invalid Device Name "
160 "length %d (buf len %d)", (int) nlen
,
161 (int) (data
+ len
- pos
));
164 os_memcpy(msg
->device_name
, pos
, nlen
);
165 for (i
= 0; i
< nlen
; i
++) {
166 if (msg
->device_name
[i
] == '\0')
168 if (msg
->device_name
[i
] < 32)
169 msg
->device_name
[i
] = '_';
171 wpa_printf(MSG_DEBUG
, "P2P: * Device Info: addr " MACSTR
172 " primary device type %s device name '%s' "
173 "config methods 0x%x",
174 MAC2STR(msg
->p2p_device_addr
),
175 wps_dev_type_bin2str(msg
->pri_dev_type
, devtype
,
177 msg
->device_name
, msg
->config_methods
);
179 case P2P_ATTR_CONFIGURATION_TIMEOUT
:
181 wpa_printf(MSG_DEBUG
, "P2P: Too short Configuration "
182 "Timeout attribute (length %d)", len
);
185 msg
->config_timeout
= data
;
186 wpa_printf(MSG_DEBUG
, "P2P: * Configuration Timeout");
188 case P2P_ATTR_INTENDED_INTERFACE_ADDR
:
189 if (len
< ETH_ALEN
) {
190 wpa_printf(MSG_DEBUG
, "P2P: Too short Intended P2P "
191 "Interface Address attribute (length %d)",
195 msg
->intended_addr
= data
;
196 wpa_printf(MSG_DEBUG
, "P2P: * Intended P2P Interface Address: "
197 MACSTR
, MAC2STR(msg
->intended_addr
));
199 case P2P_ATTR_GROUP_BSSID
:
200 if (len
< ETH_ALEN
) {
201 wpa_printf(MSG_DEBUG
, "P2P: Too short P2P Group BSSID "
202 "attribute (length %d)", len
);
205 msg
->group_bssid
= data
;
206 wpa_printf(MSG_DEBUG
, "P2P: * P2P Group BSSID: " MACSTR
,
207 MAC2STR(msg
->group_bssid
));
209 case P2P_ATTR_GROUP_ID
:
210 if (len
< ETH_ALEN
|| len
> ETH_ALEN
+ 32) {
211 wpa_printf(MSG_DEBUG
, "P2P: Invalid P2P Group ID "
212 "attribute length %d", len
);
215 msg
->group_id
= data
;
216 msg
->group_id_len
= len
;
217 wpa_printf(MSG_DEBUG
, "P2P: * P2P Group ID: Device Address "
218 MACSTR
, MAC2STR(msg
->group_id
));
219 wpa_hexdump_ascii(MSG_DEBUG
, "P2P: * P2P Group ID: SSID",
220 msg
->group_id
+ ETH_ALEN
,
221 msg
->group_id_len
- ETH_ALEN
);
223 case P2P_ATTR_INVITATION_FLAGS
:
225 wpa_printf(MSG_DEBUG
, "P2P: Too short Invitation "
226 "Flag attribute (length %d)", len
);
229 msg
->invitation_flags
= data
;
230 wpa_printf(MSG_DEBUG
, "P2P: * Invitation Flags: bitmap 0x%x",
233 case P2P_ATTR_MANAGEABILITY
:
235 wpa_printf(MSG_DEBUG
, "P2P: Too short Manageability "
236 "attribute (length %d)", len
);
239 msg
->manageability
= data
;
240 wpa_printf(MSG_DEBUG
, "P2P: * Manageability: bitmap 0x%x",
243 case P2P_ATTR_NOTICE_OF_ABSENCE
:
245 wpa_printf(MSG_DEBUG
, "P2P: Too short Notice of "
246 "Absence attribute (length %d)", len
);
251 wpa_printf(MSG_DEBUG
, "P2P: * Notice of Absence");
253 case P2P_ATTR_EXT_LISTEN_TIMING
:
255 wpa_printf(MSG_DEBUG
, "P2P: Too short Extended Listen "
256 "Timing attribute (length %d)", len
);
259 msg
->ext_listen_timing
= data
;
260 wpa_printf(MSG_DEBUG
, "P2P: * Extended Listen Timing "
261 "(period %u msec interval %u msec)",
262 WPA_GET_LE16(msg
->ext_listen_timing
),
263 WPA_GET_LE16(msg
->ext_listen_timing
+ 2));
265 case P2P_ATTR_MINOR_REASON_CODE
:
267 wpa_printf(MSG_DEBUG
, "P2P: Too short Minor Reason "
268 "Code attribute (length %d)", len
);
271 msg
->minor_reason_code
= data
;
272 wpa_printf(MSG_DEBUG
, "P2P: * Minor Reason Code: %u",
273 *msg
->minor_reason_code
);
276 wpa_printf(MSG_DEBUG
, "P2P: Skipped unknown attribute %d "
277 "(length %d)", id
, len
);
286 * p2p_parse_p2p_ie - Parse P2P IE
287 * @buf: Concatenated P2P IE(s) payload
288 * @msg: Buffer for returning parsed attributes
289 * Returns: 0 on success, -1 on failure
291 * Note: Caller is responsible for clearing the msg data structure before
292 * calling this function.
294 int p2p_parse_p2p_ie(const struct wpabuf
*buf
, struct p2p_message
*msg
)
296 const u8
*pos
= wpabuf_head_u8(buf
);
297 const u8
*end
= pos
+ wpabuf_len(buf
);
299 wpa_printf(MSG_DEBUG
, "P2P: Parsing P2P IE");
303 if (pos
+ 2 >= end
) {
304 wpa_printf(MSG_DEBUG
, "P2P: Invalid P2P attribute");
307 attr_len
= WPA_GET_LE16(pos
+ 1);
308 wpa_printf(MSG_DEBUG
, "P2P: Attribute %d length %u",
310 if (pos
+ 3 + attr_len
> end
) {
311 wpa_printf(MSG_DEBUG
, "P2P: Attribute underflow "
313 attr_len
, (int) (end
- pos
- 3));
314 wpa_hexdump(MSG_MSGDUMP
, "P2P: Data", pos
, end
- pos
);
317 if (p2p_parse_attribute(pos
[0], pos
+ 3, attr_len
, msg
))
326 static int p2p_parse_wps_ie(const struct wpabuf
*buf
, struct p2p_message
*msg
)
328 struct wps_parse_attr attr
;
330 wpa_printf(MSG_DEBUG
, "P2P: Parsing WPS IE");
331 if (wps_parse_msg(buf
, &attr
))
333 if (attr
.dev_name
&& attr
.dev_name_len
< sizeof(msg
->device_name
) &&
334 !msg
->device_name
[0])
335 os_memcpy(msg
->device_name
, attr
.dev_name
, attr
.dev_name_len
);
336 if (attr
.config_methods
) {
337 msg
->wps_config_methods
=
338 WPA_GET_BE16(attr
.config_methods
);
339 wpa_printf(MSG_DEBUG
, "P2P: Config Methods (WPS): 0x%x",
340 msg
->wps_config_methods
);
342 if (attr
.dev_password_id
) {
343 msg
->dev_password_id
= WPA_GET_BE16(attr
.dev_password_id
);
344 wpa_printf(MSG_DEBUG
, "P2P: Device Password ID: %d",
345 msg
->dev_password_id
);
347 if (attr
.primary_dev_type
) {
348 char devtype
[WPS_DEV_TYPE_BUFSIZE
];
349 msg
->wps_pri_dev_type
= attr
.primary_dev_type
;
350 wpa_printf(MSG_DEBUG
, "P2P: Primary Device Type (WPS): %s",
351 wps_dev_type_bin2str(msg
->wps_pri_dev_type
, devtype
,
360 * p2p_parse_ies - Parse P2P message IEs (both WPS and P2P IE)
361 * @data: IEs from the message
362 * @len: Length of data buffer in octets
363 * @msg: Buffer for returning parsed attributes
364 * Returns: 0 on success, -1 on failure
366 * Note: Caller is responsible for clearing the msg data structure before
367 * calling this function.
369 * Note: Caller must free temporary memory allocations by calling
370 * p2p_parse_free() when the parsed data is not needed anymore.
372 int p2p_parse_ies(const u8
*data
, size_t len
, struct p2p_message
*msg
)
374 struct ieee802_11_elems elems
;
376 ieee802_11_parse_elems(data
, len
, &elems
, 0);
377 if (elems
.ds_params
&& elems
.ds_params_len
>= 1)
378 msg
->ds_params
= elems
.ds_params
;
380 msg
->ssid
= elems
.ssid
- 2;
382 msg
->wps_attributes
= ieee802_11_vendor_ie_concat(data
, len
,
384 if (msg
->wps_attributes
&&
385 p2p_parse_wps_ie(msg
->wps_attributes
, msg
)) {
390 msg
->p2p_attributes
= ieee802_11_vendor_ie_concat(data
, len
,
392 if (msg
->p2p_attributes
&&
393 p2p_parse_p2p_ie(msg
->p2p_attributes
, msg
)) {
394 wpa_printf(MSG_DEBUG
, "P2P: Failed to parse P2P IE data");
395 if (msg
->p2p_attributes
)
396 wpa_hexdump_buf(MSG_MSGDUMP
, "P2P: P2P IE data",
397 msg
->p2p_attributes
);
407 * p2p_parse - Parse a P2P Action frame contents
408 * @data: Action frame payload after Category and Code fields
409 * @len: Length of data buffer in octets
410 * @msg: Buffer for returning parsed attributes
411 * Returns: 0 on success, -1 on failure
413 * Note: Caller must free temporary memory allocations by calling
414 * p2p_parse_free() when the parsed data is not needed anymore.
416 int p2p_parse(const u8
*data
, size_t len
, struct p2p_message
*msg
)
418 os_memset(msg
, 0, sizeof(*msg
));
419 wpa_printf(MSG_DEBUG
, "P2P: Parsing the received message");
421 wpa_printf(MSG_DEBUG
, "P2P: No Dialog Token in the message");
424 msg
->dialog_token
= data
[0];
425 wpa_printf(MSG_DEBUG
, "P2P: * Dialog Token: %d", msg
->dialog_token
);
427 return p2p_parse_ies(data
+ 1, len
- 1, msg
);
432 * p2p_parse_free - Free temporary data from P2P parsing
433 * @msg: Parsed attributes
435 void p2p_parse_free(struct p2p_message
*msg
)
437 wpabuf_free(msg
->p2p_attributes
);
438 msg
->p2p_attributes
= NULL
;
439 wpabuf_free(msg
->wps_attributes
);
440 msg
->wps_attributes
= NULL
;
444 int p2p_group_info_parse(const u8
*gi
, size_t gi_len
,
445 struct p2p_group_info
*info
)
449 os_memset(info
, 0, sizeof(*info
));
456 struct p2p_client_info
*cli
;
460 cli
= &info
->client
[info
->num_clients
];
463 return -1; /* invalid data */
464 /* g at start of P2P Client Info Descriptor */
465 /* t at Device Capability Bitmap */
466 t
= g
+ 1 + 2 * ETH_ALEN
;
468 return -1; /* invalid data */
469 cli
->p2p_device_addr
= g
+ 1;
470 cli
->p2p_interface_addr
= g
+ 1 + ETH_ALEN
;
471 cli
->dev_capab
= t
[0];
473 if (t
+ 1 + 2 + 8 + 1 > cend
)
474 return -1; /* invalid data */
476 cli
->config_methods
= WPA_GET_BE16(&t
[1]);
477 cli
->pri_dev_type
= &t
[3];
480 /* t at Number of Secondary Device Types */
481 cli
->num_sec_dev_types
= *t
++;
482 if (t
+ 8 * cli
->num_sec_dev_types
> cend
)
483 return -1; /* invalid data */
484 cli
->sec_dev_types
= t
;
485 t
+= 8 * cli
->num_sec_dev_types
;
487 /* t at Device Name in WPS TLV format */
488 if (t
+ 2 + 2 > cend
)
489 return -1; /* invalid data */
490 if (WPA_GET_BE16(t
) != ATTR_DEV_NAME
)
491 return -1; /* invalid Device Name TLV */
493 count
= WPA_GET_BE16(t
);
495 if (count
> cend
- t
)
496 return -1; /* invalid Device Name TLV */
499 cli
->dev_name
= (const char *) t
;
500 cli
->dev_name_len
= count
;
505 if (info
->num_clients
== P2P_MAX_GROUP_ENTRIES
)
513 static int p2p_group_info_text(const u8
*gi
, size_t gi_len
, char *buf
,
518 struct p2p_group_info info
;
521 if (p2p_group_info_parse(gi
, gi_len
, &info
) < 0)
524 for (i
= 0; i
< info
.num_clients
; i
++) {
525 struct p2p_client_info
*cli
;
527 char devtype
[WPS_DEV_TYPE_BUFSIZE
];
531 cli
= &info
.client
[i
];
532 ret
= os_snprintf(pos
, end
- pos
, "p2p_group_client: "
533 "dev=" MACSTR
" iface=" MACSTR
,
534 MAC2STR(cli
->p2p_device_addr
),
535 MAC2STR(cli
->p2p_interface_addr
));
536 if (ret
< 0 || ret
>= end
- pos
)
540 ret
= os_snprintf(pos
, end
- pos
,
541 " dev_capab=0x%x config_methods=0x%x "
543 cli
->dev_capab
, cli
->config_methods
,
544 wps_dev_type_bin2str(cli
->pri_dev_type
,
547 if (ret
< 0 || ret
>= end
- pos
)
551 for (s
= 0; s
< cli
->num_sec_dev_types
; s
++) {
552 ret
= os_snprintf(pos
, end
- pos
, " dev_type=%s",
553 wps_dev_type_bin2str(
554 &cli
->sec_dev_types
[s
* 8],
555 devtype
, sizeof(devtype
)));
556 if (ret
< 0 || ret
>= end
- pos
)
561 os_memcpy(name
, cli
->dev_name
, cli
->dev_name_len
);
562 name
[cli
->dev_name_len
] = '\0';
563 count
= (int) cli
->dev_name_len
- 1;
565 if (name
[count
] < 32)
570 ret
= os_snprintf(pos
, end
- pos
, " dev_name='%s'\n", name
);
571 if (ret
< 0 || ret
>= end
- pos
)
581 * p2p_attr_text - Build text format description of P2P IE attributes
582 * @data: P2P IE contents
583 * @buf: Buffer for returning text
584 * @end: Pointer to the end of the buf area
585 * Returns: Number of octets written to the buffer or -1 on faikure
587 * This function can be used to parse P2P IE contents into text format
590 int p2p_attr_text(struct wpabuf
*data
, char *buf
, char *end
)
592 struct p2p_message msg
;
596 os_memset(&msg
, 0, sizeof(msg
));
597 if (p2p_parse_p2p_ie(data
, &msg
))
600 if (msg
.capability
) {
601 ret
= os_snprintf(pos
, end
- pos
,
602 "p2p_dev_capab=0x%x\n"
603 "p2p_group_capab=0x%x\n",
604 msg
.capability
[0], msg
.capability
[1]);
605 if (ret
< 0 || ret
>= end
- pos
)
610 if (msg
.pri_dev_type
) {
611 char devtype
[WPS_DEV_TYPE_BUFSIZE
];
612 ret
= os_snprintf(pos
, end
- pos
,
613 "p2p_primary_device_type=%s\n",
614 wps_dev_type_bin2str(msg
.pri_dev_type
,
617 if (ret
< 0 || ret
>= end
- pos
)
622 ret
= os_snprintf(pos
, end
- pos
, "p2p_device_name=%s\n",
624 if (ret
< 0 || ret
>= end
- pos
)
628 if (msg
.p2p_device_addr
) {
629 ret
= os_snprintf(pos
, end
- pos
, "p2p_device_addr=" MACSTR
631 MAC2STR(msg
.p2p_device_addr
));
632 if (ret
< 0 || ret
>= end
- pos
)
637 ret
= os_snprintf(pos
, end
- pos
, "p2p_config_methods=0x%x\n",
639 if (ret
< 0 || ret
>= end
- pos
)
643 ret
= p2p_group_info_text(msg
.group_info
, msg
.group_info_len
,
653 u8
p2p_get_group_capab(const struct wpabuf
*p2p_ie
)
655 struct p2p_message msg
;
657 os_memset(&msg
, 0, sizeof(msg
));
658 if (p2p_parse_p2p_ie(p2p_ie
, &msg
))
664 return msg
.capability
[1];
668 const u8
* p2p_get_go_dev_addr(const struct wpabuf
*p2p_ie
)
670 struct p2p_message msg
;
672 os_memset(&msg
, 0, sizeof(msg
));
673 if (p2p_parse_p2p_ie(p2p_ie
, &msg
))
676 if (msg
.p2p_device_addr
)
677 return msg
.p2p_device_addr
;
679 return msg
.device_id
;