11dc9178dSRatan Gupta #include "config.h" 21dc9178dSRatan Gupta #include "snmp_conf_manager.hpp" 3212f53e8SRatan Gupta #include "snmp_serialize.hpp" 4213517baSRatan Gupta #include "snmp_util.hpp" 5213517baSRatan Gupta #include "xyz/openbmc_project/Common/error.hpp" 6213517baSRatan Gupta 7213517baSRatan Gupta #include <phosphor-logging/elog-errors.hpp> 81dc9178dSRatan Gupta #include <phosphor-logging/log.hpp> 91dc9178dSRatan Gupta 101dc9178dSRatan Gupta #include <experimental/filesystem> 111dc9178dSRatan Gupta 12213517baSRatan Gupta #include <arpa/inet.h> 13213517baSRatan Gupta 141dc9178dSRatan Gupta namespace phosphor 151dc9178dSRatan Gupta { 161dc9178dSRatan Gupta namespace network 171dc9178dSRatan Gupta { 181dc9178dSRatan Gupta namespace snmp 191dc9178dSRatan Gupta { 201dc9178dSRatan Gupta 211dc9178dSRatan Gupta using namespace phosphor::logging; 22213517baSRatan Gupta using namespace sdbusplus::xyz::openbmc_project::Common::Error; 23213517baSRatan Gupta using Argument = xyz::openbmc_project::Common::InvalidArgument; 241dc9178dSRatan Gupta 251dc9178dSRatan Gupta ConfManager::ConfManager(sdbusplus::bus::bus& bus, const char* objPath) : 26212f53e8SRatan Gupta details::CreateIface(bus, objPath, true), 27212f53e8SRatan Gupta dbusPersistentLocation(SNMP_CONF_PERSIST_PATH), bus(bus), 28212f53e8SRatan Gupta objectPath(objPath) 291dc9178dSRatan Gupta { 301dc9178dSRatan Gupta } 311dc9178dSRatan Gupta 32*d84e327dSRatan Gupta std::string ConfManager::client(std::string address, uint16_t port) 331dc9178dSRatan Gupta { 341dc9178dSRatan Gupta auto clientEntry = this->clients.find(address); 35213517baSRatan Gupta if (clientEntry != this->clients.end()) 361dc9178dSRatan Gupta { 37*d84e327dSRatan Gupta log<level::ERR>("Client already configured"), 38*d84e327dSRatan Gupta entry("ADDRESS=%s", address.c_str()); 39*d84e327dSRatan Gupta elog<InternalFailure>(); 40213517baSRatan Gupta } 41213517baSRatan Gupta try 42213517baSRatan Gupta { 43213517baSRatan Gupta // just to check whether given address is valid or not. 44213517baSRatan Gupta resolveAddress(address); 45213517baSRatan Gupta } 46213517baSRatan Gupta catch (InternalFailure& e) 47213517baSRatan Gupta { 48213517baSRatan Gupta log<level::ERR>("Not a valid address"), 49213517baSRatan Gupta entry("ADDRESS=%s", address.c_str()); 50213517baSRatan Gupta elog<InvalidArgument>(Argument::ARGUMENT_NAME("Address"), 51213517baSRatan Gupta Argument::ARGUMENT_VALUE(address.c_str())); 52213517baSRatan Gupta } 53*d84e327dSRatan Gupta 541dc9178dSRatan Gupta std::experimental::filesystem::path objPath; 551dc9178dSRatan Gupta objPath /= objectPath; 561dc9178dSRatan Gupta objPath /= generateId(address, port); 57*d84e327dSRatan Gupta // create the D-Bus object 58212f53e8SRatan Gupta auto client = std::make_unique<phosphor::network::snmp::Client>( 59212f53e8SRatan Gupta bus, objPath.string().c_str(), *this, address, port); 60212f53e8SRatan Gupta // save the D-Bus object 61212f53e8SRatan Gupta serialize(*client, dbusPersistentLocation); 62212f53e8SRatan Gupta 63212f53e8SRatan Gupta this->clients.emplace(address, std::move(client)); 64*d84e327dSRatan Gupta return objPath.string(); 651dc9178dSRatan Gupta } 661dc9178dSRatan Gupta 671dc9178dSRatan Gupta std::string ConfManager::generateId(const std::string& address, uint16_t port) 681dc9178dSRatan Gupta { 691dc9178dSRatan Gupta std::stringstream hexId; 701dc9178dSRatan Gupta std::string hashString = address; 711dc9178dSRatan Gupta hashString += std::to_string(port); 721dc9178dSRatan Gupta 731dc9178dSRatan Gupta // Only want 8 hex digits. 741dc9178dSRatan Gupta hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF); 751dc9178dSRatan Gupta return hexId.str(); 761dc9178dSRatan Gupta } 771dc9178dSRatan Gupta 781dc9178dSRatan Gupta void ConfManager::deleteSNMPClient(const std::string& address) 791dc9178dSRatan Gupta { 801dc9178dSRatan Gupta auto it = clients.find(address); 811dc9178dSRatan Gupta if (it == clients.end()) 821dc9178dSRatan Gupta { 831dc9178dSRatan Gupta log<level::ERR>("Unable to delete the snmp client.", 841dc9178dSRatan Gupta entry("ADDRESS=%s", address.c_str())); 851dc9178dSRatan Gupta return; 861dc9178dSRatan Gupta } 87212f53e8SRatan Gupta 88212f53e8SRatan Gupta std::error_code ec; 89212f53e8SRatan Gupta // remove the persistent file 90212f53e8SRatan Gupta fs::path fileName = dbusPersistentLocation; 91212f53e8SRatan Gupta fileName /= 92f3fac222SGunnar Mills it->second->address() + SEPARATOR + std::to_string(it->second->port()); 93212f53e8SRatan Gupta 94212f53e8SRatan Gupta if (fs::exists(fileName)) 95212f53e8SRatan Gupta { 96212f53e8SRatan Gupta if (!fs::remove(fileName, ec)) 97212f53e8SRatan Gupta { 98212f53e8SRatan Gupta log<level::ERR>("Unable to delete the file", 99212f53e8SRatan Gupta entry("FILE=%s", fileName.c_str()), 100212f53e8SRatan Gupta entry("ERROR=%d", ec.value())); 101212f53e8SRatan Gupta } 102212f53e8SRatan Gupta } 103212f53e8SRatan Gupta else 104212f53e8SRatan Gupta { 105212f53e8SRatan Gupta log<level::ERR>("File doesn't exist", 106212f53e8SRatan Gupta entry("FILE=%s", fileName.c_str())); 107212f53e8SRatan Gupta } 108212f53e8SRatan Gupta // remove the D-Bus Object. 1091dc9178dSRatan Gupta this->clients.erase(it); 1101dc9178dSRatan Gupta } 1111dc9178dSRatan Gupta 112212f53e8SRatan Gupta void ConfManager::restoreClients() 113212f53e8SRatan Gupta { 114212f53e8SRatan Gupta if (!fs::exists(dbusPersistentLocation) || 115212f53e8SRatan Gupta fs::is_empty(dbusPersistentLocation)) 116212f53e8SRatan Gupta { 117212f53e8SRatan Gupta return; 118212f53e8SRatan Gupta } 119212f53e8SRatan Gupta 120212f53e8SRatan Gupta for (auto& confFile : 121212f53e8SRatan Gupta fs::recursive_directory_iterator(dbusPersistentLocation)) 122212f53e8SRatan Gupta { 123212f53e8SRatan Gupta if (!fs::is_regular_file(confFile)) 124212f53e8SRatan Gupta { 125212f53e8SRatan Gupta continue; 126212f53e8SRatan Gupta } 127212f53e8SRatan Gupta 128212f53e8SRatan Gupta auto managerID = confFile.path().filename().string(); 129f3fac222SGunnar Mills auto pos = managerID.find(SEPARATOR); 130212f53e8SRatan Gupta auto ipaddress = managerID.substr(0, pos); 131212f53e8SRatan Gupta auto port_str = managerID.substr(pos + 1); 132212f53e8SRatan Gupta uint16_t port = stoi(port_str, nullptr); 133212f53e8SRatan Gupta 134212f53e8SRatan Gupta fs::path objPath = objectPath; 135212f53e8SRatan Gupta objPath /= generateId(ipaddress, port); 136212f53e8SRatan Gupta auto manager = 137212f53e8SRatan Gupta std::make_unique<Client>(bus, objPath.string().c_str(), *this); 138212f53e8SRatan Gupta if (deserialize(confFile.path(), *manager)) 139212f53e8SRatan Gupta { 140212f53e8SRatan Gupta manager->emit_object_added(); 141212f53e8SRatan Gupta this->clients.emplace(ipaddress, std::move(manager)); 142212f53e8SRatan Gupta } 143212f53e8SRatan Gupta } 144212f53e8SRatan Gupta } 145212f53e8SRatan Gupta 1461dc9178dSRatan Gupta } // namespace snmp 1471dc9178dSRatan Gupta } // namespace network 1481dc9178dSRatan Gupta } // namespace phosphor 149