1 #include "snmp_util.hpp" 2 3 #include "xyz/openbmc_project/Common/error.hpp" 4 5 #include <arpa/inet.h> 6 #include <netdb.h> 7 8 #include <phosphor-logging/elog-errors.hpp> 9 #include <phosphor-logging/lg2.hpp> 10 11 #include <string> 12 13 namespace phosphor 14 { 15 16 using namespace phosphor::logging; 17 using namespace sdbusplus::xyz::openbmc_project::Common::Error; 18 19 ObjectValueTree getManagedObjects(sdbusplus::bus_t& bus, 20 const std::string& service, 21 const std::string& objPath) 22 { 23 ObjectValueTree interfaces; 24 25 auto method = bus.new_method_call(service.c_str(), objPath.c_str(), 26 "org.freedesktop.DBus.ObjectManager", 27 "GetManagedObjects"); 28 29 try 30 { 31 auto reply = bus.call(method); 32 reply.read(interfaces); 33 } 34 catch (const sdbusplus::exception_t& e) 35 { 36 lg2::error("Failed to get managed objects: {PATH}", "PATH", objPath); 37 elog<InternalFailure>(); 38 } 39 40 return interfaces; 41 } 42 43 namespace network 44 { 45 46 std::string resolveAddress(const std::string& address) 47 { 48 addrinfo hints{}; 49 addrinfo* addr = nullptr; 50 51 hints.ai_family = AF_UNSPEC; 52 hints.ai_socktype = SOCK_STREAM; 53 hints.ai_flags |= AI_CANONNAME; 54 55 auto result = getaddrinfo(address.c_str(), NULL, &hints, &addr); 56 if (result) 57 { 58 lg2::error("getaddrinfo failed {ADDRESS}: {RC}", "ADDRESS", address, 59 "RC", result); 60 elog<InternalFailure>(); 61 } 62 63 AddrPtr addrPtr{addr}; 64 addr = nullptr; 65 66 char ipaddress[INET6_ADDRSTRLEN]{0}; 67 result = getnameinfo(addrPtr->ai_addr, addrPtr->ai_addrlen, ipaddress, 68 sizeof(ipaddress), NULL, 0, NI_NUMERICHOST); 69 if (result) 70 { 71 lg2::error("getnameinfo failed {ADDRESS}: {RC}", "ADDRESS", address, 72 "RC", result); 73 elog<InternalFailure>(); 74 } 75 76 unsigned char buf[sizeof(struct in6_addr)]; 77 int isValid = inet_pton(AF_INET, ipaddress, buf); 78 if (isValid < 0) 79 { 80 lg2::error("Invalid address {ADDRESS}: {RC}", "ADDRESS", address, "RC", 81 isValid); 82 elog<InternalFailure>(); 83 } 84 if (isValid == 0) 85 { 86 int isValid6 = inet_pton(AF_INET6, ipaddress, buf); 87 if (isValid6 < 1) 88 { 89 lg2::error("Invalid address {ADDRESS}: {RC}", "ADDRESS", address, 90 "RC", isValid); 91 elog<InternalFailure>(); 92 } 93 } 94 95 return ipaddress; 96 } 97 98 namespace snmp 99 { 100 101 static constexpr auto busName = "xyz.openbmc_project.Network.SNMP"; 102 static constexpr auto root = "/xyz/openbmc_project/network/snmp/manager"; 103 static constexpr auto clientIntf = "xyz.openbmc_project.Network.Client"; 104 105 /** @brief Gets the sdbus object for this process. 106 * @return the bus object. 107 */ 108 static auto& getBus() 109 { 110 static auto bus = sdbusplus::bus::new_default(); 111 return bus; 112 } 113 114 std::vector<std::string> getManagers() 115 { 116 std::vector<std::string> managers; 117 auto& bus = getBus(); 118 auto objTree = phosphor::getManagedObjects(bus, busName, root); 119 for (const auto& objIter : objTree) 120 { 121 try 122 { 123 auto& intfMap = objIter.second; 124 auto& snmpClientProps = intfMap.at(clientIntf); 125 auto& address = 126 std::get<std::string>(snmpClientProps.at("Address")); 127 auto& port = std::get<uint16_t>(snmpClientProps.at("Port")); 128 auto ipaddress = phosphor::network::resolveAddress(address); 129 auto mgr = std::move(ipaddress); 130 if (port > 0) 131 { 132 mgr += ":"; 133 mgr += std::to_string(port); 134 } 135 managers.push_back(mgr); 136 } 137 catch (const std::exception& e) 138 { 139 lg2::error("Invalid address: {ERROR}", "ERROR", e); 140 } 141 } 142 return managers; 143 } 144 145 } // namespace snmp 146 } // namespace network 147 } // namespace phosphor 148