xref: /openbmc/bmcweb/redfish-core/include/snmp_trap_event_clients.hpp (revision deae6a789444debc4724fb6902fc5def299afbee)
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     dbus::utility::getAllProperties(
74         "xyz.openbmc_project.Network.SNMP", objectPath,
75         "xyz.openbmc_project.Network.Client",
76         [asyncResp](const boost::system::error_code& ec,
77                     const dbus::utility::DBusPropertiesMap& properties) {
78             afterGetSnmpTrapClientdata(asyncResp, ec, properties);
79         });
80 }
81 
getSnmpTrapClient(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & id)82 inline void getSnmpTrapClient(
83     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
84 {
85     crow::connections::systemBus->async_method_call(
86         [asyncResp, id](const boost::system::error_code& ec,
87                         dbus::utility::ManagedObjectType& resp) {
88             if (ec)
89             {
90                 BMCWEB_LOG_ERROR("D-Bus response error on GetManagedObjects {}",
91                                  ec);
92                 messages::internalError(asyncResp->res);
93                 return;
94             }
95 
96             for (const auto& objpath : resp)
97             {
98                 sdbusplus::message::object_path path(objpath.first);
99                 const std::string snmpId = path.filename();
100                 if (snmpId.empty())
101                 {
102                     BMCWEB_LOG_ERROR("The SNMP client ID is wrong");
103                     messages::internalError(asyncResp->res);
104                     return;
105                 }
106                 const std::string subscriptionId = "snmp" + snmpId;
107                 if (id != subscriptionId)
108                 {
109                     continue;
110                 }
111 
112                 getSnmpTrapClientdata(asyncResp, id, objpath.first);
113                 return;
114             }
115 
116             messages::resourceNotFound(asyncResp->res, "Subscriptions", id);
117             EventServiceManager::getInstance().deleteSubscription(id);
118         },
119         "xyz.openbmc_project.Network.SNMP",
120         "/xyz/openbmc_project/network/snmp/manager",
121         "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
122 }
123 
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)124 inline void afterSnmpClientCreate(
125     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
126     const boost::system::error_code& ec, const sdbusplus::message_t& msg,
127     const std::string& host, const std::string& dbusSNMPid)
128 {
129     if (ec)
130     {
131         const sd_bus_error* dbusError = msg.get_error();
132         if (dbusError != nullptr)
133         {
134             if (std::string_view(
135                     "xyz.openbmc_project.Common.Error.InvalidArgument") ==
136                 dbusError->name)
137             {
138                 messages::propertyValueIncorrect(asyncResp->res, "Destination",
139                                                  host);
140                 return;
141             }
142             if (ec.value() != EBADR)
143             {
144                 // SNMP not installed
145                 messages::propertyValueOutOfRange(asyncResp->res, "SNMPv2c",
146                                                   "Protocol");
147                 return;
148             }
149         }
150         messages::internalError(asyncResp->res);
151         return;
152     }
153     sdbusplus::message::object_path path(dbusSNMPid);
154     const std::string snmpId = path.filename();
155     if (snmpId.empty())
156     {
157         messages::internalError(asyncResp->res);
158         return;
159     }
160 
161     std::string subscriptionId = "snmp" + snmpId;
162 
163     boost::urls::url uri = boost::urls::format(
164         "/redfish/v1/EventService/Subscriptions/{}", subscriptionId);
165     asyncResp->res.addHeader("Location", uri.buffer());
166     messages::created(asyncResp->res);
167 }
168 
169 inline void
addSnmpTrapClient(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & host,uint16_t snmpTrapPort)170     addSnmpTrapClient(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
171                       const std::string& host, uint16_t snmpTrapPort)
172 {
173     crow::connections::systemBus->async_method_call(
174         [asyncResp,
175          host](const boost::system::error_code& ec,
176                const sdbusplus::message_t& msg, const std::string& dbusSNMPid) {
177             afterSnmpClientCreate(asyncResp, ec, msg, host, dbusSNMPid);
178         },
179         "xyz.openbmc_project.Network.SNMP",
180         "/xyz/openbmc_project/network/snmp/manager",
181         "xyz.openbmc_project.Network.Client.Create", "Client", host,
182         snmpTrapPort);
183 }
184 
getSnmpSubscriptionList(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & snmpId,nlohmann::json & memberArray)185 inline void getSnmpSubscriptionList(
186     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
187     const std::string& snmpId, nlohmann::json& memberArray)
188 {
189     const std::string subscriptionId = "snmp" + snmpId;
190 
191     nlohmann::json::object_t member;
192     member["@odata.id"] = boost::urls::format(
193         "/redfish/v1/EventService/Subscriptions/{}", subscriptionId);
194     memberArray.push_back(std::move(member));
195 
196     asyncResp->res.jsonValue["Members@odata.count"] = memberArray.size();
197 }
198 
199 inline void
deleteSnmpTrapClient(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & param)200     deleteSnmpTrapClient(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
201                          const std::string& param)
202 {
203     std::string_view snmpTrapId = param;
204 
205     // Erase "snmp" in the request to find the corresponding
206     // dbus snmp client id. For example, the snmpid in the
207     // request is "snmp1", which will be "1" after being erased.
208     snmpTrapId.remove_prefix(4);
209 
210     sdbusplus::message::object_path snmpPath =
211         sdbusplus::message::object_path(
212             "/xyz/openbmc_project/network/snmp/manager") /
213         std::string(snmpTrapId);
214 
215     crow::connections::systemBus->async_method_call(
216         [asyncResp, param](const boost::system::error_code& ec) {
217             if (ec)
218             {
219                 // The snmp trap id is incorrect
220                 if (ec.value() == EBADR)
221                 {
222                     messages::resourceNotFound(asyncResp->res, "Subscription",
223                                                param);
224                     return;
225                 }
226                 messages::internalError(asyncResp->res);
227                 return;
228             }
229             messages::success(asyncResp->res);
230         },
231         "xyz.openbmc_project.Network.SNMP", static_cast<std::string>(snmpPath),
232         "xyz.openbmc_project.Object.Delete", "Delete");
233 }
234 
235 } // namespace redfish
236