1 #include "snmp_notification.hpp" 2 3 #include <phosphor-logging/elog-errors.hpp> 4 #include <phosphor-logging/log.hpp> 5 6 #include "xyz/openbmc_project/Common/error.hpp" 7 8 namespace phosphor 9 { 10 namespace network 11 { 12 namespace snmp 13 { 14 15 using namespace phosphor::logging; 16 using namespace sdbusplus::xyz::openbmc_project::Common::Error; 17 18 using snmpSessionPtr = 19 std::unique_ptr<netsnmp_session, decltype(&::snmp_close)>; 20 21 bool Notification::addPDUVar(netsnmp_pdu& pdu, const OID& objID, 22 size_t objIDLen, u_char type, Value val) 23 { 24 netsnmp_variable_list* varList = nullptr; 25 switch (type) 26 { 27 case ASN_INTEGER: 28 { 29 auto ltmp = val.get<int32_t>(); 30 varList = snmp_pdu_add_variable(&pdu, objID.data(), objIDLen, type, 31 <mp, sizeof(ltmp)); 32 } 33 break; 34 case ASN_UNSIGNED: 35 { 36 auto ltmp = val.get<uint32_t>(); 37 varList = snmp_pdu_add_variable(&pdu, objID.data(), objIDLen, type, 38 <mp, sizeof(ltmp)); 39 } 40 break; 41 case ASN_OPAQUE_U64: 42 { 43 auto ltmp = val.get<uint64_t>(); 44 varList = snmp_pdu_add_variable(&pdu, objID.data(), objIDLen, type, 45 <mp, sizeof(ltmp)); 46 } 47 break; 48 case ASN_OCTET_STR: 49 { 50 auto value = val.get<std::string>(); 51 varList = snmp_pdu_add_variable(&pdu, objID.data(), objIDLen, type, 52 value.c_str(), value.length()); 53 } 54 break; 55 } 56 return (varList == nullptr ? false : true); 57 } 58 59 void Notification::sendTrap() 60 { 61 constexpr auto comm = "public"; 62 constexpr auto localHost = "127.0.0.1"; 63 netsnmp_session session{0}; 64 65 snmp_sess_init(&session); 66 67 init_snmp("snmpapp"); 68 69 // TODO: https://github.com/openbmc/openbmc/issues/3145 70 session.version = SNMP_VERSION_2c; 71 session.community = (u_char*)comm; 72 session.community_len = strlen(comm); 73 session.callback = nullptr; 74 session.callback_magic = nullptr; 75 76 // TODO:- get it from settings D-bus object. 77 session.peername = const_cast<char*>(localHost); 78 79 // create the session 80 auto ss = snmp_add( 81 &session, netsnmp_transport_open_client("snmptrap", session.peername), 82 nullptr, nullptr); 83 if (!ss) 84 { 85 log<level::ERR>("Unable to get the snmp session.", 86 entry("SNMPMANAGER=%s", session.peername)); 87 elog<InternalFailure>(); 88 } 89 90 // Wrap the raw pointer in RAII 91 snmpSessionPtr sessionPtr(ss, &::snmp_close); 92 93 ss = nullptr; 94 95 auto pdu = snmp_pdu_create(SNMP_MSG_TRAP2); 96 if (!pdu) 97 { 98 log<level::ERR>("Failed to create notification PDU"); 99 elog<InternalFailure>(); 100 } 101 102 pdu->trap_type = SNMP_TRAP_ENTERPRISESPECIFIC; 103 104 auto trapInfo = getTrapOID(); 105 106 if (!snmp_pdu_add_variable( 107 pdu, SNMPTrapOID, sizeof(SNMPTrapOID) / sizeof(oid), ASN_OBJECT_ID, 108 trapInfo.first.data(), trapInfo.second * sizeof(oid))) 109 { 110 log<level::ERR>("Failed to add the SNMP var(trapID)"); 111 snmp_free_pdu(pdu); 112 elog<InternalFailure>(); 113 } 114 115 auto objectList = getFieldOIDList(); 116 117 for (const auto& object : objectList) 118 { 119 if (!addPDUVar(*pdu, std::get<0>(object), std::get<1>(object), 120 std::get<2>(object), std::get<3>(object))) 121 { 122 log<level::ERR>("Failed to add the SNMP var"); 123 snmp_free_pdu(pdu); 124 elog<InternalFailure>(); 125 } 126 } 127 128 // pdu is freed by snmp_send 129 if (!snmp_send(sessionPtr.get(), pdu)) 130 { 131 log<level::ERR>("Failed to send the snmp trap."); 132 elog<InternalFailure>(); 133 } 134 135 log<level::DEBUG>("Sent SNMP Trap"); 136 } 137 138 } // namespace snmp 139 } // namespace network 140 } // namespace phosphor 141