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