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