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