2 * wpa_supplicant - P2P service discovery
3 * Copyright (c) 2009-2010, Atheros Communications
4 * Copyright (c) 2010-2014, Jouni Malinen <j@w1.fi>
6 * This software may be distributed under the terms of the BSD license.
7 * See README for more details.
10 #include "utils/includes.h"
12 #include "utils/common.h"
14 #include "wpa_supplicant_i.h"
16 #include "p2p_supplicant.h"
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.
24 #define DNS_HEADER_LEN 12
27 * 27-octet in-memory packet from P2P specification containing two implied
28 * queries for _tcp.lcoal. PTR IN and _udp.local. PTR IN
30 #define P2P_SD_IN_MEMORY_LEN 27
32 static int p2p_sd_dns_uncompress_label(char **upos
, char *uend
, u8
*start
,
33 u8
**spos
, const u8
*end
)
36 u8 val
= ((*spos
)[0] & 0xc0) >> 6;
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
);
51 if (*spos
+ 2 > end
) {
52 wpa_printf(MSG_DEBUG
, "P2P: No room for full "
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
);
65 spos_tmp
= start
+ offset
;
66 return p2p_sd_dns_uncompress_label(upos
, uend
, start
,
72 len
= (*spos
)[0] & 0x3f;
77 if (*spos
+ len
> end
) {
78 wpa_printf(MSG_DEBUG
, "P2P: Invalid domain name "
79 "sequence - no room for label with length "
84 if (*upos
+ len
+ 2 > uend
)
87 os_memcpy(*upos
, *spos
, len
);
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 static int p2p_sd_dns_uncompress(char *buf
, size_t buf_len
, const u8
*msg
,
103 size_t msg_len
, size_t offset
)
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
;
114 if (offset
> msg_len
)
117 tmp
= os_malloc(DNS_HEADER_LEN
+ P2P_SD_IN_MEMORY_LEN
+ msg_len
);
120 spos
= tmp
+ DNS_HEADER_LEN
+ P2P_SD_IN_MEMORY_LEN
;
121 end
= spos
+ msg_len
;
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
);
129 uend
= buf
+ buf_len
;
131 ret
= p2p_sd_dns_uncompress_label(&upos
, uend
, tmp
, &spos
, end
);
140 } else if (upos
[-1] == '.')
148 static struct p2p_srv_bonjour
*
149 wpas_p2p_service_get_bonjour(struct wpa_supplicant
*wpa_s
,
150 const struct wpabuf
*query
)
152 struct p2p_srv_bonjour
*bsrv
;
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
),
167 static struct p2p_srv_upnp
*
168 wpas_p2p_service_get_upnp(struct wpa_supplicant
*wpa_s
, u8 version
,
171 struct p2p_srv_upnp
*usrv
;
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)
183 static void wpas_sd_add_empty(struct wpabuf
*resp
, u8 srv_proto
,
184 u8 srv_trans_id
, u8 status
)
188 if (wpabuf_tailroom(resp
) < 5)
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
);
196 wpabuf_put_u8(resp
, status
);
197 /* Response Data: empty */
198 WPA_PUT_LE16(len_pos
, (u8
*) wpabuf_put(resp
, 0) - len_pos
- 2);
202 static void wpas_sd_add_proto_not_avail(struct wpabuf
*resp
, u8 srv_proto
,
205 wpas_sd_add_empty(resp
, srv_proto
, srv_trans_id
,
206 P2P_SD_PROTO_NOT_AVAILABLE
);
210 static void wpas_sd_add_bad_request(struct wpabuf
*resp
, u8 srv_proto
,
213 wpas_sd_add_empty(resp
, srv_proto
, srv_trans_id
, P2P_SD_BAD_REQUEST
);
217 static void wpas_sd_add_not_found(struct wpabuf
*resp
, u8 srv_proto
,
220 wpas_sd_add_empty(resp
, srv_proto
, srv_trans_id
,
221 P2P_SD_REQUESTED_INFO_NOT_AVAILABLE
);
225 static void wpas_sd_all_bonjour(struct wpa_supplicant
*wpa_s
,
226 struct wpabuf
*resp
, u8 srv_trans_id
)
228 struct p2p_srv_bonjour
*bsrv
;
231 wpa_printf(MSG_DEBUG
, "P2P: SD Request for all Bonjour services");
233 if (dl_list_empty(&wpa_s
->global
->p2p_srv_bonjour
)) {
234 wpa_printf(MSG_DEBUG
, "P2P: Bonjour protocol not available");
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
))
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
);
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
));
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
-
261 static int match_bonjour_query(struct p2p_srv_bonjour
*bsrv
, const u8
*query
,
264 char str_rx
[256], str_srv
[256];
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,
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 */
276 if (p2p_sd_dns_uncompress(str_rx
, sizeof(str_rx
), query
, query_len
- 3,
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 */
284 return os_strcmp(str_rx
, str_srv
) == 0;
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
)
292 struct p2p_srv_bonjour
*bsrv
;
296 wpa_hexdump_ascii(MSG_DEBUG
, "P2P: SD Request for Bonjour",
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
,
305 if (query_len
== 0) {
306 wpas_sd_all_bonjour(wpa_s
, resp
, srv_trans_id
);
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
))
315 if (wpabuf_tailroom(resp
) <
316 5 + query_len
+ wpabuf_len(bsrv
->resp
))
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
);
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
));
333 wpabuf_put_data(resp
, query
, query_len
); /* Key */
334 wpabuf_put_buf(resp
, bsrv
->resp
); /* Value */
336 WPA_PUT_LE16(len_pos
, (u8
*) wpabuf_put(resp
, 0) - len_pos
- 2);
340 wpa_printf(MSG_DEBUG
, "P2P: Requested Bonjour service not "
342 if (wpabuf_tailroom(resp
) < 5)
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
);
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
-
359 static void wpas_sd_all_upnp(struct wpa_supplicant
*wpa_s
,
360 struct wpabuf
*resp
, u8 srv_trans_id
)
362 struct p2p_srv_upnp
*usrv
;
365 wpa_printf(MSG_DEBUG
, "P2P: SD Request for all UPnP services");
367 if (dl_list_empty(&wpa_s
->global
->p2p_srv_upnp
)) {
368 wpa_printf(MSG_DEBUG
, "P2P: UPnP protocol not available");
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
))
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
);
383 wpabuf_put_u8(resp
, P2P_SD_SUCCESS
);
385 wpabuf_put_u8(resp
, usrv
->version
);
386 wpa_printf(MSG_DEBUG
, "P2P: Matching UPnP Service: %s",
388 wpabuf_put_str(resp
, usrv
->service
);
389 WPA_PUT_LE16(len_pos
, (u8
*) wpabuf_put(resp
, 0) - len_pos
-
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
)
399 struct p2p_srv_upnp
*usrv
;
405 wpa_hexdump_ascii(MSG_DEBUG
, "P2P: SD Request for UPnP",
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
,
415 if (query_len
== 0) {
416 wpas_sd_all_upnp(wpa_s
, resp
, srv_trans_id
);
420 if (wpabuf_tailroom(resp
) < 5)
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
);
429 str
= os_malloc(query_len
);
432 os_memcpy(str
, query
+ 1, query_len
- 1);
433 str
[query_len
- 1] = '\0';
435 dl_list_for_each(usrv
, &wpa_s
->global
->p2p_srv_upnp
,
436 struct p2p_srv_upnp
, list
) {
437 if (version
!= usrv
->version
)
440 if (os_strcmp(str
, "ssdp:all") != 0 &&
441 os_strstr(usrv
->service
, str
) == NULL
)
444 if (wpabuf_tailroom(resp
) < 2)
448 wpabuf_put_u8(resp
, P2P_SD_SUCCESS
);
450 wpabuf_put_u8(resp
, version
);
452 wpabuf_put_u8(resp
, ',');
456 wpa_printf(MSG_DEBUG
, "P2P: Matching UPnP Service: %s",
458 if (wpabuf_tailroom(resp
) < os_strlen(usrv
->service
))
460 wpabuf_put_str(resp
, usrv
->service
);
465 wpa_printf(MSG_DEBUG
, "P2P: Requested UPnP service not "
468 wpabuf_put_u8(resp
, P2P_SD_REQUESTED_INFO_NOT_AVAILABLE
);
469 /* Response Data: empty */
472 WPA_PUT_LE16(len_pos
, (u8
*) wpabuf_put(resp
, 0) - len_pos
- 2);
476 #ifdef CONFIG_WIFI_DISPLAY
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
)
485 wpa_hexdump(MSG_DEBUG
, "P2P: SD Request for WFD", query
, query_len
);
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
,
495 wpa_printf(MSG_DEBUG
, "P2P: Missing WFD Requested Device "
500 if (wpabuf_tailroom(resp
) < 5)
505 wpa_printf(MSG_DEBUG
, "P2P: WSD for device role 0x%x", role
);
507 /* TODO: role specific handling */
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 */
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
]);
527 WPA_PUT_LE16(len_pos
, (u8
*) wpabuf_put(resp
, 0) - len_pos
- 2);
529 #endif /* CONFIG_WIFI_DISPLAY */
532 static int find_p2ps_substr(struct p2ps_advertisement
*adv_data
,
533 const u8
*needle
, size_t needle_len
)
535 const u8
*haystack
= (const u8
*) adv_data
->svc_info
;
536 size_t haystack_len
, i
;
538 /* Allow search term to be empty */
539 if (!needle
|| !needle_len
)
545 haystack_len
= os_strlen(adv_data
->svc_info
);
546 for (i
= 0; i
< haystack_len
; i
++) {
547 if (haystack_len
- i
< needle_len
)
549 if (os_memcmp(haystack
+ i
, needle
, needle_len
) == 0)
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
)
561 struct p2ps_advertisement
*adv_data
;
562 const u8
*svc
= &query
[1];
563 const u8
*info
= NULL
;
564 size_t svc_len
= query
[0];
567 u8
*count_pos
= NULL
;
570 wpa_hexdump(MSG_DEBUG
, "P2P: SD Request for ASP", query
, query_len
);
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
);
578 /* Info block is optional */
579 if (svc_len
+ 1 < query_len
) {
580 info
= &svc
[svc_len
];
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
);
591 /* Detect and correct for prefix search */
592 if (svc_len
&& svc
[svc_len
- 1] == '*') {
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
))
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;
609 if (adv_data
->svc_info
)
610 svc_info_len
= os_strlen(adv_data
->svc_info
);
612 if (len
> 0xff || svc_info_len
> 0xffff)
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)
621 len_pos
= wpabuf_put(resp
, 2);
622 wpabuf_put_u8(resp
, P2P_SERV_P2PS
);
623 wpabuf_put_u8(resp
, srv_trans_id
);
625 wpabuf_put_u8(resp
, P2P_SD_SUCCESS
);
626 count_pos
= wpabuf_put(resp
, 1);
628 } else if (wpabuf_tailroom(resp
) <
629 len
+ svc_info_len
+ 10)
633 wpa_printf(MSG_DEBUG
,
634 "P2P: Add Svc: %s info: %s",
638 wpa_printf(MSG_DEBUG
, "P2P: Add Svc: %s",
642 /* Advertisement ID */
643 wpabuf_put_le32(resp
, adv_data
->id
);
646 wpabuf_put_be16(resp
, adv_data
->config_methods
);
649 wpabuf_put_u8(resp
, (u8
) len
);
650 wpabuf_put_data(resp
, adv_data
->svc_name
, len
);
653 wpabuf_put_u8(resp
, adv_data
->state
);
655 /* Service Information */
656 wpabuf_put_le16(resp
, (u16
) svc_info_len
);
657 wpabuf_put_data(resp
, adv_data
->svc_info
, svc_info_len
);
659 /* Update length and count */
661 WPA_PUT_LE16(len_pos
,
662 (u8
*) wpabuf_put(resp
, 0) - len_pos
- 2);
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
);
674 void wpas_sd_request(void *ctx
, int freq
, const u8
*sa
, u8 dialog_token
,
675 u16 update_indic
, const u8
*tlvs
, size_t tlvs_len
)
677 struct wpa_supplicant
*wpa_s
= ctx
;
678 const u8
*pos
= tlvs
;
679 const u8
*end
= tlvs
+ tlvs_len
;
683 u8 srv_proto
, srv_trans_id
;
687 wpa_hexdump(MSG_MSGDUMP
, "P2P: Service Discovery Request TLVs",
689 buf_len
= 2 * tlvs_len
+ 1;
690 buf
= os_malloc(buf_len
);
692 wpa_snprintf_hex(buf
, buf_len
, tlvs
, tlvs_len
);
693 wpa_msg_ctrl(wpa_s
, MSG_INFO
, P2P_EVENT_SERV_DISC_REQ
"%d "
695 freq
, MAC2STR(sa
), dialog_token
, update_indic
,
700 if (wpa_s
->p2p_sd_over_ctrl_iface
) {
701 wpas_notify_p2p_sd_request(wpa_s
, freq
, sa
, dialog_token
,
702 update_indic
, tlvs
, tlvs_len
);
703 return; /* to be processed by an external program */
706 resp
= wpabuf_alloc(10000);
710 while (pos
+ 1 < end
) {
711 wpa_printf(MSG_DEBUG
, "P2P: Service Request TLV");
712 slen
= WPA_GET_LE16(pos
);
714 if (pos
+ slen
> end
|| slen
< 2) {
715 wpa_printf(MSG_DEBUG
, "P2P: Unexpected Query Data "
720 tlv_end
= pos
+ slen
;
723 wpa_printf(MSG_DEBUG
, "P2P: Service Protocol Type %u",
725 srv_trans_id
= *pos
++;
726 wpa_printf(MSG_DEBUG
, "P2P: Service Transaction ID %u",
729 wpa_hexdump(MSG_MSGDUMP
, "P2P: Query Data",
733 if (wpa_s
->force_long_sd
) {
734 wpa_printf(MSG_DEBUG
, "P2P: SD test - force long "
736 wpas_sd_all_bonjour(wpa_s
, resp
, srv_trans_id
);
737 wpas_sd_all_upnp(wpa_s
, resp
, srv_trans_id
);
742 case P2P_SERV_ALL_SERVICES
:
743 wpa_printf(MSG_DEBUG
, "P2P: Service Discovery Request "
745 if (dl_list_empty(&wpa_s
->global
->p2p_srv_upnp
) &&
746 dl_list_empty(&wpa_s
->global
->p2p_srv_bonjour
)) {
747 wpa_printf(MSG_DEBUG
, "P2P: No service "
748 "discovery protocols available");
749 wpas_sd_add_proto_not_avail(
750 resp
, P2P_SERV_ALL_SERVICES
,
754 wpas_sd_all_bonjour(wpa_s
, resp
, srv_trans_id
);
755 wpas_sd_all_upnp(wpa_s
, resp
, srv_trans_id
);
757 case P2P_SERV_BONJOUR
:
758 wpas_sd_req_bonjour(wpa_s
, resp
, srv_trans_id
,
762 wpas_sd_req_upnp(wpa_s
, resp
, srv_trans_id
,
765 #ifdef CONFIG_WIFI_DISPLAY
766 case P2P_SERV_WIFI_DISPLAY
:
767 wpas_sd_req_wfd(wpa_s
, resp
, srv_trans_id
,
770 #endif /* CONFIG_WIFI_DISPLAY */
772 wpas_sd_req_asp(wpa_s
, resp
, srv_trans_id
,
776 wpa_printf(MSG_DEBUG
, "P2P: Unavailable service "
777 "protocol %u", srv_proto
);
778 wpas_sd_add_proto_not_avail(resp
, srv_proto
,
787 wpas_notify_p2p_sd_request(wpa_s
, freq
, sa
, dialog_token
,
788 update_indic
, tlvs
, tlvs_len
);
790 wpas_p2p_sd_response(wpa_s
, freq
, sa
, dialog_token
, resp
);
796 static void wpas_sd_p2ps_serv_response(struct wpa_supplicant
*wpa_s
,
797 const u8
*sa
, u8 srv_trans_id
,
798 const u8
*pos
, const u8
*tlv_end
)
806 while (left
-- && pos
< tlv_end
) {
811 /* Sanity check fixed length+svc_str */
812 if (pos
+ 6 >= tlv_end
)
815 if (pos
+ svc_len
+ 10 > tlv_end
)
818 /* Advertisement ID */
819 adv_id
= WPA_GET_LE32(pos
);
823 config_methods
= WPA_GET_BE16(pos
);
828 os_memcpy(svc_str
, pos
, svc_len
);
829 svc_str
[svc_len
] = '\0';
835 /* Service Information Length */
836 buf_len
= WPA_GET_LE16(pos
);
839 /* Sanity check buffer length */
840 if (buf_len
> (unsigned int) (tlv_end
- pos
))
844 buf
= os_zalloc(2 * buf_len
+ 1);
846 utf8_escape((const char *) pos
, buf_len
, buf
,
854 wpa_msg_global(wpa_s
, MSG_INFO
, P2P_EVENT_SERV_ASP_RESP
855 MACSTR
" %x %x %x %x %s '%s'",
856 MAC2STR(sa
), srv_trans_id
, adv_id
,
857 svc_status
, config_methods
, svc_str
,
861 wpa_msg_global(wpa_s
, MSG_INFO
, P2P_EVENT_SERV_ASP_RESP
862 MACSTR
" %x %x %x %x %s",
863 MAC2STR(sa
), srv_trans_id
, adv_id
,
864 svc_status
, config_methods
, svc_str
);
870 void wpas_sd_response(void *ctx
, const u8
*sa
, u16 update_indic
,
871 const u8
*tlvs
, size_t tlvs_len
)
873 struct wpa_supplicant
*wpa_s
= ctx
;
874 const u8
*pos
= tlvs
;
875 const u8
*end
= tlvs
+ tlvs_len
;
881 wpa_hexdump(MSG_MSGDUMP
, "P2P: Service Discovery Response TLVs",
883 if (tlvs_len
> 1500) {
884 /* TODO: better way for handling this */
885 wpa_msg_ctrl(wpa_s
, MSG_INFO
,
886 P2P_EVENT_SERV_DISC_RESP MACSTR
887 " %u <long response: %u bytes>",
888 MAC2STR(sa
), update_indic
,
889 (unsigned int) tlvs_len
);
891 buf_len
= 2 * tlvs_len
+ 1;
892 buf
= os_malloc(buf_len
);
894 wpa_snprintf_hex(buf
, buf_len
, tlvs
, tlvs_len
);
895 wpa_msg_ctrl(wpa_s
, MSG_INFO
,
896 P2P_EVENT_SERV_DISC_RESP MACSTR
" %u %s",
897 MAC2STR(sa
), update_indic
, buf
);
903 u8 srv_proto
, srv_trans_id
, status
;
905 wpa_printf(MSG_DEBUG
, "P2P: Service Response TLV");
906 slen
= WPA_GET_LE16(pos
);
908 if (pos
+ slen
> end
|| slen
< 3) {
909 wpa_printf(MSG_DEBUG
, "P2P: Unexpected Response Data "
913 tlv_end
= pos
+ slen
;
916 wpa_printf(MSG_DEBUG
, "P2P: Service Protocol Type %u",
918 srv_trans_id
= *pos
++;
919 wpa_printf(MSG_DEBUG
, "P2P: Service Transaction ID %u",
922 wpa_printf(MSG_DEBUG
, "P2P: Status Code ID %u",
925 wpa_hexdump(MSG_MSGDUMP
, "P2P: Response Data",
928 if (srv_proto
== P2P_SERV_P2PS
&& pos
< tlv_end
) {
929 wpas_sd_p2ps_serv_response(wpa_s
, sa
, srv_trans_id
,
936 wpas_notify_p2p_sd_response(wpa_s
, sa
, update_indic
, tlvs
, tlvs_len
);
940 u64
wpas_p2p_sd_request(struct wpa_supplicant
*wpa_s
, const u8
*dst
,
941 const struct wpabuf
*tlvs
)
943 if (wpa_s
->global
->p2p_disabled
|| wpa_s
->global
->p2p
== NULL
)
945 return (uintptr_t) p2p_sd_request(wpa_s
->global
->p2p
, dst
, tlvs
);
949 u64
wpas_p2p_sd_request_upnp(struct wpa_supplicant
*wpa_s
, const u8
*dst
,
950 u8 version
, const char *query
)
955 tlvs
= wpabuf_alloc(2 + 1 + 1 + 1 + os_strlen(query
));
958 wpabuf_put_le16(tlvs
, 1 + 1 + 1 + os_strlen(query
));
959 wpabuf_put_u8(tlvs
, P2P_SERV_UPNP
); /* Service Protocol Type */
960 wpabuf_put_u8(tlvs
, 1); /* Service Transaction ID */
961 wpabuf_put_u8(tlvs
, version
);
962 wpabuf_put_str(tlvs
, query
);
963 ret
= wpas_p2p_sd_request(wpa_s
, dst
, tlvs
);
969 u64
wpas_p2p_sd_request_asp(struct wpa_supplicant
*wpa_s
, const u8
*dst
, u8 id
,
970 const char *svc_str
, const char *info_substr
)
973 size_t plen
, svc_len
, substr_len
= 0;
976 svc_len
= os_strlen(svc_str
);
978 substr_len
= os_strlen(info_substr
);
980 if (svc_len
> 0xff || substr_len
> 0xff)
983 plen
= 1 + 1 + 1 + svc_len
+ 1 + substr_len
;
984 tlvs
= wpabuf_alloc(2 + plen
);
988 wpabuf_put_le16(tlvs
, plen
);
989 wpabuf_put_u8(tlvs
, P2P_SERV_P2PS
);
990 wpabuf_put_u8(tlvs
, id
); /* Service Transaction ID */
991 wpabuf_put_u8(tlvs
, (u8
) svc_len
); /* Service String Length */
992 wpabuf_put_data(tlvs
, svc_str
, svc_len
);
993 wpabuf_put_u8(tlvs
, (u8
) substr_len
); /* Info Substring Length */
994 wpabuf_put_data(tlvs
, info_substr
, substr_len
);
995 ret
= wpas_p2p_sd_request(wpa_s
, dst
, tlvs
);
1002 #ifdef CONFIG_WIFI_DISPLAY
1004 static u64
wpas_p2p_sd_request_wfd(struct wpa_supplicant
*wpa_s
, const u8
*dst
,
1005 const struct wpabuf
*tlvs
)
1007 if (wpa_s
->global
->p2p_disabled
|| wpa_s
->global
->p2p
== NULL
)
1009 return (uintptr_t) p2p_sd_request_wfd(wpa_s
->global
->p2p
, dst
, tlvs
);
1013 #define MAX_WFD_SD_SUBELEMS 20
1015 static void wfd_add_sd_req_role(struct wpabuf
*tlvs
, u8 id
, u8 role
,
1016 const char *subelems
)
1023 len
= wpabuf_put(tlvs
, 2);
1024 wpabuf_put_u8(tlvs
, P2P_SERV_WIFI_DISPLAY
); /* Service Protocol Type */
1025 wpabuf_put_u8(tlvs
, id
); /* Service Transaction ID */
1027 wpabuf_put_u8(tlvs
, role
);
1032 if (val
>= 0 && val
< 256) {
1033 wpabuf_put_u8(tlvs
, val
);
1035 if (count
== MAX_WFD_SD_SUBELEMS
)
1038 pos
= os_strchr(pos
+ 1, ',');
1044 WPA_PUT_LE16(len
, (u8
*) wpabuf_put(tlvs
, 0) - len
- 2);
1048 u64
wpas_p2p_sd_request_wifi_display(struct wpa_supplicant
*wpa_s
,
1049 const u8
*dst
, const char *role
)
1051 struct wpabuf
*tlvs
;
1053 const char *subelems
;
1056 subelems
= os_strchr(role
, ' ');
1057 if (subelems
== NULL
)
1061 tlvs
= wpabuf_alloc(4 * (2 + 1 + 1 + 1 + MAX_WFD_SD_SUBELEMS
));
1065 if (os_strstr(role
, "[source]"))
1066 wfd_add_sd_req_role(tlvs
, id
++, 0x00, subelems
);
1067 if (os_strstr(role
, "[pri-sink]"))
1068 wfd_add_sd_req_role(tlvs
, id
++, 0x01, subelems
);
1069 if (os_strstr(role
, "[sec-sink]"))
1070 wfd_add_sd_req_role(tlvs
, id
++, 0x02, subelems
);
1071 if (os_strstr(role
, "[source+sink]"))
1072 wfd_add_sd_req_role(tlvs
, id
++, 0x03, subelems
);
1074 ret
= wpas_p2p_sd_request_wfd(wpa_s
, dst
, tlvs
);
1079 #endif /* CONFIG_WIFI_DISPLAY */
1082 int wpas_p2p_sd_cancel_request(struct wpa_supplicant
*wpa_s
, u64 req
)
1084 if (wpa_s
->global
->p2p_disabled
|| wpa_s
->global
->p2p
== NULL
)
1086 return p2p_sd_cancel_request(wpa_s
->global
->p2p
,
1087 (void *) (uintptr_t) req
);
1091 void wpas_p2p_sd_response(struct wpa_supplicant
*wpa_s
, int freq
,
1092 const u8
*dst
, u8 dialog_token
,
1093 const struct wpabuf
*resp_tlvs
)
1095 if (wpa_s
->global
->p2p_disabled
|| wpa_s
->global
->p2p
== NULL
)
1097 p2p_sd_response(wpa_s
->global
->p2p
, freq
, dst
, dialog_token
,
1102 void wpas_p2p_sd_service_update(struct wpa_supplicant
*wpa_s
)
1104 if (wpa_s
->global
->p2p
)
1105 p2p_sd_service_update(wpa_s
->global
->p2p
);
1109 static void wpas_p2p_srv_bonjour_free(struct p2p_srv_bonjour
*bsrv
)
1111 dl_list_del(&bsrv
->list
);
1112 wpabuf_free(bsrv
->query
);
1113 wpabuf_free(bsrv
->resp
);
1118 static void wpas_p2p_srv_upnp_free(struct p2p_srv_upnp
*usrv
)
1120 dl_list_del(&usrv
->list
);
1121 os_free(usrv
->service
);
1126 void wpas_p2p_service_flush(struct wpa_supplicant
*wpa_s
)
1128 struct p2p_srv_bonjour
*bsrv
, *bn
;
1129 struct p2p_srv_upnp
*usrv
, *un
;
1131 dl_list_for_each_safe(bsrv
, bn
, &wpa_s
->global
->p2p_srv_bonjour
,
1132 struct p2p_srv_bonjour
, list
)
1133 wpas_p2p_srv_bonjour_free(bsrv
);
1135 dl_list_for_each_safe(usrv
, un
, &wpa_s
->global
->p2p_srv_upnp
,
1136 struct p2p_srv_upnp
, list
)
1137 wpas_p2p_srv_upnp_free(usrv
);
1139 wpas_p2p_service_flush_asp(wpa_s
);
1140 wpas_p2p_sd_service_update(wpa_s
);
1144 int wpas_p2p_service_p2ps_id_exists(struct wpa_supplicant
*wpa_s
, u32 adv_id
)
1149 if (p2p_service_p2ps_id(wpa_s
->global
->p2p
, adv_id
))
1156 int wpas_p2p_service_del_asp(struct wpa_supplicant
*wpa_s
, u32 adv_id
)
1160 ret
= p2p_service_del_asp(wpa_s
->global
->p2p
, adv_id
);
1162 wpas_p2p_sd_service_update(wpa_s
);
1167 int wpas_p2p_service_add_asp(struct wpa_supplicant
*wpa_s
,
1168 int auto_accept
, u32 adv_id
,
1169 const char *adv_str
, u8 svc_state
,
1170 u16 config_methods
, const char *svc_info
)
1174 ret
= p2p_service_add_asp(wpa_s
->global
->p2p
, auto_accept
, adv_id
,
1175 adv_str
, svc_state
, config_methods
,
1178 wpas_p2p_sd_service_update(wpa_s
);
1183 void wpas_p2p_service_flush_asp(struct wpa_supplicant
*wpa_s
)
1185 p2p_service_flush_asp(wpa_s
->global
->p2p
);
1189 int wpas_p2p_service_add_bonjour(struct wpa_supplicant
*wpa_s
,
1190 struct wpabuf
*query
, struct wpabuf
*resp
)
1192 struct p2p_srv_bonjour
*bsrv
;
1194 bsrv
= os_zalloc(sizeof(*bsrv
));
1197 bsrv
->query
= query
;
1199 dl_list_add(&wpa_s
->global
->p2p_srv_bonjour
, &bsrv
->list
);
1201 wpas_p2p_sd_service_update(wpa_s
);
1206 int wpas_p2p_service_del_bonjour(struct wpa_supplicant
*wpa_s
,
1207 const struct wpabuf
*query
)
1209 struct p2p_srv_bonjour
*bsrv
;
1211 bsrv
= wpas_p2p_service_get_bonjour(wpa_s
, query
);
1214 wpas_p2p_srv_bonjour_free(bsrv
);
1215 wpas_p2p_sd_service_update(wpa_s
);
1220 int wpas_p2p_service_add_upnp(struct wpa_supplicant
*wpa_s
, u8 version
,
1221 const char *service
)
1223 struct p2p_srv_upnp
*usrv
;
1225 if (wpas_p2p_service_get_upnp(wpa_s
, version
, service
))
1226 return 0; /* Already listed */
1227 usrv
= os_zalloc(sizeof(*usrv
));
1230 usrv
->version
= version
;
1231 usrv
->service
= os_strdup(service
);
1232 if (usrv
->service
== NULL
) {
1236 dl_list_add(&wpa_s
->global
->p2p_srv_upnp
, &usrv
->list
);
1238 wpas_p2p_sd_service_update(wpa_s
);
1243 int wpas_p2p_service_del_upnp(struct wpa_supplicant
*wpa_s
, u8 version
,
1244 const char *service
)
1246 struct p2p_srv_upnp
*usrv
;
1248 usrv
= wpas_p2p_service_get_upnp(wpa_s
, version
, service
);
1251 wpas_p2p_srv_upnp_free(usrv
);
1252 wpas_p2p_sd_service_update(wpa_s
);