Send the trap to the configured SNMP managers

Get the snmp manager details from the D-bus service and send the
trap to all the configured snmp managers.

Resolves openbmc/openbmc#3058

Change-Id: I9c59ae866ab194e92a85254ca646ecc299803f26
Signed-off-by: Ratan Gupta <ratagupt@in.ibm.com>
diff --git a/snmp_util.cpp b/snmp_util.cpp
new file mode 100644
index 0000000..a8a1ff8
--- /dev/null
+++ b/snmp_util.cpp
@@ -0,0 +1,124 @@
+#include "snmp_util.hpp"
+#include "xyz/openbmc_project/Common/error.hpp"
+
+#include <phosphor-logging/elog-errors.hpp>
+#include <phosphor-logging/log.hpp>
+
+#include <netdb.h>
+#include <arpa/inet.h>
+#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{0};
+    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>();
+    }
+
+    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 = snmpClientProps.at("Address").get<std::string>();
+            auto& port = snmpClientProps.at("Port").get<uint16_t>();
+            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