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