OSDN Git Service

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