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