blob: ad06ac7a099059492eb69287fe7a5fc366d264b7 [file] [log] [blame]
The Android Open Source Project5738f832012-12-12 16:00:35 -08001/******************************************************************************
2 *
Jakub Pawlowski5b790fe2017-09-18 09:00:20 -07003 * Copyright 2014 Google, Inc.
The Android Open Source Project5738f832012-12-12 16:00:35 -08004 *
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
Marie Janssen49120dc2015-07-07 16:47:20 -070019#define LOG_TAG "bt_snoop"
20
Pavlin Radoslavov3060ec62017-02-16 11:51:48 -080021#include <mutex>
22
Etan Cohen3e59b5b2015-03-31 17:15:53 -070023#include <arpa/inet.h>
Ajay Panicker83036292018-11-16 13:06:47 -080024#include <base/logging.h>
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -070025#include <errno.h>
26#include <fcntl.h>
Pavlin Radoslavov43947202016-02-13 08:47:19 -080027#include <inttypes.h>
Scott James Remnant933926c2015-04-02 15:22:14 -070028#include <limits.h>
29#include <netinet/in.h>
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -070030#include <stdbool.h>
31#include <stdio.h>
32#include <stdlib.h>
Etan Cohen3e59b5b2015-03-31 17:15:53 -070033#include <string.h>
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -070034#include <sys/stat.h>
35#include <sys/time.h>
Jakub Pawlowski7a7e8e92017-10-09 20:53:39 -070036#include <sys/uio.h>
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -070037#include <unistd.h>
Ajay Panicker83036292018-11-16 13:06:47 -080038#include <mutex>
39#include <unordered_map>
40#include <unordered_set>
The Android Open Source Project5738f832012-12-12 16:00:35 -080041
Marie Janssendb554582015-06-26 14:53:46 -070042#include "bt_types.h"
Jack He959bc332018-08-15 12:38:37 -070043#include "common/time_util.h"
Andre Eisenbach89f5e412014-12-05 09:40:20 -080044#include "hci/include/btsnoop.h"
45#include "hci/include/btsnoop_mem.h"
Zach Johnsonfbbd42b2014-08-15 17:00:17 -070046#include "hci_layer.h"
Ajay Panicker83036292018-11-16 13:06:47 -080047#include "internal_include/bt_trace.h"
Sharvil Nanavati44802762014-12-23 23:08:58 -080048#include "osi/include/log.h"
Ajay Panicker99c34222017-04-17 20:53:24 -070049#include "osi/include/properties.h"
Ajay Panicker83036292018-11-16 13:06:47 -080050#include "stack/include/hcimsgs.h"
51#include "stack/include/rfcdefs.h"
52#include "stack/l2cap/l2c_int.h"
Zach Johnson9891f322014-09-22 22:11:55 -070053#include "stack_config.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080054
Ajay Panicker99c34222017-04-17 20:53:24 -070055// The number of of packets per btsnoop file before we rotate to the next
56// file. As of right now there are two snoop files that are rotated through.
57// The size can be dynamically configured by seting the relevant system
58// property
59#define DEFAULT_BTSNOOP_SIZE 0xffff
60
Ajay Panicker83036292018-11-16 13:06:47 -080061#define IS_DEBUGGABLE_PROPERTY "ro.debuggable"
62
63#define BTSNOOP_LOG_MODE_PROPERTY "persist.bluetooth.btsnooplogmode"
64#define BTSNOOP_DEFAULT_MODE_PROPERTY "persist.bluetooth.btsnoopdefaultmode"
65#define BTSNOOP_MODE_DISABLED "disabled"
66#define BTSNOOP_MODE_FILTERED "filtered"
67#define BTSNOOP_MODE_FULL "full"
68
Ajay Panicker99c34222017-04-17 20:53:24 -070069#define BTSNOOP_PATH_PROPERTY "persist.bluetooth.btsnooppath"
70#define DEFAULT_BTSNOOP_PATH "/data/misc/bluetooth/logs/btsnoop_hci.log"
71#define BTSNOOP_MAX_PACKETS_PROPERTY "persist.bluetooth.btsnoopsize"
72
Sharvil Nanavati611f3ab2014-03-22 14:27:07 -070073typedef enum {
74 kCommandPacket = 1,
75 kAclPacket = 2,
76 kScoPacket = 3,
77 kEventPacket = 4
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -070078} packet_type_t;
Sharvil Nanavati611f3ab2014-03-22 14:27:07 -070079
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -070080// Epoch in microseconds since 01/01/0000.
81static const uint64_t BTSNOOP_EPOCH_DELTA = 0x00dcddb30f2f8000ULL;
82
Ajay Panicker83036292018-11-16 13:06:47 -080083// Number of bytes into a packet where you can find the value for a channel.
84static const size_t ACL_CHANNEL_OFFSET = 0;
85static const size_t L2C_CHANNEL_OFFSET = 6;
86static const size_t RFC_CHANNEL_OFFSET = 8;
87static const size_t RFC_EVENT_OFFSET = 9;
88
89// The size of the L2CAP header. All information past this point is removed from
90// a filtered packet.
91static const uint32_t L2C_HEADER_SIZE = 9;
92
Zach Johnson9891f322014-09-22 22:11:55 -070093static int logfile_fd = INVALID_FD;
Pavlin Radoslavov3060ec62017-02-16 11:51:48 -080094static std::mutex btsnoop_mutex;
Zach Johnson9891f322014-09-22 22:11:55 -070095
Ajay Panicker99c34222017-04-17 20:53:24 -070096static int32_t packets_per_file;
97static int32_t packet_counter;
98
Ajay Panicker83036292018-11-16 13:06:47 -080099// Channel tracking variables for filtering.
100
101// Keeps track of L2CAP channels that need to be filtered out of the snoop
102// logs.
103class FilterTracker {
104 public:
105 // NOTE: 1 is used as a static CID for L2CAP signaling
106 std::unordered_set<uint16_t> l2c_local_cid = {1};
107 std::unordered_set<uint16_t> l2c_remote_cid = {1};
108 uint16_t rfc_local_cid = 0;
109 uint16_t rfc_remote_cid = 0;
110 std::unordered_set<uint16_t> rfc_channels = {0};
111
112 // Adds L2C channel to whitelist.
113 void addL2cCid(uint16_t local_cid, uint16_t remote_cid) {
114 l2c_local_cid.insert(local_cid);
115 l2c_remote_cid.insert(remote_cid);
116 }
117
118 // Sets L2CAP channel that RFCOMM uses.
119 void setRfcCid(uint16_t local_cid, uint16_t remote_cid) {
120 rfc_local_cid = local_cid;
121 rfc_remote_cid = remote_cid;
122 }
123
124 // Remove L2C channel from whitelist.
125 void removeL2cCid(uint16_t local_cid, uint16_t remote_cid) {
126 if (rfc_local_cid == local_cid) {
127 rfc_channels.clear();
128 rfc_channels.insert(0);
129 rfc_local_cid = 0;
130 rfc_remote_cid = 0;
131 }
132
133 l2c_local_cid.erase(local_cid);
134 l2c_remote_cid.erase(remote_cid);
135 }
136
137 void addRfcDlci(uint8_t channel) { rfc_channels.insert(channel); }
138
139 bool isWhitelistedL2c(bool local, uint16_t cid) {
140 const auto& set = local ? l2c_local_cid : l2c_remote_cid;
141 return (set.find(cid) != set.end());
142 }
143
144 bool isRfcChannel(bool local, uint16_t cid) {
145 const auto& channel = local ? rfc_local_cid : rfc_remote_cid;
146 return cid == channel;
147 }
148
149 bool isWhitelistedDlci(uint8_t dlci) {
150 return rfc_channels.find(dlci) != rfc_channels.end();
151 }
152};
153
154std::mutex filter_list_mutex;
155std::unordered_map<uint16_t, FilterTracker> filter_list;
156std::unordered_map<uint16_t, uint16_t> local_cid_to_acl;
157
158// Cached value for whether full snoop logs are enabled. So the property isn't
159// checked for every packet.
160static bool is_btsnoop_enabled;
161static bool is_btsnoop_filtered;
162
Zach Johnson9891f322014-09-22 22:11:55 -0700163// TODO(zachoverflow): merge btsnoop and btsnoop_net together
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -0700164void btsnoop_net_open();
165void btsnoop_net_close();
Myles Watson5ff20a22016-10-31 10:53:52 -0700166void btsnoop_net_write(const void* data, size_t length);
Kim Schulzf1d68e92013-09-23 12:48:47 +0200167
Ajay Panicker83036292018-11-16 13:06:47 -0800168static void delete_btsnoop_files(bool filtered);
169static std::string get_btsnoop_log_path(bool filtered);
170static std::string get_btsnoop_last_log_path(std::string log_path);
Ajay Panicker99c34222017-04-17 20:53:24 -0700171static void open_next_snoop_file();
Andre Eisenbach796523d2016-11-10 16:11:00 -0800172static void btsnoop_write_packet(packet_type_t type, uint8_t* packet,
Jack He071b5072017-02-07 17:25:15 -0800173 bool is_received, uint64_t timestamp_us);
Zach Johnson9891f322014-09-22 22:11:55 -0700174
175// Module lifecycle functions
176
Ajay Panicker83036292018-11-16 13:06:47 -0800177static future_t* start_up() {
178 std::array<char, PROPERTY_VALUE_MAX> property = {};
Ajay Panicker99c34222017-04-17 20:53:24 -0700179 std::lock_guard<std::mutex> lock(btsnoop_mutex);
180
Ajay Panicker83036292018-11-16 13:06:47 -0800181 // Default mode is FILTERED on userdebug/eng build, DISABLED on user build.
182 // It can also be overwritten by modifying the global setting.
183 int is_debuggable = osi_property_get_int32(IS_DEBUGGABLE_PROPERTY, 0);
184 std::string default_mode = BTSNOOP_MODE_DISABLED;
185 if (is_debuggable) {
186 int len = osi_property_get(BTSNOOP_DEFAULT_MODE_PROPERTY, property.data(),
Ajay Panickerc33c9982019-02-11 18:04:21 -0800187 BTSNOOP_MODE_DISABLED);
Ajay Panicker83036292018-11-16 13:06:47 -0800188 default_mode = std::string(property.data(), len);
189 }
190
191 // Get the actual mode
192 int len = osi_property_get(BTSNOOP_LOG_MODE_PROPERTY, property.data(),
193 default_mode.c_str());
194 std::string btsnoop_mode(property.data(), len);
195
196 if (btsnoop_mode == BTSNOOP_MODE_FILTERED) {
197 LOG(INFO) << __func__ << ": Filtered Snoop Logs enabled";
198 is_btsnoop_enabled = true;
199 is_btsnoop_filtered = true;
200 delete_btsnoop_files(false);
201 } else if (btsnoop_mode == BTSNOOP_MODE_FULL) {
202 LOG(INFO) << __func__ << ": Snoop Logs fully enabled";
203 is_btsnoop_enabled = true;
204 is_btsnoop_filtered = false;
205 delete_btsnoop_files(true);
Ajay Panicker99c34222017-04-17 20:53:24 -0700206 } else {
Ajay Panicker83036292018-11-16 13:06:47 -0800207 LOG(INFO) << __func__ << ": Snoop Logs disabled";
208 is_btsnoop_enabled = false;
209 is_btsnoop_filtered = false;
210 delete_btsnoop_files(true);
211 delete_btsnoop_files(false);
212 }
213
214 if (is_btsnoop_enabled) {
Ajay Panicker99c34222017-04-17 20:53:24 -0700215 open_next_snoop_file();
Jack He2b59c4a2017-05-04 13:27:25 -0700216 packets_per_file = osi_property_get_int32(BTSNOOP_MAX_PACKETS_PROPERTY,
217 DEFAULT_BTSNOOP_SIZE);
Ajay Panicker99c34222017-04-17 20:53:24 -0700218 btsnoop_net_open();
219 }
Zach Johnson9891f322014-09-22 22:11:55 -0700220
221 return NULL;
222}
223
Myles Watson5ff20a22016-10-31 10:53:52 -0700224static future_t* shut_down(void) {
Ajay Panicker99c34222017-04-17 20:53:24 -0700225 std::lock_guard<std::mutex> lock(btsnoop_mutex);
226
Ajay Panicker83036292018-11-16 13:06:47 -0800227 if (is_btsnoop_enabled) {
228 if (is_btsnoop_filtered) {
229 delete_btsnoop_files(false);
230 } else {
231 delete_btsnoop_files(true);
232 }
233 } else {
234 delete_btsnoop_files(true);
235 delete_btsnoop_files(false);
Ajay Panicker99c34222017-04-17 20:53:24 -0700236 }
237
238 if (logfile_fd != INVALID_FD) close(logfile_fd);
239 logfile_fd = INVALID_FD;
240
Ajay Panicker83036292018-11-16 13:06:47 -0800241 if (is_btsnoop_enabled) btsnoop_net_close();
Zach Johnson9891f322014-09-22 22:11:55 -0700242
243 return NULL;
244}
245
Pavlin Radoslavovb2a292b2016-10-14 19:34:48 -0700246EXPORT_SYMBOL extern const module_t btsnoop_module = {
Myles Watson5ff20a22016-10-31 10:53:52 -0700247 .name = BTSNOOP_MODULE,
248 .init = NULL,
249 .start_up = start_up,
250 .shut_down = shut_down,
251 .clean_up = NULL,
252 .dependencies = {STACK_CONFIG_MODULE, NULL}};
Zach Johnson9891f322014-09-22 22:11:55 -0700253
254// Interface functions
Myles Watson5ff20a22016-10-31 10:53:52 -0700255static void capture(const BT_HDR* buffer, bool is_received) {
Andre Eisenbach796523d2016-11-10 16:11:00 -0800256 uint8_t* p = const_cast<uint8_t*>(buffer->data + buffer->offset);
Zach Johnson9891f322014-09-22 22:11:55 -0700257
Pavlin Radoslavov3060ec62017-02-16 11:51:48 -0800258 std::lock_guard<std::mutex> lock(btsnoop_mutex);
Ajay Panicker83036292018-11-16 13:06:47 -0800259
260 struct timespec ts_now = {};
261 clock_gettime(CLOCK_REALTIME, &ts_now);
262 uint64_t timestamp_us =
263 ((uint64_t)ts_now.tv_sec * 1000000L) + ((uint64_t)ts_now.tv_nsec / 1000);
264
Jack He071b5072017-02-07 17:25:15 -0800265 btsnoop_mem_capture(buffer, timestamp_us);
Andre Eisenbach89f5e412014-12-05 09:40:20 -0800266
Myles Watson5ff20a22016-10-31 10:53:52 -0700267 if (logfile_fd == INVALID_FD) return;
Zach Johnson9891f322014-09-22 22:11:55 -0700268
269 switch (buffer->event & MSG_EVT_MASK) {
270 case MSG_HC_TO_STACK_HCI_EVT:
Jack He071b5072017-02-07 17:25:15 -0800271 btsnoop_write_packet(kEventPacket, p, false, timestamp_us);
Zach Johnson9891f322014-09-22 22:11:55 -0700272 break;
273 case MSG_HC_TO_STACK_HCI_ACL:
274 case MSG_STACK_TO_HC_HCI_ACL:
Jack He071b5072017-02-07 17:25:15 -0800275 btsnoop_write_packet(kAclPacket, p, is_received, timestamp_us);
Zach Johnson9891f322014-09-22 22:11:55 -0700276 break;
277 case MSG_HC_TO_STACK_HCI_SCO:
278 case MSG_STACK_TO_HC_HCI_SCO:
Jack He071b5072017-02-07 17:25:15 -0800279 btsnoop_write_packet(kScoPacket, p, is_received, timestamp_us);
Zach Johnson9891f322014-09-22 22:11:55 -0700280 break;
281 case MSG_STACK_TO_HC_HCI_CMD:
Jack He071b5072017-02-07 17:25:15 -0800282 btsnoop_write_packet(kCommandPacket, p, true, timestamp_us);
Zach Johnson9891f322014-09-22 22:11:55 -0700283 break;
284 }
285}
286
Ajay Panicker83036292018-11-16 13:06:47 -0800287static void whitelist_l2c_channel(uint16_t conn_handle, uint16_t local_cid,
288 uint16_t remote_cid) {
289 LOG(INFO) << __func__
290 << ": Whitelisting l2cap channel. conn_handle=" << conn_handle
291 << " cid=" << loghex(local_cid) << ":" << loghex(remote_cid);
292 std::lock_guard lock(filter_list_mutex);
Zach Johnson9891f322014-09-22 22:11:55 -0700293
Ajay Panicker83036292018-11-16 13:06:47 -0800294 // This will create the entry if there is no associated filter with the
295 // connection.
296 filter_list[conn_handle].addL2cCid(local_cid, remote_cid);
Zach Johnson9891f322014-09-22 22:11:55 -0700297}
298
Ajay Panicker83036292018-11-16 13:06:47 -0800299static void whitelist_rfc_dlci(uint16_t local_cid, uint8_t dlci) {
300 LOG(INFO) << __func__
301 << ": Whitelisting rfcomm channel. L2CAP CID=" << loghex(local_cid)
302 << " DLCI=" << loghex(dlci);
303 std::lock_guard lock(filter_list_mutex);
304
305 tL2C_CCB* p_ccb = l2cu_find_ccb_by_cid(nullptr, local_cid);
306 filter_list[p_ccb->p_lcb->handle].addRfcDlci(dlci);
Ajay Panicker99c34222017-04-17 20:53:24 -0700307}
Zach Johnson9891f322014-09-22 22:11:55 -0700308
Ajay Panicker83036292018-11-16 13:06:47 -0800309static void add_rfc_l2c_channel(uint16_t conn_handle, uint16_t local_cid,
310 uint16_t remote_cid) {
311 LOG(INFO) << __func__
312 << ": rfcomm data going over l2cap channel. conn_handle="
313 << conn_handle << " cid=" << loghex(local_cid) << ":"
314 << loghex(remote_cid);
315 std::lock_guard lock(filter_list_mutex);
316
317 filter_list[conn_handle].setRfcCid(local_cid, remote_cid);
318 local_cid_to_acl.insert({local_cid, conn_handle});
Ajay Panicker99c34222017-04-17 20:53:24 -0700319}
Pavlin Radoslavov3060ec62017-02-16 11:51:48 -0800320
Ajay Panicker83036292018-11-16 13:06:47 -0800321static void clear_l2cap_whitelist(uint16_t conn_handle, uint16_t local_cid,
322 uint16_t remote_cid) {
323 LOG(INFO) << __func__
324 << ": Clearing whitelist from l2cap channel. conn_handle="
325 << conn_handle << " cid=" << local_cid << ":" << remote_cid;
326
327 std::lock_guard lock(filter_list_mutex);
328 filter_list[conn_handle].removeL2cCid(local_cid, remote_cid);
329}
330
331static const btsnoop_t interface = {capture, whitelist_l2c_channel,
332 whitelist_rfc_dlci, add_rfc_l2c_channel,
333 clear_l2cap_whitelist};
334
335const btsnoop_t* btsnoop_get_interface() { return &interface; }
336
337static void delete_btsnoop_files(bool filtered) {
338 LOG(INFO) << __func__
339 << ": Deleting snoop logs if they exist. filtered = " << filtered;
340 auto log_path = get_btsnoop_log_path(filtered);
341 remove(log_path.c_str());
342 remove(get_btsnoop_last_log_path(log_path).c_str());
343}
344
345std::string get_btsnoop_log_path(bool filtered) {
346 char btsnoop_path[PROPERTY_VALUE_MAX];
Ajay Panicker99c34222017-04-17 20:53:24 -0700347 osi_property_get(BTSNOOP_PATH_PROPERTY, btsnoop_path, DEFAULT_BTSNOOP_PATH);
Ajay Panicker83036292018-11-16 13:06:47 -0800348 std::string result(btsnoop_path);
349 if (filtered) result = result.append(".filtered");
350
351 return result;
Ajay Panicker99c34222017-04-17 20:53:24 -0700352}
Zach Johnson9891f322014-09-22 22:11:55 -0700353
Ajay Panicker83036292018-11-16 13:06:47 -0800354std::string get_btsnoop_last_log_path(std::string btsnoop_path) {
355 return btsnoop_path.append(".last");
Ajay Panicker99c34222017-04-17 20:53:24 -0700356}
Ajay Panickerf786aac2017-03-30 10:33:19 -0700357
Ajay Panicker99c34222017-04-17 20:53:24 -0700358static void open_next_snoop_file() {
359 packet_counter = 0;
Zach Johnson9891f322014-09-22 22:11:55 -0700360
Ajay Panicker99c34222017-04-17 20:53:24 -0700361 if (logfile_fd != INVALID_FD) {
362 close(logfile_fd);
Zach Johnson9891f322014-09-22 22:11:55 -0700363 logfile_fd = INVALID_FD;
Zach Johnson9891f322014-09-22 22:11:55 -0700364 }
Ajay Panicker99c34222017-04-17 20:53:24 -0700365
Ajay Panicker83036292018-11-16 13:06:47 -0800366 auto log_path = get_btsnoop_log_path(is_btsnoop_filtered);
367 auto last_log_path = get_btsnoop_last_log_path(log_path);
Ajay Panicker99c34222017-04-17 20:53:24 -0700368
Ajay Panicker83036292018-11-16 13:06:47 -0800369 if (rename(log_path.c_str(), last_log_path.c_str()) != 0 && errno != ENOENT)
370 LOG(ERROR) << __func__ << ": unable to rename '" << log_path << "' to '"
371 << last_log_path << "' : " << strerror(errno);
Ajay Panicker99c34222017-04-17 20:53:24 -0700372
373 mode_t prevmask = umask(0);
Ajay Panicker83036292018-11-16 13:06:47 -0800374 logfile_fd = open(log_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC,
Ajay Panicker99c34222017-04-17 20:53:24 -0700375 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
376 umask(prevmask);
377 if (logfile_fd == INVALID_FD) {
Ajay Panicker83036292018-11-16 13:06:47 -0800378 LOG(ERROR) << __func__ << ": unable to open '" << log_path
379 << "' : " << strerror(errno);
Ajay Panicker99c34222017-04-17 20:53:24 -0700380 return;
381 }
382
383 write(logfile_fd, "btsnoop\0\0\0\0\1\0\0\x3\xea", 16);
Zach Johnson9891f322014-09-22 22:11:55 -0700384}
385
Andre Eisenbach796523d2016-11-10 16:11:00 -0800386typedef struct {
387 uint32_t length_original;
388 uint32_t length_captured;
389 uint32_t flags;
390 uint32_t dropped_packets;
391 uint64_t timestamp;
392 uint8_t type;
393} __attribute__((__packed__)) btsnoop_header_t;
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -0700394
Andre Eisenbach796523d2016-11-10 16:11:00 -0800395static uint64_t htonll(uint64_t ll) {
Pavlin Radoslavov16b3e922017-02-06 18:48:18 -0800396 const uint32_t l = 1;
397 if (*(reinterpret_cast<const uint8_t*>(&l)) == 1)
398 return static_cast<uint64_t>(htonl(ll & 0xffffffff)) << 32 |
399 htonl(ll >> 32);
400
Andre Eisenbach796523d2016-11-10 16:11:00 -0800401 return ll;
Sharvil Nanavati611f3ab2014-03-22 14:27:07 -0700402}
Kim Schulzf1d68e92013-09-23 12:48:47 +0200403
Ajay Panicker83036292018-11-16 13:06:47 -0800404static bool should_filter_log(bool is_received, uint8_t* packet) {
405 uint16_t acl_handle =
406 HCID_GET_HANDLE((((uint16_t)packet[ACL_CHANNEL_OFFSET + 1]) << 8) +
407 packet[ACL_CHANNEL_OFFSET]);
408
409 std::lock_guard lock(filter_list_mutex);
410 auto& filters = filter_list[acl_handle];
411 uint16_t l2c_channel =
412 (packet[L2C_CHANNEL_OFFSET + 1] << 8) + packet[L2C_CHANNEL_OFFSET];
413 if (filters.isRfcChannel(is_received, l2c_channel)) {
414 uint8_t rfc_event = packet[RFC_EVENT_OFFSET] & 0b11101111;
415 if (rfc_event == RFCOMM_SABME || rfc_event == RFCOMM_UA) {
416 return false;
417 }
418
419 uint8_t rfc_dlci = packet[RFC_CHANNEL_OFFSET] >> 2;
420 if (!filters.isWhitelistedDlci(rfc_dlci)) {
421 return true;
422 }
423 } else if (!filters.isWhitelistedL2c(is_received, l2c_channel)) {
424 return true;
425 }
426
427 return false;
428}
429
Andre Eisenbach796523d2016-11-10 16:11:00 -0800430static void btsnoop_write_packet(packet_type_t type, uint8_t* packet,
Jack He071b5072017-02-07 17:25:15 -0800431 bool is_received, uint64_t timestamp_us) {
Andre Eisenbach796523d2016-11-10 16:11:00 -0800432 uint32_t length_he = 0;
433 uint32_t flags = 0;
434
Sharvil Nanavatia7d7eb72014-06-14 23:45:16 -0700435 switch (type) {
436 case kCommandPacket:
437 length_he = packet[2] + 4;
438 flags = 2;
439 break;
440 case kAclPacket:
441 length_he = (packet[3] << 8) + packet[2] + 5;
442 flags = is_received;
443 break;
444 case kScoPacket:
445 length_he = packet[2] + 4;
446 flags = is_received;
447 break;
448 case kEventPacket:
449 length_he = packet[1] + 3;
450 flags = 3;
451 break;
452 }
Sharvil Nanavati611f3ab2014-03-22 14:27:07 -0700453
Andre Eisenbach796523d2016-11-10 16:11:00 -0800454 btsnoop_header_t header;
455 header.length_original = htonl(length_he);
Ajay Panicker83036292018-11-16 13:06:47 -0800456
457 bool blacklisted = false;
458 if (is_btsnoop_filtered && type == kAclPacket) {
459 blacklisted = should_filter_log(is_received, packet);
460 }
461
462 header.length_captured =
463 blacklisted ? htonl(L2C_HEADER_SIZE) : header.length_original;
464 if (blacklisted) length_he = L2C_HEADER_SIZE;
Andre Eisenbach796523d2016-11-10 16:11:00 -0800465 header.flags = htonl(flags);
466 header.dropped_packets = 0;
Jack He071b5072017-02-07 17:25:15 -0800467 header.timestamp = htonll(timestamp_us + BTSNOOP_EPOCH_DELTA);
Andre Eisenbach796523d2016-11-10 16:11:00 -0800468 header.type = type;
Kim Schulzf1d68e92013-09-23 12:48:47 +0200469
Andre Eisenbach796523d2016-11-10 16:11:00 -0800470 btsnoop_net_write(&header, sizeof(btsnoop_header_t));
471 btsnoop_net_write(packet, length_he - 1);
Kim Schulzf1d68e92013-09-23 12:48:47 +0200472
Andre Eisenbach796523d2016-11-10 16:11:00 -0800473 if (logfile_fd != INVALID_FD) {
Ajay Panicker99c34222017-04-17 20:53:24 -0700474 packet_counter++;
475 if (packet_counter > packets_per_file) {
476 open_next_snoop_file();
477 }
478
Andre Eisenbach796523d2016-11-10 16:11:00 -0800479 iovec iov[] = {{&header, sizeof(btsnoop_header_t)},
480 {reinterpret_cast<void*>(packet), length_he - 1}};
481 TEMP_FAILURE_RETRY(writev(logfile_fd, iov, 2));
482 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800483}