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