1 /******************************************************************************
2 *
3 * Copyright 1999-2012 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 /******************************************************************************
20 *
21 * this file contains SDP discovery functions
22 *
23 ******************************************************************************/
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "bt_common.h"
30 #include "bt_target.h"
31 #include "btm_api.h"
32 #include "btu.h"
33 #include "hcidefs.h"
34 #include "hcimsgs.h"
35 #include "l2cdefs.h"
36 #include "log/log.h"
37 #include "sdp_api.h"
38 #include "sdpint.h"
39
40 using bluetooth::Uuid;
41
42 #ifndef SDP_DEBUG_RAW
43 #define SDP_DEBUG_RAW false
44 #endif
45
46 /******************************************************************************/
47 /* L O C A L F U N C T I O N P R O T O T Y P E S */
48 /******************************************************************************/
49 static void process_service_search_rsp(tCONN_CB* p_ccb, uint8_t* p_reply,
50 uint8_t* p_reply_end);
51 static void process_service_attr_rsp(tCONN_CB* p_ccb, uint8_t* p_reply,
52 uint8_t* p_reply_end);
53 static void process_service_search_attr_rsp(tCONN_CB* p_ccb, uint8_t* p_reply,
54 uint8_t* p_reply_end);
55 static uint8_t* save_attr_seq(tCONN_CB* p_ccb, uint8_t* p, uint8_t* p_msg_end);
56 static tSDP_DISC_REC* add_record(tSDP_DISCOVERY_DB* p_db,
57 const RawAddress& p_bda);
58 static uint8_t* add_attr(uint8_t* p, uint8_t* p_end, tSDP_DISCOVERY_DB* p_db,
59 tSDP_DISC_REC* p_rec, uint16_t attr_id,
60 tSDP_DISC_ATTR* p_parent_attr, uint8_t nest_level);
61
62 /* Safety check in case we go crazy */
63 #define MAX_NEST_LEVELS 5
64
65 /*******************************************************************************
66 *
67 * Function sdpu_build_uuid_seq
68 *
69 * Description This function builds a UUID sequence from the list of
70 * passed UUIDs. It is also passed the address of the output
71 * buffer.
72 *
73 * Returns Pointer to next byte in the output buffer.
74 *
75 ******************************************************************************/
sdpu_build_uuid_seq(uint8_t * p_out,uint16_t num_uuids,Uuid * p_uuid_list)76 static uint8_t* sdpu_build_uuid_seq(uint8_t* p_out, uint16_t num_uuids,
77 Uuid* p_uuid_list) {
78 uint16_t xx;
79 uint8_t* p_len;
80
81 /* First thing is the data element header */
82 UINT8_TO_BE_STREAM(p_out, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
83
84 /* Remember where the length goes. Leave space for it. */
85 p_len = p_out;
86 p_out += 1;
87
88 /* Now, loop through and put in all the UUID(s) */
89 for (xx = 0; xx < num_uuids; xx++, p_uuid_list++) {
90 int len = p_uuid_list->GetShortestRepresentationSize();
91 if (len == Uuid::kNumBytes16) {
92 UINT8_TO_BE_STREAM(p_out, (UUID_DESC_TYPE << 3) | SIZE_TWO_BYTES);
93 UINT16_TO_BE_STREAM(p_out, p_uuid_list->As16Bit());
94 } else if (len == Uuid::kNumBytes32) {
95 UINT8_TO_BE_STREAM(p_out, (UUID_DESC_TYPE << 3) | SIZE_FOUR_BYTES);
96 UINT32_TO_BE_STREAM(p_out, p_uuid_list->As32Bit());
97 } else if (len == Uuid::kNumBytes128) {
98 UINT8_TO_BE_STREAM(p_out, (UUID_DESC_TYPE << 3) | SIZE_SIXTEEN_BYTES);
99 ARRAY_TO_BE_STREAM(p_out, p_uuid_list->To128BitBE(),
100 (int)Uuid::kNumBytes128);
101 } else {
102 DCHECK(0) << "SDP: Passed UUID has invalid length " << len;
103 }
104 }
105
106 /* Now, put in the length */
107 xx = (uint16_t)(p_out - p_len - 1);
108 UINT8_TO_BE_STREAM(p_len, xx);
109
110 return (p_out);
111 }
112
113 /*******************************************************************************
114 *
115 * Function sdp_snd_service_search_req
116 *
117 * Description Send a service search request to the SDP server.
118 *
119 * Returns void
120 *
121 ******************************************************************************/
sdp_snd_service_search_req(tCONN_CB * p_ccb,uint8_t cont_len,uint8_t * p_cont)122 static void sdp_snd_service_search_req(tCONN_CB* p_ccb, uint8_t cont_len,
123 uint8_t* p_cont) {
124 uint8_t *p, *p_start, *p_param_len;
125 BT_HDR* p_cmd = (BT_HDR*)osi_malloc(SDP_DATA_BUF_SIZE);
126 uint16_t param_len;
127
128 /* Prepare the buffer for sending the packet to L2CAP */
129 p_cmd->offset = L2CAP_MIN_OFFSET;
130 p = p_start = (uint8_t*)(p_cmd + 1) + L2CAP_MIN_OFFSET;
131
132 /* Build a service search request packet */
133 UINT8_TO_BE_STREAM(p, SDP_PDU_SERVICE_SEARCH_REQ);
134 UINT16_TO_BE_STREAM(p, p_ccb->transaction_id);
135 p_ccb->transaction_id++;
136
137 /* Skip the length, we need to add it at the end */
138 p_param_len = p;
139 p += 2;
140
141 /* Build the UID sequence. */
142 #if (SDP_BROWSE_PLUS == TRUE)
143 p = sdpu_build_uuid_seq(p, 1,
144 &p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx]);
145 #else
146 p = sdpu_build_uuid_seq(p, p_ccb->p_db->num_uuid_filters,
147 p_ccb->p_db->uuid_filters);
148 #endif
149
150 /* Set max service record count */
151 UINT16_TO_BE_STREAM(p, sdp_cb.max_recs_per_search);
152
153 /* Set continuation state */
154 UINT8_TO_BE_STREAM(p, cont_len);
155
156 /* if this is not the first request */
157 if (cont_len && p_cont) {
158 memcpy(p, p_cont, cont_len);
159 p += cont_len;
160 }
161
162 /* Go back and put the parameter length into the buffer */
163 param_len = (uint16_t)(p - p_param_len - 2);
164 UINT16_TO_BE_STREAM(p_param_len, param_len);
165
166 p_ccb->disc_state = SDP_DISC_WAIT_HANDLES;
167
168 /* Set the length of the SDP data in the buffer */
169 p_cmd->len = (uint16_t)(p - p_start);
170
171 #if (SDP_DEBUG_RAW == TRUE)
172 SDP_TRACE_WARNING("sdp_snd_service_search_req cont_len :%d disc_state:%d",
173 cont_len, p_ccb->disc_state);
174 #endif
175
176 L2CA_DataWrite(p_ccb->connection_id, p_cmd);
177
178 /* Start inactivity timer */
179 alarm_set_on_mloop(p_ccb->sdp_conn_timer, SDP_INACT_TIMEOUT_MS,
180 sdp_conn_timer_timeout, p_ccb);
181 }
182
183 /*******************************************************************************
184 *
185 * Function sdp_disc_connected
186 *
187 * Description This function is called when an SDP discovery attempt is
188 * connected.
189 *
190 * Returns void
191 *
192 ******************************************************************************/
sdp_disc_connected(tCONN_CB * p_ccb)193 void sdp_disc_connected(tCONN_CB* p_ccb) {
194 if (p_ccb->is_attr_search) {
195 p_ccb->disc_state = SDP_DISC_WAIT_SEARCH_ATTR;
196
197 process_service_search_attr_rsp(p_ccb, NULL, NULL);
198 } else {
199 /* First step is to get a list of the handles from the server. */
200 /* We are not searching for a specific attribute, so we will */
201 /* first search for the service, then get all attributes of it */
202
203 p_ccb->num_handles = 0;
204 sdp_snd_service_search_req(p_ccb, 0, NULL);
205 }
206 }
207
208 /*******************************************************************************
209 *
210 * Function sdp_disc_server_rsp
211 *
212 * Description This function is called when there is a response from
213 * the server.
214 *
215 * Returns void
216 *
217 ******************************************************************************/
sdp_disc_server_rsp(tCONN_CB * p_ccb,BT_HDR * p_msg)218 void sdp_disc_server_rsp(tCONN_CB* p_ccb, BT_HDR* p_msg) {
219 uint8_t *p, rsp_pdu;
220 bool invalid_pdu = true;
221
222 #if (SDP_DEBUG_RAW == TRUE)
223 SDP_TRACE_WARNING("sdp_disc_server_rsp disc_state:%d", p_ccb->disc_state);
224 #endif
225
226 /* stop inactivity timer when we receive a response */
227 alarm_cancel(p_ccb->sdp_conn_timer);
228
229 /* Got a reply!! Check what we got back */
230 p = (uint8_t*)(p_msg + 1) + p_msg->offset;
231 uint8_t* p_end = p + p_msg->len;
232
233 BE_STREAM_TO_UINT8(rsp_pdu, p);
234
235 p_msg->len--;
236
237 switch (rsp_pdu) {
238 case SDP_PDU_SERVICE_SEARCH_RSP:
239 if (p_ccb->disc_state == SDP_DISC_WAIT_HANDLES) {
240 process_service_search_rsp(p_ccb, p, p_end);
241 invalid_pdu = false;
242 }
243 break;
244
245 case SDP_PDU_SERVICE_ATTR_RSP:
246 if (p_ccb->disc_state == SDP_DISC_WAIT_ATTR) {
247 process_service_attr_rsp(p_ccb, p, p_end);
248 invalid_pdu = false;
249 }
250 break;
251
252 case SDP_PDU_SERVICE_SEARCH_ATTR_RSP:
253 if (p_ccb->disc_state == SDP_DISC_WAIT_SEARCH_ATTR) {
254 process_service_search_attr_rsp(p_ccb, p, p_end);
255 invalid_pdu = false;
256 }
257 break;
258 }
259
260 if (invalid_pdu) {
261 SDP_TRACE_WARNING("SDP - Unexp. PDU: %d in state: %d", rsp_pdu,
262 p_ccb->disc_state);
263 sdp_disconnect(p_ccb, SDP_GENERIC_ERROR);
264 }
265 }
266
267 /******************************************************************************
268 *
269 * Function process_service_search_rsp
270 *
271 * Description This function is called when there is a search response from
272 * the server.
273 *
274 * Returns void
275 *
276 ******************************************************************************/
process_service_search_rsp(tCONN_CB * p_ccb,uint8_t * p_reply,uint8_t * p_reply_end)277 static void process_service_search_rsp(tCONN_CB* p_ccb, uint8_t* p_reply,
278 uint8_t* p_reply_end) {
279 uint16_t xx;
280 uint16_t total, cur_handles, orig;
281 uint8_t cont_len;
282
283 if (p_reply + 8 > p_reply_end) {
284 android_errorWriteLog(0x534e4554, "74249842");
285 sdp_disconnect(p_ccb, SDP_GENERIC_ERROR);
286 return;
287 }
288 /* Skip transaction, and param len */
289 p_reply += 4;
290 BE_STREAM_TO_UINT16(total, p_reply);
291 BE_STREAM_TO_UINT16(cur_handles, p_reply);
292
293 orig = p_ccb->num_handles;
294 p_ccb->num_handles += cur_handles;
295 if (p_ccb->num_handles == 0) {
296 SDP_TRACE_WARNING("SDP - Rcvd ServiceSearchRsp, no matches");
297 sdp_disconnect(p_ccb, SDP_NO_RECS_MATCH);
298 return;
299 }
300
301 /* Save the handles that match. We will can only process a certain number. */
302 if (total > sdp_cb.max_recs_per_search) total = sdp_cb.max_recs_per_search;
303 if (p_ccb->num_handles > sdp_cb.max_recs_per_search)
304 p_ccb->num_handles = sdp_cb.max_recs_per_search;
305
306 if (p_reply + ((p_ccb->num_handles - orig) * 4) + 1 > p_reply_end) {
307 android_errorWriteLog(0x534e4554, "74249842");
308 sdp_disconnect(p_ccb, SDP_GENERIC_ERROR);
309 return;
310 }
311
312 for (xx = orig; xx < p_ccb->num_handles; xx++)
313 BE_STREAM_TO_UINT32(p_ccb->handles[xx], p_reply);
314
315 BE_STREAM_TO_UINT8(cont_len, p_reply);
316 if (cont_len != 0) {
317 if (cont_len > SDP_MAX_CONTINUATION_LEN) {
318 sdp_disconnect(p_ccb, SDP_INVALID_CONT_STATE);
319 return;
320 }
321 if (p_reply + cont_len > p_reply_end) {
322 android_errorWriteLog(0x534e4554, "68161546");
323 sdp_disconnect(p_ccb, SDP_INVALID_CONT_STATE);
324 return;
325 }
326 /* stay in the same state */
327 sdp_snd_service_search_req(p_ccb, cont_len, p_reply);
328 } else {
329 /* change state */
330 p_ccb->disc_state = SDP_DISC_WAIT_ATTR;
331
332 /* Kick off the first attribute request */
333 process_service_attr_rsp(p_ccb, NULL, NULL);
334 }
335 }
336
337 /*******************************************************************************
338 *
339 * Function sdp_copy_raw_data
340 *
341 * Description copy the raw data
342 *
343 *
344 * Returns bool
345 * true if successful
346 * false if not copied
347 *
348 ******************************************************************************/
349 #if (SDP_RAW_DATA_INCLUDED == TRUE)
sdp_copy_raw_data(tCONN_CB * p_ccb,bool offset)350 static bool sdp_copy_raw_data(tCONN_CB* p_ccb, bool offset) {
351 unsigned int cpy_len, rem_len;
352 uint32_t list_len;
353 uint8_t* p;
354 uint8_t* p_end;
355 uint8_t type;
356
357 #if (SDP_DEBUG_RAW == TRUE)
358 uint8_t num_array[SDP_MAX_LIST_BYTE_COUNT];
359 uint32_t i;
360
361 for (i = 0; i < p_ccb->list_len; i++) {
362 snprintf((char*)&num_array[i * 2], sizeof(num_array) - i * 2, "%02X",
363 (uint8_t)(p_ccb->rsp_list[i]));
364 }
365 SDP_TRACE_WARNING("result :%s", num_array);
366 #endif
367
368 if (p_ccb->p_db->raw_data) {
369 cpy_len = p_ccb->p_db->raw_size - p_ccb->p_db->raw_used;
370 list_len = p_ccb->list_len;
371 p = &p_ccb->rsp_list[0];
372 p_end = &p_ccb->rsp_list[0] + list_len;
373
374 if (offset) {
375 cpy_len -= 1;
376 type = *p++;
377 uint8_t* old_p = p;
378 p = sdpu_get_len_from_type(p, p_end, type, &list_len);
379 if (p == NULL || (p + list_len) > p_end) {
380 SDP_TRACE_WARNING("%s: bad length", __func__);
381 return false;
382 }
383 if ((int)cpy_len < (p - old_p)) {
384 SDP_TRACE_WARNING("%s: no bytes left for data", __func__);
385 return false;
386 }
387 cpy_len -= (p - old_p);
388 }
389 if (list_len < cpy_len) {
390 cpy_len = list_len;
391 }
392 rem_len = SDP_MAX_LIST_BYTE_COUNT - (unsigned int)(p - &p_ccb->rsp_list[0]);
393 if (cpy_len > rem_len) {
394 SDP_TRACE_WARNING("rem_len :%d less than cpy_len:%d", rem_len, cpy_len);
395 cpy_len = rem_len;
396 }
397 SDP_TRACE_WARNING(
398 "%s: list_len:%d cpy_len:%d p:%p p_ccb:%p p_db:%p raw_size:%d "
399 "raw_used:%d raw_data:%p",
400 __func__, list_len, cpy_len, p, p_ccb, p_ccb->p_db,
401 p_ccb->p_db->raw_size, p_ccb->p_db->raw_used, p_ccb->p_db->raw_data);
402 memcpy(&p_ccb->p_db->raw_data[p_ccb->p_db->raw_used], p, cpy_len);
403 p_ccb->p_db->raw_used += cpy_len;
404 }
405 return true;
406 }
407 #endif
408
409 /*******************************************************************************
410 *
411 * Function process_service_attr_rsp
412 *
413 * Description This function is called when there is a attribute response
414 * from the server.
415 *
416 * Returns void
417 *
418 ******************************************************************************/
process_service_attr_rsp(tCONN_CB * p_ccb,uint8_t * p_reply,uint8_t * p_reply_end)419 static void process_service_attr_rsp(tCONN_CB* p_ccb, uint8_t* p_reply,
420 uint8_t* p_reply_end) {
421 uint8_t *p_start, *p_param_len;
422 uint16_t param_len, list_byte_count;
423 bool cont_request_needed = false;
424
425 #if (SDP_DEBUG_RAW == TRUE)
426 SDP_TRACE_WARNING("process_service_attr_rsp raw inc:%d",
427 SDP_RAW_DATA_INCLUDED);
428 #endif
429 /* If p_reply is NULL, we were called after the records handles were read */
430 if (p_reply) {
431 #if (SDP_DEBUG_RAW == TRUE)
432 SDP_TRACE_WARNING("ID & len: 0x%02x-%02x-%02x-%02x", p_reply[0], p_reply[1],
433 p_reply[2], p_reply[3]);
434 #endif
435 /* Skip transaction ID and length */
436 p_reply += 4;
437
438 BE_STREAM_TO_UINT16(list_byte_count, p_reply);
439 #if (SDP_DEBUG_RAW == TRUE)
440 SDP_TRACE_WARNING("list_byte_count:%d", list_byte_count);
441 #endif
442
443 /* Copy the response to the scratchpad. First, a safety check on the length
444 */
445 if ((p_ccb->list_len + list_byte_count) > SDP_MAX_LIST_BYTE_COUNT) {
446 sdp_disconnect(p_ccb, SDP_INVALID_PDU_SIZE);
447 return;
448 }
449
450 #if (SDP_DEBUG_RAW == TRUE)
451 SDP_TRACE_WARNING("list_len: %d, list_byte_count: %d", p_ccb->list_len,
452 list_byte_count);
453 #endif
454 if (p_ccb->rsp_list == NULL)
455 p_ccb->rsp_list = (uint8_t*)osi_malloc(SDP_MAX_LIST_BYTE_COUNT);
456 memcpy(&p_ccb->rsp_list[p_ccb->list_len], p_reply, list_byte_count);
457 p_ccb->list_len += list_byte_count;
458 p_reply += list_byte_count;
459 #if (SDP_DEBUG_RAW == TRUE)
460 SDP_TRACE_WARNING("list_len: %d(attr_rsp)", p_ccb->list_len);
461
462 /* Check if we need to request a continuation */
463 SDP_TRACE_WARNING("*p_reply:%d(%d)", *p_reply, SDP_MAX_CONTINUATION_LEN);
464 #endif
465 if (*p_reply) {
466 if (*p_reply > SDP_MAX_CONTINUATION_LEN) {
467 sdp_disconnect(p_ccb, SDP_INVALID_CONT_STATE);
468 return;
469 }
470 cont_request_needed = true;
471 } else {
472 #if (SDP_RAW_DATA_INCLUDED == TRUE)
473 SDP_TRACE_WARNING("process_service_attr_rsp");
474 if (!sdp_copy_raw_data(p_ccb, false)) {
475 SDP_TRACE_ERROR("sdp_copy_raw_data failed");
476 sdp_disconnect(p_ccb, SDP_ILLEGAL_PARAMETER);
477 return;
478 }
479
480 #endif
481
482 /* Save the response in the database. Stop on any error */
483 if (!save_attr_seq(p_ccb, &p_ccb->rsp_list[0],
484 &p_ccb->rsp_list[p_ccb->list_len])) {
485 sdp_disconnect(p_ccb, SDP_DB_FULL);
486 return;
487 }
488 p_ccb->list_len = 0;
489 p_ccb->cur_handle++;
490 }
491 }
492
493 /* Now, ask for the next handle. Re-use the buffer we just got. */
494 if (p_ccb->cur_handle < p_ccb->num_handles) {
495 BT_HDR* p_msg = (BT_HDR*)osi_malloc(SDP_DATA_BUF_SIZE);
496 uint8_t* p;
497
498 p_msg->offset = L2CAP_MIN_OFFSET;
499 p = p_start = (uint8_t*)(p_msg + 1) + L2CAP_MIN_OFFSET;
500
501 /* Get all the attributes from the server */
502 UINT8_TO_BE_STREAM(p, SDP_PDU_SERVICE_ATTR_REQ);
503 UINT16_TO_BE_STREAM(p, p_ccb->transaction_id);
504 p_ccb->transaction_id++;
505
506 /* Skip the length, we need to add it at the end */
507 p_param_len = p;
508 p += 2;
509
510 UINT32_TO_BE_STREAM(p, p_ccb->handles[p_ccb->cur_handle]);
511
512 /* Max attribute byte count */
513 UINT16_TO_BE_STREAM(p, sdp_cb.max_attr_list_size);
514
515 /* If no attribute filters, build a wildcard attribute sequence */
516 if (p_ccb->p_db->num_attr_filters)
517 p = sdpu_build_attrib_seq(p, p_ccb->p_db->attr_filters,
518 p_ccb->p_db->num_attr_filters);
519 else
520 p = sdpu_build_attrib_seq(p, NULL, 0);
521
522 /* Was this a continuation request ? */
523 if (cont_request_needed) {
524 if ((p_reply + *p_reply + 1) <= p_reply_end) {
525 memcpy(p, p_reply, *p_reply + 1);
526 p += *p_reply + 1;
527 } else {
528 android_errorWriteLog(0x534e4554, "68161546");
529 }
530 } else
531 UINT8_TO_BE_STREAM(p, 0);
532
533 /* Go back and put the parameter length into the buffer */
534 param_len = (uint16_t)(p - p_param_len - 2);
535 UINT16_TO_BE_STREAM(p_param_len, param_len);
536
537 /* Set the length of the SDP data in the buffer */
538 p_msg->len = (uint16_t)(p - p_start);
539
540 L2CA_DataWrite(p_ccb->connection_id, p_msg);
541
542 /* Start inactivity timer */
543 alarm_set_on_mloop(p_ccb->sdp_conn_timer, SDP_INACT_TIMEOUT_MS,
544 sdp_conn_timer_timeout, p_ccb);
545 } else {
546 sdp_disconnect(p_ccb, SDP_SUCCESS);
547 return;
548 }
549 }
550
551 /*******************************************************************************
552 *
553 * Function process_service_search_attr_rsp
554 *
555 * Description This function is called when there is a search attribute
556 * response from the server.
557 *
558 * Returns void
559 *
560 ******************************************************************************/
process_service_search_attr_rsp(tCONN_CB * p_ccb,uint8_t * p_reply,uint8_t * p_reply_end)561 static void process_service_search_attr_rsp(tCONN_CB* p_ccb, uint8_t* p_reply,
562 uint8_t* p_reply_end) {
563 uint8_t *p, *p_start, *p_end, *p_param_len;
564 uint8_t type;
565 uint32_t seq_len;
566 uint16_t param_len, lists_byte_count = 0;
567 bool cont_request_needed = false;
568
569 #if (SDP_DEBUG_RAW == TRUE)
570 SDP_TRACE_WARNING("process_service_search_attr_rsp");
571 #endif
572 /* If p_reply is NULL, we were called for the initial read */
573 if (p_reply) {
574 if (p_reply + 4 /* transaction ID and length */ + sizeof(lists_byte_count) >
575 p_reply_end) {
576 android_errorWriteLog(0x534e4554, "79884292");
577 sdp_disconnect(p_ccb, SDP_INVALID_PDU_SIZE);
578 return;
579 }
580
581 #if (SDP_DEBUG_RAW == TRUE)
582 SDP_TRACE_WARNING("ID & len: 0x%02x-%02x-%02x-%02x", p_reply[0], p_reply[1],
583 p_reply[2], p_reply[3]);
584 #endif
585 /* Skip transaction ID and length */
586 p_reply += 4;
587
588 BE_STREAM_TO_UINT16(lists_byte_count, p_reply);
589 #if (SDP_DEBUG_RAW == TRUE)
590 SDP_TRACE_WARNING("lists_byte_count:%d", lists_byte_count);
591 #endif
592
593 /* Copy the response to the scratchpad. First, a safety check on the length
594 */
595 if ((p_ccb->list_len + lists_byte_count) > SDP_MAX_LIST_BYTE_COUNT) {
596 sdp_disconnect(p_ccb, SDP_INVALID_PDU_SIZE);
597 return;
598 }
599
600 #if (SDP_DEBUG_RAW == TRUE)
601 SDP_TRACE_WARNING("list_len: %d, list_byte_count: %d", p_ccb->list_len,
602 lists_byte_count);
603 #endif
604
605 if (p_reply + lists_byte_count + 1 /* continuation */ > p_reply_end) {
606 android_errorWriteLog(0x534e4554, "79884292");
607 sdp_disconnect(p_ccb, SDP_INVALID_PDU_SIZE);
608 return;
609 }
610
611 if (p_ccb->rsp_list == NULL)
612 p_ccb->rsp_list = (uint8_t*)osi_malloc(SDP_MAX_LIST_BYTE_COUNT);
613 memcpy(&p_ccb->rsp_list[p_ccb->list_len], p_reply, lists_byte_count);
614 p_ccb->list_len += lists_byte_count;
615 p_reply += lists_byte_count;
616 #if (SDP_DEBUG_RAW == TRUE)
617 SDP_TRACE_WARNING("list_len: %d(search_attr_rsp)", p_ccb->list_len);
618
619 /* Check if we need to request a continuation */
620 SDP_TRACE_WARNING("*p_reply:%d(%d)", *p_reply, SDP_MAX_CONTINUATION_LEN);
621 #endif
622 if (*p_reply) {
623 if (*p_reply > SDP_MAX_CONTINUATION_LEN) {
624 sdp_disconnect(p_ccb, SDP_INVALID_CONT_STATE);
625 return;
626 }
627
628 cont_request_needed = true;
629 }
630 }
631
632 #if (SDP_DEBUG_RAW == TRUE)
633 SDP_TRACE_WARNING("cont_request_needed:%d", cont_request_needed);
634 #endif
635 /* If continuation request (or first time request) */
636 if ((cont_request_needed) || (!p_reply)) {
637 BT_HDR* p_msg = (BT_HDR*)osi_malloc(SDP_DATA_BUF_SIZE);
638 uint8_t* p;
639
640 p_msg->offset = L2CAP_MIN_OFFSET;
641 p = p_start = (uint8_t*)(p_msg + 1) + L2CAP_MIN_OFFSET;
642
643 /* Build a service search request packet */
644 UINT8_TO_BE_STREAM(p, SDP_PDU_SERVICE_SEARCH_ATTR_REQ);
645 UINT16_TO_BE_STREAM(p, p_ccb->transaction_id);
646 p_ccb->transaction_id++;
647
648 /* Skip the length, we need to add it at the end */
649 p_param_len = p;
650 p += 2;
651
652 /* Build the UID sequence. */
653 #if (SDP_BROWSE_PLUS == TRUE)
654 p = sdpu_build_uuid_seq(p, 1,
655 &p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx]);
656 #else
657 p = sdpu_build_uuid_seq(p, p_ccb->p_db->num_uuid_filters,
658 p_ccb->p_db->uuid_filters);
659 #endif
660
661 /* Max attribute byte count */
662 UINT16_TO_BE_STREAM(p, sdp_cb.max_attr_list_size);
663
664 /* If no attribute filters, build a wildcard attribute sequence */
665 if (p_ccb->p_db->num_attr_filters)
666 p = sdpu_build_attrib_seq(p, p_ccb->p_db->attr_filters,
667 p_ccb->p_db->num_attr_filters);
668 else
669 p = sdpu_build_attrib_seq(p, NULL, 0);
670
671 /* No continuation for first request */
672 if (p_reply) {
673 if ((p_reply + *p_reply + 1) <= p_reply_end) {
674 memcpy(p, p_reply, *p_reply + 1);
675 p += *p_reply + 1;
676 } else {
677 android_errorWriteLog(0x534e4554, "68161546");
678 }
679 } else
680 UINT8_TO_BE_STREAM(p, 0);
681
682 /* Go back and put the parameter length into the buffer */
683 param_len = p - p_param_len - 2;
684 UINT16_TO_BE_STREAM(p_param_len, param_len);
685
686 /* Set the length of the SDP data in the buffer */
687 p_msg->len = p - p_start;
688
689 L2CA_DataWrite(p_ccb->connection_id, p_msg);
690
691 /* Start inactivity timer */
692 alarm_set_on_mloop(p_ccb->sdp_conn_timer, SDP_INACT_TIMEOUT_MS,
693 sdp_conn_timer_timeout, p_ccb);
694
695 return;
696 }
697
698 /*******************************************************************/
699 /* We now have the full response, which is a sequence of sequences */
700 /*******************************************************************/
701
702 #if (SDP_RAW_DATA_INCLUDED == TRUE)
703 SDP_TRACE_WARNING("process_service_search_attr_rsp");
704 if (!sdp_copy_raw_data(p_ccb, true)) {
705 SDP_TRACE_ERROR("sdp_copy_raw_data failed");
706 sdp_disconnect(p_ccb, SDP_ILLEGAL_PARAMETER);
707 return;
708 }
709 #endif
710
711 p = &p_ccb->rsp_list[0];
712
713 /* The contents is a sequence of attribute sequences */
714 type = *p++;
715
716 if ((type >> 3) != DATA_ELE_SEQ_DESC_TYPE) {
717 SDP_TRACE_WARNING("SDP - Wrong type: 0x%02x in attr_rsp", type);
718 return;
719 }
720 p = sdpu_get_len_from_type(p, p + p_ccb->list_len, type, &seq_len);
721 if (p == NULL || (p + seq_len) > (p + p_ccb->list_len)) {
722 SDP_TRACE_WARNING("%s: bad length", __func__);
723 sdp_disconnect(p_ccb, SDP_ILLEGAL_PARAMETER);
724 return;
725 }
726 p_end = &p_ccb->rsp_list[p_ccb->list_len];
727
728 if ((p + seq_len) != p_end) {
729 sdp_disconnect(p_ccb, SDP_INVALID_CONT_STATE);
730 return;
731 }
732
733 while (p < p_end) {
734 p = save_attr_seq(p_ccb, p, &p_ccb->rsp_list[p_ccb->list_len]);
735 if (!p) {
736 sdp_disconnect(p_ccb, SDP_DB_FULL);
737 return;
738 }
739 }
740
741 /* Since we got everything we need, disconnect the call */
742 sdp_disconnect(p_ccb, SDP_SUCCESS);
743 }
744
745 /*******************************************************************************
746 *
747 * Function save_attr_seq
748 *
749 * Description This function is called when there is a response from
750 * the server.
751 *
752 * Returns pointer to next byte or NULL if error
753 *
754 ******************************************************************************/
save_attr_seq(tCONN_CB * p_ccb,uint8_t * p,uint8_t * p_msg_end)755 static uint8_t* save_attr_seq(tCONN_CB* p_ccb, uint8_t* p, uint8_t* p_msg_end) {
756 uint32_t seq_len, attr_len;
757 uint16_t attr_id;
758 uint8_t type, *p_seq_end;
759 tSDP_DISC_REC* p_rec;
760
761 type = *p++;
762
763 if ((type >> 3) != DATA_ELE_SEQ_DESC_TYPE) {
764 SDP_TRACE_WARNING("SDP - Wrong type: 0x%02x in attr_rsp", type);
765 return (NULL);
766 }
767 p = sdpu_get_len_from_type(p, p_msg_end, type, &seq_len);
768 if (p == NULL || (p + seq_len) > p_msg_end) {
769 SDP_TRACE_WARNING("SDP - Bad len in attr_rsp %d", seq_len);
770 return (NULL);
771 }
772
773 /* Create a record */
774 p_rec = add_record(p_ccb->p_db, p_ccb->device_address);
775 if (!p_rec) {
776 SDP_TRACE_WARNING("SDP - DB full add_record");
777 return (NULL);
778 }
779
780 p_seq_end = p + seq_len;
781
782 while (p < p_seq_end) {
783 /* First get the attribute ID */
784 type = *p++;
785 p = sdpu_get_len_from_type(p, p_msg_end, type, &attr_len);
786 if (p == NULL || (p + attr_len) > p_seq_end) {
787 SDP_TRACE_WARNING("%s: Bad len in attr_rsp %d", __func__, attr_len);
788 return (NULL);
789 }
790 if (((type >> 3) != UINT_DESC_TYPE) || (attr_len != 2)) {
791 SDP_TRACE_WARNING("SDP - Bad type: 0x%02x or len: %d in attr_rsp", type,
792 attr_len);
793 return (NULL);
794 }
795 BE_STREAM_TO_UINT16(attr_id, p);
796
797 /* Now, add the attribute value */
798 p = add_attr(p, p_seq_end, p_ccb->p_db, p_rec, attr_id, NULL, 0);
799
800 if (!p) {
801 SDP_TRACE_WARNING("SDP - DB full add_attr");
802 return (NULL);
803 }
804 }
805
806 return (p);
807 }
808
809 /*******************************************************************************
810 *
811 * Function add_record
812 *
813 * Description This function allocates space for a record from the DB.
814 *
815 * Returns pointer to next byte in data stream
816 *
817 ******************************************************************************/
add_record(tSDP_DISCOVERY_DB * p_db,const RawAddress & p_bda)818 tSDP_DISC_REC* add_record(tSDP_DISCOVERY_DB* p_db, const RawAddress& p_bda) {
819 tSDP_DISC_REC* p_rec;
820
821 /* See if there is enough space in the database */
822 if (p_db->mem_free < sizeof(tSDP_DISC_REC)) return (NULL);
823
824 p_rec = (tSDP_DISC_REC*)p_db->p_free_mem;
825 p_db->p_free_mem += sizeof(tSDP_DISC_REC);
826 p_db->mem_free -= sizeof(tSDP_DISC_REC);
827
828 p_rec->p_first_attr = NULL;
829 p_rec->p_next_rec = NULL;
830
831 p_rec->remote_bd_addr = p_bda;
832
833 /* Add the record to the end of chain */
834 if (!p_db->p_first_rec)
835 p_db->p_first_rec = p_rec;
836 else {
837 tSDP_DISC_REC* p_rec1 = p_db->p_first_rec;
838
839 while (p_rec1->p_next_rec) p_rec1 = p_rec1->p_next_rec;
840
841 p_rec1->p_next_rec = p_rec;
842 }
843
844 return (p_rec);
845 }
846
847 #define SDP_ADDITIONAL_LIST_MASK 0x80
848 /*******************************************************************************
849 *
850 * Function add_attr
851 *
852 * Description This function allocates space for an attribute from the DB
853 * and copies the data into it.
854 *
855 * Returns pointer to next byte in data stream
856 *
857 ******************************************************************************/
add_attr(uint8_t * p,uint8_t * p_end,tSDP_DISCOVERY_DB * p_db,tSDP_DISC_REC * p_rec,uint16_t attr_id,tSDP_DISC_ATTR * p_parent_attr,uint8_t nest_level)858 static uint8_t* add_attr(uint8_t* p, uint8_t* p_end, tSDP_DISCOVERY_DB* p_db,
859 tSDP_DISC_REC* p_rec, uint16_t attr_id,
860 tSDP_DISC_ATTR* p_parent_attr, uint8_t nest_level) {
861 tSDP_DISC_ATTR* p_attr;
862 uint32_t attr_len;
863 uint32_t total_len;
864 uint16_t attr_type;
865 uint16_t id;
866 uint8_t type;
867 uint8_t* p_attr_end;
868 uint8_t is_additional_list = nest_level & SDP_ADDITIONAL_LIST_MASK;
869
870 nest_level &= ~(SDP_ADDITIONAL_LIST_MASK);
871
872 type = *p++;
873 p = sdpu_get_len_from_type(p, p_end, type, &attr_len);
874 if (p == NULL || (p + attr_len) > p_end) {
875 SDP_TRACE_WARNING("%s: bad length in attr_rsp", __func__);
876 return NULL;
877 }
878 attr_len &= SDP_DISC_ATTR_LEN_MASK;
879 attr_type = (type >> 3) & 0x0f;
880
881 /* See if there is enough space in the database */
882 if (attr_len > 4)
883 total_len = attr_len - 4 + (uint16_t)sizeof(tSDP_DISC_ATTR);
884 else
885 total_len = sizeof(tSDP_DISC_ATTR);
886
887 p_attr_end = p + attr_len;
888 if (p_attr_end > p_end) {
889 android_errorWriteLog(0x534e4554, "115900043");
890 SDP_TRACE_WARNING("%s: SDP - Attribute length beyond p_end", __func__);
891 return NULL;
892 }
893
894 /* Ensure it is a multiple of 4 */
895 total_len = (total_len + 3) & ~3;
896
897 /* See if there is enough space in the database */
898 if (p_db->mem_free < total_len) return (NULL);
899
900 p_attr = (tSDP_DISC_ATTR*)p_db->p_free_mem;
901 p_attr->attr_id = attr_id;
902 p_attr->attr_len_type = (uint16_t)attr_len | (attr_type << 12);
903 p_attr->p_next_attr = NULL;
904
905 /* Store the attribute value */
906 switch (attr_type) {
907 case UINT_DESC_TYPE:
908 if ((is_additional_list != 0) && (attr_len == 2)) {
909 BE_STREAM_TO_UINT16(id, p);
910 if (id != ATTR_ID_PROTOCOL_DESC_LIST)
911 p -= 2;
912 else {
913 /* Reserve the memory for the attribute now, as we need to add
914 * sub-attributes */
915 p_db->p_free_mem += sizeof(tSDP_DISC_ATTR);
916 p_db->mem_free -= sizeof(tSDP_DISC_ATTR);
917 total_len = 0;
918
919 /* SDP_TRACE_DEBUG ("SDP - attr nest level:%d(list)", nest_level); */
920 if (nest_level >= MAX_NEST_LEVELS) {
921 SDP_TRACE_ERROR("SDP - attr nesting too deep");
922 return p_attr_end;
923 }
924
925 /* Now, add the list entry */
926 p = add_attr(p, p_end, p_db, p_rec, ATTR_ID_PROTOCOL_DESC_LIST,
927 p_attr, (uint8_t)(nest_level + 1));
928
929 break;
930 }
931 }
932 /* Case falls through */
933
934 case TWO_COMP_INT_DESC_TYPE:
935 switch (attr_len) {
936 case 1:
937 p_attr->attr_value.v.u8 = *p++;
938 break;
939 case 2:
940 BE_STREAM_TO_UINT16(p_attr->attr_value.v.u16, p);
941 break;
942 case 4:
943 BE_STREAM_TO_UINT32(p_attr->attr_value.v.u32, p);
944 break;
945 default:
946 BE_STREAM_TO_ARRAY(p, p_attr->attr_value.v.array, (int32_t)attr_len);
947 break;
948 }
949 break;
950
951 case UUID_DESC_TYPE:
952 switch (attr_len) {
953 case 2:
954 BE_STREAM_TO_UINT16(p_attr->attr_value.v.u16, p);
955 break;
956 case 4:
957 BE_STREAM_TO_UINT32(p_attr->attr_value.v.u32, p);
958 if (p_attr->attr_value.v.u32 < 0x10000) {
959 attr_len = 2;
960 p_attr->attr_len_type = (uint16_t)attr_len | (attr_type << 12);
961 p_attr->attr_value.v.u16 = (uint16_t)p_attr->attr_value.v.u32;
962 }
963 break;
964 case 16:
965 /* See if we can compress his UUID down to 16 or 32bit UUIDs */
966 if (sdpu_is_base_uuid(p)) {
967 if ((p[0] == 0) && (p[1] == 0)) {
968 p_attr->attr_len_type =
969 (p_attr->attr_len_type & ~SDP_DISC_ATTR_LEN_MASK) | 2;
970 p += 2;
971 BE_STREAM_TO_UINT16(p_attr->attr_value.v.u16, p);
972 p += Uuid::kNumBytes128 - 4;
973 } else {
974 p_attr->attr_len_type =
975 (p_attr->attr_len_type & ~SDP_DISC_ATTR_LEN_MASK) | 4;
976 BE_STREAM_TO_UINT32(p_attr->attr_value.v.u32, p);
977 p += Uuid::kNumBytes128 - 4;
978 }
979 } else {
980 BE_STREAM_TO_ARRAY(p, p_attr->attr_value.v.array,
981 (int32_t)attr_len);
982 }
983 break;
984 default:
985 SDP_TRACE_WARNING("SDP - bad len in UUID attr: %d", attr_len);
986 return p_attr_end;
987 }
988 break;
989
990 case DATA_ELE_SEQ_DESC_TYPE:
991 case DATA_ELE_ALT_DESC_TYPE:
992 /* Reserve the memory for the attribute now, as we need to add
993 * sub-attributes */
994 p_db->p_free_mem += sizeof(tSDP_DISC_ATTR);
995 p_db->mem_free -= sizeof(tSDP_DISC_ATTR);
996 total_len = 0;
997
998 /* SDP_TRACE_DEBUG ("SDP - attr nest level:%d", nest_level); */
999 if (nest_level >= MAX_NEST_LEVELS) {
1000 SDP_TRACE_ERROR("SDP - attr nesting too deep");
1001 return p_attr_end;
1002 }
1003 if (is_additional_list != 0 ||
1004 attr_id == ATTR_ID_ADDITION_PROTO_DESC_LISTS)
1005 nest_level |= SDP_ADDITIONAL_LIST_MASK;
1006 /* SDP_TRACE_DEBUG ("SDP - attr nest level:0x%x(finish)", nest_level); */
1007
1008 while (p < p_attr_end) {
1009 /* Now, add the list entry */
1010 p = add_attr(p, p_end, p_db, p_rec, 0, p_attr,
1011 (uint8_t)(nest_level + 1));
1012
1013 if (!p) return (NULL);
1014 }
1015 break;
1016
1017 case TEXT_STR_DESC_TYPE:
1018 case URL_DESC_TYPE:
1019 BE_STREAM_TO_ARRAY(p, p_attr->attr_value.v.array, (int32_t)attr_len);
1020 break;
1021
1022 case BOOLEAN_DESC_TYPE:
1023 switch (attr_len) {
1024 case 1:
1025 p_attr->attr_value.v.u8 = *p++;
1026 break;
1027 default:
1028 SDP_TRACE_WARNING("SDP - bad len in boolean attr: %d", attr_len);
1029 return p_attr_end;
1030 }
1031 break;
1032
1033 default: /* switch (attr_type) */
1034 break;
1035 }
1036
1037 p_db->p_free_mem += total_len;
1038 p_db->mem_free -= total_len;
1039
1040 /* Add the attribute to the end of the chain */
1041 if (!p_parent_attr) {
1042 if (!p_rec->p_first_attr)
1043 p_rec->p_first_attr = p_attr;
1044 else {
1045 tSDP_DISC_ATTR* p_attr1 = p_rec->p_first_attr;
1046
1047 while (p_attr1->p_next_attr) p_attr1 = p_attr1->p_next_attr;
1048
1049 p_attr1->p_next_attr = p_attr;
1050 }
1051 } else {
1052 if (!p_parent_attr->attr_value.v.p_sub_attr) {
1053 p_parent_attr->attr_value.v.p_sub_attr = p_attr;
1054 /* SDP_TRACE_DEBUG ("parent:0x%x(id:%d), ch:0x%x(id:%d)",
1055 p_parent_attr, p_parent_attr->attr_id, p_attr, p_attr->attr_id); */
1056 } else {
1057 tSDP_DISC_ATTR* p_attr1 = p_parent_attr->attr_value.v.p_sub_attr;
1058 /* SDP_TRACE_DEBUG ("parent:0x%x(id:%d), ch1:0x%x(id:%d)",
1059 p_parent_attr, p_parent_attr->attr_id, p_attr1, p_attr1->attr_id); */
1060
1061 while (p_attr1->p_next_attr) p_attr1 = p_attr1->p_next_attr;
1062
1063 p_attr1->p_next_attr = p_attr;
1064 /* SDP_TRACE_DEBUG ("new ch:0x%x(id:%d)", p_attr, p_attr->attr_id); */
1065 }
1066 }
1067
1068 return (p);
1069 }
1070