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