1 #pragma once
2
3 #include "async_resp.hpp"
4 #include "dbus_singleton.hpp"
5 #include "dbus_utility.hpp"
6 #include "error_messages.hpp"
7 #include "event_service_manager.hpp"
8 #include "generated/enums/event_destination.hpp"
9 #include "http_request.hpp"
10 #include "http_response.hpp"
11 #include "logging.hpp"
12 #include "utils/dbus_utils.hpp"
13
14 #include <boost/system/error_code.hpp>
15 #include <boost/url/format.hpp>
16 #include <sdbusplus/unpack_properties.hpp>
17
18 #include <memory>
19 #include <string>
20 #include <string_view>
21
22 namespace redfish
23 {
24
afterGetSnmpTrapClientdata(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const boost::system::error_code & ec,const dbus::utility::DBusPropertiesMap & propertiesList)25 inline void afterGetSnmpTrapClientdata(
26 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
27 const boost::system::error_code& ec,
28 const dbus::utility::DBusPropertiesMap& propertiesList)
29 {
30 if (ec)
31 {
32 BMCWEB_LOG_ERROR("D-Bus response error on GetSubTree {}", ec);
33 messages::internalError(asyncResp->res);
34 return;
35 }
36
37 std::string address;
38 uint16_t port = 0;
39
40 bool success = sdbusplus::unpackPropertiesNoThrow(
41 dbus_utils::UnpackErrorPrinter(), propertiesList, "Address", address,
42 "Port", port);
43
44 if (!success)
45 {
46 messages::internalError(asyncResp->res);
47 return;
48 }
49
50 asyncResp->res.jsonValue["Destination"] =
51 boost::urls::format("snmp://{}:{}", address, port);
52 }
53
54 inline void
getSnmpTrapClientdata(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & id,const std::string & objectPath)55 getSnmpTrapClientdata(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
56 const std::string& id, const std::string& objectPath)
57 {
58 asyncResp->res.jsonValue["@odata.type"] =
59 "#EventDestination.v1_8_0.EventDestination";
60 asyncResp->res.jsonValue["Protocol"] =
61 event_destination::EventDestinationProtocol::SNMPv2c;
62 asyncResp->res.jsonValue["@odata.id"] =
63 boost::urls::format("/redfish/v1/EventService/Subscriptions/{}", id);
64
65 asyncResp->res.jsonValue["Id"] = id;
66 asyncResp->res.jsonValue["Name"] = "Event Destination";
67
68 asyncResp->res.jsonValue["SubscriptionType"] =
69 event_destination::SubscriptionType::SNMPTrap;
70 asyncResp->res.jsonValue["EventFormatType"] =
71 event_destination::EventFormatType::Event;
72
73 std::shared_ptr<Subscription> subValue =
74 EventServiceManager::getInstance().getSubscription(id);
75 if (subValue != nullptr)
76 {
77 asyncResp->res.jsonValue["Context"] = subValue->customText;
78 }
79 else
80 {
81 asyncResp->res.jsonValue["Context"] = "";
82 }
83
84 sdbusplus::asio::getAllProperties(
85 *crow::connections::systemBus, "xyz.openbmc_project.Network.SNMP",
86 objectPath, "xyz.openbmc_project.Network.Client",
87 [asyncResp](const boost::system::error_code& ec,
88 const dbus::utility::DBusPropertiesMap& properties) {
89 afterGetSnmpTrapClientdata(asyncResp, ec, properties);
90 });
91 }
92
getSnmpTrapClient(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & id)93 inline void getSnmpTrapClient(
94 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
95 {
96 crow::connections::systemBus->async_method_call(
97 [asyncResp, id](const boost::system::error_code& ec,
98 dbus::utility::ManagedObjectType& resp) {
99 if (ec)
100 {
101 BMCWEB_LOG_ERROR("D-Bus response error on GetManagedObjects {}",
102 ec);
103 messages::internalError(asyncResp->res);
104 return;
105 }
106
107 for (const auto& objpath : resp)
108 {
109 sdbusplus::message::object_path path(objpath.first);
110 const std::string snmpId = path.filename();
111 if (snmpId.empty())
112 {
113 BMCWEB_LOG_ERROR("The SNMP client ID is wrong");
114 messages::internalError(asyncResp->res);
115 return;
116 }
117 const std::string subscriptionId = "snmp" + snmpId;
118 if (id != subscriptionId)
119 {
120 continue;
121 }
122
123 getSnmpTrapClientdata(asyncResp, id, objpath.first);
124 return;
125 }
126
127 messages::resourceNotFound(asyncResp->res, "Subscriptions", id);
128 EventServiceManager::getInstance().deleteSubscription(id);
129 },
130 "xyz.openbmc_project.Network.SNMP",
131 "/xyz/openbmc_project/network/snmp/manager",
132 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
133 }
134
afterSnmpClientCreate(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const boost::system::error_code & ec,const sdbusplus::message_t & msg,const std::string & host,const std::string & dbusSNMPid)135 inline void afterSnmpClientCreate(
136 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
137 const boost::system::error_code& ec, const sdbusplus::message_t& msg,
138 const std::string& host, const std::string& dbusSNMPid)
139 {
140 if (ec)
141 {
142 const sd_bus_error* dbusError = msg.get_error();
143 if (dbusError != nullptr)
144 {
145 if (std::string_view(
146 "xyz.openbmc_project.Common.Error.InvalidArgument") ==
147 dbusError->name)
148 {
149 messages::propertyValueIncorrect(asyncResp->res, "Destination",
150 host);
151 return;
152 }
153 if (ec.value() != EBADR)
154 {
155 // SNMP not installed
156 messages::propertyValueOutOfRange(asyncResp->res, "SNMPv2c",
157 "Protocol");
158 return;
159 }
160 }
161 messages::internalError(asyncResp->res);
162 return;
163 }
164 sdbusplus::message::object_path path(dbusSNMPid);
165 const std::string snmpId = path.filename();
166 if (snmpId.empty())
167 {
168 messages::internalError(asyncResp->res);
169 return;
170 }
171
172 std::string subscriptionId = "snmp" + snmpId;
173
174 boost::urls::url uri = boost::urls::format(
175 "/redfish/v1/EventService/Subscriptions/{}", subscriptionId);
176 asyncResp->res.addHeader("Location", uri.buffer());
177 messages::created(asyncResp->res);
178 }
179
180 inline void
addSnmpTrapClient(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & host,uint16_t snmpTrapPort)181 addSnmpTrapClient(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
182 const std::string& host, uint16_t snmpTrapPort)
183 {
184 crow::connections::systemBus->async_method_call(
185 [asyncResp,
186 host](const boost::system::error_code& ec,
187 const sdbusplus::message_t& msg, const std::string& dbusSNMPid) {
188 afterSnmpClientCreate(asyncResp, ec, msg, host, dbusSNMPid);
189 },
190 "xyz.openbmc_project.Network.SNMP",
191 "/xyz/openbmc_project/network/snmp/manager",
192 "xyz.openbmc_project.Network.Client.Create", "Client", host,
193 snmpTrapPort);
194 }
195
getSnmpSubscriptionList(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & snmpId,nlohmann::json & memberArray)196 inline void getSnmpSubscriptionList(
197 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
198 const std::string& snmpId, nlohmann::json& memberArray)
199 {
200 const std::string subscriptionId = "snmp" + snmpId;
201
202 nlohmann::json::object_t member;
203 member["@odata.id"] = boost::urls::format(
204 "/redfish/v1/EventService/Subscriptions/{}", subscriptionId);
205 memberArray.push_back(std::move(member));
206
207 asyncResp->res.jsonValue["Members@odata.count"] = memberArray.size();
208 }
209
210 inline void
deleteSnmpTrapClient(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & param)211 deleteSnmpTrapClient(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
212 const std::string& param)
213 {
214 std::string_view snmpTrapId = param;
215
216 // Erase "snmp" in the request to find the corresponding
217 // dbus snmp client id. For example, the snmpid in the
218 // request is "snmp1", which will be "1" after being erased.
219 snmpTrapId.remove_prefix(4);
220
221 sdbusplus::message::object_path snmpPath =
222 sdbusplus::message::object_path(
223 "/xyz/openbmc_project/network/snmp/manager") /
224 std::string(snmpTrapId);
225
226 crow::connections::systemBus->async_method_call(
227 [asyncResp, param](const boost::system::error_code& ec) {
228 if (ec)
229 {
230 // The snmp trap id is incorrect
231 if (ec.value() == EBADR)
232 {
233 messages::resourceNotFound(asyncResp->res, "Subscription",
234 param);
235 return;
236 }
237 messages::internalError(asyncResp->res);
238 return;
239 }
240 messages::success(asyncResp->res);
241 },
242 "xyz.openbmc_project.Network.SNMP", static_cast<std::string>(snmpPath),
243 "xyz.openbmc_project.Object.Delete", "Delete");
244 }
245
246 } // namespace redfish
247