blob: d0c8133036d77b66bdddfad4137e6fe48e08b533 [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/log.hpp>
#include <string>
namespace phosphor
{
using namespace phosphor::logging;
using namespace sdbusplus::xyz::openbmc_project::Common::Error;
ObjectValueTree getManagedObjects(sdbusplus::bus::bus& 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");
auto reply = bus.call(method);
if (reply.is_method_error())
{
log<level::ERR>("Failed to get managed objects",
entry("PATH=%s", objPath.c_str()));
elog<InternalFailure>();
}
reply.read(interfaces);
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)
{
log<level::ERR>("getaddrinfo failed",
entry("ADDRESS=%s", address.c_str()));
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)
{
log<level::ERR>("getnameinfo failed",
entry("ADDRESS=%s", address.c_str()));
elog<InternalFailure>();
}
unsigned char buf[sizeof(struct in6_addr)];
int isValid = inet_pton(AF_INET, ipaddress, buf);
if (isValid < 0)
{
log<level::ERR>("Invalid address",
entry("ADDRESS=%s", address.c_str()));
elog<InternalFailure>();
}
if (isValid == 0)
{
int isValid6 = inet_pton(AF_INET6, ipaddress, buf);
if (isValid6 < 1)
{
log<level::ERR>("Invalid address",
entry("ADDRESS=%s", address.c_str()));
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)
{
log<level::ERR>(e.what());
}
}
return managers;
}
} // namespace snmp
} // namespace network
} // namespace phosphor