1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <bluetooth/log.h>
20 
21 #include <fstream>
22 #include <string>
23 #include <unordered_map>
24 #include <unordered_set>
25 #include <vector>
26 
27 #include "common/circular_buffer.h"
28 #include "hal/hci_hal.h"
29 #include "hal/snoop_logger_socket_interface.h"
30 #include "hal/snoop_logger_socket_thread.h"
31 #include "hal/syscall_wrapper_impl.h"
32 #include "module.h"
33 #include "os/repeating_alarm.h"
34 
35 namespace bluetooth {
36 namespace hal {
37 
38 #ifdef USE_FAKE_TIMERS
39 static uint64_t file_creation_time;
40 #endif
41 
42 class FilterTracker {
43 public:
44   // NOTE: 1 is used as a static CID for L2CAP signaling
45   std::unordered_set<uint16_t> l2c_local_cid = {1};
46   std::unordered_set<uint16_t> l2c_remote_cid = {1};
47   uint16_t rfcomm_local_cid = 0;
48   uint16_t rfcomm_remote_cid = 0;
49   std::unordered_set<uint16_t> rfcomm_channels = {0};
50 
51   // Adds L2C channel to acceptlist.
52   void AddL2capCid(uint16_t local_cid, uint16_t remote_cid);
53 
54   // Sets L2CAP channel that RFCOMM uses.
55   void SetRfcommCid(uint16_t local_cid, uint16_t remote_cid);
56 
57   // Remove L2C channel from acceptlist.
58   void RemoveL2capCid(uint16_t local_cid, uint16_t remote_cid);
59 
60   void AddRfcommDlci(uint8_t channel);
61 
62   bool IsAcceptlistedL2cap(bool local, uint16_t cid);
63 
64   bool IsRfcommChannel(bool local, uint16_t cid);
65 
66   bool IsAcceptlistedDlci(uint8_t dlci);
67 };
68 
69 typedef enum {
70   FILTER_PROFILE_NONE = -1,
71   FILTER_PROFILE_PBAP = 0,
72   FILTER_PROFILE_HFP_HS,
73   FILTER_PROFILE_HFP_HF,
74   FILTER_PROFILE_MAP,
75   FILTER_PROFILE_MAX,
76 } profile_type_t;
77 
78 class ProfilesFilter {
79 public:
80   void SetupProfilesFilter(bool pbap_filtered, bool map_filtered);
81 
82   bool IsHfpProfile(bool local, uint16_t cid, uint8_t dlci);
83 
84   bool IsL2capMatch(bool local, uint16_t cid);
85 
86   bool IsL2capFlowExt(bool local, uint16_t cid);
87 
88   bool IsRfcommMatch(bool local, uint16_t cid, uint8_t dlci);
89 
90   bool IsRfcommFlowExt(bool local, uint16_t cid, uint8_t dlci);
91 
92   profile_type_t CidToProfile(bool local, uint16_t cid);
93 
94   profile_type_t DlciToProfile(bool local, uint16_t cid, uint8_t dlci);
95 
96   void ProfileL2capOpen(profile_type_t profile, uint16_t lcid, uint16_t rcid, uint16_t psm,
97                         bool flow_ext);
98 
99   void ProfileL2capClose(profile_type_t profile);
100 
101   void ProfileRfcommOpen(profile_type_t profile, uint16_t lcid, uint8_t dlci, uint16_t uuid,
102                          bool flow_ext);
103 
104   void ProfileRfcommClose(profile_type_t profile);
105 
106   bool IsRfcommChannel(bool local, uint16_t cid);
107 
108   void PrintProfilesConfig();
109 
ProfileToString(profile_type_t profile)110   static inline std::string ProfileToString(profile_type_t profile) {
111     switch (profile) {
112       case FILTER_PROFILE_NONE:
113         return "FILTER_PROFILE_NONE";
114       case FILTER_PROFILE_PBAP:
115         return "FILTER_PROFILE_PBAP";
116       case FILTER_PROFILE_HFP_HS:
117         return "FILTER_PROFILE_HFP_HS";
118       case FILTER_PROFILE_HFP_HF:
119         return "FILTER_PROFILE_HFP_HF";
120       case FILTER_PROFILE_MAP:
121         return "FILTER_PROFILE_MAP";
122       default:
123         return "[Unknown profile_type_t]";
124     }
125   }
126 
127   uint16_t ch_rfc_l, ch_rfc_r;  // local & remote L2CAP channel for RFCOMM
128   uint16_t ch_last;             // last channel seen for fragment packet
129 
130 private:
131   bool setup_done_flag = false;
132   struct {
133     profile_type_t type;
134     bool enabled, l2cap_opened, rfcomm_opened;
135     bool flow_ext_l2cap, flow_ext_rfcomm;
136     uint16_t lcid, rcid, rfcomm_uuid, psm;
137     uint8_t scn;
138   } profiles[FILTER_PROFILE_MAX];
139   profile_type_t current_profile;
140 };
141 
142 class SnoopLogger : public ::bluetooth::Module {
143 public:
144   static const ModuleFactory Factory;
145 
146   static const std::string kBtSnoopMaxPacketsPerFileProperty;
147   static const std::string kIsDebuggableProperty;
148   static const std::string kBtSnoopLogModeProperty;
149   static const std::string kBtSnoopLogPersists;
150   static const std::string kBtSnoopDefaultLogModeProperty;
151   static const std::string kBtSnoopLogFilterHeadersProperty;
152   static const std::string kBtSnoopLogFilterProfileA2dpProperty;
153   static const std::string kBtSnoopLogFilterProfileMapModeProperty;
154   static const std::string kBtSnoopLogFilterProfilePbapModeProperty;
155   static const std::string kBtSnoopLogFilterProfileRfcommProperty;
156   static const std::string kSoCManufacturerProperty;
157 
158   static const std::string kBtSnoopLogModeKernel;
159   static const std::string kBtSnoopLogModeDisabled;
160   static const std::string kBtSnoopLogModeFiltered;
161   static const std::string kBtSnoopLogModeFull;
162 
163   static const std::string kSoCManufacturerQualcomm;
164 
165   static const std::string kBtSnoopLogFilterProfileModeFullfillter;
166   static const std::string kBtSnoopLogFilterProfileModeHeader;
167   static const std::string kBtSnoopLogFilterProfileModeMagic;
168   static const std::string kBtSnoopLogFilterProfileModeDisabled;
169 
170   std::unordered_map<std::string, bool> kBtSnoopLogFilterState = {
171           {kBtSnoopLogFilterHeadersProperty, false},
172           {kBtSnoopLogFilterProfileA2dpProperty, false},
173           {kBtSnoopLogFilterProfileRfcommProperty, false}};
174 
175   std::unordered_map<std::string, std::string> kBtSnoopLogFilterMode = {
176           {kBtSnoopLogFilterProfilePbapModeProperty, kBtSnoopLogFilterProfileModeDisabled},
177           {kBtSnoopLogFilterProfileMapModeProperty, kBtSnoopLogFilterProfileModeDisabled}};
178 
179   // Put in header for test
180   struct PacketHeaderType {
181     uint32_t length_original;
182     uint32_t length_captured;
183     uint32_t flags;
184     uint32_t dropped_packets;
185     uint64_t timestamp;
186     uint8_t type;
187   } __attribute__((__packed__));
188 
189   // Struct for caching info about L2CAP Media Channel
190   struct A2dpMediaChannel {
191     uint16_t conn_handle;
192     uint16_t local_cid;
193     uint16_t remote_cid;
194   };
195 
196   // Returns the maximum number of packets per file
197   // Changes to this value is only effective after restarting Bluetooth
198   static size_t GetMaxPacketsPerFile();
199 
200   static size_t GetMaxPacketsPerBuffer();
201 
202   // Get current snoop logger mode
203   std::string GetCurrentSnoopMode();
204 
205   // Returns whether the soc manufacturer is Qualcomm
206   // Changes to this value is only effective after restarting Bluetooth
207   static bool IsQualcommDebugLogEnabled();
208 
209   // Returns whether snoop log persists even after restarting Bluetooth
210   static bool IsBtSnoopLogPersisted();
211 
212   // Has to be defined from 1 to 4 per btsnoop format
213   enum PacketType {
214     CMD = 1,
215     ACL = 2,
216     SCO = 3,
217     EVT = 4,
218     ISO = 5,
219   };
220 
221   enum Direction {
222     INCOMING,
223     OUTGOING,
224   };
225 
226   void Capture(const HciPacket& packet, Direction direction, PacketType type);
227 
228   // Set a L2CAP channel as acceptlisted, allowing packets with that L2CAP CID
229   // to show up in the snoop logs.
230   void AcceptlistL2capChannel(uint16_t conn_handle, uint16_t local_cid, uint16_t remote_cid);
231 
232   // Set a RFCOMM dlci as acceptlisted, allowing packets with that RFCOMM CID
233   // to show up in the snoop logs. The local_cid is used to associate it with
234   // its corresponding ACL connection. The dlci is the channel with direction
235   // so there is no chance of a collision if two services are using the same
236   // channel but in different directions.
237   void AcceptlistRfcommDlci(uint16_t conn_handle, uint16_t local_cid, uint8_t dlci);
238 
239   // Indicate that the provided L2CAP channel is being used for RFCOMM.
240   // If packets with the provided L2CAP CID are encountered, they will be
241   // filtered on RFCOMM based on channels provided to |filter_rfcomm_channel|.
242   void AddRfcommL2capChannel(uint16_t conn_handle, uint16_t local_cid, uint16_t remote_cid);
243 
244   // Clear an L2CAP channel from being filtered.
245   void ClearL2capAcceptlist(uint16_t conn_handle, uint16_t local_cid, uint16_t remote_cid);
246 
247   // Cache A2DP Media Channel info for filtering media packets.
248   void AddA2dpMediaChannel(uint16_t conn_handle, uint16_t local_cid, uint16_t remote_cid);
249 
250   // Remove A2DP Media Channel cache
251   void RemoveA2dpMediaChannel(uint16_t conn_handle, uint16_t local_cid);
252 
253   // New RFCOMM port is opened.
254   void SetRfcommPortOpen(uint16_t conn_handle, uint16_t local_cid, uint8_t dlci, uint16_t uuid,
255                          bool flow);
256   // RFCOMM port is closed.
257   void SetRfcommPortClose(uint16_t handle, uint16_t local_cid, uint8_t dlci, uint16_t uuid);
258 
259   // New L2CAP channel is opened.
260   void SetL2capChannelOpen(uint16_t handle, uint16_t local_cid, uint16_t remote_cid, uint16_t psm,
261                            bool flow);
262   // L2CAP channel is closed.
263   void SetL2capChannelClose(uint16_t handle, uint16_t local_cid, uint16_t remote_cid);
264 
265   void RegisterSocket(SnoopLoggerSocketInterface* socket);
266 
267   // Dump the contents of the snooz buffer to a file.
268   void DumpSnoozLogToFile();
269 
270 protected:
271   // Packet type length
272   static const size_t PACKET_TYPE_LENGTH;
273   // The size of the L2CAP header. All information past this point is removed from
274   // a filtered packet.
275   static const uint32_t L2CAP_HEADER_SIZE;
276   // Max packet data size when headersfiltered option enabled
277   static const size_t MAX_HCI_ACL_LEN;
278 
279   void ListDependencies(ModuleList* list) const override;
280   void Start() override;
281   void Stop() override;
ToString()282   std::string ToString() const override { return std::string("SnoopLogger"); }
283 
284   SnoopLogger(std::string snoop_log_path, std::string snooz_log_path, size_t max_packets_per_file,
285               size_t max_packets_per_buffer, const std::string& btsnoop_mode,
286               bool qualcomm_debug_log_enabled, const std::chrono::milliseconds snooz_log_life_time,
287               const std::chrono::milliseconds snooz_log_delete_alarm_interval,
288               bool snoop_log_persists);
289   void CloseCurrentSnoopLogFile();
290   void OpenNextSnoopLogFile();
291   // Enable filters according to their sysprops
292   void EnableFilters();
293   // Disable all filters
294   void DisableFilters();
295   // Check if the filter is enabled. Pass filter name as a string.
296   bool IsFilterEnabled(std::string filter_name);
297   // Check if packet should be filtered (rfcommchannelfiltered mode)
298   bool ShouldFilterLog(bool is_received, uint8_t* packet);
299   // Calculate packet length (snoopheadersfiltered mode)
300   void CalculateAclPacketLength(uint32_t& length, uint8_t* packet, bool is_received);
301   // Strip packet's payload (profilesfiltered mode)
302   uint32_t PayloadStrip(profile_type_t current_profile, uint8_t* packet, uint32_t hdr_len,
303                         uint32_t pl_len);
304   // Filter profile packet according to its filtering mode
305   uint32_t FilterProfiles(bool is_received, uint8_t* packet);
306   // Check if packet is A2DP media packet (a2dppktsfiltered mode)
307   bool IsA2dpMediaPacket(bool is_received, uint8_t* packet);
308   // Check if channel is cached in snoop logger for filtering (a2dppktsfiltered mode)
309   bool IsA2dpMediaChannel(uint16_t conn_handle, uint16_t cid, bool is_local_cid);
310   // Handle HFP filtering while profilesfiltered enabled
311   uint32_t FilterProfilesHandleHfp(uint8_t* packet, uint32_t length, uint32_t totlen,
312                                    uint32_t offset);
313   void FilterProfilesRfcommChannel(uint8_t* packet, uint8_t& current_offset, uint32_t& length,
314                                    profile_type_t& current_profile,
315                                    bluetooth::hal::ProfilesFilter& filters, bool is_received,
316                                    uint16_t l2cap_channel, uint32_t& offset, uint32_t total_length);
317   void FilterCapturedPacket(HciPacket& packet, Direction direction, PacketType type,
318                             uint32_t& length, PacketHeaderType header);
319 
320   std::unique_ptr<SnoopLoggerSocketThread> snoop_logger_socket_thread_;
321 
322 #ifdef __ANDROID__
323   void LogTracePoint(const HciPacket& packet, Direction direction, PacketType type);
324 #endif  // __ANDROID__
325 
326 private:
327   std::string btsnoop_mode_;
328   std::string snoop_log_path_;
329   std::string snooz_log_path_;
330   std::ofstream btsnoop_ostream_;
331   size_t max_packets_per_file_;
332   common::CircularBuffer<std::string> btsnooz_buffer_;
333   bool qualcomm_debug_log_enabled_ = false;
334   size_t packet_counter_ = 0;
335   mutable std::recursive_mutex file_mutex_;
336   std::unique_ptr<os::RepeatingAlarm> alarm_;
337   std::chrono::milliseconds snooz_log_life_time_;
338   std::chrono::milliseconds snooz_log_delete_alarm_interval_;
339   SnoopLoggerSocketInterface* socket_;
340   SyscallWrapperImpl syscall_if;
341   bool snoop_log_persists = false;
342 };
343 
344 }  // namespace hal
345 }  // namespace bluetooth
346 
347 namespace std {
348 template <>
349 struct formatter<bluetooth::hal::profile_type_t> : enum_formatter<bluetooth::hal::profile_type_t> {
350 };
351 }  // namespace std
352