blob: 818bdc1f58406572b2d28cea3214575657d68c87 [file] [log] [blame]
#include "snmp_util.hpp"
#include "xyz/openbmc_project/Common/error.hpp"
#include <arpa/inet.h>
#include <netdb.h>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/lg2.hpp>
#include <string>
namespace phosphor
{
using namespace phosphor::logging;
using namespace sdbusplus::xyz::openbmc_project::Common::Error;
ObjectValueTree getManagedObjects(sdbusplus::bus_t& bus,
const std::string& service,
const std::string& objPath)
{
ObjectValueTree interfaces;
auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
"org.freedesktop.DBus.ObjectManager",
"GetManagedObjects");
try
{
auto reply = bus.call(method);
reply.read(interfaces);
}
catch (const sdbusplus::exception_t& e)
{
lg2::error("Failed to get managed objects: {PATH}", "PATH", objPath);
elog<InternalFailure>();
}
return interfaces;
}
namespace network
{
std::string resolveAddress(const std::string& address)
{
addrinfo hints{};
addrinfo* addr = nullptr;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags |= AI_CANONNAME;
auto result = getaddrinfo(address.c_str(), NULL, &hints, &addr);
if (result)
{
lg2::error("getaddrinfo failed {ADDRESS}: {RC}", "ADDRESS", address,
"RC", result);
elog<InternalFailure>();
}
AddrPtr addrPtr{addr};
addr = nullptr;
char ipaddress[INET6_ADDRSTRLEN]{0};
result = getnameinfo(addrPtr->ai_addr, addrPtr->ai_addrlen, ipaddress,
sizeof(ipaddress), NULL, 0, NI_NUMERICHOST);
if (result)
{
lg2::error("getnameinfo failed {ADDRESS}: {RC}", "ADDRESS", address,
"RC", result);
elog<InternalFailure>();
}
unsigned char buf[sizeof(struct in6_addr)];
int isValid = inet_pton(AF_INET, ipaddress, buf);
if (isValid < 0)
{
lg2::error("Invalid address {ADDRESS}: {RC}", "ADDRESS", address, "RC",
isValid);
elog<InternalFailure>();
}
if (isValid == 0)
{
int isValid6 = inet_pton(AF_INET6, ipaddress, buf);
if (isValid6 < 1)
{
lg2::error("Invalid address {ADDRESS}: {RC}", "ADDRESS", address,
"RC", isValid);
elog<InternalFailure>();
}
}
return ipaddress;
}
namespace snmp
{
static constexpr auto busName = "xyz.openbmc_project.Network.SNMP";
static constexpr auto root = "/xyz/openbmc_project/network/snmp/manager";
static constexpr auto clientIntf = "xyz.openbmc_project.Network.Client";
/** @brief Gets the sdbus object for this process.
* @return the bus object.
*/
static auto& getBus()
{
static auto bus = sdbusplus::bus::new_default();
return bus;
}
std::vector<std::string> getManagers()
{
std::vector<std::string> managers;
auto& bus = getBus();
auto objTree = phosphor::getManagedObjects(bus, busName, root);
for (const auto& objIter : objTree)
{
try
{
auto& intfMap = objIter.second;
auto& snmpClientProps = intfMap.at(clientIntf);
auto& address =
std::get<std::string>(snmpClientProps.at("Address"));
auto& port = std::get<uint16_t>(snmpClientProps.at("Port"));
auto ipaddress = phosphor::network::resolveAddress(address);
auto mgr = std::move(ipaddress);
if (port > 0)
{
mgr += ":";
mgr += std::to_string(port);
}
managers.push_back(mgr);
}
catch (const std::exception& e)
{
lg2::error("Invalid address: {ERROR}", "ERROR", e);
}
}
return managers;
}
} // namespace snmp
} // namespace network
} // namespace phosphor