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" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps/wps_defs.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps/wps_i.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p_i.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_group_member { 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_group_member *next; 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 addr[ETH_ALEN]; /* P2P Interface Address */ 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dev_addr[ETH_ALEN]; /* P2P Device Address */ 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *p2p_ie; 2561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpabuf *wfd_ie; 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *client_info; 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dev_capab; 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * struct p2p_group - Internal P2P module per-group data 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_group { 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_data *p2p; 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_group_config *cfg; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_group_member *members; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int num_members; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int group_formation; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int beacon_update; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *noa; 4161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpabuf *wfd_ie; 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct p2p_group * p2p_group_init(struct p2p_data *p2p, 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_group_config *config) 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_group *group, **groups; 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = os_zalloc(sizeof(*group)); 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group == NULL) 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt groups = os_realloc_array(p2p->groups, p2p->num_groups + 1, 5561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sizeof(struct p2p_group *)); 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (groups == NULL) { 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(group); 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt groups[p2p->num_groups++] = group; 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->groups = groups; 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->p2p = p2p; 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->cfg = config; 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->group_formation = 1; 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->beacon_update = 1; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_group_update_ies(group); 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->cfg->idle_update(group->cfg->cb_ctx, 1); 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return group; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_group_free_member(struct p2p_group_member *m) 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_free(m->wfd_ie); 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(m->p2p_ie); 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(m->client_info); 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(m); 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_group_free_members(struct p2p_group *group) 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_group_member *m, *prev; 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt m = group->members; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->members = NULL; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->num_members = 0; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (m) { 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = m; 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt m = m->next; 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_group_free_member(prev); 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_group_deinit(struct p2p_group *group) 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t g; 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_data *p2p; 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group == NULL) 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p = group->p2p; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (g = 0; g < p2p->num_groups; g++) { 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p2p->groups[g] == group) { 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (g + 1 < p2p->num_groups) { 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->groups[g] = p2p->groups[g + 1]; 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt g++; 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->num_groups--; 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_group_free_members(group); 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(group->cfg); 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(group->noa); 12161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_free(group->wfd_ie); 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(group); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_client_info(struct wpabuf *ie, struct p2p_group_member *m) 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (m->client_info == NULL) 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpabuf_tailroom(ie) < wpabuf_len(m->client_info) + 1) 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_buf(ie, m->client_info); 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_group_add_common_ies(struct p2p_group *group, 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *ie) 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 dev_capab = group->p2p->dev_capab, group_capab = 0; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* P2P Capability */ 14204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt dev_capab &= ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY; 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group_capab |= P2P_GROUP_CAPAB_GROUP_OWNER; 1441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (group->cfg->persistent_group) { 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP; 1461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (group->cfg->persistent_group == 2) 1471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt group_capab |= P2P_GROUP_CAPAB_PERSISTENT_RECONN; 1481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group->p2p->cfg->p2p_intra_bss) 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST; 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group->group_formation) 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group_capab |= P2P_GROUP_CAPAB_GROUP_FORMATION; 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group->p2p->cross_connect) 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group_capab |= P2P_GROUP_CAPAB_CROSS_CONN; 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group->num_members >= group->cfg->max_clients) 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group_capab |= P2P_GROUP_CAPAB_GROUP_LIMIT; 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_buf_add_capability(ie, dev_capab, group_capab); 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_group_add_noa(struct wpabuf *ie, struct wpabuf *noa) 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (noa == NULL) 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Notice of Absence */ 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(ie, P2P_ATTR_NOTICE_OF_ABSENCE); 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_le16(ie, wpabuf_len(noa)); 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_buf(ie, noa); 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_group_build_beacon_ie(struct p2p_group *group) 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *ie; 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *len; 17661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t extra = 0; 17761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 17861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY 17961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (group->p2p->wfd_ie_beacon) 18061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt extra = wpabuf_len(group->p2p->wfd_ie_beacon); 18161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */ 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ie = wpabuf_alloc(257 + extra); 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie == NULL) 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY 18861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (group->p2p->wfd_ie_beacon) 18961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_buf(ie, group->p2p->wfd_ie_beacon); 19061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */ 19161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = p2p_buf_add_ie_hdr(ie); 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_group_add_common_ies(group, ie); 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_buf_add_device_id(ie, group->p2p->cfg->dev_addr); 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_group_add_noa(ie, group->noa); 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_buf_update_ie_hdr(ie, len); 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ie; 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY 20361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 20461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstruct wpabuf * p2p_group_get_wfd_ie(struct p2p_group *g) 20561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 20661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return g->wfd_ie; 20761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 20861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 20961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 21061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstruct wpabuf * wifi_display_encaps(struct wpabuf *subelems) 21161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 21261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpabuf *ie; 21361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *pos, *end; 21461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 21561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (subelems == NULL) 21661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return NULL; 21761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 21861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ie = wpabuf_alloc(wpabuf_len(subelems) + 100); 21961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (ie == NULL) 22061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return NULL; 22161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 22261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos = wpabuf_head(subelems); 22361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt end = pos + wpabuf_len(subelems); 22461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 22561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt while (end > pos) { 22661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t frag_len = end - pos; 22761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (frag_len > 251) 22861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt frag_len = 251; 22961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); 23061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(ie, 4 + frag_len); 23161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_be32(ie, WFD_IE_VENDOR_TYPE); 23261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_data(ie, pos, frag_len); 23361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos += frag_len; 23461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 23561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 23661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return ie; 23761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 23861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 23961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 24061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int wifi_display_add_dev_info_descr(struct wpabuf *buf, 24161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct p2p_group_member *m) 24261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 24361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *pos, *end; 24461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *dev_info = NULL; 24561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *assoc_bssid = NULL; 24661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *coupled_sink = NULL; 24761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 zero_addr[ETH_ALEN]; 24861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 24961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (m->wfd_ie == NULL) 25061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 25161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 25261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_memset(zero_addr, 0, ETH_ALEN); 25361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos = wpabuf_head_u8(m->wfd_ie); 25461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt end = pos + wpabuf_len(m->wfd_ie); 25561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt while (pos + 1 < end) { 25661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 id; 25761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u16 len; 25861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 25961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt id = *pos++; 26061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt len = WPA_GET_BE16(pos); 26161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos += 2; 26261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (pos + len > end) 26361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 26461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 26561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt switch (id) { 26661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt case WFD_SUBELEM_DEVICE_INFO: 26761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (len < 6) 26861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 26961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt dev_info = pos; 27061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 27161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt case WFD_SUBELEM_ASSOCIATED_BSSID: 27261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (len < ETH_ALEN) 27361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 27461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt assoc_bssid = pos; 27561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 27661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt case WFD_SUBELEM_COUPLED_SINK: 27761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (len < 1 + ETH_ALEN) 27861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 27961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt coupled_sink = pos; 28061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 28161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 28261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 28361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos += len; 28461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 28561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 28661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (dev_info == NULL) 28761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 28861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 28961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, 23); 29061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_data(buf, m->dev_addr, ETH_ALEN); 29161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (assoc_bssid) 29261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_data(buf, assoc_bssid, ETH_ALEN); 29361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt else 29461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_data(buf, zero_addr, ETH_ALEN); 29561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_data(buf, dev_info, 2); /* WFD Device Info */ 29661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_data(buf, dev_info + 4, 2); /* WFD Device Max Throughput */ 29761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (coupled_sink) { 29861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_data(buf, coupled_sink, 1 + ETH_ALEN); 29961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else { 30061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, 0); 30161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_data(buf, zero_addr, ETH_ALEN); 30261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 30361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 30461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 1; 30561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 30661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 30761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 30861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic struct wpabuf * 30961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtwifi_display_build_go_ie(struct p2p_group *group) 31061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 31161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpabuf *wfd_subelems, *wfd_ie; 31261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct p2p_group_member *m; 31361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 *len; 31461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt unsigned int count = 0; 31561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 31661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!group->p2p->wfd_ie_probe_resp) 31761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return NULL; 31861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 31961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wfd_subelems = wpabuf_alloc(wpabuf_len(group->p2p->wfd_ie_probe_resp) + 32061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt group->num_members * 24 + 100); 32161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wfd_subelems == NULL) 32261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return NULL; 32361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (group->p2p->wfd_dev_info) 32461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_buf(wfd_subelems, group->p2p->wfd_dev_info); 32561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (group->p2p->wfd_assoc_bssid) 32661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_buf(wfd_subelems, 32761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt group->p2p->wfd_assoc_bssid); 32861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (group->p2p->wfd_coupled_sink_info) 32961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_buf(wfd_subelems, 33061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt group->p2p->wfd_coupled_sink_info); 33161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 33261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* Build WFD Session Info */ 33361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(wfd_subelems, WFD_SUBELEM_SESSION_INFO); 33461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt len = wpabuf_put(wfd_subelems, 2); 33561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt m = group->members; 33661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt while (m) { 33761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wifi_display_add_dev_info_descr(wfd_subelems, m)) 33861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt count++; 33961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt m = m->next; 34061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 34161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 34261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (count == 0) { 34361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* No Wi-Fi Display clients - do not include subelement */ 34461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wfd_subelems->used -= 3; 34561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else { 34661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt WPA_PUT_BE16(len, (u8 *) wpabuf_put(wfd_subelems, 0) - len - 34761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2); 34861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "WFD: WFD Session Info: %u descriptors", 34961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt count); 35061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 35161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 35261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wfd_ie = wifi_display_encaps(wfd_subelems); 35361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_free(wfd_subelems); 35461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 35561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return wfd_ie; 35661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 35761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 35861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void wifi_display_group_update(struct p2p_group *group) 35961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 36061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_free(group->wfd_ie); 36161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt group->wfd_ie = wifi_display_build_go_ie(group); 36261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 36361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 36461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */ 36561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 36661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_group_build_probe_resp_ie(struct p2p_group *group) 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *group_info; 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *ie; 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_group_member *m; 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *len; 37361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t extra = 0; 37461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 37561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY 37661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (group->wfd_ie) 37761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt extra += wpabuf_len(group->wfd_ie); 37861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */ 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ie = wpabuf_alloc(257 + extra); 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie == NULL) 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY 38561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (group->wfd_ie) 38661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_buf(ie, group->wfd_ie); 38761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */ 38861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = p2p_buf_add_ie_hdr(ie); 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_group_add_common_ies(group, ie); 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_group_add_noa(ie, group->noa); 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* P2P Device Info */ 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_buf_add_device_info(ie, group->p2p, NULL); 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* P2P Group Info */ 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group_info = wpabuf_put(ie, 0); 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(ie, P2P_ATTR_GROUP_INFO); 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_le16(ie, 0); /* Length to be filled */ 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (m = group->members; m; m = m->next) 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_client_info(ie, m); 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(group_info + 1, 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) wpabuf_put(ie, 0) - group_info - 3); 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_buf_update_ie_hdr(ie, len); 40761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ie; 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 41261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid p2p_group_update_ies(struct p2p_group *group) 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *beacon_ie; 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *probe_resp_ie; 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 41761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY 41861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wifi_display_group_update(group); 41961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */ 42061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt probe_resp_ie = p2p_group_build_probe_resp_ie(group); 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (probe_resp_ie == NULL) 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf(MSG_MSGDUMP, "P2P: Update GO Probe Response P2P IE", 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt probe_resp_ie); 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group->beacon_update) { 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt beacon_ie = p2p_group_build_beacon_ie(group); 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (beacon_ie) 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->beacon_update = 0; 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf(MSG_MSGDUMP, "P2P: Update GO Beacon P2P IE", 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt beacon_ie); 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt beacon_ie = NULL; 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->cfg->ie_update(group->cfg->cb_ctx, beacon_ie, probe_resp_ie); 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_build_client_info - Build P2P Client Info Descriptor 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: MAC address of the peer device 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @p2p_ie: P2P IE from (Re)Association Request 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dev_capab: Buffer for returning Device Capability 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dev_addr: Buffer for returning P2P Device Address 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: P2P Client Info Descriptor or %NULL on failure 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function builds P2P Client Info Descriptor based on the information 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * available from (Re)Association Request frame. Group owner can use this to 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * build the P2P Group Info attribute for Probe Response frames. 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_client_info(const u8 *addr, 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *p2p_ie, 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *dev_capab, u8 *dev_addr) 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *spos; 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_message msg; 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *len_pos; 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p2p_ie == NULL) 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&msg, 0, sizeof(msg)); 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p2p_parse_p2p_ie(p2p_ie, &msg) || 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg.capability == NULL || msg.p2p_device_info == NULL) 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc(ETH_ALEN + 1 + 1 + msg.p2p_device_info_len); 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *dev_capab = msg.capability[0]; 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(dev_addr, msg.p2p_device_addr, ETH_ALEN); 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt spos = msg.p2p_device_info; /* P2P Device address */ 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* P2P Client Info Descriptor */ 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Length to be set */ 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len_pos = wpabuf_put(buf, 1); 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* P2P Device address */ 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(buf, spos, ETH_ALEN); 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* P2P Interface address */ 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(buf, addr, ETH_ALEN); 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Device Capability Bitmap */ 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(buf, msg.capability[0]); 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Config Methods, Primary Device Type, Number of Secondary Device 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Types, Secondary Device Type List, Device Name copied from 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Device Info 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(buf, spos + ETH_ALEN, 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg.p2p_device_info_len - ETH_ALEN); 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len_pos = wpabuf_len(buf) - 1; 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int p2p_group_remove_member(struct p2p_group *group, const u8 *addr) 5031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 5041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct p2p_group_member *m, *prev; 5051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (group == NULL) 5071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 5081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt m = group->members; 5101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt prev = NULL; 5111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt while (m) { 5121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (os_memcmp(m->addr, addr, ETH_ALEN) == 0) 5131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 5141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt prev = m; 5151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt m = m->next; 5161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 5171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (m == NULL) 5191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 5201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (prev) 5221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt prev->next = m->next; 5231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt else 5241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt group->members = m->next; 5251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt p2p_group_free_member(m); 5261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt group->num_members--; 5271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 1; 5291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 5301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_group_notif_assoc(struct p2p_group *group, const u8 *addr, 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ie, size_t len) 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_group_member *m; 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group == NULL) 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt m = os_zalloc(sizeof(*m)); 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (m == NULL) 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(m->addr, addr, ETH_ALEN); 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt m->p2p_ie = ieee802_11_vendor_ie_concat(ie, len, P2P_IE_VENDOR_TYPE); 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (m->p2p_ie) { 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt m->client_info = p2p_build_client_info(addr, m->p2p_ie, 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &m->dev_capab, 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt m->dev_addr); 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 55061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY 55161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt m->wfd_ie = ieee802_11_vendor_ie_concat(ie, len, WFD_IE_VENDOR_TYPE); 55261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */ 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt p2p_group_remove_member(group, addr); 5551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt m->next = group->members; 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->members = m; 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->num_members++; 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(group->p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Add client " MACSTR 56061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt " to group (p2p=%d wfd=%d client_info=%d); num_members=%u/%u", 56161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt MAC2STR(addr), m->p2p_ie ? 1 : 0, m->wfd_ie ? 1 : 0, 56261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt m->client_info ? 1 : 0, 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->num_members, group->cfg->max_clients); 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group->num_members == group->cfg->max_clients) 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->beacon_update = 1; 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_group_update_ies(group); 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group->num_members == 1) 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->cfg->idle_update(group->cfg->cb_ctx, 0); 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * p2p_group_assoc_resp_ie(struct p2p_group *group, u8 status) 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rlen; 57861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t extra = 0; 57961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 58061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY 58161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (group->wfd_ie) 58261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt extra = wpabuf_len(group->wfd_ie); 58361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */ 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * (Re)Association Response - P2P IE 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Status attribute (shall be present when association request is 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * denied) 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Extended Listen Timing (may be present) 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 59161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt resp = wpabuf_alloc(20 + extra); 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 59461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 59561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY 59661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (group->wfd_ie) 59761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_buf(resp, group->wfd_ie); 59861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */ 59961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rlen = p2p_buf_add_ie_hdr(resp); 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (status != P2P_SC_SUCCESS) 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_buf_add_status(resp, status); 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_buf_update_ie_hdr(resp, rlen); 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_group_notif_disassoc(struct p2p_group *group, const u8 *addr) 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (p2p_group_remove_member(group, addr)) { 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(group->p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Remove " 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "client " MACSTR " from group; num_members=%u/%u", 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(addr), group->num_members, 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->cfg->max_clients); 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group->num_members == group->cfg->max_clients - 1) 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->beacon_update = 1; 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_group_update_ies(group); 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group->num_members == 0) 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->cfg->idle_update(group->cfg->cb_ctx, 1); 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_match_dev_type_member - Match client device type with requested type 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @m: Group member 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wps: WPS TLVs from Probe Request frame (concatenated WPS IEs) 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 on match, 0 on mismatch 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function can be used to match the Requested Device Type attribute in 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPS IE with the device types of a group member for deciding whether a GO 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * should reply to a Probe Request frame. 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int p2p_match_dev_type_member(struct p2p_group_member *m, 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *wps) 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_parse_attr attr; 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 num_sec; 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (m->client_info == NULL || wps == NULL) 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpabuf_head(m->client_info); 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + wpabuf_len(m->client_info); 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 1 + 2 * ETH_ALEN + 1 + 2; 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < WPS_DEV_TYPE_LEN + 1) 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_parse_msg(wps, &attr)) 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; /* assume no Requested Device Type attributes */ 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr.num_req_dev_type == 0) 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; /* no Requested Device Type attributes -> match */ 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dev_type_list_match(pos, attr.req_dev_type, attr.num_req_dev_type)) 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; /* Match with client Primary Device Type */ 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += WPS_DEV_TYPE_LEN; 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_sec = *pos++; 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < num_sec * WPS_DEV_TYPE_LEN) 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (num_sec > 0) { 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_sec--; 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dev_type_list_match(pos, attr.req_dev_type, 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr.num_req_dev_type)) 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; /* Match with client Secondary Device Type */ 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += WPS_DEV_TYPE_LEN; 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No matching device type found */ 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_group_match_dev_type(struct p2p_group *group, struct wpabuf *wps) 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_group_member *m; 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p2p_match_dev_type(group->p2p, wps)) 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; /* Match with own device type */ 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (m = group->members; m; m = m->next) { 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p2p_match_dev_type_member(m, wps)) 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; /* Match with group client device type */ 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No match with Requested Device Type */ 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 695c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtint p2p_group_match_dev_id(struct p2p_group *group, struct wpabuf *p2p) 696c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{ 697c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct p2p_group_member *m; 698c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct p2p_message msg; 699c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 700c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt os_memset(&msg, 0, sizeof(msg)); 701c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (p2p_parse_p2p_ie(p2p, &msg)) 702c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return 1; /* Failed to parse - assume no filter on Device ID */ 703c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 704c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (!msg.device_id) 705c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return 1; /* No filter on Device ID */ 706c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 707c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (os_memcmp(msg.device_id, group->p2p->cfg->dev_addr, ETH_ALEN) == 0) 708c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return 1; /* Match with our P2P Device Address */ 709c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 710c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt for (m = group->members; m; m = m->next) { 711c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (os_memcmp(msg.device_id, m->dev_addr, ETH_ALEN) == 0) 712c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return 1; /* Match with group client P2P Device Address */ 713c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 714c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 715c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* No match with Device ID */ 716c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return 0; 717c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt} 718c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 719c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_group_notif_formation_done(struct p2p_group *group) 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group == NULL) 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->group_formation = 0; 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->beacon_update = 1; 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_group_update_ies(group); 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_group_notif_noa(struct p2p_group *group, const u8 *noa, 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t noa_len) 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (noa == NULL) { 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(group->noa); 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->noa = NULL; 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group->noa) { 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpabuf_size(group->noa) >= noa_len) { 739fc41cadcff448cdd2b60e376fc6e7378e2e57b5eDmitry Shmidt group->noa->used = 0; 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(group->noa, noa, noa_len); 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(group->noa); 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->noa = NULL; 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!group->noa) { 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->noa = wpabuf_alloc_copy(noa, noa_len); 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group->noa == NULL) 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->beacon_update = 1; 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_group_update_ies(group); 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct p2p_group_member * p2p_group_get_client(struct p2p_group *group, 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *dev_id) 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_group_member *m; 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (m = group->members; m; m = m->next) { 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(dev_id, m->dev_addr, ETH_ALEN) == 0) 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return m; 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct p2p_group_member * p2p_group_get_client_iface( 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_group *group, const u8 *interface_addr) 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_group_member *m; 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (m = group->members; m; m = m->next) { 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(interface_addr, m->addr, ETH_ALEN) == 0) 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return m; 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtconst u8 * p2p_group_get_dev_addr(struct p2p_group *group, const u8 *addr) 789dca3979ccdf869f140f096b83df322a0efc84f22Dmitry Shmidt{ 790dca3979ccdf869f140f096b83df322a0efc84f22Dmitry Shmidt struct p2p_group_member *m; 791dca3979ccdf869f140f096b83df322a0efc84f22Dmitry Shmidt 7921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (group == NULL) 7931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 794dca3979ccdf869f140f096b83df322a0efc84f22Dmitry Shmidt m = p2p_group_get_client_iface(group, addr); 7951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (m && !is_zero_ether_addr(m->dev_addr)) 796dca3979ccdf869f140f096b83df322a0efc84f22Dmitry Shmidt return m->dev_addr; 7971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 798dca3979ccdf869f140f096b83df322a0efc84f22Dmitry Shmidt} 7991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_go_disc_req(void) 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc(100); 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_buf_add_action_hdr(buf, P2P_GO_DISC_REQ, 0); 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_group_go_discover(struct p2p_group *group, const u8 *dev_id, 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *searching_dev, int rx_freq) 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_group_member *m; 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *req; 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_data *p2p = group->p2p; 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int freq; 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt m = p2p_group_get_client(group, dev_id); 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (m == NULL || m->client_info == NULL) { 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "P2P: Requested client was not in this " 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "group " MACSTR, 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(group->cfg->interface_addr)); 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(m->dev_capab & P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) { 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "P2P: Requested client does not support " 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "client discoverability"); 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "P2P: Schedule GO Discoverability Request to be " 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "sent to " MACSTR, MAC2STR(dev_id)); 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = p2p_build_go_disc_req(); 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req == NULL) 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: Should really use group operating frequency here */ 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt freq = rx_freq; 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p->pending_action_state = P2P_PENDING_GO_DISC_REQ; 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, m->addr, 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->cfg->interface_addr, 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->cfg->interface_addr, 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(req), wpabuf_len(req), 200) < 0) 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "P2P: Failed to send Action frame"); 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(req); 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * p2p_group_get_interface_addr(struct p2p_group *group) 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return group->cfg->interface_addr; 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu8 p2p_group_presence_req(struct p2p_group *group, 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *client_interface_addr, 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *noa, size_t noa_len) 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_group_member *m; 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 curr_noa[50]; 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int curr_noa_len; 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt m = p2p_group_get_client_iface(group, client_interface_addr); 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (m == NULL || m->client_info == NULL) { 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "P2P: Client was not in this group"); 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE; 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "P2P: Presence Request NoA", noa, noa_len); 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group->p2p->cfg->get_noa) 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt curr_noa_len = group->p2p->cfg->get_noa( 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->p2p->cfg->cb_ctx, group->cfg->interface_addr, 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt curr_noa, sizeof(curr_noa)); 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt curr_noa_len = -1; 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (curr_noa_len < 0) 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "P2P: Failed to fetch current NoA"); 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (curr_noa_len == 0) 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "P2P: No NoA being advertized"); 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "P2P: Current NoA", curr_noa, 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt curr_noa_len); 8981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: properly process request and store copy */ 9001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (curr_noa_len > 0 || curr_noa_len == -1) 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE; 9021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return P2P_SC_SUCCESS; 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned int p2p_get_group_num_members(struct p2p_group *group) 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return group->num_members; 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * p2p_iterate_group_members(struct p2p_group *group, void **next) 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_group_member *iter = *next; 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!iter) 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iter = group->members; 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iter = iter->next; 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *next = iter; 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!iter) 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return iter->addr; 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 929c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 930c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 931c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtint p2p_group_is_client_connected(struct p2p_group *group, const u8 *dev_addr) 932c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{ 933c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct p2p_group_member *m; 934c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 935c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt for (m = group->members; m; m = m->next) { 936c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (os_memcmp(m->dev_addr, dev_addr, ETH_ALEN) == 0) 937c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return 1; 938c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 939c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 940c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return 0; 941c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt} 94204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 94304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 94404949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint p2p_group_is_group_id_match(struct p2p_group *group, const u8 *group_id, 94504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt size_t group_id_len) 94604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 94704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (group_id_len != ETH_ALEN + group->cfg->ssid_len) 94804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; 94904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (os_memcmp(group_id, group->p2p->cfg->dev_addr, ETH_ALEN) != 0) 95004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; 95104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return os_memcmp(group_id + ETH_ALEN, group->cfg->ssid, 95204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt group->cfg->ssid_len) == 0; 95304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 954