|
@@ -39,6 +39,7 @@ struct p2p_group {
|
|
|
struct p2p_data *p2p;
|
|
|
struct p2p_group_config *cfg;
|
|
|
struct p2p_group_member *members;
|
|
|
+ unsigned int num_members;
|
|
|
int group_formation;
|
|
|
int beacon_update;
|
|
|
struct wpabuf *noa;
|
|
@@ -89,6 +90,7 @@ static void p2p_group_free_members(struct p2p_group *group)
|
|
|
struct p2p_group_member *m, *prev;
|
|
|
m = group->members;
|
|
|
group->members = NULL;
|
|
|
+ group->num_members = 0;
|
|
|
while (m) {
|
|
|
prev = m;
|
|
|
m = m->next;
|
|
@@ -127,6 +129,8 @@ void p2p_group_deinit(struct p2p_group *group)
|
|
|
|
|
|
static void p2p_client_info(struct wpabuf *ie, struct p2p_group_member *m)
|
|
|
{
|
|
|
+ if (m->client_info == NULL)
|
|
|
+ return;
|
|
|
if (wpabuf_tailroom(ie) < wpabuf_len(m->client_info) + 1)
|
|
|
return;
|
|
|
wpabuf_put_buf(ie, m->client_info);
|
|
@@ -150,6 +154,8 @@ static void p2p_group_add_common_ies(struct p2p_group *group,
|
|
|
group_capab |= P2P_GROUP_CAPAB_GROUP_FORMATION;
|
|
|
if (group->p2p->cross_connect)
|
|
|
group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
|
|
|
+ if (group->num_members >= group->cfg->max_clients)
|
|
|
+ group_capab |= P2P_GROUP_CAPAB_GROUP_LIMIT;
|
|
|
p2p_buf_add_capability(ie, dev_capab, group_capab);
|
|
|
}
|
|
|
|
|
@@ -316,31 +322,21 @@ int p2p_group_notif_assoc(struct p2p_group *group, const u8 *addr,
|
|
|
return -1;
|
|
|
os_memcpy(m->addr, addr, ETH_ALEN);
|
|
|
m->p2p_ie = ieee802_11_vendor_ie_concat(ie, len, P2P_IE_VENDOR_TYPE);
|
|
|
- if (m->p2p_ie == NULL) {
|
|
|
- p2p_group_free_member(m);
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- m->client_info = p2p_build_client_info(addr, m->p2p_ie, &m->dev_capab,
|
|
|
- m->dev_addr);
|
|
|
- if (m->client_info == NULL) {
|
|
|
- /*
|
|
|
- * This can happen, e.g., when a P2P client connects to a P2P
|
|
|
- * group using the infrastructure WLAN interface instead of
|
|
|
- * P2P group interface. In that case, the P2P client may behave
|
|
|
- * as if the GO would be a P2P Manager WLAN AP.
|
|
|
- */
|
|
|
- wpa_msg(group->p2p->cfg->msg_ctx, MSG_DEBUG,
|
|
|
- "P2P: Could not build Client Info from P2P IE - "
|
|
|
- "assume " MACSTR " is not a P2P client",
|
|
|
- MAC2STR(addr));
|
|
|
- p2p_group_free_member(m);
|
|
|
- return 0;
|
|
|
+ if (m->p2p_ie) {
|
|
|
+ m->client_info = p2p_build_client_info(addr, m->p2p_ie,
|
|
|
+ &m->dev_capab,
|
|
|
+ m->dev_addr);
|
|
|
}
|
|
|
|
|
|
m->next = group->members;
|
|
|
group->members = m;
|
|
|
-
|
|
|
+ group->num_members++;
|
|
|
+ wpa_msg(group->p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Add client " MACSTR
|
|
|
+ " to group (p2p=%d client_info=%d); num_members=%u/%u",
|
|
|
+ MAC2STR(addr), m->p2p_ie ? 1 : 0, m->client_info ? 1 : 0,
|
|
|
+ group->num_members, group->cfg->max_clients);
|
|
|
+ if (group->num_members == group->cfg->max_clients)
|
|
|
+ group->beacon_update = 1;
|
|
|
p2p_group_update_ies(group);
|
|
|
|
|
|
return 0;
|
|
@@ -392,6 +388,13 @@ void p2p_group_notif_disassoc(struct p2p_group *group, const u8 *addr)
|
|
|
else
|
|
|
group->members = m->next;
|
|
|
p2p_group_free_member(m);
|
|
|
+ group->num_members--;
|
|
|
+ wpa_msg(group->p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Remove "
|
|
|
+ "client " MACSTR " from group; num_members=%u/%u",
|
|
|
+ MAC2STR(addr), group->num_members,
|
|
|
+ group->cfg->max_clients);
|
|
|
+ if (group->num_members == group->cfg->max_clients - 1)
|
|
|
+ group->beacon_update = 1;
|
|
|
p2p_group_update_ies(group);
|
|
|
}
|
|
|
}
|
|
@@ -558,7 +561,7 @@ int p2p_group_go_discover(struct p2p_group *group, const u8 *dev_id,
|
|
|
int freq;
|
|
|
|
|
|
m = p2p_group_get_client(group, dev_id);
|
|
|
- if (m == NULL) {
|
|
|
+ if (m == NULL || m->client_info == NULL) {
|
|
|
wpa_printf(MSG_DEBUG, "P2P: Requested client was not in this "
|
|
|
"group " MACSTR,
|
|
|
MAC2STR(group->cfg->interface_addr));
|
|
@@ -612,7 +615,7 @@ u8 p2p_group_presence_req(struct p2p_group *group,
|
|
|
int curr_noa_len;
|
|
|
|
|
|
m = p2p_group_get_client_iface(group, client_interface_addr);
|
|
|
- if (m == NULL) {
|
|
|
+ if (m == NULL || m->client_info == NULL) {
|
|
|
wpa_printf(MSG_DEBUG, "P2P: Client was not in this group");
|
|
|
return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
|
|
|
}
|