#include "snmp_notification.hpp" #include #include #include "xyz/openbmc_project/Common/error.hpp" namespace phosphor { namespace network { namespace snmp { using namespace phosphor::logging; using namespace sdbusplus::xyz::openbmc_project::Common::Error; using snmpSessionPtr = std::unique_ptr; bool Notification::addPDUVar(netsnmp_pdu& pdu, const OID& objID, size_t objIDLen, u_char type, Value val) { netsnmp_variable_list* varList = nullptr; switch (type) { case ASN_INTEGER: { auto ltmp = val.get(); varList = snmp_pdu_add_variable(&pdu, objID.data(), objIDLen, type, <mp, sizeof(ltmp)); } break; case ASN_UNSIGNED: { auto ltmp = val.get(); varList = snmp_pdu_add_variable(&pdu, objID.data(), objIDLen, type, <mp, sizeof(ltmp)); } break; case ASN_OPAQUE_U64: { auto ltmp = val.get(); varList = snmp_pdu_add_variable(&pdu, objID.data(), objIDLen, type, <mp, sizeof(ltmp)); } break; case ASN_OCTET_STR: { auto value = val.get(); varList = snmp_pdu_add_variable(&pdu, objID.data(), objIDLen, type, value.c_str(), value.length()); } break; } return (varList == nullptr ? false : true); } void Notification::sendTrap() { constexpr auto comm = "public"; constexpr auto localHost = "127.0.0.1"; netsnmp_session session{0}; snmp_sess_init(&session); init_snmp("snmpapp"); // TODO: https://github.com/openbmc/openbmc/issues/3145 session.version = SNMP_VERSION_2c; session.community = (u_char*)comm; session.community_len = strlen(comm); session.callback = nullptr; session.callback_magic = nullptr; // TODO:- get it from settings D-bus object. session.peername = const_cast(localHost); // create the session auto ss = snmp_add( &session, netsnmp_transport_open_client("snmptrap", session.peername), nullptr, nullptr); if (!ss) { log("Unable to get the snmp session.", entry("SNMPMANAGER=%s", session.peername)); elog(); } // Wrap the raw pointer in RAII snmpSessionPtr sessionPtr(ss, &::snmp_close); ss = nullptr; auto pdu = snmp_pdu_create(SNMP_MSG_TRAP2); if (!pdu) { log("Failed to create notification PDU"); elog(); } pdu->trap_type = SNMP_TRAP_ENTERPRISESPECIFIC; auto trapInfo = getTrapOID(); if (!snmp_pdu_add_variable( pdu, SNMPTrapOID, sizeof(SNMPTrapOID) / sizeof(oid), ASN_OBJECT_ID, trapInfo.first.data(), trapInfo.second * sizeof(oid))) { log("Failed to add the SNMP var(trapID)"); snmp_free_pdu(pdu); elog(); } auto objectList = getFieldOIDList(); for (const auto& object : objectList) { if (!addPDUVar(*pdu, std::get<0>(object), std::get<1>(object), std::get<2>(object), std::get<3>(object))) { log("Failed to add the SNMP var"); snmp_free_pdu(pdu); elog(); } } // pdu is freed by snmp_send if (!snmp_send(sessionPtr.get(), pdu)) { log("Failed to send the snmp trap."); elog(); } log("Sent SNMP Trap"); } } // namespace snmp } // namespace network } // namespace phosphor