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 
321dc9178dSRatan Gupta void 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     {
37213517baSRatan Gupta         // address is already there
38213517baSRatan Gupta         return;
39213517baSRatan Gupta     }
40213517baSRatan Gupta     try
41213517baSRatan Gupta     {
42213517baSRatan Gupta         // just to check whether given address is valid or not.
43213517baSRatan Gupta         resolveAddress(address);
44213517baSRatan Gupta     }
45213517baSRatan Gupta     catch (InternalFailure& e)
46213517baSRatan Gupta     {
47213517baSRatan Gupta         log<level::ERR>("Not a valid address"),
48213517baSRatan Gupta             entry("ADDRESS=%s", address.c_str());
49213517baSRatan Gupta         elog<InvalidArgument>(Argument::ARGUMENT_NAME("Address"),
50213517baSRatan Gupta                               Argument::ARGUMENT_VALUE(address.c_str()));
51213517baSRatan Gupta     }
52213517baSRatan Gupta     // create the D-Bus object
531dc9178dSRatan Gupta     std::experimental::filesystem::path objPath;
541dc9178dSRatan Gupta     objPath /= objectPath;
551dc9178dSRatan Gupta     objPath /= generateId(address, port);
561dc9178dSRatan Gupta 
57212f53e8SRatan Gupta     auto client = std::make_unique<phosphor::network::snmp::Client>(
58212f53e8SRatan Gupta         bus, objPath.string().c_str(), *this, address, port);
59212f53e8SRatan Gupta     // save the D-Bus object
60212f53e8SRatan Gupta     serialize(*client, dbusPersistentLocation);
61212f53e8SRatan Gupta 
62212f53e8SRatan Gupta     this->clients.emplace(address, std::move(client));
631dc9178dSRatan Gupta }
641dc9178dSRatan Gupta 
651dc9178dSRatan Gupta std::string ConfManager::generateId(const std::string& address, uint16_t port)
661dc9178dSRatan Gupta {
671dc9178dSRatan Gupta     std::stringstream hexId;
681dc9178dSRatan Gupta     std::string hashString = address;
691dc9178dSRatan Gupta     hashString += std::to_string(port);
701dc9178dSRatan Gupta 
711dc9178dSRatan Gupta     // Only want 8 hex digits.
721dc9178dSRatan Gupta     hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
731dc9178dSRatan Gupta     return hexId.str();
741dc9178dSRatan Gupta }
751dc9178dSRatan Gupta 
761dc9178dSRatan Gupta void ConfManager::deleteSNMPClient(const std::string& address)
771dc9178dSRatan Gupta {
781dc9178dSRatan Gupta     auto it = clients.find(address);
791dc9178dSRatan Gupta     if (it == clients.end())
801dc9178dSRatan Gupta     {
811dc9178dSRatan Gupta         log<level::ERR>("Unable to delete the snmp client.",
821dc9178dSRatan Gupta                         entry("ADDRESS=%s", address.c_str()));
831dc9178dSRatan Gupta         return;
841dc9178dSRatan Gupta     }
85212f53e8SRatan Gupta 
86212f53e8SRatan Gupta     std::error_code ec;
87212f53e8SRatan Gupta     // remove the persistent file
88212f53e8SRatan Gupta     fs::path fileName = dbusPersistentLocation;
89212f53e8SRatan Gupta     fileName /=
90*f3fac222SGunnar Mills         it->second->address() + SEPARATOR + std::to_string(it->second->port());
91212f53e8SRatan Gupta 
92212f53e8SRatan Gupta     if (fs::exists(fileName))
93212f53e8SRatan Gupta     {
94212f53e8SRatan Gupta         if (!fs::remove(fileName, ec))
95212f53e8SRatan Gupta         {
96212f53e8SRatan Gupta             log<level::ERR>("Unable to delete the file",
97212f53e8SRatan Gupta                             entry("FILE=%s", fileName.c_str()),
98212f53e8SRatan Gupta                             entry("ERROR=%d", ec.value()));
99212f53e8SRatan Gupta         }
100212f53e8SRatan Gupta     }
101212f53e8SRatan Gupta     else
102212f53e8SRatan Gupta     {
103212f53e8SRatan Gupta         log<level::ERR>("File doesn't exist",
104212f53e8SRatan Gupta                         entry("FILE=%s", fileName.c_str()));
105212f53e8SRatan Gupta     }
106212f53e8SRatan Gupta     // remove the D-Bus Object.
1071dc9178dSRatan Gupta     this->clients.erase(it);
1081dc9178dSRatan Gupta }
1091dc9178dSRatan Gupta 
110212f53e8SRatan Gupta void ConfManager::restoreClients()
111212f53e8SRatan Gupta {
112212f53e8SRatan Gupta     if (!fs::exists(dbusPersistentLocation) ||
113212f53e8SRatan Gupta         fs::is_empty(dbusPersistentLocation))
114212f53e8SRatan Gupta     {
115212f53e8SRatan Gupta         return;
116212f53e8SRatan Gupta     }
117212f53e8SRatan Gupta 
118212f53e8SRatan Gupta     for (auto& confFile :
119212f53e8SRatan Gupta          fs::recursive_directory_iterator(dbusPersistentLocation))
120212f53e8SRatan Gupta     {
121212f53e8SRatan Gupta         if (!fs::is_regular_file(confFile))
122212f53e8SRatan Gupta         {
123212f53e8SRatan Gupta             continue;
124212f53e8SRatan Gupta         }
125212f53e8SRatan Gupta 
126212f53e8SRatan Gupta         auto managerID = confFile.path().filename().string();
127*f3fac222SGunnar Mills         auto pos = managerID.find(SEPARATOR);
128212f53e8SRatan Gupta         auto ipaddress = managerID.substr(0, pos);
129212f53e8SRatan Gupta         auto port_str = managerID.substr(pos + 1);
130212f53e8SRatan Gupta         uint16_t port = stoi(port_str, nullptr);
131212f53e8SRatan Gupta 
132212f53e8SRatan Gupta         fs::path objPath = objectPath;
133212f53e8SRatan Gupta         objPath /= generateId(ipaddress, port);
134212f53e8SRatan Gupta         auto manager =
135212f53e8SRatan Gupta             std::make_unique<Client>(bus, objPath.string().c_str(), *this);
136212f53e8SRatan Gupta         if (deserialize(confFile.path(), *manager))
137212f53e8SRatan Gupta         {
138212f53e8SRatan Gupta             manager->emit_object_added();
139212f53e8SRatan Gupta             this->clients.emplace(ipaddress, std::move(manager));
140212f53e8SRatan Gupta         }
141212f53e8SRatan Gupta     }
142212f53e8SRatan Gupta }
143212f53e8SRatan Gupta 
1441dc9178dSRatan Gupta } // namespace snmp
1451dc9178dSRatan Gupta } // namespace network
1461dc9178dSRatan Gupta } // namespace phosphor
147