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