1 #include "config.h" 2 #include "snmp_conf_manager.hpp" 3 #include "snmp_serialize.hpp" 4 #include "snmp_util.hpp" 5 #include "xyz/openbmc_project/Common/error.hpp" 6 7 #include <phosphor-logging/elog-errors.hpp> 8 #include <phosphor-logging/log.hpp> 9 10 #include <experimental/filesystem> 11 12 #include <arpa/inet.h> 13 14 namespace phosphor 15 { 16 namespace network 17 { 18 namespace snmp 19 { 20 21 using namespace phosphor::logging; 22 using namespace sdbusplus::xyz::openbmc_project::Common::Error; 23 using Argument = xyz::openbmc_project::Common::InvalidArgument; 24 25 ConfManager::ConfManager(sdbusplus::bus::bus& bus, const char* objPath) : 26 details::CreateIface(bus, objPath, true), 27 dbusPersistentLocation(SNMP_CONF_PERSIST_PATH), bus(bus), 28 objectPath(objPath) 29 { 30 } 31 32 std::string ConfManager::client(std::string address, uint16_t port) 33 { 34 auto clientEntry = this->clients.find(address); 35 if (clientEntry != this->clients.end()) 36 { 37 log<level::ERR>("Client already configured"), 38 entry("ADDRESS=%s", address.c_str()); 39 elog<InternalFailure>(); 40 } 41 try 42 { 43 // just to check whether given address is valid or not. 44 resolveAddress(address); 45 } 46 catch (InternalFailure& e) 47 { 48 log<level::ERR>("Not a valid address"), 49 entry("ADDRESS=%s", address.c_str()); 50 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Address"), 51 Argument::ARGUMENT_VALUE(address.c_str())); 52 } 53 54 std::experimental::filesystem::path objPath; 55 objPath /= objectPath; 56 objPath /= generateId(address, port); 57 // create the D-Bus object 58 auto client = std::make_unique<phosphor::network::snmp::Client>( 59 bus, objPath.string().c_str(), *this, address, port); 60 // save the D-Bus object 61 serialize(*client, dbusPersistentLocation); 62 63 this->clients.emplace(address, std::move(client)); 64 return objPath.string(); 65 } 66 67 std::string ConfManager::generateId(const std::string& address, uint16_t port) 68 { 69 std::stringstream hexId; 70 std::string hashString = address; 71 hashString += std::to_string(port); 72 73 // Only want 8 hex digits. 74 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF); 75 return hexId.str(); 76 } 77 78 void ConfManager::deleteSNMPClient(const std::string& address) 79 { 80 auto it = clients.find(address); 81 if (it == clients.end()) 82 { 83 log<level::ERR>("Unable to delete the snmp client.", 84 entry("ADDRESS=%s", address.c_str())); 85 return; 86 } 87 88 std::error_code ec; 89 // remove the persistent file 90 fs::path fileName = dbusPersistentLocation; 91 fileName /= 92 it->second->address() + SEPARATOR + std::to_string(it->second->port()); 93 94 if (fs::exists(fileName)) 95 { 96 if (!fs::remove(fileName, ec)) 97 { 98 log<level::ERR>("Unable to delete the file", 99 entry("FILE=%s", fileName.c_str()), 100 entry("ERROR=%d", ec.value())); 101 } 102 } 103 else 104 { 105 log<level::ERR>("File doesn't exist", 106 entry("FILE=%s", fileName.c_str())); 107 } 108 // remove the D-Bus Object. 109 this->clients.erase(it); 110 } 111 112 void ConfManager::restoreClients() 113 { 114 if (!fs::exists(dbusPersistentLocation) || 115 fs::is_empty(dbusPersistentLocation)) 116 { 117 return; 118 } 119 120 for (auto& confFile : 121 fs::recursive_directory_iterator(dbusPersistentLocation)) 122 { 123 if (!fs::is_regular_file(confFile)) 124 { 125 continue; 126 } 127 128 auto managerID = confFile.path().filename().string(); 129 auto pos = managerID.find(SEPARATOR); 130 auto ipaddress = managerID.substr(0, pos); 131 auto port_str = managerID.substr(pos + 1); 132 uint16_t port = stoi(port_str, nullptr); 133 134 fs::path objPath = objectPath; 135 objPath /= generateId(ipaddress, port); 136 auto manager = 137 std::make_unique<Client>(bus, objPath.string().c_str(), *this); 138 if (deserialize(confFile.path(), *manager)) 139 { 140 manager->emit_object_added(); 141 this->clients.emplace(ipaddress, std::move(manager)); 142 } 143 } 144 } 145 146 } // namespace snmp 147 } // namespace network 148 } // namespace phosphor 149