• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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