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