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