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