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