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