1 #include "config.h" 2 3 #include "snmp_conf_manager.hpp" 4 5 #include "snmp_serialize.hpp" 6 #include "snmp_util.hpp" 7 #include "xyz/openbmc_project/Common/error.hpp" 8 9 #include <arpa/inet.h> 10 11 #include <phosphor-logging/elog-errors.hpp> 12 #include <phosphor-logging/lg2.hpp> 13 14 #include <filesystem> 15 16 namespace phosphor 17 { 18 namespace network 19 { 20 namespace snmp 21 { 22 23 using namespace phosphor::logging; 24 using namespace sdbusplus::xyz::openbmc_project::Common::Error; 25 using Argument = xyz::openbmc_project::Common::InvalidArgument; 26 27 ConfManager::ConfManager(sdbusplus::bus_t& bus, const char* objPath) : 28 details::CreateIface(bus, objPath, 29 details::CreateIface::action::defer_emit), 30 dbusPersistentLocation(SNMP_CONF_PERSIST_PATH), bus(bus), 31 objectPath(objPath) 32 {} 33 34 std::string ConfManager::client(std::string address, uint16_t port) 35 { 36 // will throw exception if it is already configured. 37 checkClientConfigured(address, port); 38 39 try 40 { 41 // just to check whether given address is valid or not. 42 resolveAddress(address); 43 } 44 catch (const InternalFailure& e) 45 { 46 lg2::error("{ADDRESS} is not a valid address", "ADDRESS", address); 47 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Address"), 48 Argument::ARGUMENT_VALUE(address.c_str())); 49 } 50 51 lastClientId++; 52 // create the D-Bus object 53 std::filesystem::path objPath; 54 objPath /= objectPath; 55 objPath /= std::to_string(lastClientId); 56 57 auto client = std::make_unique<phosphor::network::snmp::Client>( 58 bus, objPath.string().c_str(), *this, address, port); 59 60 // save the D-Bus object 61 serialize(lastClientId, *client, dbusPersistentLocation); 62 63 this->clients.emplace(lastClientId, std::move(client)); 64 return objPath.string(); 65 } 66 67 void ConfManager::checkClientConfigured(const std::string& address, 68 uint16_t port) 69 { 70 if (address.empty()) 71 { 72 lg2::error("{ADDRESS} is not a valid address", "ADDRESS", address); 73 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ADDRESS"), 74 Argument::ARGUMENT_VALUE(address.c_str())); 75 } 76 77 for (const auto& val : clients) 78 { 79 if (val.second.get()->address() == address && 80 val.second.get()->port() == port) 81 { 82 lg2::error("Client already exist"); 83 // TODO Add the error(Object already exist) in the D-Bus interface 84 // then make the change here,meanwhile send the Internal Failure. 85 elog<InvalidArgument>( 86 Argument::ARGUMENT_NAME("ADDRESS"), 87 Argument::ARGUMENT_VALUE("Client already exist.")); 88 } 89 } 90 } 91 92 void ConfManager::deleteSNMPClient(Id id) 93 { 94 auto it = clients.find(id); 95 if (it == clients.end()) 96 { 97 lg2::error("Unable to delete the snmp client: {ID}", "ID", id); 98 return; 99 } 100 101 std::error_code ec; 102 // remove the persistent file 103 fs::path fileName = dbusPersistentLocation; 104 fileName /= std::to_string(id); 105 106 if (fs::exists(fileName)) 107 { 108 if (!fs::remove(fileName, ec)) 109 { 110 lg2::error("Unable to delete {FILE}: {EC}", "FILE", fileName, "EC", 111 ec.value()); 112 } 113 } 114 else 115 { 116 lg2::error("{FILE} doesn't exist", "FILE", fileName); 117 } 118 // remove the D-Bus Object. 119 this->clients.erase(it); 120 } 121 122 void ConfManager::restoreClients() 123 { 124 if (!fs::exists(dbusPersistentLocation) || 125 fs::is_empty(dbusPersistentLocation)) 126 { 127 return; 128 } 129 130 for (auto& confFile : 131 fs::recursive_directory_iterator(dbusPersistentLocation)) 132 { 133 if (!fs::is_regular_file(confFile)) 134 { 135 continue; 136 } 137 138 auto managerID = confFile.path().filename().string(); 139 Id idNum = std::stol(managerID); 140 141 fs::path objPath = objectPath; 142 objPath /= managerID; 143 auto manager = 144 std::make_unique<Client>(bus, objPath.string().c_str(), *this); 145 if (deserialize(confFile.path(), *manager)) 146 { 147 manager->emit_object_added(); 148 this->clients.emplace(idNum, std::move(manager)); 149 if (idNum > lastClientId) 150 { 151 lastClientId = idNum; 152 } 153 } 154 } 155 } 156 157 } // namespace snmp 158 } // namespace network 159 } // namespace phosphor 160