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