1 /*
2 * wpa_supplicant - P2P service discovery
3 * Copyright (c) 2009-2010, Atheros Communications
4 * Copyright (c) 2010-2014, Jouni Malinen <j@w1.fi>
5 *
6 * This software may be distributed under the terms of the BSD license.
7 * See README for more details.
8 */
9
10 #include "utils/includes.h"
11
12 #include "utils/common.h"
13 #include "p2p/p2p.h"
14 #include "wpa_supplicant_i.h"
15 #include "notify.h"
16 #include "p2p_supplicant.h"
17 #ifdef CONFIG_LIBWPA_VENDOR
18 #include "wpa_client.h"
19 #endif
20
21 /*
22 * DNS Header section is used only to calculate compression pointers, so the
23 * contents of this data does not matter, but the length needs to be reserved
24 * in the virtual packet.
25 */
26 #define DNS_HEADER_LEN 12
27
28 /*
29 * 27-octet in-memory packet from P2P specification containing two implied
30 * queries for _tcp.lcoal. PTR IN and _udp.local. PTR IN
31 */
32 #define P2P_SD_IN_MEMORY_LEN 27
33
p2p_sd_dns_uncompress_label(char ** upos,char * uend,u8 * start,u8 ** spos,const u8 * end)34 static int p2p_sd_dns_uncompress_label(char **upos, char *uend, u8 *start,
35 u8 **spos, const u8 *end)
36 {
37 while (*spos < end) {
38 u8 val = ((*spos)[0] & 0xc0) >> 6;
39 int len;
40
41 if (val == 1 || val == 2) {
42 /* These are reserved values in RFC 1035 */
43 wpa_printf(MSG_DEBUG, "P2P: Invalid domain name "
44 "sequence starting with 0x%x", val);
45 return -1;
46 }
47
48 if (val == 3) {
49 u16 offset;
50 u8 *spos_tmp;
51
52 /* Offset */
53 if (end - *spos < 2) {
54 wpa_printf(MSG_DEBUG, "P2P: No room for full "
55 "DNS offset field");
56 return -1;
57 }
58
59 offset = (((*spos)[0] & 0x3f) << 8) | (*spos)[1];
60 if (offset >= *spos - start) {
61 wpa_printf(MSG_DEBUG, "P2P: Invalid DNS "
62 "pointer offset %u", offset);
63 return -1;
64 }
65
66 (*spos) += 2;
67 spos_tmp = start + offset;
68 return p2p_sd_dns_uncompress_label(upos, uend, start,
69 &spos_tmp,
70 *spos - 2);
71 }
72
73 /* Label */
74 len = (*spos)[0] & 0x3f;
75 if (len == 0)
76 return 0;
77
78 (*spos)++;
79 if (len > end - *spos) {
80 wpa_printf(MSG_DEBUG, "P2P: Invalid domain name "
81 "sequence - no room for label with length "
82 "%u", len);
83 return -1;
84 }
85
86 if (len + 2 > uend - *upos)
87 return -2;
88
89 os_memcpy(*upos, *spos, len);
90 *spos += len;
91 *upos += len;
92 (*upos)[0] = '.';
93 (*upos)++;
94 (*upos)[0] = '\0';
95 }
96
97 return 0;
98 }
99
100
101 /* Uncompress domain names per RFC 1035 using the P2P SD in-memory packet.
102 * Returns -1 on parsing error (invalid input sequence), -2 if output buffer is
103 * not large enough */
p2p_sd_dns_uncompress(char * buf,size_t buf_len,const u8 * msg,size_t msg_len,size_t offset)104 static int p2p_sd_dns_uncompress(char *buf, size_t buf_len, const u8 *msg,
105 size_t msg_len, size_t offset)
106 {
107 /* 27-octet in-memory packet from P2P specification */
108 const char *prefix = "\x04_tcp\x05local\x00\x00\x0C\x00\x01"
109 "\x04_udp\xC0\x11\x00\x0C\x00\x01";
110 u8 *tmp, *end, *spos;
111 char *upos, *uend;
112 int ret = 0;
113
114 if (buf_len < 2)
115 return -1;
116 if (offset > msg_len)
117 return -1;
118
119 tmp = os_malloc(DNS_HEADER_LEN + P2P_SD_IN_MEMORY_LEN + msg_len);
120 if (tmp == NULL)
121 return -1;
122 spos = tmp + DNS_HEADER_LEN + P2P_SD_IN_MEMORY_LEN;
123 end = spos + msg_len;
124 spos += offset;
125
126 os_memset(tmp, 0, DNS_HEADER_LEN);
127 os_memcpy(tmp + DNS_HEADER_LEN, prefix, P2P_SD_IN_MEMORY_LEN);
128 os_memcpy(tmp + DNS_HEADER_LEN + P2P_SD_IN_MEMORY_LEN, msg, msg_len);
129
130 upos = buf;
131 uend = buf + buf_len;
132
133 ret = p2p_sd_dns_uncompress_label(&upos, uend, tmp, &spos, end);
134 if (ret) {
135 os_free(tmp);
136 return ret;
137 }
138
139 if (upos == buf) {
140 upos[0] = '.';
141 upos[1] = '\0';
142 } else if (upos[-1] == '.')
143 upos[-1] = '\0';
144
145 os_free(tmp);
146 return 0;
147 }
148
149
150 static struct p2p_srv_bonjour *
wpas_p2p_service_get_bonjour(struct wpa_supplicant * wpa_s,const struct wpabuf * query)151 wpas_p2p_service_get_bonjour(struct wpa_supplicant *wpa_s,
152 const struct wpabuf *query)
153 {
154 struct p2p_srv_bonjour *bsrv;
155 size_t len;
156
157 len = wpabuf_len(query);
158 dl_list_for_each(bsrv, &wpa_s->global->p2p_srv_bonjour,
159 struct p2p_srv_bonjour, list) {
160 if (len == wpabuf_len(bsrv->query) &&
161 os_memcmp(wpabuf_head(query), wpabuf_head(bsrv->query),
162 len) == 0)
163 return bsrv;
164 }
165 return NULL;
166 }
167
168
169 static struct p2p_srv_upnp *
wpas_p2p_service_get_upnp(struct wpa_supplicant * wpa_s,u8 version,const char * service)170 wpas_p2p_service_get_upnp(struct wpa_supplicant *wpa_s, u8 version,
171 const char *service)
172 {
173 struct p2p_srv_upnp *usrv;
174
175 dl_list_for_each(usrv, &wpa_s->global->p2p_srv_upnp,
176 struct p2p_srv_upnp, list) {
177 if (version == usrv->version &&
178 os_strcmp(service, usrv->service) == 0)
179 return usrv;
180 }
181 return NULL;
182 }
183
184
wpas_sd_add_empty(struct wpabuf * resp,u8 srv_proto,u8 srv_trans_id,u8 status)185 static void wpas_sd_add_empty(struct wpabuf *resp, u8 srv_proto,
186 u8 srv_trans_id, u8 status)
187 {
188 u8 *len_pos;
189
190 if (wpabuf_tailroom(resp) < 5)
191 return;
192
193 /* Length (to be filled) */
194 len_pos = wpabuf_put(resp, 2);
195 wpabuf_put_u8(resp, srv_proto);
196 wpabuf_put_u8(resp, srv_trans_id);
197 /* Status Code */
198 wpabuf_put_u8(resp, status);
199 /* Response Data: empty */
200 WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos - 2);
201 }
202
203
wpas_sd_add_proto_not_avail(struct wpabuf * resp,u8 srv_proto,u8 srv_trans_id)204 static void wpas_sd_add_proto_not_avail(struct wpabuf *resp, u8 srv_proto,
205 u8 srv_trans_id)
206 {
207 wpas_sd_add_empty(resp, srv_proto, srv_trans_id,
208 P2P_SD_PROTO_NOT_AVAILABLE);
209 }
210
211
wpas_sd_add_bad_request(struct wpabuf * resp,u8 srv_proto,u8 srv_trans_id)212 static void wpas_sd_add_bad_request(struct wpabuf *resp, u8 srv_proto,
213 u8 srv_trans_id)
214 {
215 wpas_sd_add_empty(resp, srv_proto, srv_trans_id, P2P_SD_BAD_REQUEST);
216 }
217
218
wpas_sd_add_not_found(struct wpabuf * resp,u8 srv_proto,u8 srv_trans_id)219 static void wpas_sd_add_not_found(struct wpabuf *resp, u8 srv_proto,
220 u8 srv_trans_id)
221 {
222 wpas_sd_add_empty(resp, srv_proto, srv_trans_id,
223 P2P_SD_REQUESTED_INFO_NOT_AVAILABLE);
224 }
225
226
wpas_sd_all_bonjour(struct wpa_supplicant * wpa_s,struct wpabuf * resp,u8 srv_trans_id)227 static void wpas_sd_all_bonjour(struct wpa_supplicant *wpa_s,
228 struct wpabuf *resp, u8 srv_trans_id)
229 {
230 struct p2p_srv_bonjour *bsrv;
231 u8 *len_pos;
232
233 wpa_printf(MSG_DEBUG, "P2P: SD Request for all Bonjour services");
234
235 if (dl_list_empty(&wpa_s->global->p2p_srv_bonjour)) {
236 wpa_printf(MSG_DEBUG, "P2P: Bonjour protocol not available");
237 return;
238 }
239
240 dl_list_for_each(bsrv, &wpa_s->global->p2p_srv_bonjour,
241 struct p2p_srv_bonjour, list) {
242 if (wpabuf_tailroom(resp) <
243 5 + wpabuf_len(bsrv->query) + wpabuf_len(bsrv->resp))
244 return;
245 /* Length (to be filled) */
246 len_pos = wpabuf_put(resp, 2);
247 wpabuf_put_u8(resp, P2P_SERV_BONJOUR);
248 wpabuf_put_u8(resp, srv_trans_id);
249 /* Status Code */
250 wpabuf_put_u8(resp, P2P_SD_SUCCESS);
251 wpa_hexdump_ascii(MSG_DEBUG, "P2P: Matching Bonjour service",
252 wpabuf_head(bsrv->resp),
253 wpabuf_len(bsrv->resp));
254 /* Response Data */
255 wpabuf_put_buf(resp, bsrv->query); /* Key */
256 wpabuf_put_buf(resp, bsrv->resp); /* Value */
257 WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos -
258 2);
259 }
260 }
261
262
match_bonjour_query(struct p2p_srv_bonjour * bsrv,const u8 * query,size_t query_len)263 static int match_bonjour_query(struct p2p_srv_bonjour *bsrv, const u8 *query,
264 size_t query_len)
265 {
266 char str_rx[256], str_srv[256];
267
268 if (query_len < 3 || wpabuf_len(bsrv->query) < 3)
269 return 0; /* Too short to include DNS Type and Version */
270 if (os_memcmp(query + query_len - 3,
271 wpabuf_head_u8(bsrv->query) + wpabuf_len(bsrv->query) - 3,
272 3) != 0)
273 return 0; /* Mismatch in DNS Type or Version */
274 if (query_len == wpabuf_len(bsrv->query) &&
275 os_memcmp(query, wpabuf_head(bsrv->query), query_len - 3) == 0)
276 return 1; /* Binary match */
277
278 if (p2p_sd_dns_uncompress(str_rx, sizeof(str_rx), query, query_len - 3,
279 0))
280 return 0; /* Failed to uncompress query */
281 if (p2p_sd_dns_uncompress(str_srv, sizeof(str_srv),
282 wpabuf_head(bsrv->query),
283 wpabuf_len(bsrv->query) - 3, 0))
284 return 0; /* Failed to uncompress service */
285
286 return os_strcmp(str_rx, str_srv) == 0;
287 }
288
289
wpas_sd_req_bonjour(struct wpa_supplicant * wpa_s,struct wpabuf * resp,u8 srv_trans_id,const u8 * query,size_t query_len)290 static void wpas_sd_req_bonjour(struct wpa_supplicant *wpa_s,
291 struct wpabuf *resp, u8 srv_trans_id,
292 const u8 *query, size_t query_len)
293 {
294 struct p2p_srv_bonjour *bsrv;
295 u8 *len_pos;
296 int matches = 0;
297
298 wpa_hexdump_ascii(MSG_DEBUG, "P2P: SD Request for Bonjour",
299 query, query_len);
300 if (dl_list_empty(&wpa_s->global->p2p_srv_bonjour)) {
301 wpa_printf(MSG_DEBUG, "P2P: Bonjour protocol not available");
302 wpas_sd_add_proto_not_avail(resp, P2P_SERV_BONJOUR,
303 srv_trans_id);
304 return;
305 }
306
307 if (query_len == 0) {
308 wpas_sd_all_bonjour(wpa_s, resp, srv_trans_id);
309 return;
310 }
311
312 dl_list_for_each(bsrv, &wpa_s->global->p2p_srv_bonjour,
313 struct p2p_srv_bonjour, list) {
314 if (!match_bonjour_query(bsrv, query, query_len))
315 continue;
316
317 if (wpabuf_tailroom(resp) <
318 5 + query_len + wpabuf_len(bsrv->resp))
319 return;
320
321 matches++;
322
323 /* Length (to be filled) */
324 len_pos = wpabuf_put(resp, 2);
325 wpabuf_put_u8(resp, P2P_SERV_BONJOUR);
326 wpabuf_put_u8(resp, srv_trans_id);
327
328 /* Status Code */
329 wpabuf_put_u8(resp, P2P_SD_SUCCESS);
330 wpa_hexdump_ascii(MSG_DEBUG, "P2P: Matching Bonjour service",
331 wpabuf_head(bsrv->resp),
332 wpabuf_len(bsrv->resp));
333
334 /* Response Data */
335 wpabuf_put_data(resp, query, query_len); /* Key */
336 wpabuf_put_buf(resp, bsrv->resp); /* Value */
337
338 WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos - 2);
339 }
340
341 if (matches == 0) {
342 wpa_printf(MSG_DEBUG, "P2P: Requested Bonjour service not "
343 "available");
344 if (wpabuf_tailroom(resp) < 5)
345 return;
346
347 /* Length (to be filled) */
348 len_pos = wpabuf_put(resp, 2);
349 wpabuf_put_u8(resp, P2P_SERV_BONJOUR);
350 wpabuf_put_u8(resp, srv_trans_id);
351
352 /* Status Code */
353 wpabuf_put_u8(resp, P2P_SD_REQUESTED_INFO_NOT_AVAILABLE);
354 /* Response Data: empty */
355 WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos -
356 2);
357 }
358 }
359
360
wpas_sd_all_upnp(struct wpa_supplicant * wpa_s,struct wpabuf * resp,u8 srv_trans_id)361 static void wpas_sd_all_upnp(struct wpa_supplicant *wpa_s,
362 struct wpabuf *resp, u8 srv_trans_id)
363 {
364 struct p2p_srv_upnp *usrv;
365 u8 *len_pos;
366
367 wpa_printf(MSG_DEBUG, "P2P: SD Request for all UPnP services");
368
369 if (dl_list_empty(&wpa_s->global->p2p_srv_upnp)) {
370 wpa_printf(MSG_DEBUG, "P2P: UPnP protocol not available");
371 return;
372 }
373
374 dl_list_for_each(usrv, &wpa_s->global->p2p_srv_upnp,
375 struct p2p_srv_upnp, list) {
376 if (wpabuf_tailroom(resp) < 5 + 1 + os_strlen(usrv->service))
377 return;
378
379 /* Length (to be filled) */
380 len_pos = wpabuf_put(resp, 2);
381 wpabuf_put_u8(resp, P2P_SERV_UPNP);
382 wpabuf_put_u8(resp, srv_trans_id);
383
384 /* Status Code */
385 wpabuf_put_u8(resp, P2P_SD_SUCCESS);
386 /* Response Data */
387 wpabuf_put_u8(resp, usrv->version);
388 wpa_printf(MSG_DEBUG, "P2P: Matching UPnP Service: %s",
389 usrv->service);
390 wpabuf_put_str(resp, usrv->service);
391 WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos -
392 2);
393 }
394 }
395
396
wpas_sd_req_upnp(struct wpa_supplicant * wpa_s,struct wpabuf * resp,u8 srv_trans_id,const u8 * query,size_t query_len)397 static void wpas_sd_req_upnp(struct wpa_supplicant *wpa_s,
398 struct wpabuf *resp, u8 srv_trans_id,
399 const u8 *query, size_t query_len)
400 {
401 struct p2p_srv_upnp *usrv;
402 u8 *len_pos;
403 u8 version;
404 char *str;
405 int count = 0;
406
407 wpa_hexdump_ascii(MSG_DEBUG, "P2P: SD Request for UPnP",
408 query, query_len);
409
410 if (dl_list_empty(&wpa_s->global->p2p_srv_upnp)) {
411 wpa_printf(MSG_DEBUG, "P2P: UPnP protocol not available");
412 wpas_sd_add_proto_not_avail(resp, P2P_SERV_UPNP,
413 srv_trans_id);
414 return;
415 }
416
417 if (query_len == 0) {
418 wpas_sd_all_upnp(wpa_s, resp, srv_trans_id);
419 return;
420 }
421
422 if (wpabuf_tailroom(resp) < 5)
423 return;
424
425 /* Length (to be filled) */
426 len_pos = wpabuf_put(resp, 2);
427 wpabuf_put_u8(resp, P2P_SERV_UPNP);
428 wpabuf_put_u8(resp, srv_trans_id);
429
430 version = query[0];
431 str = os_malloc(query_len);
432 if (str == NULL)
433 return;
434 os_memcpy(str, query + 1, query_len - 1);
435 str[query_len - 1] = '\0';
436
437 dl_list_for_each(usrv, &wpa_s->global->p2p_srv_upnp,
438 struct p2p_srv_upnp, list) {
439 if (version != usrv->version)
440 continue;
441
442 if (os_strcmp(str, "ssdp:all") != 0 &&
443 os_strstr(usrv->service, str) == NULL)
444 continue;
445
446 if (wpabuf_tailroom(resp) < 2)
447 break;
448 if (count == 0) {
449 /* Status Code */
450 wpabuf_put_u8(resp, P2P_SD_SUCCESS);
451 /* Response Data */
452 wpabuf_put_u8(resp, version);
453 } else
454 wpabuf_put_u8(resp, ',');
455
456 count++;
457
458 wpa_printf(MSG_DEBUG, "P2P: Matching UPnP Service: %s",
459 usrv->service);
460 if (wpabuf_tailroom(resp) < os_strlen(usrv->service))
461 break;
462 wpabuf_put_str(resp, usrv->service);
463 }
464 os_free(str);
465
466 if (count == 0) {
467 wpa_printf(MSG_DEBUG, "P2P: Requested UPnP service not "
468 "available");
469 /* Status Code */
470 wpabuf_put_u8(resp, P2P_SD_REQUESTED_INFO_NOT_AVAILABLE);
471 /* Response Data: empty */
472 }
473
474 WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos - 2);
475 }
476
477
478 #ifdef CONFIG_WIFI_DISPLAY
wpas_sd_req_wfd(struct wpa_supplicant * wpa_s,struct wpabuf * resp,u8 srv_trans_id,const u8 * query,size_t query_len)479 static void wpas_sd_req_wfd(struct wpa_supplicant *wpa_s,
480 struct wpabuf *resp, u8 srv_trans_id,
481 const u8 *query, size_t query_len)
482 {
483 const u8 *pos;
484 u8 role;
485 u8 *len_pos;
486
487 wpa_hexdump(MSG_DEBUG, "P2P: SD Request for WFD", query, query_len);
488
489 if (!wpa_s->global->wifi_display) {
490 wpa_printf(MSG_DEBUG, "P2P: WFD protocol not available");
491 wpas_sd_add_proto_not_avail(resp, P2P_SERV_WIFI_DISPLAY,
492 srv_trans_id);
493 return;
494 }
495
496 if (query_len < 1) {
497 wpa_printf(MSG_DEBUG, "P2P: Missing WFD Requested Device "
498 "Role");
499 return;
500 }
501
502 if (wpabuf_tailroom(resp) < 5)
503 return;
504
505 pos = query;
506 role = *pos++;
507 wpa_printf(MSG_DEBUG, "P2P: WSD for device role 0x%x", role);
508
509 /* TODO: role specific handling */
510
511 /* Length (to be filled) */
512 len_pos = wpabuf_put(resp, 2);
513 wpabuf_put_u8(resp, P2P_SERV_WIFI_DISPLAY);
514 wpabuf_put_u8(resp, srv_trans_id);
515 wpabuf_put_u8(resp, P2P_SD_SUCCESS); /* Status Code */
516
517 while (pos < query + query_len) {
518 if (*pos < MAX_WFD_SUBELEMS &&
519 wpa_s->global->wfd_subelem[*pos] &&
520 wpabuf_tailroom(resp) >=
521 wpabuf_len(wpa_s->global->wfd_subelem[*pos])) {
522 wpa_printf(MSG_DEBUG, "P2P: Add WSD response "
523 "subelement %u", *pos);
524 wpabuf_put_buf(resp, wpa_s->global->wfd_subelem[*pos]);
525 }
526 pos++;
527 }
528
529 WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos - 2);
530 }
531 #endif /* CONFIG_WIFI_DISPLAY */
532
533
find_p2ps_substr(struct p2ps_advertisement * adv_data,const u8 * needle,size_t needle_len)534 static int find_p2ps_substr(struct p2ps_advertisement *adv_data,
535 const u8 *needle, size_t needle_len)
536 {
537 const u8 *haystack = (const u8 *) adv_data->svc_info;
538 size_t haystack_len, i;
539
540 /* Allow search term to be empty */
541 if (!needle || !needle_len)
542 return 1;
543
544 if (!haystack)
545 return 0;
546
547 haystack_len = os_strlen(adv_data->svc_info);
548 for (i = 0; i < haystack_len; i++) {
549 if (haystack_len - i < needle_len)
550 break;
551 if (os_memcmp(haystack + i, needle, needle_len) == 0)
552 return 1;
553 }
554
555 return 0;
556 }
557
558
wpas_sd_req_asp(struct wpa_supplicant * wpa_s,struct wpabuf * resp,u8 srv_trans_id,const u8 * query,size_t query_len)559 static void wpas_sd_req_asp(struct wpa_supplicant *wpa_s,
560 struct wpabuf *resp, u8 srv_trans_id,
561 const u8 *query, size_t query_len)
562 {
563 struct p2ps_advertisement *adv_data;
564 const u8 *svc = &query[1];
565 const u8 *info = NULL;
566 size_t svc_len = query[0];
567 size_t info_len = 0;
568 int prefix = 0;
569 u8 *count_pos = NULL;
570 u8 *len_pos = NULL;
571
572 wpa_hexdump(MSG_DEBUG, "P2P: SD Request for ASP", query, query_len);
573
574 if (!wpa_s->global->p2p) {
575 wpa_printf(MSG_DEBUG, "P2P: ASP protocol not available");
576 wpas_sd_add_proto_not_avail(resp, P2P_SERV_P2PS, srv_trans_id);
577 return;
578 }
579
580 /* Info block is optional */
581 if (svc_len + 1 < query_len) {
582 info = &svc[svc_len];
583 info_len = *info++;
584 }
585
586 /* Range check length of svc string and info block */
587 if (svc_len + (info_len ? info_len + 2 : 1) > query_len) {
588 wpa_printf(MSG_DEBUG, "P2P: ASP bad request");
589 wpas_sd_add_bad_request(resp, P2P_SERV_P2PS, srv_trans_id);
590 return;
591 }
592
593 /* Detect and correct for prefix search */
594 if (svc_len && svc[svc_len - 1] == '*') {
595 prefix = 1;
596 svc_len--;
597 }
598
599 for (adv_data = p2p_get_p2ps_adv_list(wpa_s->global->p2p);
600 adv_data; adv_data = adv_data->next) {
601 /* If not a prefix match, reject length mismatches */
602 if (!prefix && svc_len != os_strlen(adv_data->svc_name))
603 continue;
604
605 /* Search each service for request */
606 if (os_memcmp(adv_data->svc_name, svc, svc_len) == 0 &&
607 find_p2ps_substr(adv_data, info, info_len)) {
608 size_t len = os_strlen(adv_data->svc_name);
609 size_t svc_info_len = 0;
610
611 if (adv_data->svc_info)
612 svc_info_len = os_strlen(adv_data->svc_info);
613
614 if (len > 0xff || svc_info_len > 0xffff)
615 return;
616
617 /* Length & Count to be filled as we go */
618 if (!len_pos && !count_pos) {
619 if (wpabuf_tailroom(resp) <
620 len + svc_info_len + 16)
621 return;
622
623 len_pos = wpabuf_put(resp, 2);
624 wpabuf_put_u8(resp, P2P_SERV_P2PS);
625 wpabuf_put_u8(resp, srv_trans_id);
626 /* Status Code */
627 wpabuf_put_u8(resp, P2P_SD_SUCCESS);
628 count_pos = wpabuf_put(resp, 1);
629 *count_pos = 0;
630 } else if (wpabuf_tailroom(resp) <
631 len + svc_info_len + 10)
632 return;
633
634 if (svc_info_len) {
635 wpa_printf(MSG_DEBUG,
636 "P2P: Add Svc: %s info: %s",
637 adv_data->svc_name,
638 adv_data->svc_info);
639 } else {
640 wpa_printf(MSG_DEBUG, "P2P: Add Svc: %s",
641 adv_data->svc_name);
642 }
643
644 /* Advertisement ID */
645 wpabuf_put_le32(resp, adv_data->id);
646
647 /* Config Methods */
648 wpabuf_put_be16(resp, adv_data->config_methods);
649
650 /* Service Name */
651 wpabuf_put_u8(resp, (u8) len);
652 wpabuf_put_data(resp, adv_data->svc_name, len);
653
654 /* Service State */
655 wpabuf_put_u8(resp, adv_data->state);
656
657 /* Service Information */
658 wpabuf_put_le16(resp, (u16) svc_info_len);
659 wpabuf_put_data(resp, adv_data->svc_info, svc_info_len);
660
661 /* Update length and count */
662 (*count_pos)++;
663 WPA_PUT_LE16(len_pos,
664 (u8 *) wpabuf_put(resp, 0) - len_pos - 2);
665 }
666 }
667
668 /* Return error if no matching svc found */
669 if (count_pos == NULL) {
670 wpa_printf(MSG_DEBUG, "P2P: ASP service not found");
671 wpas_sd_add_not_found(resp, P2P_SERV_P2PS, srv_trans_id);
672 }
673 }
674
675
wpas_sd_all_asp(struct wpa_supplicant * wpa_s,struct wpabuf * resp,u8 srv_trans_id)676 static void wpas_sd_all_asp(struct wpa_supplicant *wpa_s,
677 struct wpabuf *resp, u8 srv_trans_id)
678 {
679 /* Query data to add all P2PS advertisements:
680 * - Service name length: 1
681 * - Service name: '*'
682 * - Service Information Request Length: 0
683 */
684 const u8 q[] = { 1, (const u8) '*', 0 };
685
686 if (p2p_get_p2ps_adv_list(wpa_s->global->p2p))
687 wpas_sd_req_asp(wpa_s, resp, srv_trans_id, q, sizeof(q));
688 }
689
690
wpas_sd_request(void * ctx,int freq,const u8 * sa,u8 dialog_token,u16 update_indic,const u8 * tlvs,size_t tlvs_len)691 void wpas_sd_request(void *ctx, int freq, const u8 *sa, u8 dialog_token,
692 u16 update_indic, const u8 *tlvs, size_t tlvs_len)
693 {
694 struct wpa_supplicant *wpa_s = ctx;
695 const u8 *pos = tlvs;
696 const u8 *end = tlvs + tlvs_len;
697 const u8 *tlv_end;
698 u16 slen;
699 struct wpabuf *resp;
700 u8 srv_proto, srv_trans_id;
701 size_t buf_len;
702 char *buf;
703
704 wpa_hexdump(MSG_MSGDUMP, "P2P: Service Discovery Request TLVs",
705 tlvs, tlvs_len);
706 buf_len = 2 * tlvs_len + 1;
707 buf = os_malloc(buf_len);
708 if (buf) {
709 wpa_snprintf_hex(buf, buf_len, tlvs, tlvs_len);
710 wpa_msg_ctrl(wpa_s, MSG_INFO, P2P_EVENT_SERV_DISC_REQ "%d "
711 MACSTR " %u %u %s",
712 freq, MAC2STR(sa), dialog_token, update_indic,
713 buf);
714 #ifdef CONFIG_LIBWPA_VENDOR
715 struct P2pServDiscReqInfoParam p2pServDiscReqInfoParam;
716 p2pServDiscReqInfoParam.freq = freq;
717 p2pServDiscReqInfoParam.dialogToken = dialog_token;
718 p2pServDiscReqInfoParam.updateIndic = update_indic;
719 os_memcpy(p2pServDiscReqInfoParam.mac, sa, ETH_ALEN);
720 os_memcpy(p2pServDiscReqInfoParam.tlvs, tlvs, WIFI_P2P_TLVS_LENGTH);
721 wpa_printf(MSG_INFO, "WPA_EVENT_SERV_DISC_REQ " MACSTR_SEC,
722 MAC2STR_SEC(p2pServDiscReqInfoParam.mac));
723 WpaEventReport(wpa_s->ifname, WPA_EVENT_SERV_DISC_REQ, (void *) &p2pServDiscReqInfoParam);
724 #endif
725 os_free(buf);
726 }
727
728 if (wpa_s->p2p_sd_over_ctrl_iface) {
729 wpas_notify_p2p_sd_request(wpa_s, freq, sa, dialog_token,
730 update_indic, tlvs, tlvs_len);
731 return; /* to be processed by an external program */
732 }
733
734 resp = wpabuf_alloc(10000);
735 if (resp == NULL)
736 return;
737
738 while (end - pos > 1) {
739 wpa_printf(MSG_DEBUG, "P2P: Service Request TLV");
740 slen = WPA_GET_LE16(pos);
741 pos += 2;
742 if (slen > end - pos || slen < 2) {
743 wpa_printf(MSG_DEBUG, "P2P: Unexpected Query Data "
744 "length");
745 wpabuf_free(resp);
746 return;
747 }
748 tlv_end = pos + slen;
749
750 srv_proto = *pos++;
751 wpa_printf(MSG_DEBUG, "P2P: Service Protocol Type %u",
752 srv_proto);
753 srv_trans_id = *pos++;
754 wpa_printf(MSG_DEBUG, "P2P: Service Transaction ID %u",
755 srv_trans_id);
756
757 wpa_hexdump(MSG_MSGDUMP, "P2P: Query Data",
758 pos, tlv_end - pos);
759
760
761 if (wpa_s->force_long_sd) {
762 wpa_printf(MSG_DEBUG, "P2P: SD test - force long "
763 "response");
764 wpas_sd_all_bonjour(wpa_s, resp, srv_trans_id);
765 wpas_sd_all_upnp(wpa_s, resp, srv_trans_id);
766 wpas_sd_all_asp(wpa_s, resp, srv_trans_id);
767 goto done;
768 }
769
770 switch (srv_proto) {
771 case P2P_SERV_ALL_SERVICES:
772 wpa_printf(MSG_DEBUG, "P2P: Service Discovery Request "
773 "for all services");
774 if (dl_list_empty(&wpa_s->global->p2p_srv_upnp) &&
775 dl_list_empty(&wpa_s->global->p2p_srv_bonjour) &&
776 !p2p_get_p2ps_adv_list(wpa_s->global->p2p)) {
777 wpa_printf(MSG_DEBUG, "P2P: No service "
778 "discovery protocols available");
779 wpas_sd_add_proto_not_avail(
780 resp, P2P_SERV_ALL_SERVICES,
781 srv_trans_id);
782 break;
783 }
784 wpas_sd_all_bonjour(wpa_s, resp, srv_trans_id);
785 wpas_sd_all_upnp(wpa_s, resp, srv_trans_id);
786 wpas_sd_all_asp(wpa_s, resp, srv_trans_id);
787 break;
788 case P2P_SERV_BONJOUR:
789 wpas_sd_req_bonjour(wpa_s, resp, srv_trans_id,
790 pos, tlv_end - pos);
791 break;
792 case P2P_SERV_UPNP:
793 wpas_sd_req_upnp(wpa_s, resp, srv_trans_id,
794 pos, tlv_end - pos);
795 break;
796 #ifdef CONFIG_WIFI_DISPLAY
797 case P2P_SERV_WIFI_DISPLAY:
798 wpas_sd_req_wfd(wpa_s, resp, srv_trans_id,
799 pos, tlv_end - pos);
800 break;
801 #endif /* CONFIG_WIFI_DISPLAY */
802 case P2P_SERV_P2PS:
803 wpas_sd_req_asp(wpa_s, resp, srv_trans_id,
804 pos, tlv_end - pos);
805 break;
806 default:
807 wpa_printf(MSG_DEBUG, "P2P: Unavailable service "
808 "protocol %u", srv_proto);
809 wpas_sd_add_proto_not_avail(resp, srv_proto,
810 srv_trans_id);
811 break;
812 }
813
814 pos = tlv_end;
815 }
816
817 done:
818 wpas_notify_p2p_sd_request(wpa_s, freq, sa, dialog_token,
819 update_indic, tlvs, tlvs_len);
820
821 wpas_p2p_sd_response(wpa_s, freq, sa, dialog_token, resp);
822
823 wpabuf_free(resp);
824 }
825
826
wpas_sd_p2ps_serv_response(struct wpa_supplicant * wpa_s,const u8 * sa,u8 srv_trans_id,const u8 * pos,const u8 * tlv_end)827 static void wpas_sd_p2ps_serv_response(struct wpa_supplicant *wpa_s,
828 const u8 *sa, u8 srv_trans_id,
829 const u8 *pos, const u8 *tlv_end)
830 {
831 u8 left = *pos++;
832 u32 adv_id;
833 u8 svc_status;
834 u16 config_methods;
835 char svc_str[256];
836
837 while (left-- && pos < tlv_end) {
838 char *buf = NULL;
839 size_t buf_len;
840 u8 svc_len;
841
842 /* Validity check fixed length+svc_str */
843 if (6 >= tlv_end - pos)
844 break;
845 svc_len = pos[6];
846 if (svc_len + 10 > tlv_end - pos)
847 break;
848
849 /* Advertisement ID */
850 adv_id = WPA_GET_LE32(pos);
851 pos += sizeof(u32);
852
853 /* Config Methods */
854 config_methods = WPA_GET_BE16(pos);
855 pos += sizeof(u16);
856
857 /* Service Name */
858 pos++; /* svc_len */
859 os_memcpy(svc_str, pos, svc_len);
860 svc_str[svc_len] = '\0';
861 pos += svc_len;
862
863 /* Service Status */
864 svc_status = *pos++;
865
866 /* Service Information Length */
867 buf_len = WPA_GET_LE16(pos);
868 pos += sizeof(u16);
869
870 /* Validity check buffer length */
871 if (buf_len > (unsigned int) (tlv_end - pos))
872 break;
873
874 if (buf_len) {
875 buf = os_zalloc(2 * buf_len + 1);
876 if (buf) {
877 utf8_escape((const char *) pos, buf_len, buf,
878 2 * buf_len + 1);
879 }
880 }
881
882 pos += buf_len;
883
884 if (buf) {
885 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_SERV_ASP_RESP
886 MACSTR " %x %x %x %x %s '%s'",
887 MAC2STR(sa), srv_trans_id, adv_id,
888 svc_status, config_methods, svc_str,
889 buf);
890 wpa_printf(MSG_INFO, P2P_EVENT_SERV_ASP_RESP
891 MACSTR_SEC " %x %x %x %x %s '%s'",
892 MAC2STR_SEC(sa), srv_trans_id, adv_id,
893 svc_status, config_methods, svc_str,
894 buf);
895 os_free(buf);
896 } else {
897 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_SERV_ASP_RESP
898 MACSTR " %x %x %x %x %s",
899 MAC2STR(sa), srv_trans_id, adv_id,
900 svc_status, config_methods, svc_str);
901 wpa_printf(MSG_INFO, P2P_EVENT_SERV_ASP_RESP
902 MACSTR_SEC " %x %x %x %x %s",
903 MAC2STR_SEC(sa), srv_trans_id, adv_id,
904 svc_status, config_methods, svc_str);
905 }
906 }
907 }
908
909
wpas_sd_response(void * ctx,const u8 * sa,u16 update_indic,const u8 * tlvs,size_t tlvs_len)910 void wpas_sd_response(void *ctx, const u8 *sa, u16 update_indic,
911 const u8 *tlvs, size_t tlvs_len)
912 {
913 struct wpa_supplicant *wpa_s = ctx;
914 const u8 *pos = tlvs;
915 const u8 *end = tlvs + tlvs_len;
916 const u8 *tlv_end;
917 u16 slen;
918 size_t buf_len;
919 char *buf;
920
921 wpa_hexdump(MSG_MSGDUMP, "P2P: Service Discovery Response TLVs",
922 tlvs, tlvs_len);
923 if (tlvs_len > 1500) {
924 /* TODO: better way for handling this */
925 wpa_msg_ctrl(wpa_s, MSG_INFO,
926 P2P_EVENT_SERV_DISC_RESP MACSTR
927 " %u <long response: %u bytes>",
928 MAC2STR(sa), update_indic,
929 (unsigned int) tlvs_len);
930 } else {
931 buf_len = 2 * tlvs_len + 1;
932 buf = os_malloc(buf_len);
933 if (buf) {
934 wpa_snprintf_hex(buf, buf_len, tlvs, tlvs_len);
935 wpa_msg_ctrl(wpa_s, MSG_INFO,
936 P2P_EVENT_SERV_DISC_RESP MACSTR " %u %s",
937 MAC2STR(sa), update_indic, buf);
938 os_free(buf);
939 }
940 }
941 #ifdef CONFIG_LIBWPA_VENDOR
942 struct P2pServDiscRespParam p2pServDiscRespParam;
943 p2pServDiscRespParam.updateIndicator = update_indic;
944 os_memcpy(p2pServDiscRespParam.srcAddress, sa, ETH_ALEN);
945 os_memcpy(p2pServDiscRespParam.tlvs, tlvs, WIFI_P2P_TLVS_LENGTH);
946 wpa_printf(MSG_INFO, "WPA_EVENT_SERV_DISC_RESP %d " MACSTR_SEC, p2pServDiscRespParam.updateIndicator,
947 MAC2STR_SEC(p2pServDiscRespParam.srcAddress));
948 WpaEventReport(wpa_s->ifname, WPA_EVENT_SERV_DISC_RESP, (void *) &p2pServDiscRespParam);
949 #endif
950 while (end - pos >= 2) {
951 u8 srv_proto, srv_trans_id, status;
952
953 wpa_printf(MSG_DEBUG, "P2P: Service Response TLV");
954 slen = WPA_GET_LE16(pos);
955 pos += 2;
956 if (slen > end - pos || slen < 3) {
957 wpa_printf(MSG_DEBUG, "P2P: Unexpected Response Data "
958 "length");
959 return;
960 }
961 tlv_end = pos + slen;
962
963 srv_proto = *pos++;
964 wpa_printf(MSG_DEBUG, "P2P: Service Protocol Type %u",
965 srv_proto);
966 srv_trans_id = *pos++;
967 wpa_printf(MSG_DEBUG, "P2P: Service Transaction ID %u",
968 srv_trans_id);
969 status = *pos++;
970 wpa_printf(MSG_DEBUG, "P2P: Status Code ID %u",
971 status);
972
973 wpa_hexdump(MSG_MSGDUMP, "P2P: Response Data",
974 pos, tlv_end - pos);
975
976 if (srv_proto == P2P_SERV_P2PS && pos < tlv_end) {
977 wpas_sd_p2ps_serv_response(wpa_s, sa, srv_trans_id,
978 pos, tlv_end);
979 }
980
981 pos = tlv_end;
982 }
983
984 wpas_notify_p2p_sd_response(wpa_s, sa, update_indic, tlvs, tlvs_len);
985 }
986
987
wpas_p2p_sd_request(struct wpa_supplicant * wpa_s,const u8 * dst,const struct wpabuf * tlvs)988 u64 wpas_p2p_sd_request(struct wpa_supplicant *wpa_s, const u8 *dst,
989 const struct wpabuf *tlvs)
990 {
991 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
992 return 0;
993 return (uintptr_t) p2p_sd_request(wpa_s->global->p2p, dst, tlvs);
994 }
995
996
wpas_p2p_sd_request_upnp(struct wpa_supplicant * wpa_s,const u8 * dst,u8 version,const char * query)997 u64 wpas_p2p_sd_request_upnp(struct wpa_supplicant *wpa_s, const u8 *dst,
998 u8 version, const char *query)
999 {
1000 struct wpabuf *tlvs;
1001 u64 ret;
1002
1003 tlvs = wpabuf_alloc(2 + 1 + 1 + 1 + os_strlen(query));
1004 if (tlvs == NULL)
1005 return 0;
1006 wpabuf_put_le16(tlvs, 1 + 1 + 1 + os_strlen(query));
1007 wpabuf_put_u8(tlvs, P2P_SERV_UPNP); /* Service Protocol Type */
1008 wpabuf_put_u8(tlvs, 1); /* Service Transaction ID */
1009 wpabuf_put_u8(tlvs, version);
1010 wpabuf_put_str(tlvs, query);
1011 ret = wpas_p2p_sd_request(wpa_s, dst, tlvs);
1012 wpabuf_free(tlvs);
1013 return ret;
1014 }
1015
1016
wpas_p2p_sd_request_asp(struct wpa_supplicant * wpa_s,const u8 * dst,u8 id,const char * svc_str,const char * info_substr)1017 u64 wpas_p2p_sd_request_asp(struct wpa_supplicant *wpa_s, const u8 *dst, u8 id,
1018 const char *svc_str, const char *info_substr)
1019 {
1020 struct wpabuf *tlvs;
1021 size_t plen, svc_len, substr_len = 0;
1022 u64 ret;
1023
1024 svc_len = os_strlen(svc_str);
1025 if (info_substr)
1026 substr_len = os_strlen(info_substr);
1027
1028 if (svc_len > 0xff || substr_len > 0xff)
1029 return 0;
1030
1031 plen = 1 + 1 + 1 + svc_len + 1 + substr_len;
1032 tlvs = wpabuf_alloc(2 + plen);
1033 if (tlvs == NULL)
1034 return 0;
1035
1036 wpabuf_put_le16(tlvs, plen);
1037 wpabuf_put_u8(tlvs, P2P_SERV_P2PS);
1038 wpabuf_put_u8(tlvs, id); /* Service Transaction ID */
1039 wpabuf_put_u8(tlvs, (u8) svc_len); /* Service String Length */
1040 wpabuf_put_data(tlvs, svc_str, svc_len);
1041 wpabuf_put_u8(tlvs, (u8) substr_len); /* Info Substring Length */
1042 wpabuf_put_data(tlvs, info_substr, substr_len);
1043 ret = wpas_p2p_sd_request(wpa_s, dst, tlvs);
1044 wpabuf_free(tlvs);
1045
1046 return ret;
1047 }
1048
1049
1050 #ifdef CONFIG_WIFI_DISPLAY
1051
wpas_p2p_sd_request_wfd(struct wpa_supplicant * wpa_s,const u8 * dst,const struct wpabuf * tlvs)1052 static u64 wpas_p2p_sd_request_wfd(struct wpa_supplicant *wpa_s, const u8 *dst,
1053 const struct wpabuf *tlvs)
1054 {
1055 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
1056 return 0;
1057 return (uintptr_t) p2p_sd_request_wfd(wpa_s->global->p2p, dst, tlvs);
1058 }
1059
1060
1061 #define MAX_WFD_SD_SUBELEMS 20
1062
wfd_add_sd_req_role(struct wpabuf * tlvs,u8 id,u8 role,const char * subelems)1063 static void wfd_add_sd_req_role(struct wpabuf *tlvs, u8 id, u8 role,
1064 const char *subelems)
1065 {
1066 u8 *len;
1067 const char *pos;
1068 int val;
1069 int count = 0;
1070
1071 len = wpabuf_put(tlvs, 2);
1072 wpabuf_put_u8(tlvs, P2P_SERV_WIFI_DISPLAY); /* Service Protocol Type */
1073 wpabuf_put_u8(tlvs, id); /* Service Transaction ID */
1074
1075 wpabuf_put_u8(tlvs, role);
1076
1077 pos = subelems;
1078 while (*pos) {
1079 val = atoi(pos);
1080 if (val >= 0 && val < 256) {
1081 wpabuf_put_u8(tlvs, val);
1082 count++;
1083 if (count == MAX_WFD_SD_SUBELEMS)
1084 break;
1085 }
1086 pos = os_strchr(pos + 1, ',');
1087 if (pos == NULL)
1088 break;
1089 pos++;
1090 }
1091
1092 WPA_PUT_LE16(len, (u8 *) wpabuf_put(tlvs, 0) - len - 2);
1093 }
1094
1095
wpas_p2p_sd_request_wifi_display(struct wpa_supplicant * wpa_s,const u8 * dst,const char * role)1096 u64 wpas_p2p_sd_request_wifi_display(struct wpa_supplicant *wpa_s,
1097 const u8 *dst, const char *role)
1098 {
1099 struct wpabuf *tlvs;
1100 u64 ret;
1101 const char *subelems;
1102 u8 id = 1;
1103
1104 subelems = os_strchr(role, ' ');
1105 if (subelems == NULL)
1106 return 0;
1107 subelems++;
1108
1109 tlvs = wpabuf_alloc(4 * (2 + 1 + 1 + 1 + MAX_WFD_SD_SUBELEMS));
1110 if (tlvs == NULL)
1111 return 0;
1112
1113 if (os_strstr(role, "[source]"))
1114 wfd_add_sd_req_role(tlvs, id++, 0x00, subelems);
1115 if (os_strstr(role, "[pri-sink]"))
1116 wfd_add_sd_req_role(tlvs, id++, 0x01, subelems);
1117 if (os_strstr(role, "[sec-sink]"))
1118 wfd_add_sd_req_role(tlvs, id++, 0x02, subelems);
1119 if (os_strstr(role, "[source+sink]"))
1120 wfd_add_sd_req_role(tlvs, id++, 0x03, subelems);
1121
1122 ret = wpas_p2p_sd_request_wfd(wpa_s, dst, tlvs);
1123 wpabuf_free(tlvs);
1124 return ret;
1125 }
1126
1127 #endif /* CONFIG_WIFI_DISPLAY */
1128
1129
wpas_p2p_sd_cancel_request(struct wpa_supplicant * wpa_s,u64 req)1130 int wpas_p2p_sd_cancel_request(struct wpa_supplicant *wpa_s, u64 req)
1131 {
1132 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
1133 return -1;
1134 return p2p_sd_cancel_request(wpa_s->global->p2p,
1135 (void *) (uintptr_t) req);
1136 }
1137
1138
wpas_p2p_sd_response(struct wpa_supplicant * wpa_s,int freq,const u8 * dst,u8 dialog_token,const struct wpabuf * resp_tlvs)1139 void wpas_p2p_sd_response(struct wpa_supplicant *wpa_s, int freq,
1140 const u8 *dst, u8 dialog_token,
1141 const struct wpabuf *resp_tlvs)
1142 {
1143 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
1144 return;
1145 p2p_sd_response(wpa_s->global->p2p, freq, dst, dialog_token,
1146 resp_tlvs);
1147 }
1148
1149
wpas_p2p_sd_service_update(struct wpa_supplicant * wpa_s)1150 void wpas_p2p_sd_service_update(struct wpa_supplicant *wpa_s)
1151 {
1152 if (wpa_s->global->p2p)
1153 p2p_sd_service_update(wpa_s->global->p2p);
1154 }
1155
1156
wpas_p2p_srv_bonjour_free(struct p2p_srv_bonjour * bsrv)1157 static void wpas_p2p_srv_bonjour_free(struct p2p_srv_bonjour *bsrv)
1158 {
1159 dl_list_del(&bsrv->list);
1160 wpabuf_free(bsrv->query);
1161 wpabuf_free(bsrv->resp);
1162 os_free(bsrv);
1163 }
1164
1165
wpas_p2p_srv_upnp_free(struct p2p_srv_upnp * usrv)1166 static void wpas_p2p_srv_upnp_free(struct p2p_srv_upnp *usrv)
1167 {
1168 dl_list_del(&usrv->list);
1169 os_free(usrv->service);
1170 os_free(usrv);
1171 }
1172
1173
wpas_p2p_service_flush(struct wpa_supplicant * wpa_s)1174 void wpas_p2p_service_flush(struct wpa_supplicant *wpa_s)
1175 {
1176 struct p2p_srv_bonjour *bsrv, *bn;
1177 struct p2p_srv_upnp *usrv, *un;
1178
1179 dl_list_for_each_safe(bsrv, bn, &wpa_s->global->p2p_srv_bonjour,
1180 struct p2p_srv_bonjour, list)
1181 wpas_p2p_srv_bonjour_free(bsrv);
1182
1183 dl_list_for_each_safe(usrv, un, &wpa_s->global->p2p_srv_upnp,
1184 struct p2p_srv_upnp, list)
1185 wpas_p2p_srv_upnp_free(usrv);
1186
1187 wpas_p2p_service_flush_asp(wpa_s);
1188 wpas_p2p_sd_service_update(wpa_s);
1189 }
1190
1191
wpas_p2p_service_p2ps_id_exists(struct wpa_supplicant * wpa_s,u32 adv_id)1192 int wpas_p2p_service_p2ps_id_exists(struct wpa_supplicant *wpa_s, u32 adv_id)
1193 {
1194 if (adv_id == 0)
1195 return 1;
1196
1197 if (p2p_service_p2ps_id(wpa_s->global->p2p, adv_id))
1198 return 1;
1199
1200 return 0;
1201 }
1202
1203
wpas_p2p_service_del_asp(struct wpa_supplicant * wpa_s,u32 adv_id)1204 int wpas_p2p_service_del_asp(struct wpa_supplicant *wpa_s, u32 adv_id)
1205 {
1206 int ret;
1207
1208 ret = p2p_service_del_asp(wpa_s->global->p2p, adv_id);
1209 if (ret == 0)
1210 wpas_p2p_sd_service_update(wpa_s);
1211 return ret;
1212 }
1213
1214
wpas_p2p_service_add_asp(struct wpa_supplicant * wpa_s,int auto_accept,u32 adv_id,const char * adv_str,u8 svc_state,u16 config_methods,const char * svc_info,const u8 * cpt_priority)1215 int wpas_p2p_service_add_asp(struct wpa_supplicant *wpa_s,
1216 int auto_accept, u32 adv_id,
1217 const char *adv_str, u8 svc_state,
1218 u16 config_methods, const char *svc_info,
1219 const u8 *cpt_priority)
1220 {
1221 int ret;
1222
1223 ret = p2p_service_add_asp(wpa_s->global->p2p, auto_accept, adv_id,
1224 adv_str, svc_state, config_methods,
1225 svc_info, cpt_priority);
1226 if (ret == 0)
1227 wpas_p2p_sd_service_update(wpa_s);
1228 return ret;
1229 }
1230
1231
wpas_p2p_service_flush_asp(struct wpa_supplicant * wpa_s)1232 void wpas_p2p_service_flush_asp(struct wpa_supplicant *wpa_s)
1233 {
1234 p2p_service_flush_asp(wpa_s->global->p2p);
1235 }
1236
1237
wpas_p2p_service_add_bonjour(struct wpa_supplicant * wpa_s,struct wpabuf * query,struct wpabuf * resp)1238 int wpas_p2p_service_add_bonjour(struct wpa_supplicant *wpa_s,
1239 struct wpabuf *query, struct wpabuf *resp)
1240 {
1241 struct p2p_srv_bonjour *bsrv;
1242
1243 bsrv = os_zalloc(sizeof(*bsrv));
1244 if (bsrv == NULL)
1245 return -1;
1246 bsrv->query = query;
1247 bsrv->resp = resp;
1248 dl_list_add(&wpa_s->global->p2p_srv_bonjour, &bsrv->list);
1249
1250 wpas_p2p_sd_service_update(wpa_s);
1251 return 0;
1252 }
1253
1254
wpas_p2p_service_del_bonjour(struct wpa_supplicant * wpa_s,const struct wpabuf * query)1255 int wpas_p2p_service_del_bonjour(struct wpa_supplicant *wpa_s,
1256 const struct wpabuf *query)
1257 {
1258 struct p2p_srv_bonjour *bsrv;
1259
1260 bsrv = wpas_p2p_service_get_bonjour(wpa_s, query);
1261 if (bsrv == NULL)
1262 return -1;
1263 wpas_p2p_srv_bonjour_free(bsrv);
1264 wpas_p2p_sd_service_update(wpa_s);
1265 return 0;
1266 }
1267
1268
wpas_p2p_service_add_upnp(struct wpa_supplicant * wpa_s,u8 version,const char * service)1269 int wpas_p2p_service_add_upnp(struct wpa_supplicant *wpa_s, u8 version,
1270 const char *service)
1271 {
1272 struct p2p_srv_upnp *usrv;
1273
1274 if (wpas_p2p_service_get_upnp(wpa_s, version, service))
1275 return 0; /* Already listed */
1276 usrv = os_zalloc(sizeof(*usrv));
1277 if (usrv == NULL)
1278 return -1;
1279 usrv->version = version;
1280 usrv->service = os_strdup(service);
1281 if (usrv->service == NULL) {
1282 os_free(usrv);
1283 return -1;
1284 }
1285 dl_list_add(&wpa_s->global->p2p_srv_upnp, &usrv->list);
1286
1287 wpas_p2p_sd_service_update(wpa_s);
1288 return 0;
1289 }
1290
1291
wpas_p2p_service_del_upnp(struct wpa_supplicant * wpa_s,u8 version,const char * service)1292 int wpas_p2p_service_del_upnp(struct wpa_supplicant *wpa_s, u8 version,
1293 const char *service)
1294 {
1295 struct p2p_srv_upnp *usrv;
1296
1297 usrv = wpas_p2p_service_get_upnp(wpa_s, version, service);
1298 if (usrv == NULL)
1299 return -1;
1300 wpas_p2p_srv_upnp_free(usrv);
1301 wpas_p2p_sd_service_update(wpa_s);
1302 return 0;
1303 }
1304