18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Wi-Fi Direct - P2P group operations
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"
142e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt#include "common/wpa_ctrl.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps/wps_defs.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps/wps_i.h"
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p_i.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_group_member {
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_member *next;
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 addr[ETH_ALEN]; /* P2P Interface Address */
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 dev_addr[ETH_ALEN]; /* P2P Device Address */
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *p2p_ie;
2661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct wpabuf *wfd_ie;
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *client_info;
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 dev_capab;
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * struct p2p_group - Internal P2P module per-group data
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_group {
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p;
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_config *cfg;
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_member *members;
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int num_members;
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int group_formation;
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int beacon_update;
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *noa;
4261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct wpabuf *wfd_ie;
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_group * p2p_group_init(struct p2p_data *p2p,
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  struct p2p_group_config *config)
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group *group, **groups;
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group = os_zalloc(sizeof(*group));
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group == NULL)
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	groups = os_realloc_array(p2p->groups, p2p->num_groups + 1,
5661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				  sizeof(struct p2p_group *));
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (groups == NULL) {
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(group);
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	groups[p2p->num_groups++] = group;
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->groups = groups;
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->p2p = p2p;
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->cfg = config;
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->group_formation = 1;
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->beacon_update = 1;
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_group_update_ies(group);
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->cfg->idle_update(group->cfg->cb_ctx, 1);
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return group;
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_group_free_member(struct p2p_group_member *m)
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(m->wfd_ie);
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(m->p2p_ie);
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(m->client_info);
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(m);
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_group_free_members(struct p2p_group *group)
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_member *m, *prev;
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	m = group->members;
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->members = NULL;
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->num_members = 0;
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (m) {
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = m;
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		m = m->next;
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_group_free_member(prev);
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_group_deinit(struct p2p_group *group)
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t g;
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p;
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group == NULL)
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p = group->p2p;
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (g = 0; g < p2p->num_groups; g++) {
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->groups[g] == group) {
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			while (g + 1 < p2p->num_groups) {
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p->groups[g] = p2p->groups[g + 1];
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				g++;
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->num_groups--;
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_group_free_members(group);
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(group->cfg);
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(group->noa);
12261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(group->wfd_ie);
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(group);
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_client_info(struct wpabuf *ie, struct p2p_group_member *m)
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (m->client_info == NULL)
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpabuf_tailroom(ie) < wpabuf_len(m->client_info) + 1)
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_buf(ie, m->client_info);
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_group_add_common_ies(struct p2p_group *group,
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     struct wpabuf *ie)
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	u8 dev_capab = group->p2p->dev_capab, group_capab = 0;
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P Capability */
14304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	dev_capab &= ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group_capab |= P2P_GROUP_CAPAB_GROUP_OWNER;
1451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (group->cfg->persistent_group) {
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
1471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (group->cfg->persistent_group == 2)
1481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			group_capab |= P2P_GROUP_CAPAB_PERSISTENT_RECONN;
1491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group->p2p->cfg->p2p_intra_bss)
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST;
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group->group_formation)
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group_capab |= P2P_GROUP_CAPAB_GROUP_FORMATION;
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group->p2p->cross_connect)
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group->num_members >= group->cfg->max_clients)
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group_capab |= P2P_GROUP_CAPAB_GROUP_LIMIT;
158cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	group_capab |= P2P_GROUP_CAPAB_IP_ADDR_ALLOCATION;
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_capability(ie, dev_capab, group_capab);
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_group_add_noa(struct wpabuf *ie, struct wpabuf *noa)
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (noa == NULL)
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Notice of Absence */
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(ie, P2P_ATTR_NOTICE_OF_ABSENCE);
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_le16(ie, wpabuf_len(noa));
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_buf(ie, noa);
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
174a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtstatic struct wpabuf * p2p_group_encaps_probe_resp(struct wpabuf *subelems)
175a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{
176a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	struct wpabuf *ie;
177a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	const u8 *pos, *end;
178a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	size_t len;
179a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
180a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (subelems == NULL)
181a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return NULL;
182a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
183a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	len = wpabuf_len(subelems) + 100;
184a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
185a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	ie = wpabuf_alloc(len);
186a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (ie == NULL)
187a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return NULL;
188a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
189a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	pos = wpabuf_head(subelems);
190a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	end = pos + wpabuf_len(subelems);
191a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
192a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	while (end > pos) {
193a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		size_t frag_len = end - pos;
194a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		if (frag_len > 251)
195a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			frag_len = 251;
196a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC);
197a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		wpabuf_put_u8(ie, 4 + frag_len);
198a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		wpabuf_put_be32(ie, P2P_IE_VENDOR_TYPE);
199a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		wpabuf_put_data(ie, pos, frag_len);
200a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		pos += frag_len;
201a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
202a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
203a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	return ie;
204a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt}
205a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
206a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_group_build_beacon_ie(struct p2p_group *group)
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *ie;
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
21161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t extra = 0;
21261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
21361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
21461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (group->p2p->wfd_ie_beacon)
21561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		extra = wpabuf_len(group->p2p->wfd_ie_beacon);
21661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2182e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	if (group->p2p->vendor_elem &&
2192e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	    group->p2p->vendor_elem[VENDOR_ELEM_BEACON_P2P_GO])
2202e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		extra += wpabuf_len(group->p2p->vendor_elem[VENDOR_ELEM_BEACON_P2P_GO]);
2212e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
22261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	ie = wpabuf_alloc(257 + extra);
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie == NULL)
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
22761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (group->p2p->wfd_ie_beacon)
22861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(ie, group->p2p->wfd_ie_beacon);
22961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
23061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
2312e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	if (group->p2p->vendor_elem &&
2322e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	    group->p2p->vendor_elem[VENDOR_ELEM_BEACON_P2P_GO])
2332e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		wpabuf_put_buf(ie,
2342e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			       group->p2p->vendor_elem[VENDOR_ELEM_BEACON_P2P_GO]);
2352e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(ie);
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_group_add_common_ies(group, ie);
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_device_id(ie, group->p2p->cfg->dev_addr);
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_group_add_noa(ie, group->noa);
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(ie, len);
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ie;
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
24761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
24861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstruct wpabuf * p2p_group_get_wfd_ie(struct p2p_group *g)
24961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
25061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return g->wfd_ie;
25161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
25261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
25361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
25461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstruct wpabuf * wifi_display_encaps(struct wpabuf *subelems)
25561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
25661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct wpabuf *ie;
25761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	const u8 *pos, *end;
25861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
25961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (subelems == NULL)
26061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return NULL;
26161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
26261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	ie = wpabuf_alloc(wpabuf_len(subelems) + 100);
26361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (ie == NULL)
26461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return NULL;
26561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
26661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	pos = wpabuf_head(subelems);
26761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	end = pos + wpabuf_len(subelems);
26861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
26961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	while (end > pos) {
27061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		size_t frag_len = end - pos;
27161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (frag_len > 251)
27261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			frag_len = 251;
27361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC);
27461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_u8(ie, 4 + frag_len);
27561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_be32(ie, WFD_IE_VENDOR_TYPE);
27661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_data(ie, pos, frag_len);
27761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += frag_len;
27861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
27961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
28061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return ie;
28161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
28261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
28361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
28461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int wifi_display_add_dev_info_descr(struct wpabuf *buf,
28561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					   struct p2p_group_member *m)
28661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
28761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	const u8 *pos, *end;
28861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	const u8 *dev_info = NULL;
28961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	const u8 *assoc_bssid = NULL;
29061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	const u8 *coupled_sink = NULL;
29161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 zero_addr[ETH_ALEN];
29261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
29361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (m->wfd_ie == NULL)
29461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return 0;
29561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
29661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_memset(zero_addr, 0, ETH_ALEN);
29761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	pos = wpabuf_head_u8(m->wfd_ie);
29861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	end = pos + wpabuf_len(m->wfd_ie);
29961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	while (pos + 1 < end) {
30061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		u8 id;
30161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		u16 len;
30261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
30361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		id = *pos++;
30461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		len = WPA_GET_BE16(pos);
30561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += 2;
30661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (pos + len > end)
30761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			break;
30861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
30961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		switch (id) {
31061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		case WFD_SUBELEM_DEVICE_INFO:
31161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if (len < 6)
31261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				break;
31361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			dev_info = pos;
31461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			break;
31561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		case WFD_SUBELEM_ASSOCIATED_BSSID:
31661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if (len < ETH_ALEN)
31761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				break;
31861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			assoc_bssid = pos;
31961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			break;
32061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		case WFD_SUBELEM_COUPLED_SINK:
32161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if (len < 1 + ETH_ALEN)
32261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				break;
32361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			coupled_sink = pos;
32461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			break;
32561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
32661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
32761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += len;
32861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
32961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
33061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (dev_info == NULL)
33161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return 0;
33261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
33361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_put_u8(buf, 23);
33461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_put_data(buf, m->dev_addr, ETH_ALEN);
33561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (assoc_bssid)
33661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_data(buf, assoc_bssid, ETH_ALEN);
33761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	else
33861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_data(buf, zero_addr, ETH_ALEN);
33961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_put_data(buf, dev_info, 2); /* WFD Device Info */
34061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_put_data(buf, dev_info + 4, 2); /* WFD Device Max Throughput */
34161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (coupled_sink) {
34261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_data(buf, coupled_sink, 1 + ETH_ALEN);
34361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else {
34461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_u8(buf, 0);
34561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_data(buf, zero_addr, ETH_ALEN);
34661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
34761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
34861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 1;
34961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
35061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
35161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
35261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic struct wpabuf *
35361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtwifi_display_build_go_ie(struct p2p_group *group)
35461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
35561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct wpabuf *wfd_subelems, *wfd_ie;
35661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct p2p_group_member *m;
35761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 *len;
35861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	unsigned int count = 0;
35961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
36061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (!group->p2p->wfd_ie_probe_resp)
36161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return NULL;
36261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
36361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wfd_subelems = wpabuf_alloc(wpabuf_len(group->p2p->wfd_ie_probe_resp) +
36461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				    group->num_members * 24 + 100);
36561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (wfd_subelems == NULL)
36661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return NULL;
36761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (group->p2p->wfd_dev_info)
36861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(wfd_subelems, group->p2p->wfd_dev_info);
36961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (group->p2p->wfd_assoc_bssid)
37061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(wfd_subelems,
37161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			       group->p2p->wfd_assoc_bssid);
37261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (group->p2p->wfd_coupled_sink_info)
37361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(wfd_subelems,
37461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			       group->p2p->wfd_coupled_sink_info);
37561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
37661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	/* Build WFD Session Info */
37761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_put_u8(wfd_subelems, WFD_SUBELEM_SESSION_INFO);
37861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	len = wpabuf_put(wfd_subelems, 2);
37961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	m = group->members;
38061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	while (m) {
38161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (wifi_display_add_dev_info_descr(wfd_subelems, m))
38261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			count++;
38361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		m = m->next;
38461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
38561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
38661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (count == 0) {
38761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		/* No Wi-Fi Display clients - do not include subelement */
38861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wfd_subelems->used -= 3;
38961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else {
39061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		WPA_PUT_BE16(len, (u8 *) wpabuf_put(wfd_subelems, 0) - len -
39161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			     2);
392b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(group->p2p, "WFD: WFD Session Info: %u descriptors",
393b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			count);
39461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
39561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
39661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wfd_ie = wifi_display_encaps(wfd_subelems);
39761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(wfd_subelems);
39861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
39961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return wfd_ie;
40061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
40161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
40261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void wifi_display_group_update(struct p2p_group *group)
40361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
40461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(group->wfd_ie);
40561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	group->wfd_ie = wifi_display_build_go_ie(group);
40661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
40761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
40861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
40961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
41061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
411cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtvoid p2p_buf_add_group_info(struct p2p_group *group, struct wpabuf *buf,
412cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			    int max_clients)
413cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{
414cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	u8 *group_info;
415cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	int count = 0;
416cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	struct p2p_group_member *m;
417cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
418cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	p2p_dbg(group->p2p, "* P2P Group Info");
419cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	group_info = wpabuf_put(buf, 0);
420cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	wpabuf_put_u8(buf, P2P_ATTR_GROUP_INFO);
421cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	wpabuf_put_le16(buf, 0); /* Length to be filled */
422cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	for (m = group->members; m; m = m->next) {
423cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_client_info(buf, m);
424cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		count++;
425cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		if (max_clients >= 0 && count >= max_clients)
426cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			break;
427cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
428cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	WPA_PUT_LE16(group_info + 1,
429cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		     (u8 *) wpabuf_put(buf, 0) - group_info - 3);
430cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt}
431cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
432cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
433cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtvoid p2p_group_buf_add_id(struct p2p_group *group, struct wpabuf *buf)
434cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{
435cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	p2p_buf_add_group_id(buf, group->p2p->cfg->dev_addr, group->cfg->ssid,
436cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			     group->cfg->ssid_len);
437cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt}
438cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
439cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_group_build_probe_resp_ie(struct p2p_group *group)
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
442a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	struct wpabuf *p2p_subelems, *ie;
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44433077b18208aab987e14cd26f0f501c7666a89ffJouni Malinen	p2p_subelems = wpabuf_alloc(500);
445a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (p2p_subelems == NULL)
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
448a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	p2p_group_add_common_ies(group, p2p_subelems);
449a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	p2p_group_add_noa(p2p_subelems, group->noa);
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P Device Info */
452a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	p2p_buf_add_device_info(p2p_subelems, group->p2p, NULL);
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
454444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt	/* P2P Group Info: Only when at least one P2P Client is connected */
455cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (group->members)
456cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		p2p_buf_add_group_info(group, p2p_subelems, -1);
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
458a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	ie = p2p_group_encaps_probe_resp(p2p_subelems);
459a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	wpabuf_free(p2p_subelems);
46061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
4612e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	if (group->p2p->vendor_elem &&
4622e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	    group->p2p->vendor_elem[VENDOR_ELEM_PROBE_RESP_P2P_GO]) {
4632e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		struct wpabuf *extra;
4642e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		extra = wpabuf_dup(group->p2p->vendor_elem[VENDOR_ELEM_PROBE_RESP_P2P_GO]);
4652e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		ie = wpabuf_concat(extra, ie);
4662e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	}
4672e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
46833077b18208aab987e14cd26f0f501c7666a89ffJouni Malinen#ifdef CONFIG_WIFI_DISPLAY
46933077b18208aab987e14cd26f0f501c7666a89ffJouni Malinen	if (group->wfd_ie) {
47033077b18208aab987e14cd26f0f501c7666a89ffJouni Malinen		struct wpabuf *wfd = wpabuf_dup(group->wfd_ie);
47133077b18208aab987e14cd26f0f501c7666a89ffJouni Malinen		ie = wpabuf_concat(wfd, ie);
47233077b18208aab987e14cd26f0f501c7666a89ffJouni Malinen	}
47333077b18208aab987e14cd26f0f501c7666a89ffJouni Malinen#endif /* CONFIG_WIFI_DISPLAY */
47433077b18208aab987e14cd26f0f501c7666a89ffJouni Malinen
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ie;
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
47961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid p2p_group_update_ies(struct p2p_group *group)
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *beacon_ie;
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *probe_resp_ie;
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
48461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
48561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wifi_display_group_update(group);
48661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
48761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	probe_resp_ie = p2p_group_build_probe_resp_ie(group);
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (probe_resp_ie == NULL)
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_buf(MSG_MSGDUMP, "P2P: Update GO Probe Response P2P IE",
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			probe_resp_ie);
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group->beacon_update) {
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		beacon_ie = p2p_group_build_beacon_ie(group);
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (beacon_ie)
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group->beacon_update = 0;
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_buf(MSG_MSGDUMP, "P2P: Update GO Beacon P2P IE",
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				beacon_ie);
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		beacon_ie = NULL;
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->cfg->ie_update(group->cfg->cb_ctx, beacon_ie, probe_resp_ie);
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_build_client_info - Build P2P Client Info Descriptor
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: MAC address of the peer device
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p_ie: P2P IE from (Re)Association Request
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dev_capab: Buffer for returning Device Capability
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dev_addr: Buffer for returning P2P Device Address
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: P2P Client Info Descriptor or %NULL on failure
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function builds P2P Client Info Descriptor based on the information
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * available from (Re)Association Request frame. Group owner can use this to
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * build the P2P Group Info attribute for Probe Response frames.
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_client_info(const u8 *addr,
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     struct wpabuf *p2p_ie,
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     u8 *dev_capab, u8 *dev_addr)
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *spos;
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len_pos;
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_ie == NULL)
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_p2p_ie(p2p_ie, &msg) ||
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg.capability == NULL || msg.p2p_device_info == NULL)
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = wpabuf_alloc(ETH_ALEN + 1 + 1 + msg.p2p_device_info_len);
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*dev_capab = msg.capability[0];
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev_addr, msg.p2p_device_addr, ETH_ALEN);
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	spos = msg.p2p_device_info; /* P2P Device address */
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P Client Info Descriptor */
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Length to be set */
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len_pos = wpabuf_put(buf, 1);
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P Device address */
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(buf, spos, ETH_ALEN);
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P Interface address */
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(buf, addr, ETH_ALEN);
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Device Capability Bitmap */
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, msg.capability[0]);
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Config Methods, Primary Device Type, Number of Secondary Device
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Types, Secondary Device Type List, Device Name copied from
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Device Info
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(buf, spos + ETH_ALEN,
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg.p2p_device_info_len - ETH_ALEN);
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*len_pos = wpabuf_len(buf) - 1;
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int p2p_group_remove_member(struct p2p_group *group, const u8 *addr)
5701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
5711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_group_member *m, *prev;
5721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
5731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (group == NULL)
5741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
5751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
5761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	m = group->members;
5771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	prev = NULL;
5781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	while (m) {
5791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (os_memcmp(m->addr, addr, ETH_ALEN) == 0)
5801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			break;
5811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		prev = m;
5821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		m = m->next;
5831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
5841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
5851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (m == NULL)
5861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
5871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
5881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (prev)
5891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		prev->next = m->next;
5901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	else
5911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		group->members = m->next;
5921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_group_free_member(m);
5931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	group->num_members--;
5941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
5951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return 1;
5961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
5971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
5981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_group_notif_assoc(struct p2p_group *group, const u8 *addr,
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  const u8 *ie, size_t len)
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_member *m;
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group == NULL)
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6072f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt	p2p_add_device(group->p2p, addr, 0, NULL, 0, ie, len, 0);
6082f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	m = os_zalloc(sizeof(*m));
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (m == NULL)
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(m->addr, addr, ETH_ALEN);
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	m->p2p_ie = ieee802_11_vendor_ie_concat(ie, len, P2P_IE_VENDOR_TYPE);
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (m->p2p_ie) {
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		m->client_info = p2p_build_client_info(addr, m->p2p_ie,
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       &m->dev_capab,
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       m->dev_addr);
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
61961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
62061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	m->wfd_ie = ieee802_11_vendor_ie_concat(ie, len, WFD_IE_VENDOR_TYPE);
62161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_group_remove_member(group, addr);
6241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	m->next = group->members;
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->members = m;
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->num_members++;
628b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(group->p2p,  "Add client " MACSTR
62961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		" to group (p2p=%d wfd=%d client_info=%d); num_members=%u/%u",
63061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		MAC2STR(addr), m->p2p_ie ? 1 : 0, m->wfd_ie ? 1 : 0,
63161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		m->client_info ? 1 : 0,
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group->num_members, group->cfg->max_clients);
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group->num_members == group->cfg->max_clients)
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group->beacon_update = 1;
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_group_update_ies(group);
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group->num_members == 1)
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group->cfg->idle_update(group->cfg->cb_ctx, 0);
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * p2p_group_assoc_resp_ie(struct p2p_group *group, u8 status)
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *rlen;
64761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t extra = 0;
64861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
64961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
65061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (group->wfd_ie)
65161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		extra = wpabuf_len(group->wfd_ie);
65261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6542e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	if (group->p2p->vendor_elem &&
6552e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	    group->p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_RESP])
6562e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		extra += wpabuf_len(group->p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_RESP]);
6572e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (Re)Association Response - P2P IE
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Status attribute (shall be present when association request is
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *	denied)
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Extended Listen Timing (may be present)
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
66461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	resp = wpabuf_alloc(20 + extra);
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
66761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
66861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
66961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (group->wfd_ie)
67061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(resp, group->wfd_ie);
67161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
67261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
6732e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	if (group->p2p->vendor_elem &&
6742e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	    group->p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_RESP])
6752e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		wpabuf_put_buf(resp,
6762e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt			       group->p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_RESP]);
6772e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rlen = p2p_buf_add_ie_hdr(resp);
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (status != P2P_SC_SUCCESS)
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_status(resp, status);
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(resp, rlen);
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return resp;
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_group_notif_disassoc(struct p2p_group *group, const u8 *addr)
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p_group_remove_member(group, addr)) {
690b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(group->p2p, "Remove client " MACSTR
691b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			" from group; num_members=%u/%u",
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(addr), group->num_members,
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group->cfg->max_clients);
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (group->num_members == group->cfg->max_clients - 1)
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group->beacon_update = 1;
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_group_update_ies(group);
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (group->num_members == 0)
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group->cfg->idle_update(group->cfg->cb_ctx, 1);
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_match_dev_type_member - Match client device type with requested type
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @m: Group member
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wps: WPS TLVs from Probe Request frame (concatenated WPS IEs)
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 on match, 0 on mismatch
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function can be used to match the Requested Device Type attribute in
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPS IE with the device types of a group member for deciding whether a GO
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * should reply to a Probe Request frame.
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_match_dev_type_member(struct p2p_group_member *m,
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     struct wpabuf *wps)
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end;
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wps_parse_attr attr;
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 num_sec;
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (m->client_info == NULL || wps == NULL)
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = wpabuf_head(m->client_info);
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + wpabuf_len(m->client_info);
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 1 + 2 * ETH_ALEN + 1 + 2;
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < WPS_DEV_TYPE_LEN + 1)
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wps_parse_msg(wps, &attr))
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* assume no Requested Device Type attributes */
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (attr.num_req_dev_type == 0)
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* no Requested Device Type attributes -> match */
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev_type_list_match(pos, attr.req_dev_type, attr.num_req_dev_type))
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Match with client Primary Device Type */
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += WPS_DEV_TYPE_LEN;
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	num_sec = *pos++;
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < num_sec * WPS_DEV_TYPE_LEN)
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (num_sec > 0) {
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num_sec--;
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev_type_list_match(pos, attr.req_dev_type,
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					attr.num_req_dev_type))
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 1; /* Match with client Secondary Device Type */
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += WPS_DEV_TYPE_LEN;
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* No matching device type found */
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_group_match_dev_type(struct p2p_group *group, struct wpabuf *wps)
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_member *m;
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_match_dev_type(group->p2p, wps))
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Match with own device type */
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (m = group->members; m; m = m->next) {
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p_match_dev_type_member(m, wps))
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 1; /* Match with group client device type */
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* No match with Requested Device Type */
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
773c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtint p2p_group_match_dev_id(struct p2p_group *group, struct wpabuf *p2p)
774c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{
775c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	struct p2p_group_member *m;
776c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	struct p2p_message msg;
777c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
778c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
779c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (p2p_parse_p2p_ie(p2p, &msg))
780c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return 1; /* Failed to parse - assume no filter on Device ID */
781c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
782c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (!msg.device_id)
783c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return 1; /* No filter on Device ID */
784c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
785c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (os_memcmp(msg.device_id, group->p2p->cfg->dev_addr, ETH_ALEN) == 0)
786c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return 1; /* Match with our P2P Device Address */
787c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
788c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	for (m = group->members; m; m = m->next) {
789c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (os_memcmp(msg.device_id, m->dev_addr, ETH_ALEN) == 0)
790c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			return 1; /* Match with group client P2P Device Address */
791c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
792c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
793c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	/* No match with Device ID */
794c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	return 0;
795c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt}
796c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
797c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_group_notif_formation_done(struct p2p_group *group)
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group == NULL)
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->group_formation = 0;
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->beacon_update = 1;
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_group_update_ies(group);
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_group_notif_noa(struct p2p_group *group, const u8 *noa,
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			size_t noa_len)
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (noa == NULL) {
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(group->noa);
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group->noa = NULL;
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (group->noa) {
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (wpabuf_size(group->noa) >= noa_len) {
817fc41cadcff448cdd2b60e376fc6e7378e2e57b5eDmitry Shmidt				group->noa->used = 0;
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpabuf_put_data(group->noa, noa, noa_len);
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} else {
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpabuf_free(group->noa);
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				group->noa = NULL;
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!group->noa) {
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group->noa = wpabuf_alloc_copy(noa, noa_len);
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (group->noa == NULL)
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->beacon_update = 1;
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_group_update_ies(group);
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct p2p_group_member * p2p_group_get_client(struct p2p_group *group,
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						      const u8 *dev_id)
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_member *m;
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (m = group->members; m; m = m->next) {
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(dev_id, m->dev_addr, ETH_ALEN) == 0)
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return m;
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct p2p_group_member * p2p_group_get_client_iface(
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group *group, const u8 *interface_addr)
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_member *m;
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (m = group->members; m; m = m->next) {
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(interface_addr, m->addr, ETH_ALEN) == 0)
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return m;
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
8661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtconst u8 * p2p_group_get_dev_addr(struct p2p_group *group, const u8 *addr)
867dca3979ccdf869f140f096b83df322a0efc84f22Dmitry Shmidt{
868dca3979ccdf869f140f096b83df322a0efc84f22Dmitry Shmidt	struct p2p_group_member *m;
869dca3979ccdf869f140f096b83df322a0efc84f22Dmitry Shmidt
8701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (group == NULL)
8711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return NULL;
872dca3979ccdf869f140f096b83df322a0efc84f22Dmitry Shmidt	m = p2p_group_get_client_iface(group, addr);
8731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (m && !is_zero_ether_addr(m->dev_addr))
874dca3979ccdf869f140f096b83df322a0efc84f22Dmitry Shmidt		return m->dev_addr;
8751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return NULL;
876dca3979ccdf869f140f096b83df322a0efc84f22Dmitry Shmidt}
8771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_go_disc_req(void)
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = wpabuf_alloc(100);
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_action_hdr(buf, P2P_GO_DISC_REQ, 0);
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_group_go_discover(struct p2p_group *group, const u8 *dev_id,
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  const u8 *searching_dev, int rx_freq)
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_member *m;
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = group->p2p;
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	m = p2p_group_get_client(group, dev_id);
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (m == NULL || m->client_info == NULL) {
903b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(group->p2p, "Requested client was not in this group "
904b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			MACSTR, MAC2STR(group->cfg->interface_addr));
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!(m->dev_capab & P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
909b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(group->p2p, "Requested client does not support client discoverability");
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
913b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(group->p2p, "Schedule GO Discoverability Request to be sent to "
914b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		MACSTR, MAC2STR(dev_id));
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req = p2p_build_go_disc_req();
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL)
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: Should really use group operating frequency here */
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	freq = rx_freq;
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_PENDING_GO_DISC_REQ;
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, m->addr,
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  group->cfg->interface_addr,
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  group->cfg->interface_addr,
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  wpabuf_head(req), wpabuf_len(req), 200) < 0)
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
929b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to send Action frame");
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(req);
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * p2p_group_get_interface_addr(struct p2p_group *group)
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return group->cfg->interface_addr;
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu8 p2p_group_presence_req(struct p2p_group *group,
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  const u8 *client_interface_addr,
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  const u8 *noa, size_t noa_len)
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_member *m;
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 curr_noa[50];
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int curr_noa_len;
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	m = p2p_group_get_client_iface(group, client_interface_addr);
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (m == NULL || m->client_info == NULL) {
954b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(group->p2p, "Client was not in this group");
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "P2P: Presence Request NoA", noa, noa_len);
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group->p2p->cfg->get_noa)
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		curr_noa_len = group->p2p->cfg->get_noa(
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group->p2p->cfg->cb_ctx, group->cfg->interface_addr,
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			curr_noa, sizeof(curr_noa));
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		curr_noa_len = -1;
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (curr_noa_len < 0)
967b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(group->p2p, "Failed to fetch current NoA");
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (curr_noa_len == 0)
969b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(group->p2p, "No NoA being advertized");
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "P2P: Current NoA", curr_noa,
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    curr_noa_len);
9731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: properly process request and store copy */
9751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (curr_noa_len > 0 || curr_noa_len == -1)
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
9771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return P2P_SC_SUCCESS;
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned int p2p_get_group_num_members(struct p2p_group *group)
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return group->num_members;
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * p2p_iterate_group_members(struct p2p_group *group, void **next)
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_member *iter = *next;
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!iter)
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		iter = group->members;
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		iter = iter->next;
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*next = iter;
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!iter)
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1002d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt	return iter->dev_addr;
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1004c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1005c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1006c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtint p2p_group_is_client_connected(struct p2p_group *group, const u8 *dev_addr)
1007c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{
1008c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	struct p2p_group_member *m;
1009c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1010c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	for (m = group->members; m; m = m->next) {
1011c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (os_memcmp(m->dev_addr, dev_addr, ETH_ALEN) == 0)
1012c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			return 1;
1013c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
1014c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1015c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	return 0;
1016c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt}
101704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
101804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
101904949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint p2p_group_is_group_id_match(struct p2p_group *group, const u8 *group_id,
102004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				size_t group_id_len)
102104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
102204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (group_id_len != ETH_ALEN + group->cfg->ssid_len)
102304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 0;
102404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (os_memcmp(group_id, group->p2p->cfg->dev_addr, ETH_ALEN) != 0)
102504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 0;
102604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return os_memcmp(group_id + ETH_ALEN, group->cfg->ssid,
102704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 group->cfg->ssid_len) == 0;
102804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
1029b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt
1030b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt
1031b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidtvoid p2p_group_force_beacon_update_ies(struct p2p_group *group)
1032b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt{
1033b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt	group->beacon_update = 1;
1034b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt	p2p_group_update_ies(group);
1035b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt}
1036cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
1037cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
1038cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtint p2p_group_get_freq(struct p2p_group *group)
1039cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{
1040cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	return group->cfg->freq;
1041cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt}
1042d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt
1043d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt
1044d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidtconst struct p2p_group_config * p2p_group_get_config(struct p2p_group *group)
1045d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt{
1046d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt	return group->cfg;
1047d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt}
1048d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt
1049d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt
1050d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidtvoid p2p_loop_on_all_groups(struct p2p_data *p2p,
1051d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt			    int (*group_callback)(struct p2p_group *group,
1052d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt						  void *user_data),
1053d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt			    void *user_data)
1054d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt{
1055d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt	unsigned int i;
1056d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt
1057d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt	for (i = 0; i < p2p->num_groups; i++) {
1058d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt		if (!group_callback(p2p->groups[i], user_data))
1059d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt			break;
1060d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt	}
1061d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt}
1062