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