xref: /openbmc/bmcweb/features/redfish/include/snmp_trap_event_clients.hpp (revision 127afa70bfa236b2949f5c385704e00de99557e4)
140e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0
240e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors
33d30708fSChicago Duan #pragma once
43d30708fSChicago Duan 
53d30708fSChicago Duan #include "async_resp.hpp"
63d30708fSChicago Duan #include "dbus_utility.hpp"
73d30708fSChicago Duan #include "error_messages.hpp"
83d30708fSChicago Duan #include "event_service_manager.hpp"
9539d8c6bSEd Tanous #include "generated/enums/event_destination.hpp"
103d30708fSChicago Duan #include "http_response.hpp"
113d30708fSChicago Duan #include "logging.hpp"
123d30708fSChicago Duan #include "utils/dbus_utils.hpp"
133d30708fSChicago Duan 
14d7857201SEd Tanous #include <asm-generic/errno.h>
15d7857201SEd Tanous #include <systemd/sd-bus.h>
16d7857201SEd Tanous 
173d30708fSChicago Duan #include <boost/system/error_code.hpp>
183d30708fSChicago Duan #include <boost/url/format.hpp>
19d7857201SEd Tanous #include <boost/url/url.hpp>
20d7857201SEd Tanous #include <sdbusplus/message.hpp>
21d7857201SEd Tanous #include <sdbusplus/message/native_types.hpp>
223d30708fSChicago Duan #include <sdbusplus/unpack_properties.hpp>
233d30708fSChicago Duan 
24d7857201SEd Tanous #include <cstdint>
253d30708fSChicago Duan #include <memory>
263d30708fSChicago Duan #include <string>
273d30708fSChicago Duan #include <string_view>
28d7857201SEd Tanous #include <utility>
293d30708fSChicago Duan 
303d30708fSChicago Duan namespace redfish
313d30708fSChicago Duan {
323d30708fSChicago Duan 
333d30708fSChicago Duan inline void afterGetSnmpTrapClientdata(
343d30708fSChicago Duan     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
353d30708fSChicago Duan     const boost::system::error_code& ec,
363d30708fSChicago Duan     const dbus::utility::DBusPropertiesMap& propertiesList)
373d30708fSChicago Duan {
383d30708fSChicago Duan     if (ec)
393d30708fSChicago Duan     {
4062598e31SEd Tanous         BMCWEB_LOG_ERROR("D-Bus response error on GetSubTree {}", ec);
413d30708fSChicago Duan         messages::internalError(asyncResp->res);
423d30708fSChicago Duan         return;
433d30708fSChicago Duan     }
443d30708fSChicago Duan 
453d30708fSChicago Duan     std::string address;
463d30708fSChicago Duan     uint16_t port = 0;
473d30708fSChicago Duan 
483d30708fSChicago Duan     bool success = sdbusplus::unpackPropertiesNoThrow(
493d30708fSChicago Duan         dbus_utils::UnpackErrorPrinter(), propertiesList, "Address", address,
503d30708fSChicago Duan         "Port", port);
513d30708fSChicago Duan 
523d30708fSChicago Duan     if (!success)
533d30708fSChicago Duan     {
543d30708fSChicago Duan         messages::internalError(asyncResp->res);
553d30708fSChicago Duan         return;
563d30708fSChicago Duan     }
573d30708fSChicago Duan 
583d30708fSChicago Duan     asyncResp->res.jsonValue["Destination"] =
593d30708fSChicago Duan         boost::urls::format("snmp://{}:{}", address, port);
603d30708fSChicago Duan }
613d30708fSChicago Duan 
62504af5a0SPatrick Williams inline void getSnmpTrapClientdata(
63504af5a0SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id,
64504af5a0SPatrick Williams     const std::string& objectPath)
653d30708fSChicago Duan {
663d30708fSChicago Duan     asyncResp->res.jsonValue["@odata.type"] =
673d30708fSChicago Duan         "#EventDestination.v1_8_0.EventDestination";
68539d8c6bSEd Tanous     asyncResp->res.jsonValue["Protocol"] =
69539d8c6bSEd Tanous         event_destination::EventDestinationProtocol::SNMPv2c;
703d30708fSChicago Duan     asyncResp->res.jsonValue["@odata.id"] =
713d30708fSChicago Duan         boost::urls::format("/redfish/v1/EventService/Subscriptions/{}", id);
723d30708fSChicago Duan 
733d30708fSChicago Duan     asyncResp->res.jsonValue["Id"] = id;
743d30708fSChicago Duan     asyncResp->res.jsonValue["Name"] = "Event Destination";
753d30708fSChicago Duan 
76539d8c6bSEd Tanous     asyncResp->res.jsonValue["SubscriptionType"] =
77539d8c6bSEd Tanous         event_destination::SubscriptionType::SNMPTrap;
78539d8c6bSEd Tanous     asyncResp->res.jsonValue["EventFormatType"] =
79539d8c6bSEd Tanous         event_destination::EventFormatType::Event;
803d30708fSChicago Duan 
81*127afa70SJanet Adkins     /* Context is required Redfish field,
82*127afa70SJanet Adkins      * but SNMP backend doesn't support a context string.
83*127afa70SJanet Adkins      */
84*127afa70SJanet Adkins     asyncResp->res.jsonValue["Context"] = "";
85*127afa70SJanet Adkins 
86deae6a78SEd Tanous     dbus::utility::getAllProperties(
87deae6a78SEd Tanous         "xyz.openbmc_project.Network.SNMP", objectPath,
88deae6a78SEd Tanous         "xyz.openbmc_project.Network.Client",
893d30708fSChicago Duan         [asyncResp](const boost::system::error_code& ec,
903d30708fSChicago Duan                     const dbus::utility::DBusPropertiesMap& properties) {
913d30708fSChicago Duan             afterGetSnmpTrapClientdata(asyncResp, ec, properties);
923d30708fSChicago Duan         });
933d30708fSChicago Duan }
943d30708fSChicago Duan 
95bd79bce8SPatrick Williams inline void getSnmpTrapClient(
96bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
973d30708fSChicago Duan {
98177612aaSEd Tanous     dbus::utility::async_method_call(
99177612aaSEd Tanous         asyncResp,
1003d30708fSChicago Duan         [asyncResp, id](const boost::system::error_code& ec,
1013d30708fSChicago Duan                         dbus::utility::ManagedObjectType& resp) {
1023d30708fSChicago Duan             if (ec)
1033d30708fSChicago Duan             {
10462598e31SEd Tanous                 BMCWEB_LOG_ERROR("D-Bus response error on GetManagedObjects {}",
10562598e31SEd Tanous                                  ec);
1063d30708fSChicago Duan                 messages::internalError(asyncResp->res);
1073d30708fSChicago Duan                 return;
1083d30708fSChicago Duan             }
1093d30708fSChicago Duan 
1103d30708fSChicago Duan             for (const auto& objpath : resp)
1113d30708fSChicago Duan             {
1123d30708fSChicago Duan                 sdbusplus::message::object_path path(objpath.first);
1133d30708fSChicago Duan                 const std::string snmpId = path.filename();
1143d30708fSChicago Duan                 if (snmpId.empty())
1153d30708fSChicago Duan                 {
11662598e31SEd Tanous                     BMCWEB_LOG_ERROR("The SNMP client ID is wrong");
1173d30708fSChicago Duan                     messages::internalError(asyncResp->res);
1183d30708fSChicago Duan                     return;
1193d30708fSChicago Duan                 }
1203d30708fSChicago Duan                 const std::string subscriptionId = "snmp" + snmpId;
1213d30708fSChicago Duan                 if (id != subscriptionId)
1223d30708fSChicago Duan                 {
1233d30708fSChicago Duan                     continue;
1243d30708fSChicago Duan                 }
1253d30708fSChicago Duan 
1263d30708fSChicago Duan                 getSnmpTrapClientdata(asyncResp, id, objpath.first);
1273d30708fSChicago Duan                 return;
1283d30708fSChicago Duan             }
1293d30708fSChicago Duan 
1303d30708fSChicago Duan             messages::resourceNotFound(asyncResp->res, "Subscriptions", id);
1313d30708fSChicago Duan             EventServiceManager::getInstance().deleteSubscription(id);
1323d30708fSChicago Duan         },
1333d30708fSChicago Duan         "xyz.openbmc_project.Network.SNMP",
1343d30708fSChicago Duan         "/xyz/openbmc_project/network/snmp/manager",
1353d30708fSChicago Duan         "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
1363d30708fSChicago Duan }
1373d30708fSChicago Duan 
13863509dd5SRavi Teja inline void afterSnmpClientCreate(
13963509dd5SRavi Teja     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
14063509dd5SRavi Teja     const boost::system::error_code& ec, const sdbusplus::message_t& msg,
14163509dd5SRavi Teja     const std::string& host, const std::string& dbusSNMPid)
1423d30708fSChicago Duan {
1433d30708fSChicago Duan     if (ec)
1443d30708fSChicago Duan     {
14563509dd5SRavi Teja         const sd_bus_error* dbusError = msg.get_error();
14663509dd5SRavi Teja         if (dbusError != nullptr)
14763509dd5SRavi Teja         {
14863509dd5SRavi Teja             if (std::string_view(
14963509dd5SRavi Teja                     "xyz.openbmc_project.Common.Error.InvalidArgument") ==
15063509dd5SRavi Teja                 dbusError->name)
15163509dd5SRavi Teja             {
15263509dd5SRavi Teja                 messages::propertyValueIncorrect(asyncResp->res, "Destination",
15363509dd5SRavi Teja                                                  host);
15463509dd5SRavi Teja                 return;
15563509dd5SRavi Teja             }
1563d30708fSChicago Duan             if (ec.value() != EBADR)
1573d30708fSChicago Duan             {
1583d30708fSChicago Duan                 // SNMP not installed
1593d30708fSChicago Duan                 messages::propertyValueOutOfRange(asyncResp->res, "SNMPv2c",
1603d30708fSChicago Duan                                                   "Protocol");
1613d30708fSChicago Duan                 return;
1623d30708fSChicago Duan             }
16363509dd5SRavi Teja         }
1643d30708fSChicago Duan         messages::internalError(asyncResp->res);
1653d30708fSChicago Duan         return;
1663d30708fSChicago Duan     }
1673d30708fSChicago Duan     sdbusplus::message::object_path path(dbusSNMPid);
1683d30708fSChicago Duan     const std::string snmpId = path.filename();
1693d30708fSChicago Duan     if (snmpId.empty())
1703d30708fSChicago Duan     {
1713d30708fSChicago Duan         messages::internalError(asyncResp->res);
1723d30708fSChicago Duan         return;
1733d30708fSChicago Duan     }
1743d30708fSChicago Duan 
1753d30708fSChicago Duan     std::string subscriptionId = "snmp" + snmpId;
1763d30708fSChicago Duan 
1773d30708fSChicago Duan     boost::urls::url uri = boost::urls::format(
1783d30708fSChicago Duan         "/redfish/v1/EventService/Subscriptions/{}", subscriptionId);
1793d30708fSChicago Duan     asyncResp->res.addHeader("Location", uri.buffer());
1803d30708fSChicago Duan     messages::created(asyncResp->res);
1813d30708fSChicago Duan }
1823d30708fSChicago Duan 
183504af5a0SPatrick Williams inline void addSnmpTrapClient(
184504af5a0SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1853d30708fSChicago Duan     const std::string& host, uint16_t snmpTrapPort)
1863d30708fSChicago Duan {
187177612aaSEd Tanous     dbus::utility::async_method_call(
188177612aaSEd Tanous         asyncResp,
189bd79bce8SPatrick Williams         [asyncResp,
190bd79bce8SPatrick Williams          host](const boost::system::error_code& ec,
191bd79bce8SPatrick Williams                const sdbusplus::message_t& msg, const std::string& dbusSNMPid) {
19263509dd5SRavi Teja             afterSnmpClientCreate(asyncResp, ec, msg, host, dbusSNMPid);
1933d30708fSChicago Duan         },
1943d30708fSChicago Duan         "xyz.openbmc_project.Network.SNMP",
1953d30708fSChicago Duan         "/xyz/openbmc_project/network/snmp/manager",
1963d30708fSChicago Duan         "xyz.openbmc_project.Network.Client.Create", "Client", host,
1973d30708fSChicago Duan         snmpTrapPort);
1983d30708fSChicago Duan }
1993d30708fSChicago Duan 
200bd79bce8SPatrick Williams inline void getSnmpSubscriptionList(
201bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
202bd79bce8SPatrick Williams     const std::string& snmpId, nlohmann::json& memberArray)
2033d30708fSChicago Duan {
2043d30708fSChicago Duan     const std::string subscriptionId = "snmp" + snmpId;
2053d30708fSChicago Duan 
2063d30708fSChicago Duan     nlohmann::json::object_t member;
2073d30708fSChicago Duan     member["@odata.id"] = boost::urls::format(
2083d30708fSChicago Duan         "/redfish/v1/EventService/Subscriptions/{}", subscriptionId);
2093d30708fSChicago Duan     memberArray.push_back(std::move(member));
2103d30708fSChicago Duan 
2113d30708fSChicago Duan     asyncResp->res.jsonValue["Members@odata.count"] = memberArray.size();
2123d30708fSChicago Duan }
2133d30708fSChicago Duan 
214504af5a0SPatrick Williams inline void deleteSnmpTrapClient(
215504af5a0SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2163d30708fSChicago Duan     const std::string& param)
2173d30708fSChicago Duan {
2183d30708fSChicago Duan     std::string_view snmpTrapId = param;
2193d30708fSChicago Duan 
2203d30708fSChicago Duan     // Erase "snmp" in the request to find the corresponding
2213d30708fSChicago Duan     // dbus snmp client id. For example, the snmpid in the
2223d30708fSChicago Duan     // request is "snmp1", which will be "1" after being erased.
2233d30708fSChicago Duan     snmpTrapId.remove_prefix(4);
2243d30708fSChicago Duan 
2253d30708fSChicago Duan     sdbusplus::message::object_path snmpPath =
2263d30708fSChicago Duan         sdbusplus::message::object_path(
2273d30708fSChicago Duan             "/xyz/openbmc_project/network/snmp/manager") /
2283d30708fSChicago Duan         std::string(snmpTrapId);
2293d30708fSChicago Duan 
230177612aaSEd Tanous     dbus::utility::async_method_call(
231177612aaSEd Tanous         asyncResp,
2323d30708fSChicago Duan         [asyncResp, param](const boost::system::error_code& ec) {
2333d30708fSChicago Duan             if (ec)
2343d30708fSChicago Duan             {
2353d30708fSChicago Duan                 // The snmp trap id is incorrect
2363d30708fSChicago Duan                 if (ec.value() == EBADR)
2373d30708fSChicago Duan                 {
2383d30708fSChicago Duan                     messages::resourceNotFound(asyncResp->res, "Subscription",
2393d30708fSChicago Duan                                                param);
2403d30708fSChicago Duan                     return;
2413d30708fSChicago Duan                 }
2423d30708fSChicago Duan                 messages::internalError(asyncResp->res);
2433d30708fSChicago Duan                 return;
2443d30708fSChicago Duan             }
2453d30708fSChicago Duan             messages::success(asyncResp->res);
2463d30708fSChicago Duan         },
2473d30708fSChicago Duan         "xyz.openbmc_project.Network.SNMP", static_cast<std::string>(snmpPath),
2483d30708fSChicago Duan         "xyz.openbmc_project.Object.Delete", "Delete");
2493d30708fSChicago Duan }
2503d30708fSChicago Duan 
2513d30708fSChicago Duan } // namespace redfish
252