Home | History | Annotate | Download | only in p2p
      1 /*
      2  * Wi-Fi Direct - P2P group operations
      3  * Copyright (c) 2009-2010, Atheros Communications
      4  *
      5  * This program is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License version 2 as
      7  * published by the Free Software Foundation.
      8  *
      9  * Alternatively, this software may be distributed under the terms of BSD
     10  * license.
     11  *
     12  * See README and COPYING for more details.
     13  */
     14 
     15 #include "includes.h"
     16 
     17 #include "common.h"
     18 #include "common/ieee802_11_defs.h"
     19 #include "common/ieee802_11_common.h"
     20 #include "wps/wps_defs.h"
     21 #include "wps/wps_i.h"
     22 #include "p2p_i.h"
     23 #include "p2p.h"
     24 
     25 
     26 struct p2p_group_member {
     27 	struct p2p_group_member *next;
     28 	u8 addr[ETH_ALEN]; /* P2P Interface Address */
     29 	u8 dev_addr[ETH_ALEN]; /* P2P Device Address */
     30 	struct wpabuf *p2p_ie;
     31 	struct wpabuf *client_info;
     32 	u8 dev_capab;
     33 };
     34 
     35 /**
     36  * struct p2p_group - Internal P2P module per-group data
     37  */
     38 struct p2p_group {
     39 	struct p2p_data *p2p;
     40 	struct p2p_group_config *cfg;
     41 	struct p2p_group_member *members;
     42 	unsigned int num_members;
     43 	int group_formation;
     44 	int beacon_update;
     45 	struct wpabuf *noa;
     46 };
     47 
     48 
     49 static void p2p_group_update_ies(struct p2p_group *group);
     50 
     51 
     52 struct p2p_group * p2p_group_init(struct p2p_data *p2p,
     53 				  struct p2p_group_config *config)
     54 {
     55 	struct p2p_group *group, **groups;
     56 
     57 	group = os_zalloc(sizeof(*group));
     58 	if (group == NULL)
     59 		return NULL;
     60 
     61 	groups = os_realloc(p2p->groups, (p2p->num_groups + 1) *
     62 			    sizeof(struct p2p_group *));
     63 	if (groups == NULL) {
     64 		os_free(group);
     65 		return NULL;
     66 	}
     67 	groups[p2p->num_groups++] = group;
     68 	p2p->groups = groups;
     69 
     70 	group->p2p = p2p;
     71 	group->cfg = config;
     72 	group->group_formation = 1;
     73 	group->beacon_update = 1;
     74 	p2p_group_update_ies(group);
     75 	group->cfg->idle_update(group->cfg->cb_ctx, 1);
     76 
     77 	return group;
     78 }
     79 
     80 
     81 static void p2p_group_free_member(struct p2p_group_member *m)
     82 {
     83 	wpabuf_free(m->p2p_ie);
     84 	wpabuf_free(m->client_info);
     85 	os_free(m);
     86 }
     87 
     88 
     89 static void p2p_group_free_members(struct p2p_group *group)
     90 {
     91 	struct p2p_group_member *m, *prev;
     92 	m = group->members;
     93 	group->members = NULL;
     94 	group->num_members = 0;
     95 	while (m) {
     96 		prev = m;
     97 		m = m->next;
     98 		p2p_group_free_member(prev);
     99 	}
    100 }
    101 
    102 
    103 void p2p_group_deinit(struct p2p_group *group)
    104 {
    105 	size_t g;
    106 	struct p2p_data *p2p;
    107 
    108 	if (group == NULL)
    109 		return;
    110 
    111 	p2p = group->p2p;
    112 
    113 	for (g = 0; g < p2p->num_groups; g++) {
    114 		if (p2p->groups[g] == group) {
    115 			while (g + 1 < p2p->num_groups) {
    116 				p2p->groups[g] = p2p->groups[g + 1];
    117 				g++;
    118 			}
    119 			p2p->num_groups--;
    120 			break;
    121 		}
    122 	}
    123 
    124 	p2p_group_free_members(group);
    125 	os_free(group->cfg);
    126 	wpabuf_free(group->noa);
    127 	os_free(group);
    128 }
    129 
    130 
    131 static void p2p_client_info(struct wpabuf *ie, struct p2p_group_member *m)
    132 {
    133 	if (m->client_info == NULL)
    134 		return;
    135 	if (wpabuf_tailroom(ie) < wpabuf_len(m->client_info) + 1)
    136 		return;
    137 	wpabuf_put_buf(ie, m->client_info);
    138 }
    139 
    140 
    141 static void p2p_group_add_common_ies(struct p2p_group *group,
    142 				     struct wpabuf *ie)
    143 {
    144 	u8 dev_capab = 0, group_capab = 0;
    145 
    146 	/* P2P Capability */
    147 	dev_capab |= P2P_DEV_CAPAB_SERVICE_DISCOVERY;
    148 	dev_capab |= P2P_DEV_CAPAB_INVITATION_PROCEDURE;
    149 	group_capab |= P2P_GROUP_CAPAB_GROUP_OWNER;
    150 	if (group->cfg->persistent_group)
    151 		group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
    152 	if (group->p2p->cfg->p2p_intra_bss)
    153 		group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST;
    154 	if (group->group_formation)
    155 		group_capab |= P2P_GROUP_CAPAB_GROUP_FORMATION;
    156 	if (group->p2p->cross_connect)
    157 		group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
    158 	if (group->num_members >= group->cfg->max_clients)
    159 		group_capab |= P2P_GROUP_CAPAB_GROUP_LIMIT;
    160 	p2p_buf_add_capability(ie, dev_capab, group_capab);
    161 }
    162 
    163 
    164 static void p2p_group_add_noa(struct wpabuf *ie, struct wpabuf *noa)
    165 {
    166 	if (noa == NULL)
    167 		return;
    168 	/* Notice of Absence */
    169 	wpabuf_put_u8(ie, P2P_ATTR_NOTICE_OF_ABSENCE);
    170 	wpabuf_put_le16(ie, wpabuf_len(noa));
    171 	wpabuf_put_buf(ie, noa);
    172 }
    173 
    174 
    175 static struct wpabuf * p2p_group_build_beacon_ie(struct p2p_group *group)
    176 {
    177 	struct wpabuf *ie;
    178 	u8 *len;
    179 
    180 	ie = wpabuf_alloc(257);
    181 	if (ie == NULL)
    182 		return NULL;
    183 
    184 	len = p2p_buf_add_ie_hdr(ie);
    185 	p2p_group_add_common_ies(group, ie);
    186 #ifdef ANDROID_BRCM_P2P_PATCH
    187 	/* P2P_ADDR: Use p2p_dev_addr instead of own mac addr*/
    188 	p2p_buf_add_device_id(ie, group->p2p->cfg->p2p_dev_addr);
    189 #else
    190 	p2p_buf_add_device_id(ie, group->p2p->cfg->dev_addr);
    191 #endif
    192 	p2p_group_add_noa(ie, group->noa);
    193 	p2p_buf_update_ie_hdr(ie, len);
    194 
    195 	return ie;
    196 }
    197 
    198 
    199 static struct wpabuf * p2p_group_build_probe_resp_ie(struct p2p_group *group)
    200 {
    201 	u8 *group_info;
    202 	struct wpabuf *ie;
    203 	struct p2p_group_member *m;
    204 	u8 *len;
    205 
    206 	ie = wpabuf_alloc(257);
    207 	if (ie == NULL)
    208 		return NULL;
    209 
    210 	len = p2p_buf_add_ie_hdr(ie);
    211 
    212 	p2p_group_add_common_ies(group, ie);
    213 	p2p_group_add_noa(ie, group->noa);
    214 
    215 	/* P2P Device Info */
    216 	p2p_buf_add_device_info(ie, group->p2p, NULL);
    217 
    218 	/* P2P Group Info */
    219 	group_info = wpabuf_put(ie, 0);
    220 	wpabuf_put_u8(ie, P2P_ATTR_GROUP_INFO);
    221 	wpabuf_put_le16(ie, 0); /* Length to be filled */
    222 	for (m = group->members; m; m = m->next)
    223 		p2p_client_info(ie, m);
    224 	WPA_PUT_LE16(group_info + 1,
    225 		     (u8 *) wpabuf_put(ie, 0) - group_info - 3);
    226 
    227 	p2p_buf_update_ie_hdr(ie, len);
    228 	return ie;
    229 }
    230 
    231 
    232 static void p2p_group_update_ies(struct p2p_group *group)
    233 {
    234 	struct wpabuf *beacon_ie;
    235 	struct wpabuf *probe_resp_ie;
    236 
    237 	probe_resp_ie = p2p_group_build_probe_resp_ie(group);
    238 	if (probe_resp_ie == NULL)
    239 		return;
    240 	wpa_hexdump_buf(MSG_MSGDUMP, "P2P: Update GO Probe Response P2P IE",
    241 			probe_resp_ie);
    242 
    243 	if (group->beacon_update) {
    244 		beacon_ie = p2p_group_build_beacon_ie(group);
    245 		if (beacon_ie)
    246 			group->beacon_update = 0;
    247 		wpa_hexdump_buf(MSG_MSGDUMP, "P2P: Update GO Beacon P2P IE",
    248 				beacon_ie);
    249 	} else
    250 		beacon_ie = NULL;
    251 
    252 	group->cfg->ie_update(group->cfg->cb_ctx, beacon_ie, probe_resp_ie);
    253 }
    254 
    255 
    256 /**
    257  * p2p_build_client_info - Build P2P Client Info Descriptor
    258  * @addr: MAC address of the peer device
    259  * @p2p_ie: P2P IE from (Re)Association Request
    260  * @dev_capab: Buffer for returning Device Capability
    261  * @dev_addr: Buffer for returning P2P Device Address
    262  * Returns: P2P Client Info Descriptor or %NULL on failure
    263  *
    264  * This function builds P2P Client Info Descriptor based on the information
    265  * available from (Re)Association Request frame. Group owner can use this to
    266  * build the P2P Group Info attribute for Probe Response frames.
    267  */
    268 static struct wpabuf * p2p_build_client_info(const u8 *addr,
    269 					     struct wpabuf *p2p_ie,
    270 					     u8 *dev_capab, u8 *dev_addr)
    271 {
    272 	const u8 *spos;
    273 	struct p2p_message msg;
    274 	u8 *len_pos;
    275 	struct wpabuf *buf;
    276 
    277 	if (p2p_ie == NULL)
    278 		return NULL;
    279 
    280 	os_memset(&msg, 0, sizeof(msg));
    281 	if (p2p_parse_p2p_ie(p2p_ie, &msg) ||
    282 	    msg.capability == NULL || msg.p2p_device_info == NULL)
    283 		return NULL;
    284 
    285 	buf = wpabuf_alloc(ETH_ALEN + 1 + 1 + msg.p2p_device_info_len);
    286 	if (buf == NULL)
    287 		return NULL;
    288 
    289 	*dev_capab = msg.capability[0];
    290 	os_memcpy(dev_addr, msg.p2p_device_addr, ETH_ALEN);
    291 
    292 	spos = msg.p2p_device_info; /* P2P Device address */
    293 
    294 	/* P2P Client Info Descriptor */
    295 	/* Length to be set */
    296 	len_pos = wpabuf_put(buf, 1);
    297 	/* P2P Device address */
    298 	wpabuf_put_data(buf, spos, ETH_ALEN);
    299 	/* P2P Interface address */
    300 	wpabuf_put_data(buf, addr, ETH_ALEN);
    301 	/* Device Capability Bitmap */
    302 	wpabuf_put_u8(buf, msg.capability[0]);
    303 	/*
    304 	 * Config Methods, Primary Device Type, Number of Secondary Device
    305 	 * Types, Secondary Device Type List, Device Name copied from
    306 	 * Device Info
    307 	 */
    308 	wpabuf_put_data(buf, spos + ETH_ALEN,
    309 			msg.p2p_device_info_len - ETH_ALEN);
    310 
    311 	*len_pos = wpabuf_len(buf) - 1;
    312 
    313 
    314 	return buf;
    315 }
    316 
    317 
    318 int p2p_group_notif_assoc(struct p2p_group *group, const u8 *addr,
    319 			  const u8 *ie, size_t len)
    320 {
    321 	struct p2p_group_member *m;
    322 
    323 	if (group == NULL)
    324 		return -1;
    325 
    326 	m = os_zalloc(sizeof(*m));
    327 	if (m == NULL)
    328 		return -1;
    329 	os_memcpy(m->addr, addr, ETH_ALEN);
    330 	m->p2p_ie = ieee802_11_vendor_ie_concat(ie, len, P2P_IE_VENDOR_TYPE);
    331 	if (m->p2p_ie) {
    332 		m->client_info = p2p_build_client_info(addr, m->p2p_ie,
    333 						       &m->dev_capab,
    334 						       m->dev_addr);
    335 	}
    336 
    337 	m->next = group->members;
    338 	group->members = m;
    339 	group->num_members++;
    340 	wpa_msg(group->p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Add client " MACSTR
    341 		" to group (p2p=%d client_info=%d); num_members=%u/%u",
    342 		MAC2STR(addr), m->p2p_ie ? 1 : 0, m->client_info ? 1 : 0,
    343 		group->num_members, group->cfg->max_clients);
    344 	if (group->num_members == group->cfg->max_clients)
    345 		group->beacon_update = 1;
    346 	p2p_group_update_ies(group);
    347 	if (group->num_members == 1)
    348 		group->cfg->idle_update(group->cfg->cb_ctx, 0);
    349 
    350 	return 0;
    351 }
    352 
    353 
    354 struct wpabuf * p2p_group_assoc_resp_ie(struct p2p_group *group, u8 status)
    355 {
    356 	struct wpabuf *resp;
    357 	u8 *rlen;
    358 
    359 	/*
    360 	 * (Re)Association Response - P2P IE
    361 	 * Status attribute (shall be present when association request is
    362 	 *	denied)
    363 	 * Extended Listen Timing (may be present)
    364 	 */
    365 	resp = wpabuf_alloc(20);
    366 	if (resp == NULL)
    367 		return NULL;
    368 	rlen = p2p_buf_add_ie_hdr(resp);
    369 	if (status != P2P_SC_SUCCESS)
    370 		p2p_buf_add_status(resp, status);
    371 	p2p_buf_update_ie_hdr(resp, rlen);
    372 
    373 	return resp;
    374 }
    375 
    376 
    377 void p2p_group_notif_disassoc(struct p2p_group *group, const u8 *addr)
    378 {
    379 	struct p2p_group_member *m, *prev;
    380 
    381 	if (group == NULL)
    382 		return;
    383 
    384 	m = group->members;
    385 	prev = NULL;
    386 	while (m) {
    387 		if (os_memcmp(m->addr, addr, ETH_ALEN) == 0)
    388 			break;
    389 		prev = m;
    390 		m = m->next;
    391 	}
    392 
    393 	if (m) {
    394 		if (prev)
    395 			prev->next = m->next;
    396 		else
    397 			group->members = m->next;
    398 		p2p_group_free_member(m);
    399 		group->num_members--;
    400 		wpa_msg(group->p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Remove "
    401 			"client " MACSTR " from group; num_members=%u/%u",
    402 			MAC2STR(addr), group->num_members,
    403 			group->cfg->max_clients);
    404 		if (group->num_members == group->cfg->max_clients - 1)
    405 			group->beacon_update = 1;
    406 		p2p_group_update_ies(group);
    407 		if (group->num_members == 0)
    408 			group->cfg->idle_update(group->cfg->cb_ctx, 1);
    409 	}
    410 }
    411 
    412 
    413 /**
    414  * p2p_match_dev_type_member - Match client device type with requested type
    415  * @m: Group member
    416  * @wps: WPS TLVs from Probe Request frame (concatenated WPS IEs)
    417  * Returns: 1 on match, 0 on mismatch
    418  *
    419  * This function can be used to match the Requested Device Type attribute in
    420  * WPS IE with the device types of a group member for deciding whether a GO
    421  * should reply to a Probe Request frame.
    422  */
    423 static int p2p_match_dev_type_member(struct p2p_group_member *m,
    424 				     struct wpabuf *wps)
    425 {
    426 	const u8 *pos, *end;
    427 	struct wps_parse_attr attr;
    428 	u8 num_sec;
    429 
    430 	if (m->client_info == NULL || wps == NULL)
    431 		return 0;
    432 
    433 	pos = wpabuf_head(m->client_info);
    434 	end = pos + wpabuf_len(m->client_info);
    435 
    436 	pos += 1 + 2 * ETH_ALEN + 1 + 2;
    437 	if (end - pos < WPS_DEV_TYPE_LEN + 1)
    438 		return 0;
    439 
    440 	if (wps_parse_msg(wps, &attr))
    441 		return 1; /* assume no Requested Device Type attributes */
    442 
    443 	if (attr.num_req_dev_type == 0)
    444 		return 1; /* no Requested Device Type attributes -> match */
    445 
    446 	if (dev_type_list_match(pos, attr.req_dev_type, attr.num_req_dev_type))
    447 		return 1; /* Match with client Primary Device Type */
    448 
    449 	pos += WPS_DEV_TYPE_LEN;
    450 	num_sec = *pos++;
    451 	if (end - pos < num_sec * WPS_DEV_TYPE_LEN)
    452 		return 0;
    453 	while (num_sec > 0) {
    454 		num_sec--;
    455 		if (dev_type_list_match(pos, attr.req_dev_type,
    456 					attr.num_req_dev_type))
    457 			return 1; /* Match with client Secondary Device Type */
    458 		pos += WPS_DEV_TYPE_LEN;
    459 	}
    460 
    461 	/* No matching device type found */
    462 	return 0;
    463 }
    464 
    465 
    466 int p2p_group_match_dev_type(struct p2p_group *group, struct wpabuf *wps)
    467 {
    468 	struct p2p_group_member *m;
    469 
    470 	if (p2p_match_dev_type(group->p2p, wps))
    471 		return 1; /* Match with own device type */
    472 
    473 	for (m = group->members; m; m = m->next) {
    474 		if (p2p_match_dev_type_member(m, wps))
    475 			return 1; /* Match with group client device type */
    476 	}
    477 
    478 	/* No match with Requested Device Type */
    479 	return 0;
    480 }
    481 
    482 
    483 void p2p_group_notif_formation_done(struct p2p_group *group)
    484 {
    485 	if (group == NULL)
    486 		return;
    487 	group->group_formation = 0;
    488 	group->beacon_update = 1;
    489 	p2p_group_update_ies(group);
    490 }
    491 
    492 
    493 int p2p_group_notif_noa(struct p2p_group *group, const u8 *noa,
    494 			size_t noa_len)
    495 {
    496 	if (noa == NULL) {
    497 		wpabuf_free(group->noa);
    498 		group->noa = NULL;
    499 	} else {
    500 		if (group->noa) {
    501 			if (wpabuf_size(group->noa) >= noa_len) {
    502 			#ifdef ANDROID_BRCM_P2P_PATCH
    503 				group->noa->used = 0;
    504 			#else
    505 				group->noa->size = 0;
    506 			#endif
    507 				wpabuf_put_data(group->noa, noa, noa_len);
    508 			} else {
    509 				wpabuf_free(group->noa);
    510 				group->noa = NULL;
    511 			}
    512 		}
    513 
    514 		if (!group->noa) {
    515 			group->noa = wpabuf_alloc_copy(noa, noa_len);
    516 			if (group->noa == NULL)
    517 				return -1;
    518 		}
    519 	}
    520 
    521 	group->beacon_update = 1;
    522 	p2p_group_update_ies(group);
    523 	return 0;
    524 }
    525 
    526 
    527 static struct p2p_group_member * p2p_group_get_client(struct p2p_group *group,
    528 						      const u8 *dev_id)
    529 {
    530 	struct p2p_group_member *m;
    531 
    532 	for (m = group->members; m; m = m->next) {
    533 		if (os_memcmp(dev_id, m->dev_addr, ETH_ALEN) == 0)
    534 			return m;
    535 	}
    536 
    537 	return NULL;
    538 }
    539 
    540 
    541 static struct p2p_group_member * p2p_group_get_client_iface(
    542 	struct p2p_group *group, const u8 *interface_addr)
    543 {
    544 	struct p2p_group_member *m;
    545 
    546 	for (m = group->members; m; m = m->next) {
    547 		if (os_memcmp(interface_addr, m->addr, ETH_ALEN) == 0)
    548 			return m;
    549 	}
    550 
    551 	return NULL;
    552 }
    553 
    554 #ifdef ANDROID_BRCM_P2P_PATCH
    555 u8 * p2p_group_get_dev_addr(struct p2p_group *group, const u8 *addr)
    556 {
    557 	struct p2p_group_member *m;
    558 
    559 	m = p2p_group_get_client_iface(group, addr);
    560 
    561 	if (m)
    562 		return m->dev_addr;
    563 	else
    564 		return NULL;
    565 }
    566 #endif /* ANDROID_BRCM_P2P_PATCH */
    567 
    568 static struct wpabuf * p2p_build_go_disc_req(void)
    569 {
    570 	struct wpabuf *buf;
    571 
    572 	buf = wpabuf_alloc(100);
    573 	if (buf == NULL)
    574 		return NULL;
    575 
    576 	p2p_buf_add_action_hdr(buf, P2P_GO_DISC_REQ, 0);
    577 
    578 	return buf;
    579 }
    580 
    581 
    582 int p2p_group_go_discover(struct p2p_group *group, const u8 *dev_id,
    583 			  const u8 *searching_dev, int rx_freq)
    584 {
    585 	struct p2p_group_member *m;
    586 	struct wpabuf *req;
    587 	struct p2p_data *p2p = group->p2p;
    588 	int freq;
    589 
    590 	m = p2p_group_get_client(group, dev_id);
    591 	if (m == NULL || m->client_info == NULL) {
    592 		wpa_printf(MSG_DEBUG, "P2P: Requested client was not in this "
    593 			   "group " MACSTR,
    594 			   MAC2STR(group->cfg->interface_addr));
    595 		return -1;
    596 	}
    597 
    598 	if (!(m->dev_capab & P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
    599 		wpa_printf(MSG_DEBUG, "P2P: Requested client does not support "
    600 			   "client discoverability");
    601 		return -1;
    602 	}
    603 
    604 	wpa_printf(MSG_DEBUG, "P2P: Schedule GO Discoverability Request to be "
    605 		   "sent to " MACSTR, MAC2STR(dev_id));
    606 
    607 	req = p2p_build_go_disc_req();
    608 	if (req == NULL)
    609 		return -1;
    610 
    611 	/* TODO: Should really use group operating frequency here */
    612 	freq = rx_freq;
    613 
    614 	p2p->pending_action_state = P2P_PENDING_GO_DISC_REQ;
    615 	if (p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, m->addr,
    616 				  group->cfg->interface_addr,
    617 				  group->cfg->interface_addr,
    618 				  wpabuf_head(req), wpabuf_len(req), 200) < 0)
    619 	{
    620 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
    621 			"P2P: Failed to send Action frame");
    622 	}
    623 
    624 	wpabuf_free(req);
    625 
    626 	return 0;
    627 }
    628 
    629 
    630 const u8 * p2p_group_get_interface_addr(struct p2p_group *group)
    631 {
    632 	return group->cfg->interface_addr;
    633 }
    634 
    635 
    636 u8 p2p_group_presence_req(struct p2p_group *group,
    637 			  const u8 *client_interface_addr,
    638 			  const u8 *noa, size_t noa_len)
    639 {
    640 	struct p2p_group_member *m;
    641 	u8 curr_noa[50];
    642 	int curr_noa_len;
    643 
    644 	m = p2p_group_get_client_iface(group, client_interface_addr);
    645 	if (m == NULL || m->client_info == NULL) {
    646 		wpa_printf(MSG_DEBUG, "P2P: Client was not in this group");
    647 		return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
    648 	}
    649 
    650 	wpa_hexdump(MSG_DEBUG, "P2P: Presence Request NoA", noa, noa_len);
    651 
    652 	if (group->p2p->cfg->get_noa)
    653 		curr_noa_len = group->p2p->cfg->get_noa(
    654 			group->p2p->cfg->cb_ctx, group->cfg->interface_addr,
    655 			curr_noa, sizeof(curr_noa));
    656 	else
    657 		curr_noa_len = -1;
    658 	if (curr_noa_len < 0)
    659 		wpa_printf(MSG_DEBUG, "P2P: Failed to fetch current NoA");
    660 	else if (curr_noa_len == 0)
    661 		wpa_printf(MSG_DEBUG, "P2P: No NoA being advertized");
    662 	else
    663 		wpa_hexdump(MSG_DEBUG, "P2P: Current NoA", curr_noa,
    664 			    curr_noa_len);
    665 #ifndef ANDROID_BRCM_P2P_PATCH
    666 	/* TODO: properly process request and store copy */
    667 	if (curr_noa_len > 0)
    668 		return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
    669 #endif
    670 	return P2P_SC_SUCCESS;
    671 }
    672 
    673 
    674 unsigned int p2p_get_group_num_members(struct p2p_group *group)
    675 {
    676 	return group->num_members;
    677 }
    678 
    679 
    680 const u8 * p2p_iterate_group_members(struct p2p_group *group, void **next)
    681 {
    682 	struct p2p_group_member *iter = *next;
    683 
    684 	if (!iter)
    685 		iter = group->members;
    686 	else
    687 		iter = iter->next;
    688 
    689 	*next = iter;
    690 
    691 	if (!iter)
    692 		return NULL;
    693 
    694 	return iter->addr;
    695 }
    696