diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index a6c546ca9..8b354494e 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -183,10 +183,8 @@ skip_wpa_check: ieee802_1x_notify_port_enabled(sta->eapol_sm, 1); #ifdef CONFIG_P2P - if (elems.p2p) { - p2p_group_notif_assoc(hapd->p2p_group, sta->addr, - all_ies, all_ies_len); - } + p2p_group_notif_assoc(hapd->p2p_group, sta->addr, + all_ies, all_ies_len); #endif /* CONFIG_P2P */ return 0; diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index c73a79459..241240fca 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -781,17 +781,12 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, sta->p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len, P2P_IE_VENDOR_TYPE); - if (p2p_group_notif_assoc(hapd->p2p_group, sta->addr, - ies, ies_len) < 0) { - wpa_printf(MSG_DEBUG, "P2P: Invalid P2P IE in " - "(Re)Association Request frame from " - MACSTR, MAC2STR(sta->addr)); - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } } else { wpabuf_free(sta->p2p_ie); sta->p2p_ie = NULL; } + + p2p_group_notif_assoc(hapd->p2p_group, sta->addr, ies, ies_len); #endif /* CONFIG_P2P */ return WLAN_STATUS_SUCCESS; diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index d425eb751..108af5d4b 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -1014,6 +1014,11 @@ struct p2p_group_config { */ u8 interface_addr[ETH_ALEN]; + /** + * max_clients - Maximum number of clients in the group + */ + unsigned int max_clients; + /** * cb_ctx - Context to use with callback functions */ diff --git a/src/p2p/p2p_group.c b/src/p2p/p2p_group.c index 4ee84cded..22a1ca73c 100644 --- a/src/p2p/p2p_group.c +++ b/src/p2p/p2p_group.c @@ -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; } diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 950e51690..ab298f2b0 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -3014,6 +3014,11 @@ struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s, cfg->persistent_group = persistent_group; os_memcpy(cfg->interface_addr, wpa_s->own_addr, ETH_ALEN); + if (wpa_s->max_stations && + wpa_s->max_stations < wpa_s->conf->max_num_sta) + cfg->max_clients = wpa_s->max_stations; + else + cfg->max_clients = wpa_s->conf->max_num_sta; cfg->cb_ctx = wpa_s; cfg->ie_update = wpas_p2p_ie_update;