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