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/log.hpp> 13 14 #include <experimental/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::bus& bus, const char* objPath) : 28 details::CreateIface(bus, objPath, true), 29 dbusPersistentLocation(SNMP_CONF_PERSIST_PATH), bus(bus), 30 objectPath(objPath) 31 {} 32 33 std::string ConfManager::client(std::string address, uint16_t port) 34 { 35 // will throw exception if it is already configured. 36 checkClientConfigured(address, port); 37 38 lastClientId++; 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 log<level::ERR>("Not a valid address"), 47 entry("ADDRESS=%s", address.c_str()); 48 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Address"), 49 Argument::ARGUMENT_VALUE(address.c_str())); 50 } 51 52 // create the D-Bus object 53 std::experimental::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 log<level::ERR>("Invalid address"); 73 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ADDRESS"), 74 Argument::ARGUMENT_VALUE(address.c_str())); 75 } 76 77 unsigned char buf[sizeof(struct in6_addr)]; 78 int isValid = inet_pton(AF_INET, address.c_str(), buf); 79 if (isValid < 1) 80 { 81 log<level::ERR>("Invalid address"); 82 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ADDRESS"), 83 Argument::ARGUMENT_VALUE(address.c_str())); 84 } 85 86 for (const auto& val : clients) 87 { 88 if (val.second.get()->address() == address && 89 val.second.get()->port() == port) 90 { 91 log<level::ERR>("Client already exist"); 92 // TODO Add the error(Object already exist) in the D-Bus interface 93 // then make the change here,meanwhile send the Internal Failure. 94 elog<InvalidArgument>( 95 Argument::ARGUMENT_NAME("ADDRESS"), 96 Argument::ARGUMENT_VALUE("Client already exist.")); 97 } 98 } 99 } 100 101 void ConfManager::deleteSNMPClient(Id id) 102 { 103 auto it = clients.find(id); 104 if (it == clients.end()) 105 { 106 log<level::ERR>("Unable to delete the snmp client.", 107 entry("ID=%d", id)); 108 return; 109 } 110 111 std::error_code ec; 112 // remove the persistent file 113 fs::path fileName = dbusPersistentLocation; 114 fileName /= std::to_string(id); 115 116 if (fs::exists(fileName)) 117 { 118 if (!fs::remove(fileName, ec)) 119 { 120 log<level::ERR>("Unable to delete the file", 121 entry("FILE=%s", fileName.c_str()), 122 entry("ERROR=%d", ec.value())); 123 } 124 } 125 else 126 { 127 log<level::ERR>("File doesn't exist", 128 entry("FILE=%s", fileName.c_str())); 129 } 130 // remove the D-Bus Object. 131 this->clients.erase(it); 132 } 133 134 void ConfManager::restoreClients() 135 { 136 if (!fs::exists(dbusPersistentLocation) || 137 fs::is_empty(dbusPersistentLocation)) 138 { 139 return; 140 } 141 142 for (auto& confFile : 143 fs::recursive_directory_iterator(dbusPersistentLocation)) 144 { 145 if (!fs::is_regular_file(confFile)) 146 { 147 continue; 148 } 149 150 auto managerID = confFile.path().filename().string(); 151 Id idNum = std::stol(managerID); 152 153 fs::path objPath = objectPath; 154 objPath /= managerID; 155 auto manager = 156 std::make_unique<Client>(bus, objPath.string().c_str(), *this); 157 if (deserialize(confFile.path(), *manager)) 158 { 159 manager->emit_object_added(); 160 this->clients.emplace(idNum, std::move(manager)); 161 if (idNum > lastClientId) 162 { 163 lastClientId = idNum; 164 } 165 } 166 } 167 } 168 169 } // namespace snmp 170 } // namespace network 171 } // namespace phosphor 172