11dc9178dSRatan Gupta #include "config.h"
21334b7b3SPatrick Williams
31dc9178dSRatan Gupta #include "snmp_conf_manager.hpp"
41334b7b3SPatrick Williams
5212f53e8SRatan Gupta #include "snmp_serialize.hpp"
6213517baSRatan Gupta #include "snmp_util.hpp"
7213517baSRatan Gupta #include "xyz/openbmc_project/Common/error.hpp"
8213517baSRatan Gupta
91334b7b3SPatrick Williams #include <arpa/inet.h>
101334b7b3SPatrick Williams
11213517baSRatan Gupta #include <phosphor-logging/elog-errors.hpp>
124caedfbbSGeorge Liu #include <phosphor-logging/lg2.hpp>
131dc9178dSRatan Gupta
1434d129a9SRatan Gupta #include <filesystem>
151dc9178dSRatan Gupta
161dc9178dSRatan Gupta namespace phosphor
171dc9178dSRatan Gupta {
181dc9178dSRatan Gupta namespace network
191dc9178dSRatan Gupta {
201dc9178dSRatan Gupta namespace snmp
211dc9178dSRatan Gupta {
221dc9178dSRatan Gupta
231dc9178dSRatan Gupta using namespace phosphor::logging;
24213517baSRatan Gupta using namespace sdbusplus::xyz::openbmc_project::Common::Error;
25213517baSRatan Gupta using Argument = xyz::openbmc_project::Common::InvalidArgument;
261dc9178dSRatan Gupta
ConfManager(sdbusplus::bus_t & bus,const char * objPath)2787d3edd6SPatrick Williams ConfManager::ConfManager(sdbusplus::bus_t& bus, const char* objPath) :
28b9b4c7dbSPatrick Williams details::CreateIface(bus, objPath,
29b9b4c7dbSPatrick Williams details::CreateIface::action::defer_emit),
30212f53e8SRatan Gupta dbusPersistentLocation(SNMP_CONF_PERSIST_PATH), bus(bus),
31212f53e8SRatan Gupta objectPath(objPath)
321334b7b3SPatrick Williams {}
331dc9178dSRatan Gupta
client(std::string address,uint16_t port)34d84e327dSRatan Gupta std::string ConfManager::client(std::string address, uint16_t port)
351dc9178dSRatan Gupta {
369c4fed6dSRatan Gupta // will throw exception if it is already configured.
379c4fed6dSRatan Gupta checkClientConfigured(address, port);
38a7ff3850SRatan Gupta
39213517baSRatan Gupta try
40213517baSRatan Gupta {
41213517baSRatan Gupta // just to check whether given address is valid or not.
42213517baSRatan Gupta resolveAddress(address);
43213517baSRatan Gupta }
44c3600d86SPatrick Williams catch (const InternalFailure& e)
45213517baSRatan Gupta {
464caedfbbSGeorge Liu lg2::error("{ADDRESS} is not a valid address", "ADDRESS", address);
47213517baSRatan Gupta elog<InvalidArgument>(Argument::ARGUMENT_NAME("Address"),
48213517baSRatan Gupta Argument::ARGUMENT_VALUE(address.c_str()));
49213517baSRatan Gupta }
50d84e327dSRatan Gupta
5154d83f5aSGeorge Liu lastClientId++;
52a7ff3850SRatan Gupta // create the D-Bus object
5334d129a9SRatan Gupta std::filesystem::path objPath;
541dc9178dSRatan Gupta objPath /= objectPath;
55a7ff3850SRatan Gupta objPath /= std::to_string(lastClientId);
56a7ff3850SRatan Gupta
57212f53e8SRatan Gupta auto client = std::make_unique<phosphor::network::snmp::Client>(
58212f53e8SRatan Gupta bus, objPath.string().c_str(), *this, address, port);
59212f53e8SRatan Gupta
60a7ff3850SRatan Gupta // save the D-Bus object
61a7ff3850SRatan Gupta serialize(lastClientId, *client, dbusPersistentLocation);
62a7ff3850SRatan Gupta
63a7ff3850SRatan Gupta this->clients.emplace(lastClientId, std::move(client));
64d84e327dSRatan Gupta return objPath.string();
651dc9178dSRatan Gupta }
661dc9178dSRatan Gupta
checkClientConfigured(const std::string & address,uint16_t port)679c4fed6dSRatan Gupta void ConfManager::checkClientConfigured(const std::string& address,
689c4fed6dSRatan Gupta uint16_t port)
699c4fed6dSRatan Gupta {
709c4fed6dSRatan Gupta if (address.empty())
719c4fed6dSRatan Gupta {
724caedfbbSGeorge Liu lg2::error("{ADDRESS} is not a valid address", "ADDRESS", address);
739c4fed6dSRatan Gupta elog<InvalidArgument>(Argument::ARGUMENT_NAME("ADDRESS"),
749c4fed6dSRatan Gupta Argument::ARGUMENT_VALUE(address.c_str()));
759c4fed6dSRatan Gupta }
769c4fed6dSRatan Gupta
779c4fed6dSRatan Gupta for (const auto& val : clients)
789c4fed6dSRatan Gupta {
799c4fed6dSRatan Gupta if (val.second.get()->address() == address &&
809c4fed6dSRatan Gupta val.second.get()->port() == port)
819c4fed6dSRatan Gupta {
824caedfbbSGeorge Liu lg2::error("Client already exist");
839c4fed6dSRatan Gupta // TODO Add the error(Object already exist) in the D-Bus interface
849c4fed6dSRatan Gupta // then make the change here,meanwhile send the Internal Failure.
859c4fed6dSRatan Gupta elog<InvalidArgument>(
869c4fed6dSRatan Gupta Argument::ARGUMENT_NAME("ADDRESS"),
879c4fed6dSRatan Gupta Argument::ARGUMENT_VALUE("Client already exist."));
889c4fed6dSRatan Gupta }
899c4fed6dSRatan Gupta }
909c4fed6dSRatan Gupta }
919c4fed6dSRatan Gupta
deleteSNMPClient(Id id)92a7ff3850SRatan Gupta void ConfManager::deleteSNMPClient(Id id)
931dc9178dSRatan Gupta {
94a7ff3850SRatan Gupta auto it = clients.find(id);
951dc9178dSRatan Gupta if (it == clients.end())
961dc9178dSRatan Gupta {
974caedfbbSGeorge Liu lg2::error("Unable to delete the snmp client: {ID}", "ID", 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 {
1104caedfbbSGeorge Liu lg2::error("Unable to delete {FILE}: {EC}", "FILE", fileName, "EC",
1114caedfbbSGeorge Liu ec.value());
112212f53e8SRatan Gupta }
113212f53e8SRatan Gupta }
114212f53e8SRatan Gupta else
115212f53e8SRatan Gupta {
1164caedfbbSGeorge Liu lg2::error("{FILE} doesn't exist", "FILE", fileName);
117212f53e8SRatan Gupta }
118212f53e8SRatan Gupta // remove the D-Bus Object.
1191dc9178dSRatan Gupta this->clients.erase(it);
1201dc9178dSRatan Gupta }
1211dc9178dSRatan Gupta
restoreClients()122212f53e8SRatan Gupta void ConfManager::restoreClients()
123212f53e8SRatan Gupta {
124212f53e8SRatan Gupta if (!fs::exists(dbusPersistentLocation) ||
125212f53e8SRatan Gupta fs::is_empty(dbusPersistentLocation))
126212f53e8SRatan Gupta {
127212f53e8SRatan Gupta return;
128212f53e8SRatan Gupta }
129212f53e8SRatan Gupta
130212f53e8SRatan Gupta for (auto& confFile :
131212f53e8SRatan Gupta fs::recursive_directory_iterator(dbusPersistentLocation))
132212f53e8SRatan Gupta {
133212f53e8SRatan Gupta if (!fs::is_regular_file(confFile))
134212f53e8SRatan Gupta {
135212f53e8SRatan Gupta continue;
136212f53e8SRatan Gupta }
137212f53e8SRatan Gupta
138212f53e8SRatan Gupta auto managerID = confFile.path().filename().string();
139a7ff3850SRatan Gupta Id idNum = std::stol(managerID);
140212f53e8SRatan Gupta
141212f53e8SRatan Gupta fs::path objPath = objectPath;
142a7ff3850SRatan Gupta objPath /= managerID;
143*9fa30b98SPatrick Williams auto manager =
144*9fa30b98SPatrick Williams std::make_unique<Client>(bus, objPath.string().c_str(), *this);
145212f53e8SRatan Gupta if (deserialize(confFile.path(), *manager))
146212f53e8SRatan Gupta {
147212f53e8SRatan Gupta manager->emit_object_added();
148a7ff3850SRatan Gupta this->clients.emplace(idNum, std::move(manager));
149a7ff3850SRatan Gupta if (idNum > lastClientId)
150a7ff3850SRatan Gupta {
151a7ff3850SRatan Gupta lastClientId = idNum;
152a7ff3850SRatan Gupta }
153212f53e8SRatan Gupta }
154212f53e8SRatan Gupta }
155212f53e8SRatan Gupta }
156212f53e8SRatan Gupta
1571dc9178dSRatan Gupta } // namespace snmp
1581dc9178dSRatan Gupta } // namespace network
1591dc9178dSRatan Gupta } // namespace phosphor
160