Loading tools/rootcanal/Android.bp +3 −0 Original line number Diff line number Diff line Loading @@ -345,6 +345,7 @@ cc_test_host { srcs: [ "test/async_manager_unittest.cc", "test/h4_parser_unittest.cc", "test/invalid_packet_handler_unittest.cc", "test/pcap_filter_unittest.cc", "test/posix_socket_unittest.cc", ], Loading @@ -356,6 +357,8 @@ cc_test_host { ], shared_libs: [ "libbase", "libcrypto", "libprotobuf-cpp-full", ], static_libs: [ "libbt-rootcanal", Loading tools/rootcanal/model/controller/dual_mode_controller.cc +202 −186 File changed.Preview size limit exceeded, changes collapsed. Show changes tools/rootcanal/model/controller/dual_mode_controller.h +20 −2 Original line number Diff line number Diff line Loading @@ -89,7 +89,7 @@ class DualModeController : public Device { /// to an external tracker. Packets are rejected if they failed to /// be parsed, or run into an unimplemented part of the controller. void RegisterInvalidPacketHandler( std::function<void(uint32_t, InvalidPacketReason, std::string, const std::function<void(uint32_t, InvalidPacketReason, std::string, std::vector<uint8_t> const&)>& handler); // Set the callbacks for sending packets to the HCI. Loading Loading @@ -553,6 +553,24 @@ class DualModeController : public Device { void SendCommandCompleteUnknownOpCodeEvent( bluetooth::hci::OpCode op_code) const; // Validate that a received packet is correctly formatted. // If the packet failed to be parsed, the function sends a // HCI Hardware Error event to the host and logs the packet to // the configured handler. template <typename T> bool CheckPacketView(T const& view, std::string reason) { if (view.IsValid()) { return true; } // Send a hardware error to reset the host, and report the packet // for tracing. send_event_(bluetooth::hci::HardwareErrorBuilder::Create(0x43)); invalid_packet_handler_(id_, InvalidPacketReason::kParseError, reason, view.bytes().bytes()); return false; } // Callbacks to send packets back to the HCI. std::function<void(std::shared_ptr<bluetooth::hci::AclBuilder>)> send_acl_; std::function<void(std::shared_ptr<bluetooth::hci::EventBuilder>)> Loading tools/rootcanal/test/invalid_packet_handler_unittest.cc 0 → 100644 +82 −0 Original line number Diff line number Diff line /* * Copyright 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <gtest/gtest.h> #include "log.h" #include "model/controller/dual_mode_controller.h" namespace rootcanal { using namespace bluetooth::hci; class InvalidPacketHandlerTest : public ::testing::Test { public: InvalidPacketHandlerTest() = default; ~InvalidPacketHandlerTest() override = default; protected: DualModeController controller_; }; // Set Event Mask command with missing parameters. const std::vector<uint8_t> kInvalidCommandPacket = {0x01, 0x0C, 0x03, 0xff, 0xff, 0xff}; // Hardware Error event with code 0x43. const std::vector<uint8_t> kHardwareErrorEvent = {0x10, 0x01, 0x43}; TEST_F(InvalidPacketHandlerTest, DefaultHandler) { // Validate that the default invalid packet handler causes // an abort when an invalid packet is received. ASSERT_DEATH(controller_.HandleCommand(std::make_shared<std::vector<uint8_t>>( kInvalidCommandPacket)), ""); } TEST_F(InvalidPacketHandlerTest, RegisteredHandler) { static struct { uint32_t id; InvalidPacketReason reason; std::vector<uint8_t> bytes; } invalid_packet; static std::vector<uint8_t> hci_event; // Validate that the registered invalid packet handler is correctly // invoked when an invalid packet is received. controller_.RegisterInvalidPacketHandler( [&](uint32_t id, InvalidPacketReason reason, std::string, std::vector<uint8_t> const& bytes) { invalid_packet.id = id; invalid_packet.reason = reason; invalid_packet.bytes = bytes; }); controller_.RegisterEventChannel( [&](std::shared_ptr<std::vector<uint8_t>> packet) { hci_event = std::vector<uint8_t>(*packet); }); controller_.HandleCommand( std::make_shared<std::vector<uint8_t>>(kInvalidCommandPacket)); ASSERT_EQ(invalid_packet.id, controller_.id_); ASSERT_EQ(invalid_packet.reason, InvalidPacketReason::kParseError); ASSERT_EQ(invalid_packet.bytes, kInvalidCommandPacket); ASSERT_EQ(hci_event, kHardwareErrorEvent); } } // namespace rootcanal Loading
tools/rootcanal/Android.bp +3 −0 Original line number Diff line number Diff line Loading @@ -345,6 +345,7 @@ cc_test_host { srcs: [ "test/async_manager_unittest.cc", "test/h4_parser_unittest.cc", "test/invalid_packet_handler_unittest.cc", "test/pcap_filter_unittest.cc", "test/posix_socket_unittest.cc", ], Loading @@ -356,6 +357,8 @@ cc_test_host { ], shared_libs: [ "libbase", "libcrypto", "libprotobuf-cpp-full", ], static_libs: [ "libbt-rootcanal", Loading
tools/rootcanal/model/controller/dual_mode_controller.cc +202 −186 File changed.Preview size limit exceeded, changes collapsed. Show changes
tools/rootcanal/model/controller/dual_mode_controller.h +20 −2 Original line number Diff line number Diff line Loading @@ -89,7 +89,7 @@ class DualModeController : public Device { /// to an external tracker. Packets are rejected if they failed to /// be parsed, or run into an unimplemented part of the controller. void RegisterInvalidPacketHandler( std::function<void(uint32_t, InvalidPacketReason, std::string, const std::function<void(uint32_t, InvalidPacketReason, std::string, std::vector<uint8_t> const&)>& handler); // Set the callbacks for sending packets to the HCI. Loading Loading @@ -553,6 +553,24 @@ class DualModeController : public Device { void SendCommandCompleteUnknownOpCodeEvent( bluetooth::hci::OpCode op_code) const; // Validate that a received packet is correctly formatted. // If the packet failed to be parsed, the function sends a // HCI Hardware Error event to the host and logs the packet to // the configured handler. template <typename T> bool CheckPacketView(T const& view, std::string reason) { if (view.IsValid()) { return true; } // Send a hardware error to reset the host, and report the packet // for tracing. send_event_(bluetooth::hci::HardwareErrorBuilder::Create(0x43)); invalid_packet_handler_(id_, InvalidPacketReason::kParseError, reason, view.bytes().bytes()); return false; } // Callbacks to send packets back to the HCI. std::function<void(std::shared_ptr<bluetooth::hci::AclBuilder>)> send_acl_; std::function<void(std::shared_ptr<bluetooth::hci::EventBuilder>)> Loading
tools/rootcanal/test/invalid_packet_handler_unittest.cc 0 → 100644 +82 −0 Original line number Diff line number Diff line /* * Copyright 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <gtest/gtest.h> #include "log.h" #include "model/controller/dual_mode_controller.h" namespace rootcanal { using namespace bluetooth::hci; class InvalidPacketHandlerTest : public ::testing::Test { public: InvalidPacketHandlerTest() = default; ~InvalidPacketHandlerTest() override = default; protected: DualModeController controller_; }; // Set Event Mask command with missing parameters. const std::vector<uint8_t> kInvalidCommandPacket = {0x01, 0x0C, 0x03, 0xff, 0xff, 0xff}; // Hardware Error event with code 0x43. const std::vector<uint8_t> kHardwareErrorEvent = {0x10, 0x01, 0x43}; TEST_F(InvalidPacketHandlerTest, DefaultHandler) { // Validate that the default invalid packet handler causes // an abort when an invalid packet is received. ASSERT_DEATH(controller_.HandleCommand(std::make_shared<std::vector<uint8_t>>( kInvalidCommandPacket)), ""); } TEST_F(InvalidPacketHandlerTest, RegisteredHandler) { static struct { uint32_t id; InvalidPacketReason reason; std::vector<uint8_t> bytes; } invalid_packet; static std::vector<uint8_t> hci_event; // Validate that the registered invalid packet handler is correctly // invoked when an invalid packet is received. controller_.RegisterInvalidPacketHandler( [&](uint32_t id, InvalidPacketReason reason, std::string, std::vector<uint8_t> const& bytes) { invalid_packet.id = id; invalid_packet.reason = reason; invalid_packet.bytes = bytes; }); controller_.RegisterEventChannel( [&](std::shared_ptr<std::vector<uint8_t>> packet) { hci_event = std::vector<uint8_t>(*packet); }); controller_.HandleCommand( std::make_shared<std::vector<uint8_t>>(kInvalidCommandPacket)); ASSERT_EQ(invalid_packet.id, controller_.id_); ASSERT_EQ(invalid_packet.reason, InvalidPacketReason::kParseError); ASSERT_EQ(invalid_packet.bytes, kInvalidCommandPacket); ASSERT_EQ(hci_event, kHardwareErrorEvent); } } // namespace rootcanal