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