p2p_group.c revision 1f69aa52ea2e0a73ac502565df8c666ee49cab6a
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Wi-Fi Direct - P2P group operations
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2009-2010, Atheros Communications
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This program is free software; you can redistribute it and/or modify
68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * published by the Free Software Foundation.
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * license.
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See README and COPYING for more details.
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_common.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps/wps_defs.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps/wps_i.h"
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p_i.h"
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p.h"
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_group_member {
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_member *next;
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 addr[ETH_ALEN]; /* P2P Interface Address */
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 dev_addr[ETH_ALEN]; /* P2P Device Address */
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *p2p_ie;
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *client_info;
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 dev_capab;
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * struct p2p_group - Internal P2P module per-group data
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_group {
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p;
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_config *cfg;
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_member *members;
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int num_members;
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int group_formation;
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int beacon_update;
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *noa;
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_group_update_ies(struct p2p_group *group);
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_group * p2p_group_init(struct p2p_data *p2p,
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  struct p2p_group_config *config)
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group *group, **groups;
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group = os_zalloc(sizeof(*group));
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group == NULL)
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	groups = os_realloc(p2p->groups, (p2p->num_groups + 1) *
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    sizeof(struct p2p_group *));
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (groups == NULL) {
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(group);
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	groups[p2p->num_groups++] = group;
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->groups = groups;
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->p2p = p2p;
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->cfg = config;
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->group_formation = 1;
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->beacon_update = 1;
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_group_update_ies(group);
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->cfg->idle_update(group->cfg->cb_ctx, 1);
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return group;
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_group_free_member(struct p2p_group_member *m)
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(m->p2p_ie);
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(m->client_info);
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(m);
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_group_free_members(struct p2p_group *group)
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_member *m, *prev;
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	m = group->members;
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->members = NULL;
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->num_members = 0;
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (m) {
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = m;
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		m = m->next;
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_group_free_member(prev);
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_group_deinit(struct p2p_group *group)
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t g;
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p;
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group == NULL)
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p = group->p2p;
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (g = 0; g < p2p->num_groups; g++) {
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p->groups[g] == group) {
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			while (g + 1 < p2p->num_groups) {
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p2p->groups[g] = p2p->groups[g + 1];
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				g++;
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p2p->num_groups--;
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_group_free_members(group);
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(group->cfg);
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(group->noa);
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(group);
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_client_info(struct wpabuf *ie, struct p2p_group_member *m)
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (m->client_info == NULL)
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpabuf_tailroom(ie) < wpabuf_len(m->client_info) + 1)
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_buf(ie, m->client_info);
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_group_add_common_ies(struct p2p_group *group,
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     struct wpabuf *ie)
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 dev_capab = 0, group_capab = 0;
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P Capability */
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev_capab |= P2P_DEV_CAPAB_SERVICE_DISCOVERY;
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev_capab |= P2P_DEV_CAPAB_INVITATION_PROCEDURE;
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group_capab |= P2P_GROUP_CAPAB_GROUP_OWNER;
1501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (group->cfg->persistent_group) {
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
1521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (group->cfg->persistent_group == 2)
1531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			group_capab |= P2P_GROUP_CAPAB_PERSISTENT_RECONN;
1541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group->p2p->cfg->p2p_intra_bss)
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST;
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group->group_formation)
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group_capab |= P2P_GROUP_CAPAB_GROUP_FORMATION;
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group->p2p->cross_connect)
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group->num_members >= group->cfg->max_clients)
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group_capab |= P2P_GROUP_CAPAB_GROUP_LIMIT;
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_capability(ie, dev_capab, group_capab);
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_group_add_noa(struct wpabuf *ie, struct wpabuf *noa)
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (noa == NULL)
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Notice of Absence */
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(ie, P2P_ATTR_NOTICE_OF_ABSENCE);
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_le16(ie, wpabuf_len(noa));
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_buf(ie, noa);
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_group_build_beacon_ie(struct p2p_group *group)
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *ie;
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ie = wpabuf_alloc(257);
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie == NULL)
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(ie);
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_group_add_common_ies(group, ie);
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_device_id(ie, group->p2p->cfg->dev_addr);
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_group_add_noa(ie, group->noa);
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(ie, len);
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ie;
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_group_build_probe_resp_ie(struct p2p_group *group)
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *group_info;
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *ie;
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_member *m;
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ie = wpabuf_alloc(257);
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie == NULL)
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(ie);
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_group_add_common_ies(group, ie);
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_group_add_noa(ie, group->noa);
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P Device Info */
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_device_info(ie, group->p2p, NULL);
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P Group Info */
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group_info = wpabuf_put(ie, 0);
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(ie, P2P_ATTR_GROUP_INFO);
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_le16(ie, 0); /* Length to be filled */
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (m = group->members; m; m = m->next)
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_client_info(ie, m);
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_LE16(group_info + 1,
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     (u8 *) wpabuf_put(ie, 0) - group_info - 3);
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(ie, len);
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ie;
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_group_update_ies(struct p2p_group *group)
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *beacon_ie;
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *probe_resp_ie;
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	probe_resp_ie = p2p_group_build_probe_resp_ie(group);
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (probe_resp_ie == NULL)
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_buf(MSG_MSGDUMP, "P2P: Update GO Probe Response P2P IE",
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			probe_resp_ie);
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group->beacon_update) {
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		beacon_ie = p2p_group_build_beacon_ie(group);
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (beacon_ie)
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group->beacon_update = 0;
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_buf(MSG_MSGDUMP, "P2P: Update GO Beacon P2P IE",
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				beacon_ie);
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		beacon_ie = NULL;
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->cfg->ie_update(group->cfg->cb_ctx, beacon_ie, probe_resp_ie);
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_build_client_info - Build P2P Client Info Descriptor
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: MAC address of the peer device
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p_ie: P2P IE from (Re)Association Request
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dev_capab: Buffer for returning Device Capability
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dev_addr: Buffer for returning P2P Device Address
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: P2P Client Info Descriptor or %NULL on failure
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function builds P2P Client Info Descriptor based on the information
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * available from (Re)Association Request frame. Group owner can use this to
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * build the P2P Group Info attribute for Probe Response frames.
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_client_info(const u8 *addr,
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     struct wpabuf *p2p_ie,
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     u8 *dev_capab, u8 *dev_addr)
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *spos;
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len_pos;
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_ie == NULL)
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&msg, 0, sizeof(msg));
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse_p2p_ie(p2p_ie, &msg) ||
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    msg.capability == NULL || msg.p2p_device_info == NULL)
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = wpabuf_alloc(ETH_ALEN + 1 + 1 + msg.p2p_device_info_len);
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*dev_capab = msg.capability[0];
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev_addr, msg.p2p_device_addr, ETH_ALEN);
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	spos = msg.p2p_device_info; /* P2P Device address */
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P Client Info Descriptor */
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Length to be set */
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len_pos = wpabuf_put(buf, 1);
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P Device address */
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(buf, spos, ETH_ALEN);
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* P2P Interface address */
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(buf, addr, ETH_ALEN);
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Device Capability Bitmap */
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, msg.capability[0]);
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Config Methods, Primary Device Type, Number of Secondary Device
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Types, Secondary Device Type List, Device Name copied from
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Device Info
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(buf, spos + ETH_ALEN,
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg.p2p_device_info_len - ETH_ALEN);
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*len_pos = wpabuf_len(buf) - 1;
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int p2p_group_remove_member(struct p2p_group *group, const u8 *addr)
3171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
3181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_group_member *m, *prev;
3191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (group == NULL)
3211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
3221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	m = group->members;
3241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	prev = NULL;
3251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	while (m) {
3261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (os_memcmp(m->addr, addr, ETH_ALEN) == 0)
3271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			break;
3281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		prev = m;
3291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		m = m->next;
3301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
3311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (m == NULL)
3331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
3341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (prev)
3361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		prev->next = m->next;
3371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	else
3381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		group->members = m->next;
3391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_group_free_member(m);
3401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	group->num_members--;
3411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return 1;
3431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
3441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_group_notif_assoc(struct p2p_group *group, const u8 *addr,
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  const u8 *ie, size_t len)
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_member *m;
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group == NULL)
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	m = os_zalloc(sizeof(*m));
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (m == NULL)
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(m->addr, addr, ETH_ALEN);
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	m->p2p_ie = ieee802_11_vendor_ie_concat(ie, len, P2P_IE_VENDOR_TYPE);
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (m->p2p_ie) {
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		m->client_info = p2p_build_client_info(addr, m->p2p_ie,
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       &m->dev_capab,
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       m->dev_addr);
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	p2p_group_remove_member(group, addr);
3661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	m->next = group->members;
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->members = m;
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->num_members++;
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(group->p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Add client " MACSTR
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" to group (p2p=%d client_info=%d); num_members=%u/%u",
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(addr), m->p2p_ie ? 1 : 0, m->client_info ? 1 : 0,
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group->num_members, group->cfg->max_clients);
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group->num_members == group->cfg->max_clients)
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group->beacon_update = 1;
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_group_update_ies(group);
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group->num_members == 1)
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group->cfg->idle_update(group->cfg->cb_ctx, 0);
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * p2p_group_assoc_resp_ie(struct p2p_group *group, u8 status)
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *rlen;
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (Re)Association Response - P2P IE
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Status attribute (shall be present when association request is
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *	denied)
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Extended Listen Timing (may be present)
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = wpabuf_alloc(20);
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rlen = p2p_buf_add_ie_hdr(resp);
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (status != P2P_SC_SUCCESS)
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_status(resp, status);
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(resp, rlen);
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return resp;
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_group_notif_disassoc(struct p2p_group *group, const u8 *addr)
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (p2p_group_remove_member(group, addr)) {
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(group->p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Remove "
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"client " MACSTR " from group; num_members=%u/%u",
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(addr), group->num_members,
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group->cfg->max_clients);
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (group->num_members == group->cfg->max_clients - 1)
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group->beacon_update = 1;
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_group_update_ies(group);
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (group->num_members == 0)
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group->cfg->idle_update(group->cfg->cb_ctx, 1);
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_match_dev_type_member - Match client device type with requested type
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @m: Group member
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wps: WPS TLVs from Probe Request frame (concatenated WPS IEs)
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 on match, 0 on mismatch
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function can be used to match the Requested Device Type attribute in
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPS IE with the device types of a group member for deciding whether a GO
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * should reply to a Probe Request frame.
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_match_dev_type_member(struct p2p_group_member *m,
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     struct wpabuf *wps)
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end;
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wps_parse_attr attr;
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 num_sec;
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (m->client_info == NULL || wps == NULL)
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = wpabuf_head(m->client_info);
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + wpabuf_len(m->client_info);
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 1 + 2 * ETH_ALEN + 1 + 2;
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < WPS_DEV_TYPE_LEN + 1)
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wps_parse_msg(wps, &attr))
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* assume no Requested Device Type attributes */
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (attr.num_req_dev_type == 0)
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* no Requested Device Type attributes -> match */
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev_type_list_match(pos, attr.req_dev_type, attr.num_req_dev_type))
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Match with client Primary Device Type */
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += WPS_DEV_TYPE_LEN;
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	num_sec = *pos++;
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < num_sec * WPS_DEV_TYPE_LEN)
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (num_sec > 0) {
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num_sec--;
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev_type_list_match(pos, attr.req_dev_type,
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					attr.num_req_dev_type))
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 1; /* Match with client Secondary Device Type */
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += WPS_DEV_TYPE_LEN;
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* No matching device type found */
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_group_match_dev_type(struct p2p_group *group, struct wpabuf *wps)
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_member *m;
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_match_dev_type(group->p2p, wps))
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Match with own device type */
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (m = group->members; m; m = m->next) {
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p2p_match_dev_type_member(m, wps))
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 1; /* Match with group client device type */
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* No match with Requested Device Type */
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_group_notif_formation_done(struct p2p_group *group)
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group == NULL)
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->group_formation = 0;
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->beacon_update = 1;
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_group_update_ies(group);
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_group_notif_noa(struct p2p_group *group, const u8 *noa,
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			size_t noa_len)
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (noa == NULL) {
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(group->noa);
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group->noa = NULL;
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (group->noa) {
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (wpabuf_size(group->noa) >= noa_len) {
512fc41cadcff448cdd2b60e376fc6e7378e2e57b5eDmitry Shmidt				group->noa->used = 0;
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpabuf_put_data(group->noa, noa, noa_len);
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} else {
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpabuf_free(group->noa);
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				group->noa = NULL;
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!group->noa) {
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group->noa = wpabuf_alloc_copy(noa, noa_len);
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (group->noa == NULL)
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	group->beacon_update = 1;
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_group_update_ies(group);
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct p2p_group_member * p2p_group_get_client(struct p2p_group *group,
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						      const u8 *dev_id)
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_member *m;
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (m = group->members; m; m = m->next) {
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(dev_id, m->dev_addr, ETH_ALEN) == 0)
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return m;
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct p2p_group_member * p2p_group_get_client_iface(
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group *group, const u8 *interface_addr)
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_member *m;
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (m = group->members; m; m = m->next) {
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(interface_addr, m->addr, ETH_ALEN) == 0)
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return m;
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
5611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtconst u8 * p2p_group_get_dev_addr(struct p2p_group *group, const u8 *addr)
562dca3979ccdf869f140f096b83df322a0efc84f22Dmitry Shmidt{
563dca3979ccdf869f140f096b83df322a0efc84f22Dmitry Shmidt	struct p2p_group_member *m;
564dca3979ccdf869f140f096b83df322a0efc84f22Dmitry Shmidt
5651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (group == NULL)
5661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return NULL;
567dca3979ccdf869f140f096b83df322a0efc84f22Dmitry Shmidt	m = p2p_group_get_client_iface(group, addr);
5681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (m && !is_zero_ether_addr(m->dev_addr))
569dca3979ccdf869f140f096b83df322a0efc84f22Dmitry Shmidt		return m->dev_addr;
5701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return NULL;
571dca3979ccdf869f140f096b83df322a0efc84f22Dmitry Shmidt}
5721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_go_disc_req(void)
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = wpabuf_alloc(100);
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_action_hdr(buf, P2P_GO_DISC_REQ, 0);
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_group_go_discover(struct p2p_group *group, const u8 *dev_id,
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  const u8 *searching_dev, int rx_freq)
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_member *m;
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_data *p2p = group->p2p;
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	m = p2p_group_get_client(group, dev_id);
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (m == NULL || m->client_info == NULL) {
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Requested client was not in this "
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "group " MACSTR,
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   MAC2STR(group->cfg->interface_addr));
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!(m->dev_capab & P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Requested client does not support "
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "client discoverability");
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "P2P: Schedule GO Discoverability Request to be "
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "sent to " MACSTR, MAC2STR(dev_id));
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req = p2p_build_go_disc_req();
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL)
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: Should really use group operating frequency here */
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	freq = rx_freq;
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_PENDING_GO_DISC_REQ;
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, m->addr,
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  group->cfg->interface_addr,
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  group->cfg->interface_addr,
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  wpabuf_head(req), wpabuf_len(req), 200) < 0)
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to send Action frame");
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(req);
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * p2p_group_get_interface_addr(struct p2p_group *group)
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return group->cfg->interface_addr;
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu8 p2p_group_presence_req(struct p2p_group *group,
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  const u8 *client_interface_addr,
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  const u8 *noa, size_t noa_len)
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_member *m;
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 curr_noa[50];
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int curr_noa_len;
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	m = p2p_group_get_client_iface(group, client_interface_addr);
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (m == NULL || m->client_info == NULL) {
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Client was not in this group");
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "P2P: Presence Request NoA", noa, noa_len);
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (group->p2p->cfg->get_noa)
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		curr_noa_len = group->p2p->cfg->get_noa(
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group->p2p->cfg->cb_ctx, group->cfg->interface_addr,
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			curr_noa, sizeof(curr_noa));
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		curr_noa_len = -1;
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (curr_noa_len < 0)
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: Failed to fetch current NoA");
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (curr_noa_len == 0)
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "P2P: No NoA being advertized");
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "P2P: Current NoA", curr_noa,
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    curr_noa_len);
6711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: properly process request and store copy */
6731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (curr_noa_len > 0 || curr_noa_len == -1)
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
6751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return P2P_SC_SUCCESS;
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned int p2p_get_group_num_members(struct p2p_group *group)
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return group->num_members;
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * p2p_iterate_group_members(struct p2p_group *group, void **next)
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_group_member *iter = *next;
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!iter)
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		iter = group->members;
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		iter = iter->next;
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*next = iter;
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!iter)
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return iter->addr;
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
702