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 
32d84e327dSRatan Gupta std::string ConfManager::client(std::string address, uint16_t port)
331dc9178dSRatan Gupta {
34*9c4fed6dSRatan Gupta     // will throw exception if it is already configured.
35*9c4fed6dSRatan Gupta     checkClientConfigured(address, port);
36a7ff3850SRatan Gupta 
37a7ff3850SRatan Gupta     lastClientId++;
38213517baSRatan Gupta     try
39213517baSRatan Gupta     {
40213517baSRatan Gupta         // just to check whether given address is valid or not.
41213517baSRatan Gupta         resolveAddress(address);
42213517baSRatan Gupta     }
43213517baSRatan Gupta     catch (InternalFailure& e)
44213517baSRatan Gupta     {
45213517baSRatan Gupta         log<level::ERR>("Not a valid address"),
46213517baSRatan Gupta             entry("ADDRESS=%s", address.c_str());
47213517baSRatan Gupta         elog<InvalidArgument>(Argument::ARGUMENT_NAME("Address"),
48213517baSRatan Gupta                               Argument::ARGUMENT_VALUE(address.c_str()));
49213517baSRatan Gupta     }
50d84e327dSRatan Gupta 
51a7ff3850SRatan Gupta     // create the D-Bus object
521dc9178dSRatan Gupta     std::experimental::filesystem::path objPath;
531dc9178dSRatan Gupta     objPath /= objectPath;
54a7ff3850SRatan Gupta     objPath /= std::to_string(lastClientId);
55a7ff3850SRatan Gupta 
56212f53e8SRatan Gupta     auto client = std::make_unique<phosphor::network::snmp::Client>(
57212f53e8SRatan Gupta         bus, objPath.string().c_str(), *this, address, port);
58212f53e8SRatan Gupta 
59a7ff3850SRatan Gupta     // save the D-Bus object
60a7ff3850SRatan Gupta     serialize(lastClientId, *client, dbusPersistentLocation);
61a7ff3850SRatan Gupta 
62a7ff3850SRatan Gupta     this->clients.emplace(lastClientId, std::move(client));
63d84e327dSRatan Gupta     return objPath.string();
641dc9178dSRatan Gupta }
651dc9178dSRatan Gupta 
66*9c4fed6dSRatan Gupta void ConfManager::checkClientConfigured(const std::string& address,
67*9c4fed6dSRatan Gupta                                         uint16_t port)
68*9c4fed6dSRatan Gupta {
69*9c4fed6dSRatan Gupta     if (address.empty())
70*9c4fed6dSRatan Gupta     {
71*9c4fed6dSRatan Gupta         log<level::ERR>("Invalid address");
72*9c4fed6dSRatan Gupta         elog<InvalidArgument>(Argument::ARGUMENT_NAME("ADDRESS"),
73*9c4fed6dSRatan Gupta                               Argument::ARGUMENT_VALUE(address.c_str()));
74*9c4fed6dSRatan Gupta     }
75*9c4fed6dSRatan Gupta 
76*9c4fed6dSRatan Gupta     for (const auto& val : clients)
77*9c4fed6dSRatan Gupta     {
78*9c4fed6dSRatan Gupta         if (val.second.get()->address() == address &&
79*9c4fed6dSRatan Gupta             val.second.get()->port() == port)
80*9c4fed6dSRatan Gupta         {
81*9c4fed6dSRatan Gupta             log<level::ERR>("Client already exist");
82*9c4fed6dSRatan Gupta             // TODO Add the error(Object already exist) in the D-Bus interface
83*9c4fed6dSRatan Gupta             // then make the change here,meanwhile send the Internal Failure.
84*9c4fed6dSRatan Gupta             elog<InvalidArgument>(
85*9c4fed6dSRatan Gupta                 Argument::ARGUMENT_NAME("ADDRESS"),
86*9c4fed6dSRatan Gupta                 Argument::ARGUMENT_VALUE("Client already exist."));
87*9c4fed6dSRatan Gupta         }
88*9c4fed6dSRatan Gupta     }
89*9c4fed6dSRatan Gupta }
90*9c4fed6dSRatan Gupta 
91a7ff3850SRatan Gupta void ConfManager::deleteSNMPClient(Id id)
921dc9178dSRatan Gupta {
93a7ff3850SRatan Gupta     auto it = clients.find(id);
941dc9178dSRatan Gupta     if (it == clients.end())
951dc9178dSRatan Gupta     {
961dc9178dSRatan Gupta         log<level::ERR>("Unable to delete the snmp client.",
97a7ff3850SRatan Gupta                         entry("ID=%d", id));
981dc9178dSRatan Gupta         return;
991dc9178dSRatan Gupta     }
100212f53e8SRatan Gupta 
101212f53e8SRatan Gupta     std::error_code ec;
102212f53e8SRatan Gupta     // remove the persistent file
103212f53e8SRatan Gupta     fs::path fileName = dbusPersistentLocation;
104a7ff3850SRatan Gupta     fileName /= std::to_string(id);
105212f53e8SRatan Gupta 
106212f53e8SRatan Gupta     if (fs::exists(fileName))
107212f53e8SRatan Gupta     {
108212f53e8SRatan Gupta         if (!fs::remove(fileName, ec))
109212f53e8SRatan Gupta         {
110212f53e8SRatan Gupta             log<level::ERR>("Unable to delete the file",
111212f53e8SRatan Gupta                             entry("FILE=%s", fileName.c_str()),
112212f53e8SRatan Gupta                             entry("ERROR=%d", ec.value()));
113212f53e8SRatan Gupta         }
114212f53e8SRatan Gupta     }
115212f53e8SRatan Gupta     else
116212f53e8SRatan Gupta     {
117212f53e8SRatan Gupta         log<level::ERR>("File doesn't exist",
118212f53e8SRatan Gupta                         entry("FILE=%s", fileName.c_str()));
119212f53e8SRatan Gupta     }
120212f53e8SRatan Gupta     // remove the D-Bus Object.
1211dc9178dSRatan Gupta     this->clients.erase(it);
1221dc9178dSRatan Gupta }
1231dc9178dSRatan Gupta 
124212f53e8SRatan Gupta void ConfManager::restoreClients()
125212f53e8SRatan Gupta {
126212f53e8SRatan Gupta     if (!fs::exists(dbusPersistentLocation) ||
127212f53e8SRatan Gupta         fs::is_empty(dbusPersistentLocation))
128212f53e8SRatan Gupta     {
129212f53e8SRatan Gupta         return;
130212f53e8SRatan Gupta     }
131212f53e8SRatan Gupta 
132212f53e8SRatan Gupta     for (auto& confFile :
133212f53e8SRatan Gupta          fs::recursive_directory_iterator(dbusPersistentLocation))
134212f53e8SRatan Gupta     {
135212f53e8SRatan Gupta         if (!fs::is_regular_file(confFile))
136212f53e8SRatan Gupta         {
137212f53e8SRatan Gupta             continue;
138212f53e8SRatan Gupta         }
139212f53e8SRatan Gupta 
140212f53e8SRatan Gupta         auto managerID = confFile.path().filename().string();
141a7ff3850SRatan Gupta         Id idNum = std::stol(managerID);
142212f53e8SRatan Gupta 
143212f53e8SRatan Gupta         fs::path objPath = objectPath;
144a7ff3850SRatan Gupta         objPath /= managerID;
145212f53e8SRatan Gupta         auto manager =
146212f53e8SRatan Gupta             std::make_unique<Client>(bus, objPath.string().c_str(), *this);
147212f53e8SRatan Gupta         if (deserialize(confFile.path(), *manager))
148212f53e8SRatan Gupta         {
149212f53e8SRatan Gupta             manager->emit_object_added();
150a7ff3850SRatan Gupta             this->clients.emplace(idNum, std::move(manager));
151a7ff3850SRatan Gupta             if (idNum > lastClientId)
152a7ff3850SRatan Gupta             {
153a7ff3850SRatan Gupta                 lastClientId = idNum;
154a7ff3850SRatan Gupta             }
155212f53e8SRatan Gupta         }
156212f53e8SRatan Gupta     }
157212f53e8SRatan Gupta }
158212f53e8SRatan Gupta 
1591dc9178dSRatan Gupta } // namespace snmp
1601dc9178dSRatan Gupta } // namespace network
1611dc9178dSRatan Gupta } // namespace phosphor
162