2 * Wi-Fi Direct - P2P group operations
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_defs.h"
21 #include "wps/wps_i.h"
26 struct p2p_group_member
{
27 struct p2p_group_member
*next
;
28 u8 addr
[ETH_ALEN
]; /* P2P Interface Address */
29 u8 dev_addr
[ETH_ALEN
]; /* P2P Device Address */
30 struct wpabuf
*p2p_ie
;
31 struct wpabuf
*client_info
;
36 * struct p2p_group - Internal P2P module per-group data
40 struct p2p_group_config
*cfg
;
41 struct p2p_group_member
*members
;
42 unsigned int num_members
;
49 static void p2p_group_update_ies(struct p2p_group
*group
);
52 struct p2p_group
* p2p_group_init(struct p2p_data
*p2p
,
53 struct p2p_group_config
*config
)
55 struct p2p_group
*group
, **groups
;
57 group
= os_zalloc(sizeof(*group
));
61 groups
= os_realloc(p2p
->groups
, (p2p
->num_groups
+ 1) *
62 sizeof(struct p2p_group
*));
67 groups
[p2p
->num_groups
++] = group
;
72 group
->group_formation
= 1;
73 group
->beacon_update
= 1;
74 p2p_group_update_ies(group
);
75 group
->cfg
->idle_update(group
->cfg
->cb_ctx
, 1);
81 static void p2p_group_free_member(struct p2p_group_member
*m
)
83 wpabuf_free(m
->p2p_ie
);
84 wpabuf_free(m
->client_info
);
89 static void p2p_group_free_members(struct p2p_group
*group
)
91 struct p2p_group_member
*m
, *prev
;
93 group
->members
= NULL
;
94 group
->num_members
= 0;
98 p2p_group_free_member(prev
);
103 void p2p_group_deinit(struct p2p_group
*group
)
106 struct p2p_data
*p2p
;
113 for (g
= 0; g
< p2p
->num_groups
; g
++) {
114 if (p2p
->groups
[g
] == group
) {
115 while (g
+ 1 < p2p
->num_groups
) {
116 p2p
->groups
[g
] = p2p
->groups
[g
+ 1];
124 p2p_group_free_members(group
);
126 wpabuf_free(group
->noa
);
131 static void p2p_client_info(struct wpabuf
*ie
, struct p2p_group_member
*m
)
133 if (m
->client_info
== NULL
)
135 if (wpabuf_tailroom(ie
) < wpabuf_len(m
->client_info
) + 1)
137 wpabuf_put_buf(ie
, m
->client_info
);
141 static void p2p_group_add_common_ies(struct p2p_group
*group
,
144 u8 dev_capab
= 0, group_capab
= 0;
147 dev_capab
|= P2P_DEV_CAPAB_SERVICE_DISCOVERY
;
148 dev_capab
|= P2P_DEV_CAPAB_INVITATION_PROCEDURE
;
149 group_capab
|= P2P_GROUP_CAPAB_GROUP_OWNER
;
150 if (group
->cfg
->persistent_group
) {
151 group_capab
|= P2P_GROUP_CAPAB_PERSISTENT_GROUP
;
152 if (group
->cfg
->persistent_group
== 2)
153 group_capab
|= P2P_GROUP_CAPAB_PERSISTENT_RECONN
;
155 if (group
->p2p
->cfg
->p2p_intra_bss
)
156 group_capab
|= P2P_GROUP_CAPAB_INTRA_BSS_DIST
;
157 if (group
->group_formation
)
158 group_capab
|= P2P_GROUP_CAPAB_GROUP_FORMATION
;
159 if (group
->p2p
->cross_connect
)
160 group_capab
|= P2P_GROUP_CAPAB_CROSS_CONN
;
161 if (group
->num_members
>= group
->cfg
->max_clients
)
162 group_capab
|= P2P_GROUP_CAPAB_GROUP_LIMIT
;
163 p2p_buf_add_capability(ie
, dev_capab
, group_capab
);
167 static void p2p_group_add_noa(struct wpabuf
*ie
, struct wpabuf
*noa
)
171 /* Notice of Absence */
172 wpabuf_put_u8(ie
, P2P_ATTR_NOTICE_OF_ABSENCE
);
173 wpabuf_put_le16(ie
, wpabuf_len(noa
));
174 wpabuf_put_buf(ie
, noa
);
178 static struct wpabuf
* p2p_group_build_beacon_ie(struct p2p_group
*group
)
183 ie
= wpabuf_alloc(257);
187 len
= p2p_buf_add_ie_hdr(ie
);
188 p2p_group_add_common_ies(group
, ie
);
189 p2p_buf_add_device_id(ie
, group
->p2p
->cfg
->dev_addr
);
190 p2p_group_add_noa(ie
, group
->noa
);
191 p2p_buf_update_ie_hdr(ie
, len
);
197 static struct wpabuf
* p2p_group_build_probe_resp_ie(struct p2p_group
*group
)
201 struct p2p_group_member
*m
;
204 ie
= wpabuf_alloc(257);
208 len
= p2p_buf_add_ie_hdr(ie
);
210 p2p_group_add_common_ies(group
, ie
);
211 p2p_group_add_noa(ie
, group
->noa
);
213 /* P2P Device Info */
214 p2p_buf_add_device_info(ie
, group
->p2p
, NULL
);
217 group_info
= wpabuf_put(ie
, 0);
218 wpabuf_put_u8(ie
, P2P_ATTR_GROUP_INFO
);
219 wpabuf_put_le16(ie
, 0); /* Length to be filled */
220 for (m
= group
->members
; m
; m
= m
->next
)
221 p2p_client_info(ie
, m
);
222 WPA_PUT_LE16(group_info
+ 1,
223 (u8
*) wpabuf_put(ie
, 0) - group_info
- 3);
225 p2p_buf_update_ie_hdr(ie
, len
);
230 static void p2p_group_update_ies(struct p2p_group
*group
)
232 struct wpabuf
*beacon_ie
;
233 struct wpabuf
*probe_resp_ie
;
235 probe_resp_ie
= p2p_group_build_probe_resp_ie(group
);
236 if (probe_resp_ie
== NULL
)
238 wpa_hexdump_buf(MSG_MSGDUMP
, "P2P: Update GO Probe Response P2P IE",
241 if (group
->beacon_update
) {
242 beacon_ie
= p2p_group_build_beacon_ie(group
);
244 group
->beacon_update
= 0;
245 wpa_hexdump_buf(MSG_MSGDUMP
, "P2P: Update GO Beacon P2P IE",
250 group
->cfg
->ie_update(group
->cfg
->cb_ctx
, beacon_ie
, probe_resp_ie
);
255 * p2p_build_client_info - Build P2P Client Info Descriptor
256 * @addr: MAC address of the peer device
257 * @p2p_ie: P2P IE from (Re)Association Request
258 * @dev_capab: Buffer for returning Device Capability
259 * @dev_addr: Buffer for returning P2P Device Address
260 * Returns: P2P Client Info Descriptor or %NULL on failure
262 * This function builds P2P Client Info Descriptor based on the information
263 * available from (Re)Association Request frame. Group owner can use this to
264 * build the P2P Group Info attribute for Probe Response frames.
266 static struct wpabuf
* p2p_build_client_info(const u8
*addr
,
267 struct wpabuf
*p2p_ie
,
268 u8
*dev_capab
, u8
*dev_addr
)
271 struct p2p_message msg
;
278 os_memset(&msg
, 0, sizeof(msg
));
279 if (p2p_parse_p2p_ie(p2p_ie
, &msg
) ||
280 msg
.capability
== NULL
|| msg
.p2p_device_info
== NULL
)
283 buf
= wpabuf_alloc(ETH_ALEN
+ 1 + 1 + msg
.p2p_device_info_len
);
287 *dev_capab
= msg
.capability
[0];
288 os_memcpy(dev_addr
, msg
.p2p_device_addr
, ETH_ALEN
);
290 spos
= msg
.p2p_device_info
; /* P2P Device address */
292 /* P2P Client Info Descriptor */
293 /* Length to be set */
294 len_pos
= wpabuf_put(buf
, 1);
295 /* P2P Device address */
296 wpabuf_put_data(buf
, spos
, ETH_ALEN
);
297 /* P2P Interface address */
298 wpabuf_put_data(buf
, addr
, ETH_ALEN
);
299 /* Device Capability Bitmap */
300 wpabuf_put_u8(buf
, msg
.capability
[0]);
302 * Config Methods, Primary Device Type, Number of Secondary Device
303 * Types, Secondary Device Type List, Device Name copied from
306 wpabuf_put_data(buf
, spos
+ ETH_ALEN
,
307 msg
.p2p_device_info_len
- ETH_ALEN
);
309 *len_pos
= wpabuf_len(buf
) - 1;
316 static int p2p_group_remove_member(struct p2p_group
*group
, const u8
*addr
)
318 struct p2p_group_member
*m
, *prev
;
326 if (os_memcmp(m
->addr
, addr
, ETH_ALEN
) == 0)
336 prev
->next
= m
->next
;
338 group
->members
= m
->next
;
339 p2p_group_free_member(m
);
340 group
->num_members
--;
346 int p2p_group_notif_assoc(struct p2p_group
*group
, const u8
*addr
,
347 const u8
*ie
, size_t len
)
349 struct p2p_group_member
*m
;
354 m
= os_zalloc(sizeof(*m
));
357 os_memcpy(m
->addr
, addr
, ETH_ALEN
);
358 m
->p2p_ie
= ieee802_11_vendor_ie_concat(ie
, len
, P2P_IE_VENDOR_TYPE
);
360 m
->client_info
= p2p_build_client_info(addr
, m
->p2p_ie
,
365 p2p_group_remove_member(group
, addr
);
367 m
->next
= group
->members
;
369 group
->num_members
++;
370 wpa_msg(group
->p2p
->cfg
->msg_ctx
, MSG_DEBUG
, "P2P: Add client " MACSTR
371 " to group (p2p=%d client_info=%d); num_members=%u/%u",
372 MAC2STR(addr
), m
->p2p_ie
? 1 : 0, m
->client_info
? 1 : 0,
373 group
->num_members
, group
->cfg
->max_clients
);
374 if (group
->num_members
== group
->cfg
->max_clients
)
375 group
->beacon_update
= 1;
376 p2p_group_update_ies(group
);
377 if (group
->num_members
== 1)
378 group
->cfg
->idle_update(group
->cfg
->cb_ctx
, 0);
384 struct wpabuf
* p2p_group_assoc_resp_ie(struct p2p_group
*group
, u8 status
)
390 * (Re)Association Response - P2P IE
391 * Status attribute (shall be present when association request is
393 * Extended Listen Timing (may be present)
395 resp
= wpabuf_alloc(20);
398 rlen
= p2p_buf_add_ie_hdr(resp
);
399 if (status
!= P2P_SC_SUCCESS
)
400 p2p_buf_add_status(resp
, status
);
401 p2p_buf_update_ie_hdr(resp
, rlen
);
407 void p2p_group_notif_disassoc(struct p2p_group
*group
, const u8
*addr
)
409 if (p2p_group_remove_member(group
, addr
)) {
410 wpa_msg(group
->p2p
->cfg
->msg_ctx
, MSG_DEBUG
, "P2P: Remove "
411 "client " MACSTR
" from group; num_members=%u/%u",
412 MAC2STR(addr
), group
->num_members
,
413 group
->cfg
->max_clients
);
414 if (group
->num_members
== group
->cfg
->max_clients
- 1)
415 group
->beacon_update
= 1;
416 p2p_group_update_ies(group
);
417 if (group
->num_members
== 0)
418 group
->cfg
->idle_update(group
->cfg
->cb_ctx
, 1);
424 * p2p_match_dev_type_member - Match client device type with requested type
426 * @wps: WPS TLVs from Probe Request frame (concatenated WPS IEs)
427 * Returns: 1 on match, 0 on mismatch
429 * This function can be used to match the Requested Device Type attribute in
430 * WPS IE with the device types of a group member for deciding whether a GO
431 * should reply to a Probe Request frame.
433 static int p2p_match_dev_type_member(struct p2p_group_member
*m
,
437 struct wps_parse_attr attr
;
440 if (m
->client_info
== NULL
|| wps
== NULL
)
443 pos
= wpabuf_head(m
->client_info
);
444 end
= pos
+ wpabuf_len(m
->client_info
);
446 pos
+= 1 + 2 * ETH_ALEN
+ 1 + 2;
447 if (end
- pos
< WPS_DEV_TYPE_LEN
+ 1)
450 if (wps_parse_msg(wps
, &attr
))
451 return 1; /* assume no Requested Device Type attributes */
453 if (attr
.num_req_dev_type
== 0)
454 return 1; /* no Requested Device Type attributes -> match */
456 if (dev_type_list_match(pos
, attr
.req_dev_type
, attr
.num_req_dev_type
))
457 return 1; /* Match with client Primary Device Type */
459 pos
+= WPS_DEV_TYPE_LEN
;
461 if (end
- pos
< num_sec
* WPS_DEV_TYPE_LEN
)
463 while (num_sec
> 0) {
465 if (dev_type_list_match(pos
, attr
.req_dev_type
,
466 attr
.num_req_dev_type
))
467 return 1; /* Match with client Secondary Device Type */
468 pos
+= WPS_DEV_TYPE_LEN
;
471 /* No matching device type found */
476 int p2p_group_match_dev_type(struct p2p_group
*group
, struct wpabuf
*wps
)
478 struct p2p_group_member
*m
;
480 if (p2p_match_dev_type(group
->p2p
, wps
))
481 return 1; /* Match with own device type */
483 for (m
= group
->members
; m
; m
= m
->next
) {
484 if (p2p_match_dev_type_member(m
, wps
))
485 return 1; /* Match with group client device type */
488 /* No match with Requested Device Type */
493 int p2p_group_match_dev_id(struct p2p_group
*group
, struct wpabuf
*p2p
)
495 struct p2p_group_member
*m
;
496 struct p2p_message msg
;
498 os_memset(&msg
, 0, sizeof(msg
));
499 if (p2p_parse_p2p_ie(p2p
, &msg
))
500 return 1; /* Failed to parse - assume no filter on Device ID */
503 return 1; /* No filter on Device ID */
505 if (os_memcmp(msg
.device_id
, group
->p2p
->cfg
->dev_addr
, ETH_ALEN
) == 0)
506 return 1; /* Match with our P2P Device Address */
508 for (m
= group
->members
; m
; m
= m
->next
) {
509 if (os_memcmp(msg
.device_id
, m
->dev_addr
, ETH_ALEN
) == 0)
510 return 1; /* Match with group client P2P Device Address */
513 /* No match with Device ID */
518 void p2p_group_notif_formation_done(struct p2p_group
*group
)
522 group
->group_formation
= 0;
523 group
->beacon_update
= 1;
524 p2p_group_update_ies(group
);
528 int p2p_group_notif_noa(struct p2p_group
*group
, const u8
*noa
,
532 wpabuf_free(group
->noa
);
536 if (wpabuf_size(group
->noa
) >= noa_len
) {
537 group
->noa
->used
= 0;
538 wpabuf_put_data(group
->noa
, noa
, noa_len
);
540 wpabuf_free(group
->noa
);
546 group
->noa
= wpabuf_alloc_copy(noa
, noa_len
);
547 if (group
->noa
== NULL
)
552 group
->beacon_update
= 1;
553 p2p_group_update_ies(group
);
558 static struct p2p_group_member
* p2p_group_get_client(struct p2p_group
*group
,
561 struct p2p_group_member
*m
;
563 for (m
= group
->members
; m
; m
= m
->next
) {
564 if (os_memcmp(dev_id
, m
->dev_addr
, ETH_ALEN
) == 0)
572 static struct p2p_group_member
* p2p_group_get_client_iface(
573 struct p2p_group
*group
, const u8
*interface_addr
)
575 struct p2p_group_member
*m
;
577 for (m
= group
->members
; m
; m
= m
->next
) {
578 if (os_memcmp(interface_addr
, m
->addr
, ETH_ALEN
) == 0)
586 const u8
* p2p_group_get_dev_addr(struct p2p_group
*group
, const u8
*addr
)
588 struct p2p_group_member
*m
;
592 m
= p2p_group_get_client_iface(group
, addr
);
593 if (m
&& !is_zero_ether_addr(m
->dev_addr
))
599 static struct wpabuf
* p2p_build_go_disc_req(void)
603 buf
= wpabuf_alloc(100);
607 p2p_buf_add_action_hdr(buf
, P2P_GO_DISC_REQ
, 0);
613 int p2p_group_go_discover(struct p2p_group
*group
, const u8
*dev_id
,
614 const u8
*searching_dev
, int rx_freq
)
616 struct p2p_group_member
*m
;
618 struct p2p_data
*p2p
= group
->p2p
;
621 m
= p2p_group_get_client(group
, dev_id
);
622 if (m
== NULL
|| m
->client_info
== NULL
) {
623 wpa_printf(MSG_DEBUG
, "P2P: Requested client was not in this "
625 MAC2STR(group
->cfg
->interface_addr
));
629 if (!(m
->dev_capab
& P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY
)) {
630 wpa_printf(MSG_DEBUG
, "P2P: Requested client does not support "
631 "client discoverability");
635 wpa_printf(MSG_DEBUG
, "P2P: Schedule GO Discoverability Request to be "
636 "sent to " MACSTR
, MAC2STR(dev_id
));
638 req
= p2p_build_go_disc_req();
642 /* TODO: Should really use group operating frequency here */
645 p2p
->pending_action_state
= P2P_PENDING_GO_DISC_REQ
;
646 if (p2p
->cfg
->send_action(p2p
->cfg
->cb_ctx
, freq
, m
->addr
,
647 group
->cfg
->interface_addr
,
648 group
->cfg
->interface_addr
,
649 wpabuf_head(req
), wpabuf_len(req
), 200) < 0)
651 wpa_msg(p2p
->cfg
->msg_ctx
, MSG_DEBUG
,
652 "P2P: Failed to send Action frame");
661 const u8
* p2p_group_get_interface_addr(struct p2p_group
*group
)
663 return group
->cfg
->interface_addr
;
667 u8
p2p_group_presence_req(struct p2p_group
*group
,
668 const u8
*client_interface_addr
,
669 const u8
*noa
, size_t noa_len
)
671 struct p2p_group_member
*m
;
675 m
= p2p_group_get_client_iface(group
, client_interface_addr
);
676 if (m
== NULL
|| m
->client_info
== NULL
) {
677 wpa_printf(MSG_DEBUG
, "P2P: Client was not in this group");
678 return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE
;
681 wpa_hexdump(MSG_DEBUG
, "P2P: Presence Request NoA", noa
, noa_len
);
683 if (group
->p2p
->cfg
->get_noa
)
684 curr_noa_len
= group
->p2p
->cfg
->get_noa(
685 group
->p2p
->cfg
->cb_ctx
, group
->cfg
->interface_addr
,
686 curr_noa
, sizeof(curr_noa
));
689 if (curr_noa_len
< 0)
690 wpa_printf(MSG_DEBUG
, "P2P: Failed to fetch current NoA");
691 else if (curr_noa_len
== 0)
692 wpa_printf(MSG_DEBUG
, "P2P: No NoA being advertized");
694 wpa_hexdump(MSG_DEBUG
, "P2P: Current NoA", curr_noa
,
697 /* TODO: properly process request and store copy */
698 if (curr_noa_len
> 0 || curr_noa_len
== -1)
699 return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE
;
701 return P2P_SC_SUCCESS
;
705 unsigned int p2p_get_group_num_members(struct p2p_group
*group
)
707 return group
->num_members
;
711 const u8
* p2p_iterate_group_members(struct p2p_group
*group
, void **next
)
713 struct p2p_group_member
*iter
= *next
;
716 iter
= group
->members
;
729 int p2p_group_is_client_connected(struct p2p_group
*group
, const u8
*dev_addr
)
731 struct p2p_group_member
*m
;
733 for (m
= group
->members
; m
; m
= m
->next
) {
734 if (os_memcmp(m
->dev_addr
, dev_addr
, ETH_ALEN
) == 0)