| // Copyright (c) 2012 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "debugd/src/debug_daemon.h" |
| |
| #include <base/files/file_path.h> |
| #include <base/files/file_util.h> |
| #include <base/logging.h> |
| #include <chromeos/dbus/service_constants.h> |
| #include <dbus-c++/dbus.h> |
| |
| #include "debugd/src/constants.h" |
| |
| namespace debugd { |
| |
| namespace { |
| |
| const char kDevCoredumpDBusErrorString[] = |
| "org.chromium.debugd.error.DevCoreDump"; |
| |
| } // namespace |
| |
| DebugDaemon::DebugDaemon(DBus::Connection* connection, |
| DBus::BusDispatcher* dispatcher) |
| : DBus::ObjectAdaptor(*connection, kDebugdServicePath), |
| dbus_(connection), |
| dispatcher_(dispatcher) {} |
| |
| bool DebugDaemon::Init() { |
| battery_tool_ = new BatteryTool(); |
| crash_sender_tool_ = new CrashSenderTool(); |
| debug_logs_tool_ = new DebugLogsTool(); |
| debug_mode_tool_ = new DebugModeTool(dbus_); |
| dev_features_tool_wrapper_ = |
| new RestrictedToolWrapper<DevFeaturesTool>(dbus_); |
| example_tool_ = new ExampleTool(); |
| icmp_tool_ = new ICMPTool(); |
| modem_status_tool_ = new ModemStatusTool(); |
| netif_tool_ = new NetifTool(); |
| network_status_tool_ = new NetworkStatusTool(); |
| packet_capture_tool_ = new PacketCaptureTool(); |
| ping_tool_ = new PingTool(); |
| route_tool_ = new RouteTool(); |
| sysrq_tool_ = new SysrqTool(); |
| systrace_tool_ = new SystraceTool(); |
| tracepath_tool_ = new TracePathTool(); |
| log_tool_ = new LogTool(); |
| perf_tool_ = new PerfTool(); |
| storage_tool_ = new StorageTool(); |
| memory_tool_ = new MemtesterTool(); |
| wimax_status_tool_ = new WiMaxStatusTool(); |
| if (!dbus_->acquire_name(kDebugdServiceName)) { |
| LOG(ERROR) << "Failed to acquire D-Bus name " << kDebugdServiceName; |
| return false; |
| } |
| session_manager_proxy_.reset(new SessionManagerProxy(dbus_)); |
| if (dev_features_tool_wrapper_->restriction().InDevMode() && |
| base::PathExists( |
| base::FilePath(debugd::kDevFeaturesChromeRemoteDebuggingFlagPath))) { |
| session_manager_proxy_->EnableChromeRemoteDebugging(); |
| } |
| return true; |
| } |
| |
| void DebugDaemon::Run() { |
| dispatcher_->enter(); |
| while (1) { |
| dispatcher_->do_iteration(); |
| } |
| // Unreachable. |
| dispatcher_->leave(); |
| } |
| |
| std::string DebugDaemon::PingStart( |
| const DBus::FileDescriptor& outfd, |
| const std::string& destination, |
| const std::map<std::string, DBus::Variant>& options, |
| DBus::Error& error) { // NOLINT |
| return ping_tool_->Start(outfd, destination, options, &error); |
| } |
| |
| void DebugDaemon::PingStop(const std::string& handle, |
| DBus::Error& error) { // NOLINT |
| return ping_tool_->Stop(handle, &error); |
| } |
| |
| std::string DebugDaemon::TracePathStart( |
| const DBus::FileDescriptor& outfd, |
| const std::string& destination, |
| const std::map<std::string, DBus::Variant>& options, |
| DBus::Error& error) { // NOLINT |
| return tracepath_tool_->Start(outfd, destination, options, &error); |
| } |
| |
| void DebugDaemon::TracePathStop(const std::string& handle, |
| DBus::Error& error) { // NOLINT |
| return tracepath_tool_->Stop(handle, &error); |
| } |
| |
| void DebugDaemon::SystraceStart(const std::string& categories, |
| DBus::Error& error) { // NOLINT |
| (void) systrace_tool_->Start(categories, &error); |
| } |
| |
| void DebugDaemon::SystraceStop(const DBus::FileDescriptor& outfd, |
| DBus::Error& error) { // NOLINT |
| return systrace_tool_->Stop(outfd, &error); |
| } |
| |
| std::string DebugDaemon::SystraceStatus(DBus::Error& error) { // NOLINT |
| return systrace_tool_->Status(&error); |
| } |
| |
| std::vector<std::string> DebugDaemon::GetRoutes( |
| const std::map<std::string, DBus::Variant>& options, |
| DBus::Error& error) { // NOLINT |
| return route_tool_->GetRoutes(options, &error); |
| } |
| |
| std::string DebugDaemon::GetModemStatus(DBus::Error& error) { // NOLINT |
| return modem_status_tool_->GetModemStatus(&error); |
| } |
| |
| std::string DebugDaemon::RunModemCommand(const std::string& command, |
| DBus::Error& error) { // NOLINT |
| return modem_status_tool_->RunModemCommand(command); |
| } |
| |
| std::string DebugDaemon::GetNetworkStatus(DBus::Error& error) { // NOLINT |
| return network_status_tool_->GetNetworkStatus(&error); |
| } |
| |
| std::string DebugDaemon::GetWiMaxStatus(DBus::Error& error) { // NOLINT |
| return wimax_status_tool_->GetWiMaxStatus(&error); |
| } |
| |
| void DebugDaemon::GetPerfOutput( |
| const uint32_t& duration_sec, |
| const std::vector<std::string>& perf_args, |
| int32_t& status, |
| std::vector<uint8_t>& perf_data, |
| std::vector<uint8_t>& perf_stat, |
| DBus::Error& error) { // NOLINT |
| status = perf_tool_->GetPerfOutput( |
| duration_sec, perf_args, &perf_data, &perf_stat, &error); |
| } |
| |
| void DebugDaemon::GetRandomPerfOutput( |
| const uint32_t& duration_sec, |
| int32_t& status, |
| std::vector<uint8_t>& perf_data, |
| std::vector<uint8_t>& perf_stat, |
| DBus::Error& error) { // NOLINT |
| status = perf_tool_->GetRandomPerfOutput( |
| duration_sec, &perf_data, &perf_stat, &error); |
| } |
| |
| std::vector<uint8_t> DebugDaemon::GetRichPerfData( |
| const uint32_t& duration_sec, DBus::Error& error) { // NOLINT |
| return perf_tool_->GetRichPerfData(duration_sec, &error); |
| } |
| |
| void DebugDaemon::GetDebugLogs(const DBus::FileDescriptor& fd, |
| DBus::Error& error) { // NOLINT |
| debug_logs_tool_->GetDebugLogs(true, // is_compressed, |
| fd, |
| &error); |
| } |
| |
| void DebugDaemon::DumpDebugLogs(const bool& is_compressed, |
| const DBus::FileDescriptor& fd, |
| DBus::Error& error) { // NOLINT |
| debug_logs_tool_->GetDebugLogs(is_compressed, fd, &error); |
| } |
| |
| void DebugDaemon::SetDebugMode(const std::string& subsystem, |
| DBus::Error& error) { // NOLINT |
| debug_mode_tool_->SetDebugMode(subsystem, &error); |
| } |
| |
| std::string DebugDaemon::GetLog(const std::string& name, |
| DBus::Error& error) { // NOLINT |
| return log_tool_->GetLog(name, &error); |
| } |
| |
| std::map<std::string, std::string> DebugDaemon::GetAllLogs( |
| DBus::Error& error) { // NOLINT |
| return log_tool_->GetAllLogs(dbus_, &error); |
| } |
| |
| std::map<std::string, std::string> DebugDaemon::GetFeedbackLogs( |
| DBus::Error& error) { // NOLINT |
| return log_tool_->GetFeedbackLogs(dbus_, &error); |
| } |
| |
| std::map<std::string, std::string> DebugDaemon::GetUserLogFiles( |
| DBus::Error& error) { // NOLINT |
| return log_tool_->GetUserLogFiles(&error); |
| } |
| |
| std::string DebugDaemon::GetExample(DBus::Error& error) { // NOLINT |
| return example_tool_->GetExample(&error); |
| } |
| |
| std::string DebugDaemon::GetInterfaces(DBus::Error& error) { // NOLINT |
| return netif_tool_->GetInterfaces(&error); |
| } |
| |
| std::string DebugDaemon::TestICMP(const std::string& host, |
| DBus::Error& error) { // NOLINT |
| return icmp_tool_->TestICMP(host, &error); |
| } |
| |
| std::string DebugDaemon::TestICMPWithOptions( |
| const std::string& host, |
| const std::map<std::string, std::string>& options, |
| DBus::Error& error) { // NOLINT |
| return icmp_tool_->TestICMPWithOptions(host, options, &error); |
| } |
| |
| std::string DebugDaemon::BatteryFirmware(const std::string& option, |
| DBus::Error& error) { // NOLINT |
| return battery_tool_->BatteryFirmware(option, &error); |
| } |
| |
| std::string DebugDaemon::Smartctl(const std::string& option, |
| DBus::Error& error) { // NOLINT |
| return storage_tool_->Smartctl(option, &error); |
| } |
| |
| std::string DebugDaemon::MemtesterStart(const DBus::FileDescriptor& outfd, |
| const uint32_t& memory, |
| DBus::Error& error) { // NOLINT |
| return memory_tool_->Start(outfd, memory, &error); |
| } |
| |
| void DebugDaemon::MemtesterStop(const std::string& handle, |
| DBus::Error& error) { // NOLINT |
| return memory_tool_->Stop(handle, &error); |
| } |
| |
| std::string DebugDaemon::BadblocksStart(const DBus::FileDescriptor& outfd, |
| DBus::Error& error) { // NOLINT |
| return storage_tool_->Start(outfd, &error); |
| } |
| |
| void DebugDaemon::BadblocksStop(const std::string& handle, |
| DBus::Error& error) { // NOLINT |
| return storage_tool_->Stop(handle, &error); |
| } |
| |
| std::string DebugDaemon::PacketCaptureStart( |
| const DBus::FileDescriptor& statfd, |
| const DBus::FileDescriptor& outfd, |
| const std::map<std::string, DBus::Variant>& options, |
| DBus::Error& error) { // NOLINT |
| return packet_capture_tool_->Start(statfd, outfd, options, &error); |
| } |
| |
| void DebugDaemon::PacketCaptureStop(const std::string& handle, |
| DBus::Error& error) { // NOLINT |
| return packet_capture_tool_->Stop(handle, &error); |
| } |
| |
| void DebugDaemon::LogKernelTaskStates(DBus::Error& error) { // NOLINT |
| sysrq_tool_->LogKernelTaskStates(&error); |
| } |
| |
| void DebugDaemon::UploadCrashes(DBus::Error& error) { // NOLINT |
| crash_sender_tool_->UploadCrashes(&error); |
| } |
| |
| void DebugDaemon::RemoveRootfsVerification(DBus::Error& error) { // NOLINT |
| dev_features_tool_wrapper_->CallToolFunction( |
| [&error](DevFeaturesTool* tool) { |
| tool->RemoveRootfsVerification(&error); |
| }, |
| &error); |
| } |
| |
| void DebugDaemon::EnableBootFromUsb(DBus::Error& error) { // NOLINT |
| dev_features_tool_wrapper_->CallToolFunction( |
| [&error](DevFeaturesTool* tool) { tool->EnableBootFromUsb(&error); }, |
| &error); |
| } |
| |
| void DebugDaemon::EnableChromeRemoteDebugging(DBus::Error& error) { // NOLINT |
| dev_features_tool_wrapper_->CallToolFunction( |
| [&error](DevFeaturesTool* tool) { |
| tool->EnableChromeRemoteDebugging(&error); |
| }, |
| &error); |
| } |
| |
| void DebugDaemon::ConfigureSshServer(DBus::Error& error) { // NOLINT |
| dev_features_tool_wrapper_->CallToolFunction( |
| [&error](DevFeaturesTool* tool) { tool->ConfigureSshServer(&error); }, |
| &error); |
| } |
| |
| void DebugDaemon::SetUserPassword(const std::string& username, |
| const std::string& password, |
| DBus::Error& error) { // NOLINT |
| dev_features_tool_wrapper_->CallToolFunction( |
| [username, password, &error](DevFeaturesTool* tool) { |
| tool->SetUserPassword(username, password, &error); |
| }, |
| &error); |
| } |
| |
| void DebugDaemon::EnableChromeDevFeatures(const std::string& root_password, |
| DBus::Error& error) { // NOLINT |
| dev_features_tool_wrapper_->CallToolFunction( |
| [root_password, &error](DevFeaturesTool* tool) { |
| tool->EnableChromeDevFeatures(root_password, &error); |
| }, |
| &error); |
| } |
| |
| int32_t DebugDaemon::QueryDevFeatures(DBus::Error& error) { // NOLINT |
| // Special case: if access fails here, we return DEV_FEATURES_DISABLED rather |
| // than a D-Bus error. However, we still want to return an error if we can |
| // access the tool but the tool execution fails so use error in the lambda. |
| int32_t features = DEV_FEATURES_DISABLED; |
| dev_features_tool_wrapper_->CallToolFunction( |
| [&features, &error](DevFeaturesTool* tool) { |
| features = tool->QueryDevFeatures(&error); |
| }, |
| nullptr); |
| return features; |
| } |
| |
| void DebugDaemon::EnableDevCoredumpUpload(DBus::Error& error) { // NOLINT |
| if (base::PathExists( |
| base::FilePath(debugd::kDeviceCoredumpUploadFlagPath))) { |
| VLOG(1) << "Device coredump upload already enabled"; |
| return; |
| } |
| if (base::WriteFile( |
| base::FilePath(debugd::kDeviceCoredumpUploadFlagPath), "", 0) < 0) { |
| error.set(kDevCoredumpDBusErrorString, "Failed to write flag file."); |
| PLOG(ERROR) << "Failed to write flag file."; |
| return; |
| } |
| } |
| |
| void DebugDaemon::DisableDevCoredumpUpload(DBus::Error& error) { // NOLINT |
| if (!base::PathExists( |
| base::FilePath(debugd::kDeviceCoredumpUploadFlagPath))) { |
| VLOG(1) << "Device coredump upload already disabled"; |
| return; |
| } |
| if (!base::DeleteFile( |
| base::FilePath(debugd::kDeviceCoredumpUploadFlagPath), false)) { |
| error.set(kDevCoredumpDBusErrorString, "Failed to delete flag file."); |
| PLOG(ERROR) << "Failed to delete flag file."; |
| return; |
| } |
| } |
| |
| } // namespace debugd |