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 software may be distributed under the terms of the BSD license.
      6  * See README for more details.
      7  */
      8 
      9 #include "includes.h"
     10 
     11 #include "common.h"
     12 #include "common/ieee802_11_defs.h"
     13 #include "common/ieee802_11_common.h"
     14 #include "wps/wps_defs.h"
     15 #include "wps/wps_i.h"
     16 #include "p2p_i.h"
     17 #include "p2p.h"
     18 
     19 
     20 struct p2p_group_member {
     21 	struct p2p_group_member *next;
     22 	u8 addr[ETH_ALEN]; /* P2P Interface Address */
     23 	u8 dev_addr[ETH_ALEN]; /* P2P Device Address */
     24 	struct wpabuf *p2p_ie;
     25 	struct wpabuf *wfd_ie;
     26 	struct wpabuf *client_info;
     27 	u8 dev_capab;
     28 };
     29 
     30 /**
     31  * struct p2p_group - Internal P2P module per-group data
     32  */
     33 struct p2p_group {
     34 	struct p2p_data *p2p;
     35 	struct p2p_group_config *cfg;
     36 	struct p2p_group_member *members;
     37 	unsigned int num_members;
     38 	int group_formation;
     39 	int beacon_update;
     40 	struct wpabuf *noa;
     41 	struct wpabuf *wfd_ie;
     42 };
     43 
     44 
     45 struct p2p_group * p2p_group_init(struct p2p_data *p2p,
     46 				  struct p2p_group_config *config)
     47 {
     48 	struct p2p_group *group, **groups;
     49 
     50 	group = os_zalloc(sizeof(*group));
     51 	if (group == NULL)
     52 		return NULL;
     53 
     54 	groups = os_realloc_array(p2p->groups, p2p->num_groups + 1,
     55 				  sizeof(struct p2p_group *));
     56 	if (groups == NULL) {
     57 		os_free(group);
     58 		return NULL;
     59 	}
     60 	groups[p2p->num_groups++] = group;
     61 	p2p->groups = groups;
     62 
     63 	group->p2p = p2p;
     64 	group->cfg = config;
     65 	group->group_formation = 1;
     66 	group->beacon_update = 1;
     67 	p2p_group_update_ies(group);
     68 	group->cfg->idle_update(group->cfg->cb_ctx, 1);
     69 
     70 	return group;
     71 }
     72 
     73 
     74 static void p2p_group_free_member(struct p2p_group_member *m)
     75 {
     76 	wpabuf_free(m->wfd_ie);
     77 	wpabuf_free(m->p2p_ie);
     78 	wpabuf_free(m->client_info);
     79 	os_free(m);
     80 }
     81 
     82 
     83 static void p2p_group_free_members(struct p2p_group *group)
     84 {
     85 	struct p2p_group_member *m, *prev;
     86 	m = group->members;
     87 	group->members = NULL;
     88 	group->num_members = 0;
     89 	while (m) {
     90 		prev = m;
     91 		m = m->next;
     92 		p2p_group_free_member(prev);
     93 	}
     94 }
     95 
     96 
     97 void p2p_group_deinit(struct p2p_group *group)
     98 {
     99 	size_t g;
    100 	struct p2p_data *p2p;
    101 
    102 	if (group == NULL)
    103 		return;
    104 
    105 	p2p = group->p2p;
    106 
    107 	for (g = 0; g < p2p->num_groups; g++) {
    108 		if (p2p->groups[g] == group) {
    109 			while (g + 1 < p2p->num_groups) {
    110 				p2p->groups[g] = p2p->groups[g + 1];
    111 				g++;
    112 			}
    113 			p2p->num_groups--;
    114 			break;
    115 		}
    116 	}
    117 
    118 	p2p_group_free_members(group);
    119 	os_free(group->cfg);
    120 	wpabuf_free(group->noa);
    121 	wpabuf_free(group->wfd_ie);
    122 	os_free(group);
    123 }
    124 
    125 
    126 static void p2p_client_info(struct wpabuf *ie, struct p2p_group_member *m)
    127 {
    128 	if (m->client_info == NULL)
    129 		return;
    130 	if (wpabuf_tailroom(ie) < wpabuf_len(m->client_info) + 1)
    131 		return;
    132 	wpabuf_put_buf(ie, m->client_info);
    133 }
    134 
    135 
    136 static void p2p_group_add_common_ies(struct p2p_group *group,
    137 				     struct wpabuf *ie)
    138 {
    139 	u8 dev_capab = group->p2p->dev_capab, group_capab = 0;
    140 
    141 	/* P2P Capability */
    142 	dev_capab &= ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
    143 	group_capab |= P2P_GROUP_CAPAB_GROUP_OWNER;
    144 	if (group->cfg->persistent_group) {
    145 		group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
    146 		if (group->cfg->persistent_group == 2)
    147 			group_capab |= P2P_GROUP_CAPAB_PERSISTENT_RECONN;
    148 	}
    149 	if (group->p2p->cfg->p2p_intra_bss)
    150 		group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST;
    151 	if (group->group_formation)
    152 		group_capab |= P2P_GROUP_CAPAB_GROUP_FORMATION;
    153 	if (group->p2p->cross_connect)
    154 		group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
    155 	if (group->num_members >= group->cfg->max_clients)
    156 		group_capab |= P2P_GROUP_CAPAB_GROUP_LIMIT;
    157 	p2p_buf_add_capability(ie, dev_capab, group_capab);
    158 }
    159 
    160 
    161 static void p2p_group_add_noa(struct wpabuf *ie, struct wpabuf *noa)
    162 {
    163 	if (noa == NULL)
    164 		return;
    165 	/* Notice of Absence */
    166 	wpabuf_put_u8(ie, P2P_ATTR_NOTICE_OF_ABSENCE);
    167 	wpabuf_put_le16(ie, wpabuf_len(noa));
    168 	wpabuf_put_buf(ie, noa);
    169 }
    170 
    171 
    172 static struct wpabuf * p2p_group_build_beacon_ie(struct p2p_group *group)
    173 {
    174 	struct wpabuf *ie;
    175 	u8 *len;
    176 	size_t extra = 0;
    177 
    178 #ifdef CONFIG_WIFI_DISPLAY
    179 	if (group->p2p->wfd_ie_beacon)
    180 		extra = wpabuf_len(group->p2p->wfd_ie_beacon);
    181 #endif /* CONFIG_WIFI_DISPLAY */
    182 
    183 	ie = wpabuf_alloc(257 + extra);
    184 	if (ie == NULL)
    185 		return NULL;
    186 
    187 #ifdef CONFIG_WIFI_DISPLAY
    188 	if (group->p2p->wfd_ie_beacon)
    189 		wpabuf_put_buf(ie, group->p2p->wfd_ie_beacon);
    190 #endif /* CONFIG_WIFI_DISPLAY */
    191 
    192 	len = p2p_buf_add_ie_hdr(ie);
    193 	p2p_group_add_common_ies(group, ie);
    194 	p2p_buf_add_device_id(ie, group->p2p->cfg->dev_addr);
    195 	p2p_group_add_noa(ie, group->noa);
    196 	p2p_buf_update_ie_hdr(ie, len);
    197 
    198 	return ie;
    199 }
    200 
    201 
    202 #ifdef CONFIG_WIFI_DISPLAY
    203 
    204 struct wpabuf * p2p_group_get_wfd_ie(struct p2p_group *g)
    205 {
    206 	return g->wfd_ie;
    207 }
    208 
    209 
    210 struct wpabuf * wifi_display_encaps(struct wpabuf *subelems)
    211 {
    212 	struct wpabuf *ie;
    213 	const u8 *pos, *end;
    214 
    215 	if (subelems == NULL)
    216 		return NULL;
    217 
    218 	ie = wpabuf_alloc(wpabuf_len(subelems) + 100);
    219 	if (ie == NULL)
    220 		return NULL;
    221 
    222 	pos = wpabuf_head(subelems);
    223 	end = pos + wpabuf_len(subelems);
    224 
    225 	while (end > pos) {
    226 		size_t frag_len = end - pos;
    227 		if (frag_len > 251)
    228 			frag_len = 251;
    229 		wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC);
    230 		wpabuf_put_u8(ie, 4 + frag_len);
    231 		wpabuf_put_be32(ie, WFD_IE_VENDOR_TYPE);
    232 		wpabuf_put_data(ie, pos, frag_len);
    233 		pos += frag_len;
    234 	}
    235 
    236 	return ie;
    237 }
    238 
    239 
    240 static int wifi_display_add_dev_info_descr(struct wpabuf *buf,
    241 					   struct p2p_group_member *m)
    242 {
    243 	const u8 *pos, *end;
    244 	const u8 *dev_info = NULL;
    245 	const u8 *assoc_bssid = NULL;
    246 	const u8 *coupled_sink = NULL;
    247 	u8 zero_addr[ETH_ALEN];
    248 
    249 	if (m->wfd_ie == NULL)
    250 		return 0;
    251 
    252 	os_memset(zero_addr, 0, ETH_ALEN);
    253 	pos = wpabuf_head_u8(m->wfd_ie);
    254 	end = pos + wpabuf_len(m->wfd_ie);
    255 	while (pos + 1 < end) {
    256 		u8 id;
    257 		u16 len;
    258 
    259 		id = *pos++;
    260 		len = WPA_GET_BE16(pos);
    261 		pos += 2;
    262 		if (pos + len > end)
    263 			break;
    264 
    265 		switch (id) {
    266 		case WFD_SUBELEM_DEVICE_INFO:
    267 			if (len < 6)
    268 				break;
    269 			dev_info = pos;
    270 			break;
    271 		case WFD_SUBELEM_ASSOCIATED_BSSID:
    272 			if (len < ETH_ALEN)
    273 				break;
    274 			assoc_bssid = pos;
    275 			break;
    276 		case WFD_SUBELEM_COUPLED_SINK:
    277 			if (len < 1 + ETH_ALEN)
    278 				break;
    279 			coupled_sink = pos;
    280 			break;
    281 		}
    282 
    283 		pos += len;
    284 	}
    285 
    286 	if (dev_info == NULL)
    287 		return 0;
    288 
    289 	wpabuf_put_u8(buf, 23);
    290 	wpabuf_put_data(buf, m->dev_addr, ETH_ALEN);
    291 	if (assoc_bssid)
    292 		wpabuf_put_data(buf, assoc_bssid, ETH_ALEN);
    293 	else
    294 		wpabuf_put_data(buf, zero_addr, ETH_ALEN);
    295 	wpabuf_put_data(buf, dev_info, 2); /* WFD Device Info */
    296 	wpabuf_put_data(buf, dev_info + 4, 2); /* WFD Device Max Throughput */
    297 	if (coupled_sink) {
    298 		wpabuf_put_data(buf, coupled_sink, 1 + ETH_ALEN);
    299 	} else {
    300 		wpabuf_put_u8(buf, 0);
    301 		wpabuf_put_data(buf, zero_addr, ETH_ALEN);
    302 	}
    303 
    304 	return 1;
    305 }
    306 
    307 
    308 static struct wpabuf *
    309 wifi_display_build_go_ie(struct p2p_group *group)
    310 {
    311 	struct wpabuf *wfd_subelems, *wfd_ie;
    312 	struct p2p_group_member *m;
    313 	u8 *len;
    314 	unsigned int count = 0;
    315 
    316 	if (!group->p2p->wfd_ie_probe_resp)
    317 		return NULL;
    318 
    319 	wfd_subelems = wpabuf_alloc(wpabuf_len(group->p2p->wfd_ie_probe_resp) +
    320 				    group->num_members * 24 + 100);
    321 	if (wfd_subelems == NULL)
    322 		return NULL;
    323 	if (group->p2p->wfd_dev_info)
    324 		wpabuf_put_buf(wfd_subelems, group->p2p->wfd_dev_info);
    325 	if (group->p2p->wfd_assoc_bssid)
    326 		wpabuf_put_buf(wfd_subelems,
    327 			       group->p2p->wfd_assoc_bssid);
    328 	if (group->p2p->wfd_coupled_sink_info)
    329 		wpabuf_put_buf(wfd_subelems,
    330 			       group->p2p->wfd_coupled_sink_info);
    331 
    332 	/* Build WFD Session Info */
    333 	wpabuf_put_u8(wfd_subelems, WFD_SUBELEM_SESSION_INFO);
    334 	len = wpabuf_put(wfd_subelems, 2);
    335 	m = group->members;
    336 	while (m) {
    337 		if (wifi_display_add_dev_info_descr(wfd_subelems, m))
    338 			count++;
    339 		m = m->next;
    340 	}
    341 
    342 	if (count == 0) {
    343 		/* No Wi-Fi Display clients - do not include subelement */
    344 		wfd_subelems->used -= 3;
    345 	} else {
    346 		WPA_PUT_BE16(len, (u8 *) wpabuf_put(wfd_subelems, 0) - len -
    347 			     2);
    348 		wpa_printf(MSG_DEBUG, "WFD: WFD Session Info: %u descriptors",
    349 			   count);
    350 	}
    351 
    352 	wfd_ie = wifi_display_encaps(wfd_subelems);
    353 	wpabuf_free(wfd_subelems);
    354 
    355 	return wfd_ie;
    356 }
    357 
    358 static void wifi_display_group_update(struct p2p_group *group)
    359 {
    360 	wpabuf_free(group->wfd_ie);
    361 	group->wfd_ie = wifi_display_build_go_ie(group);
    362 }
    363 
    364 #endif /* CONFIG_WIFI_DISPLAY */
    365 
    366 
    367 static struct wpabuf * p2p_group_build_probe_resp_ie(struct p2p_group *group)
    368 {
    369 	u8 *group_info;
    370 	struct wpabuf *ie;
    371 	struct p2p_group_member *m;
    372 	u8 *len;
    373 	size_t extra = 0;
    374 
    375 #ifdef CONFIG_WIFI_DISPLAY
    376 	if (group->wfd_ie)
    377 		extra += wpabuf_len(group->wfd_ie);
    378 #endif /* CONFIG_WIFI_DISPLAY */
    379 
    380 	ie = wpabuf_alloc(257 + extra);
    381 	if (ie == NULL)
    382 		return NULL;
    383 
    384 #ifdef CONFIG_WIFI_DISPLAY
    385 	if (group->wfd_ie)
    386 		wpabuf_put_buf(ie, group->wfd_ie);
    387 #endif /* CONFIG_WIFI_DISPLAY */
    388 
    389 	len = p2p_buf_add_ie_hdr(ie);
    390 
    391 	p2p_group_add_common_ies(group, ie);
    392 	p2p_group_add_noa(ie, group->noa);
    393 
    394 	/* P2P Device Info */
    395 	p2p_buf_add_device_info(ie, group->p2p, NULL);
    396 
    397 	/* P2P Group Info */
    398 	group_info = wpabuf_put(ie, 0);
    399 	wpabuf_put_u8(ie, P2P_ATTR_GROUP_INFO);
    400 	wpabuf_put_le16(ie, 0); /* Length to be filled */
    401 	for (m = group->members; m; m = m->next)
    402 		p2p_client_info(ie, m);
    403 	WPA_PUT_LE16(group_info + 1,
    404 		     (u8 *) wpabuf_put(ie, 0) - group_info - 3);
    405 
    406 	p2p_buf_update_ie_hdr(ie, len);
    407 
    408 	return ie;
    409 }
    410 
    411 
    412 void p2p_group_update_ies(struct p2p_group *group)
    413 {
    414 	struct wpabuf *beacon_ie;
    415 	struct wpabuf *probe_resp_ie;
    416 
    417 #ifdef CONFIG_WIFI_DISPLAY
    418 	wifi_display_group_update(group);
    419 #endif /* CONFIG_WIFI_DISPLAY */
    420 
    421 	probe_resp_ie = p2p_group_build_probe_resp_ie(group);
    422 	if (probe_resp_ie == NULL)
    423 		return;
    424 	wpa_hexdump_buf(MSG_MSGDUMP, "P2P: Update GO Probe Response P2P IE",
    425 			probe_resp_ie);
    426 
    427 	if (group->beacon_update) {
    428 		beacon_ie = p2p_group_build_beacon_ie(group);
    429 		if (beacon_ie)
    430 			group->beacon_update = 0;
    431 		wpa_hexdump_buf(MSG_MSGDUMP, "P2P: Update GO Beacon P2P IE",
    432 				beacon_ie);
    433 	} else
    434 		beacon_ie = NULL;
    435 
    436 	group->cfg->ie_update(group->cfg->cb_ctx, beacon_ie, probe_resp_ie);
    437 }
    438 
    439 
    440 /**
    441  * p2p_build_client_info - Build P2P Client Info Descriptor
    442  * @addr: MAC address of the peer device
    443  * @p2p_ie: P2P IE from (Re)Association Request
    444  * @dev_capab: Buffer for returning Device Capability
    445  * @dev_addr: Buffer for returning P2P Device Address
    446  * Returns: P2P Client Info Descriptor or %NULL on failure
    447  *
    448  * This function builds P2P Client Info Descriptor based on the information
    449  * available from (Re)Association Request frame. Group owner can use this to
    450  * build the P2P Group Info attribute for Probe Response frames.
    451  */
    452 static struct wpabuf * p2p_build_client_info(const u8 *addr,
    453 					     struct wpabuf *p2p_ie,
    454 					     u8 *dev_capab, u8 *dev_addr)
    455 {
    456 	const u8 *spos;
    457 	struct p2p_message msg;
    458 	u8 *len_pos;
    459 	struct wpabuf *buf;
    460 
    461 	if (p2p_ie == NULL)
    462 		return NULL;
    463 
    464 	os_memset(&msg, 0, sizeof(msg));
    465 	if (p2p_parse_p2p_ie(p2p_ie, &msg) ||
    466 	    msg.capability == NULL || msg.p2p_device_info == NULL)
    467 		return NULL;
    468 
    469 	buf = wpabuf_alloc(ETH_ALEN + 1 + 1 + msg.p2p_device_info_len);
    470 	if (buf == NULL)
    471 		return NULL;
    472 
    473 	*dev_capab = msg.capability[0];
    474 	os_memcpy(dev_addr, msg.p2p_device_addr, ETH_ALEN);
    475 
    476 	spos = msg.p2p_device_info; /* P2P Device address */
    477 
    478 	/* P2P Client Info Descriptor */
    479 	/* Length to be set */
    480 	len_pos = wpabuf_put(buf, 1);
    481 	/* P2P Device address */
    482 	wpabuf_put_data(buf, spos, ETH_ALEN);
    483 	/* P2P Interface address */
    484 	wpabuf_put_data(buf, addr, ETH_ALEN);
    485 	/* Device Capability Bitmap */
    486 	wpabuf_put_u8(buf, msg.capability[0]);
    487 	/*
    488 	 * Config Methods, Primary Device Type, Number of Secondary Device
    489 	 * Types, Secondary Device Type List, Device Name copied from
    490 	 * Device Info
    491 	 */
    492 	wpabuf_put_data(buf, spos + ETH_ALEN,
    493 			msg.p2p_device_info_len - ETH_ALEN);
    494 
    495 	*len_pos = wpabuf_len(buf) - 1;
    496 
    497 
    498 	return buf;
    499 }
    500 
    501 
    502 static int p2p_group_remove_member(struct p2p_group *group, const u8 *addr)
    503 {
    504 	struct p2p_group_member *m, *prev;
    505 
    506 	if (group == NULL)
    507 		return 0;
    508 
    509 	m = group->members;
    510 	prev = NULL;
    511 	while (m) {
    512 		if (os_memcmp(m->addr, addr, ETH_ALEN) == 0)
    513 			break;
    514 		prev = m;
    515 		m = m->next;
    516 	}
    517 
    518 	if (m == NULL)
    519 		return 0;
    520 
    521 	if (prev)
    522 		prev->next = m->next;
    523 	else
    524 		group->members = m->next;
    525 	p2p_group_free_member(m);
    526 	group->num_members--;
    527 
    528 	return 1;
    529 }
    530 
    531 
    532 int p2p_group_notif_assoc(struct p2p_group *group, const u8 *addr,
    533 			  const u8 *ie, size_t len)
    534 {
    535 	struct p2p_group_member *m;
    536 
    537 	if (group == NULL)
    538 		return -1;
    539 
    540 	m = os_zalloc(sizeof(*m));
    541 	if (m == NULL)
    542 		return -1;
    543 	os_memcpy(m->addr, addr, ETH_ALEN);
    544 	m->p2p_ie = ieee802_11_vendor_ie_concat(ie, len, P2P_IE_VENDOR_TYPE);
    545 	if (m->p2p_ie) {
    546 		m->client_info = p2p_build_client_info(addr, m->p2p_ie,
    547 						       &m->dev_capab,
    548 						       m->dev_addr);
    549 	}
    550 #ifdef CONFIG_WIFI_DISPLAY
    551 	m->wfd_ie = ieee802_11_vendor_ie_concat(ie, len, WFD_IE_VENDOR_TYPE);
    552 #endif /* CONFIG_WIFI_DISPLAY */
    553 
    554 	p2p_group_remove_member(group, addr);
    555 
    556 	m->next = group->members;
    557 	group->members = m;
    558 	group->num_members++;
    559 	wpa_msg(group->p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Add client " MACSTR
    560 		" to group (p2p=%d wfd=%d client_info=%d); num_members=%u/%u",
    561 		MAC2STR(addr), m->p2p_ie ? 1 : 0, m->wfd_ie ? 1 : 0,
    562 		m->client_info ? 1 : 0,
    563 		group->num_members, group->cfg->max_clients);
    564 	if (group->num_members == group->cfg->max_clients)
    565 		group->beacon_update = 1;
    566 	p2p_group_update_ies(group);
    567 	if (group->num_members == 1)
    568 		group->cfg->idle_update(group->cfg->cb_ctx, 0);
    569 
    570 	return 0;
    571 }
    572 
    573 
    574 struct wpabuf * p2p_group_assoc_resp_ie(struct p2p_group *group, u8 status)
    575 {
    576 	struct wpabuf *resp;
    577 	u8 *rlen;
    578 	size_t extra = 0;
    579 
    580 #ifdef CONFIG_WIFI_DISPLAY
    581 	if (group->wfd_ie)
    582 		extra = wpabuf_len(group->wfd_ie);
    583 #endif /* CONFIG_WIFI_DISPLAY */
    584 
    585 	/*
    586 	 * (Re)Association Response - P2P IE
    587 	 * Status attribute (shall be present when association request is
    588 	 *	denied)
    589 	 * Extended Listen Timing (may be present)
    590 	 */
    591 	resp = wpabuf_alloc(20 + extra);
    592 	if (resp == NULL)
    593 		return NULL;
    594 
    595 #ifdef CONFIG_WIFI_DISPLAY
    596 	if (group->wfd_ie)
    597 		wpabuf_put_buf(resp, group->wfd_ie);
    598 #endif /* CONFIG_WIFI_DISPLAY */
    599 
    600 	rlen = p2p_buf_add_ie_hdr(resp);
    601 	if (status != P2P_SC_SUCCESS)
    602 		p2p_buf_add_status(resp, status);
    603 	p2p_buf_update_ie_hdr(resp, rlen);
    604 
    605 	return resp;
    606 }
    607 
    608 
    609 void p2p_group_notif_disassoc(struct p2p_group *group, const u8 *addr)
    610 {
    611 	if (p2p_group_remove_member(group, addr)) {
    612 		wpa_msg(group->p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Remove "
    613 			"client " MACSTR " from group; num_members=%u/%u",
    614 			MAC2STR(addr), group->num_members,
    615 			group->cfg->max_clients);
    616 		if (group->num_members == group->cfg->max_clients - 1)
    617 			group->beacon_update = 1;
    618 		p2p_group_update_ies(group);
    619 		if (group->num_members == 0)
    620 			group->cfg->idle_update(group->cfg->cb_ctx, 1);
    621 	}
    622 }
    623 
    624 
    625 /**
    626  * p2p_match_dev_type_member - Match client device type with requested type
    627  * @m: Group member
    628  * @wps: WPS TLVs from Probe Request frame (concatenated WPS IEs)
    629  * Returns: 1 on match, 0 on mismatch
    630  *
    631  * This function can be used to match the Requested Device Type attribute in
    632  * WPS IE with the device types of a group member for deciding whether a GO
    633  * should reply to a Probe Request frame.
    634  */
    635 static int p2p_match_dev_type_member(struct p2p_group_member *m,
    636 				     struct wpabuf *wps)
    637 {
    638 	const u8 *pos, *end;
    639 	struct wps_parse_attr attr;
    640 	u8 num_sec;
    641 
    642 	if (m->client_info == NULL || wps == NULL)
    643 		return 0;
    644 
    645 	pos = wpabuf_head(m->client_info);
    646 	end = pos + wpabuf_len(m->client_info);
    647 
    648 	pos += 1 + 2 * ETH_ALEN + 1 + 2;
    649 	if (end - pos < WPS_DEV_TYPE_LEN + 1)
    650 		return 0;
    651 
    652 	if (wps_parse_msg(wps, &attr))
    653 		return 1; /* assume no Requested Device Type attributes */
    654 
    655 	if (attr.num_req_dev_type == 0)
    656 		return 1; /* no Requested Device Type attributes -> match */
    657 
    658 	if (dev_type_list_match(pos, attr.req_dev_type, attr.num_req_dev_type))
    659 		return 1; /* Match with client Primary Device Type */
    660 
    661 	pos += WPS_DEV_TYPE_LEN;
    662 	num_sec = *pos++;
    663 	if (end - pos < num_sec * WPS_DEV_TYPE_LEN)
    664 		return 0;
    665 	while (num_sec > 0) {
    666 		num_sec--;
    667 		if (dev_type_list_match(pos, attr.req_dev_type,
    668 					attr.num_req_dev_type))
    669 			return 1; /* Match with client Secondary Device Type */
    670 		pos += WPS_DEV_TYPE_LEN;
    671 	}
    672 
    673 	/* No matching device type found */
    674 	return 0;
    675 }
    676 
    677 
    678 int p2p_group_match_dev_type(struct p2p_group *group, struct wpabuf *wps)
    679 {
    680 	struct p2p_group_member *m;
    681 
    682 	if (p2p_match_dev_type(group->p2p, wps))
    683 		return 1; /* Match with own device type */
    684 
    685 	for (m = group->members; m; m = m->next) {
    686 		if (p2p_match_dev_type_member(m, wps))
    687 			return 1; /* Match with group client device type */
    688 	}
    689 
    690 	/* No match with Requested Device Type */
    691 	return 0;
    692 }
    693 
    694 
    695 int p2p_group_match_dev_id(struct p2p_group *group, struct wpabuf *p2p)
    696 {
    697 	struct p2p_group_member *m;
    698 	struct p2p_message msg;
    699 
    700 	os_memset(&msg, 0, sizeof(msg));
    701 	if (p2p_parse_p2p_ie(p2p, &msg))
    702 		return 1; /* Failed to parse - assume no filter on Device ID */
    703 
    704 	if (!msg.device_id)
    705 		return 1; /* No filter on Device ID */
    706 
    707 	if (os_memcmp(msg.device_id, group->p2p->cfg->dev_addr, ETH_ALEN) == 0)
    708 		return 1; /* Match with our P2P Device Address */
    709 
    710 	for (m = group->members; m; m = m->next) {
    711 		if (os_memcmp(msg.device_id, m->dev_addr, ETH_ALEN) == 0)
    712 			return 1; /* Match with group client P2P Device Address */
    713 	}
    714 
    715 	/* No match with Device ID */
    716 	return 0;
    717 }
    718 
    719 
    720 void p2p_group_notif_formation_done(struct p2p_group *group)
    721 {
    722 	if (group == NULL)
    723 		return;
    724 	group->group_formation = 0;
    725 	group->beacon_update = 1;
    726 	p2p_group_update_ies(group);
    727 }
    728 
    729 
    730 int p2p_group_notif_noa(struct p2p_group *group, const u8 *noa,
    731 			size_t noa_len)
    732 {
    733 	if (noa == NULL) {
    734 		wpabuf_free(group->noa);
    735 		group->noa = NULL;
    736 	} else {
    737 		if (group->noa) {
    738 			if (wpabuf_size(group->noa) >= noa_len) {
    739 				group->noa->used = 0;
    740 				wpabuf_put_data(group->noa, noa, noa_len);
    741 			} else {
    742 				wpabuf_free(group->noa);
    743 				group->noa = NULL;
    744 			}
    745 		}
    746 
    747 		if (!group->noa) {
    748 			group->noa = wpabuf_alloc_copy(noa, noa_len);
    749 			if (group->noa == NULL)
    750 				return -1;
    751 		}
    752 	}
    753 
    754 	group->beacon_update = 1;
    755 	p2p_group_update_ies(group);
    756 	return 0;
    757 }
    758 
    759 
    760 static struct p2p_group_member * p2p_group_get_client(struct p2p_group *group,
    761 						      const u8 *dev_id)
    762 {
    763 	struct p2p_group_member *m;
    764 
    765 	for (m = group->members; m; m = m->next) {
    766 		if (os_memcmp(dev_id, m->dev_addr, ETH_ALEN) == 0)
    767 			return m;
    768 	}
    769 
    770 	return NULL;
    771 }
    772 
    773 
    774 static struct p2p_group_member * p2p_group_get_client_iface(
    775 	struct p2p_group *group, const u8 *interface_addr)
    776 {
    777 	struct p2p_group_member *m;
    778 
    779 	for (m = group->members; m; m = m->next) {
    780 		if (os_memcmp(interface_addr, m->addr, ETH_ALEN) == 0)
    781 			return m;
    782 	}
    783 
    784 	return NULL;
    785 }
    786 
    787 
    788 const u8 * p2p_group_get_dev_addr(struct p2p_group *group, const u8 *addr)
    789 {
    790 	struct p2p_group_member *m;
    791 
    792 	if (group == NULL)
    793 		return NULL;
    794 	m = p2p_group_get_client_iface(group, addr);
    795 	if (m && !is_zero_ether_addr(m->dev_addr))
    796 		return m->dev_addr;
    797 	return NULL;
    798 }
    799 
    800 
    801 static struct wpabuf * p2p_build_go_disc_req(void)
    802 {
    803 	struct wpabuf *buf;
    804 
    805 	buf = wpabuf_alloc(100);
    806 	if (buf == NULL)
    807 		return NULL;
    808 
    809 	p2p_buf_add_action_hdr(buf, P2P_GO_DISC_REQ, 0);
    810 
    811 	return buf;
    812 }
    813 
    814 
    815 int p2p_group_go_discover(struct p2p_group *group, const u8 *dev_id,
    816 			  const u8 *searching_dev, int rx_freq)
    817 {
    818 	struct p2p_group_member *m;
    819 	struct wpabuf *req;
    820 	struct p2p_data *p2p = group->p2p;
    821 	int freq;
    822 
    823 	m = p2p_group_get_client(group, dev_id);
    824 	if (m == NULL || m->client_info == NULL) {
    825 		wpa_printf(MSG_DEBUG, "P2P: Requested client was not in this "
    826 			   "group " MACSTR,
    827 			   MAC2STR(group->cfg->interface_addr));
    828 		return -1;
    829 	}
    830 
    831 	if (!(m->dev_capab & P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
    832 		wpa_printf(MSG_DEBUG, "P2P: Requested client does not support "
    833 			   "client discoverability");
    834 		return -1;
    835 	}
    836 
    837 	wpa_printf(MSG_DEBUG, "P2P: Schedule GO Discoverability Request to be "
    838 		   "sent to " MACSTR, MAC2STR(dev_id));
    839 
    840 	req = p2p_build_go_disc_req();
    841 	if (req == NULL)
    842 		return -1;
    843 
    844 	/* TODO: Should really use group operating frequency here */
    845 	freq = rx_freq;
    846 
    847 	p2p->pending_action_state = P2P_PENDING_GO_DISC_REQ;
    848 	if (p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, m->addr,
    849 				  group->cfg->interface_addr,
    850 				  group->cfg->interface_addr,
    851 				  wpabuf_head(req), wpabuf_len(req), 200) < 0)
    852 	{
    853 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
    854 			"P2P: Failed to send Action frame");
    855 	}
    856 
    857 	wpabuf_free(req);
    858 
    859 	return 0;
    860 }
    861 
    862 
    863 const u8 * p2p_group_get_interface_addr(struct p2p_group *group)
    864 {
    865 	return group->cfg->interface_addr;
    866 }
    867 
    868 
    869 u8 p2p_group_presence_req(struct p2p_group *group,
    870 			  const u8 *client_interface_addr,
    871 			  const u8 *noa, size_t noa_len)
    872 {
    873 	struct p2p_group_member *m;
    874 	u8 curr_noa[50];
    875 	int curr_noa_len;
    876 
    877 	m = p2p_group_get_client_iface(group, client_interface_addr);
    878 	if (m == NULL || m->client_info == NULL) {
    879 		wpa_printf(MSG_DEBUG, "P2P: Client was not in this group");
    880 		return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
    881 	}
    882 
    883 	wpa_hexdump(MSG_DEBUG, "P2P: Presence Request NoA", noa, noa_len);
    884 
    885 	if (group->p2p->cfg->get_noa)
    886 		curr_noa_len = group->p2p->cfg->get_noa(
    887 			group->p2p->cfg->cb_ctx, group->cfg->interface_addr,
    888 			curr_noa, sizeof(curr_noa));
    889 	else
    890 		curr_noa_len = -1;
    891 	if (curr_noa_len < 0)
    892 		wpa_printf(MSG_DEBUG, "P2P: Failed to fetch current NoA");
    893 	else if (curr_noa_len == 0)
    894 		wpa_printf(MSG_DEBUG, "P2P: No NoA being advertized");
    895 	else
    896 		wpa_hexdump(MSG_DEBUG, "P2P: Current NoA", curr_noa,
    897 			    curr_noa_len);
    898 
    899 	/* TODO: properly process request and store copy */
    900 	if (curr_noa_len > 0 || curr_noa_len == -1)
    901 		return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
    902 
    903 	return P2P_SC_SUCCESS;
    904 }
    905 
    906 
    907 unsigned int p2p_get_group_num_members(struct p2p_group *group)
    908 {
    909 	return group->num_members;
    910 }
    911 
    912 
    913 const u8 * p2p_iterate_group_members(struct p2p_group *group, void **next)
    914 {
    915 	struct p2p_group_member *iter = *next;
    916 
    917 	if (!iter)
    918 		iter = group->members;
    919 	else
    920 		iter = iter->next;
    921 
    922 	*next = iter;
    923 
    924 	if (!iter)
    925 		return NULL;
    926 
    927 	return iter->addr;
    928 }
    929 
    930 
    931 int p2p_group_is_client_connected(struct p2p_group *group, const u8 *dev_addr)
    932 {
    933 	struct p2p_group_member *m;
    934 
    935 	for (m = group->members; m; m = m->next) {
    936 		if (os_memcmp(m->dev_addr, dev_addr, ETH_ALEN) == 0)
    937 			return 1;
    938 	}
    939 
    940 	return 0;
    941 }
    942 
    943 
    944 int p2p_group_is_group_id_match(struct p2p_group *group, const u8 *group_id,
    945 				size_t group_id_len)
    946 {
    947 	if (group_id_len != ETH_ALEN + group->cfg->ssid_len)
    948 		return 0;
    949 	if (os_memcmp(group_id, group->p2p->cfg->dev_addr, ETH_ALEN) != 0)
    950 		return 0;
    951 	return os_memcmp(group_id + ETH_ALEN, group->cfg->ssid,
    952 			 group->cfg->ssid_len) == 0;
    953 }
    954