• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 2015 Google Inc.
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 #include <assert.h>
20 #include <resolv.h>
21 #include <zlib.h>
22 
23 #include "btif/include/btif_debug.h"
24 #include "btif/include/btif_debug_btsnoop.h"
25 #include "hci/include/btsnoop_mem.h"
26 #include "include/bt_target.h"
27 #include "osi/include/ringbuffer.h"
28 
29 #define REDUCE_HCI_TYPE_TO_SIGNIFICANT_BITS(type) (type >> 8)
30 
31 // Total btsnoop memory log buffer size
32 #ifndef BTSNOOP_MEM_BUFFER_SIZE
33 static const size_t BTSNOOP_MEM_BUFFER_SIZE = (256 * 1024);
34 #endif
35 
36 // Block size for copying buffers (for compression/encoding etc.)
37 static const size_t BLOCK_SIZE = 16384;
38 
39 // Maximum line length in bugreport (should be multiple of 4 for base64 output)
40 static const uint8_t MAX_LINE_LENGTH = 128;
41 
42 static ringbuffer_t *buffer = NULL;
43 static uint64_t last_timestamp_ms = 0;
44 
45 static size_t btsnoop_calculate_packet_length(uint16_t type, const uint8_t *data, size_t length);
46 
btsnoop_cb(const uint16_t type,const uint8_t * data,const size_t length)47 static void btsnoop_cb(const uint16_t type, const uint8_t *data, const size_t length) {
48   btsnooz_header_t header;
49 
50   size_t included_length = btsnoop_calculate_packet_length(type, data, length);
51   if (included_length == 0)
52     return;
53 
54   // Make room in the ring buffer
55 
56   while (ringbuffer_available(buffer) < (included_length + sizeof(btsnooz_header_t))) {
57     ringbuffer_pop(buffer, (uint8_t *)&header, sizeof(btsnooz_header_t));
58     ringbuffer_delete(buffer, header.length - 1);
59   }
60 
61   // Insert data
62 
63   const uint64_t now = btif_debug_ts();
64 
65   header.type = REDUCE_HCI_TYPE_TO_SIGNIFICANT_BITS(type);
66   header.length = included_length + 1;  // +1 for type byte
67   header.packet_length = length + 1;  // +1 for type byte.
68   header.delta_time_ms = last_timestamp_ms ? now - last_timestamp_ms : 0;
69   last_timestamp_ms = now;
70 
71   ringbuffer_insert(buffer, (uint8_t *)&header, sizeof(btsnooz_header_t));
72   ringbuffer_insert(buffer, data, included_length);
73 }
74 
btsnoop_calculate_packet_length(uint16_t type,const uint8_t * data,size_t length)75 static size_t btsnoop_calculate_packet_length(uint16_t type, const uint8_t *data, size_t length) {
76   static const size_t HCI_ACL_HEADER_SIZE = 4;
77   static const size_t L2CAP_HEADER_SIZE = 4;
78   static const size_t L2CAP_CID_OFFSET = (HCI_ACL_HEADER_SIZE + 2);
79   static const uint16_t L2CAP_SIGNALING_CID = 0x0001;
80 
81   // Maximum amount of ACL data to log.
82   // Enough for an RFCOMM frame up to the frame check;
83   // not enough for a HID report or audio data.
84   static const size_t MAX_HCI_ACL_LEN = 14;
85 
86   // Calculate packet length to be included
87 
88   switch (type) {
89     case BT_EVT_TO_LM_HCI_CMD:
90       return length;
91 
92     case BT_EVT_TO_BTU_HCI_EVT:
93       return length;
94 
95     case BT_EVT_TO_LM_HCI_ACL:
96     case BT_EVT_TO_BTU_HCI_ACL:
97     {
98       size_t len_hci_acl = HCI_ACL_HEADER_SIZE + L2CAP_HEADER_SIZE;
99       // Check if we have enough data for an L2CAP header
100       if (length > len_hci_acl) {
101         uint16_t l2cap_cid = data[L2CAP_CID_OFFSET] | (data[L2CAP_CID_OFFSET + 1] << 8);
102         if (l2cap_cid == L2CAP_SIGNALING_CID) {
103           // For the signaling CID, take the full packet.
104           // That way, the PSM setup is captured, allowing decoding of PSMs down the road.
105           return length;
106         } else {
107           // Otherwise, return as much as we reasonably can
108           len_hci_acl = MAX_HCI_ACL_LEN;
109         }
110       }
111       return len_hci_acl < length ? len_hci_acl : length;
112     }
113 
114     case BT_EVT_TO_LM_HCI_SCO:
115     case BT_EVT_TO_BTU_HCI_SCO:
116       // We're not logging SCO packets at this time since they are not currently used.
117       // FALLTHROUGH
118     default:
119       return 0;
120   }
121 }
122 
btsnoop_compress(ringbuffer_t * rb_dst,ringbuffer_t * rb_src)123 static bool btsnoop_compress(ringbuffer_t *rb_dst, ringbuffer_t *rb_src) {
124   assert(rb_dst != NULL);
125   assert(rb_src != NULL);
126 
127   z_stream zs = {.zalloc = Z_NULL, .zfree = Z_NULL, .opaque = Z_NULL};
128   if (deflateInit(&zs, Z_DEFAULT_COMPRESSION) != Z_OK)
129     return false;
130 
131   bool rc = true;
132   uint8_t block_src[BLOCK_SIZE];
133   uint8_t block_dst[BLOCK_SIZE];
134 
135   const size_t num_blocks = (ringbuffer_size(rb_src) + BLOCK_SIZE - 1) / BLOCK_SIZE;
136   for (size_t i = 0; i < num_blocks; ++i) {
137     zs.avail_in = ringbuffer_peek(rb_src, i * BLOCK_SIZE, block_src, BLOCK_SIZE);
138     zs.next_in = block_src;
139 
140     do {
141       zs.avail_out = BLOCK_SIZE;
142       zs.next_out = block_dst;
143 
144       int err = deflate(&zs, (i == num_blocks - 1) ? Z_FINISH : Z_NO_FLUSH);
145       if (err == Z_STREAM_ERROR) {
146         rc = false;
147         break;
148       }
149 
150       const size_t length = BLOCK_SIZE - zs.avail_out;
151       ringbuffer_insert(rb_dst, block_dst, length);
152     } while (zs.avail_out == 0);
153   }
154 
155   deflateEnd(&zs);
156   return rc;
157 }
158 
btif_debug_btsnoop_init(void)159 void btif_debug_btsnoop_init(void) {
160   if (buffer == NULL)
161     buffer = ringbuffer_init(BTSNOOP_MEM_BUFFER_SIZE);
162   btsnoop_mem_set_callback(btsnoop_cb);
163 }
164 
btif_debug_btsnoop_dump(int fd)165 void btif_debug_btsnoop_dump(int fd) {
166   dprintf(fd, "--- BEGIN:BTSNOOP_LOG_SUMMARY (%zu bytes in) ---\n", ringbuffer_size(buffer));
167 
168   ringbuffer_t *ringbuffer = ringbuffer_init(BTSNOOP_MEM_BUFFER_SIZE);
169   if (ringbuffer == NULL) {
170     dprintf(fd, "%s Unable to allocate memory for compression", __func__);
171     return;
172   }
173 
174   // Prepend preamble
175 
176   btsnooz_preamble_t preamble;
177   preamble.version = BTSNOOZ_CURRENT_VERSION;
178   preamble.last_timestamp_ms = last_timestamp_ms;
179   ringbuffer_insert(ringbuffer, (uint8_t *)&preamble, sizeof(btsnooz_preamble_t));
180 
181   // Compress data
182 
183   bool rc = btsnoop_compress(ringbuffer, buffer);
184   if (rc == false) {
185     dprintf(fd, "%s Log compression failed", __func__);
186     goto error;
187   }
188 
189   // Base64 encode & output
190 
191   uint8_t b64_in[3] = {0};
192   char b64_out[5] = {0};
193 
194   size_t line_length = 0;
195   while (ringbuffer_size(ringbuffer) > 0) {
196     size_t read = ringbuffer_pop(ringbuffer, b64_in, 3);
197     if (line_length >= MAX_LINE_LENGTH) {
198       dprintf(fd, "\n");
199       line_length = 0;
200     }
201     line_length += b64_ntop(b64_in, read, b64_out, 5);
202     dprintf(fd, "%s", b64_out);
203   }
204 
205   dprintf(fd, "\n--- END:BTSNOOP_LOG_SUMMARY ---\n");
206 
207 error:
208   ringbuffer_free(ringbuffer);
209 }
210