xref: /openbmc/phosphor-snmp/snmp_util.cpp (revision ed2ee733)
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/log.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::bus& 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     auto reply = bus.call(method);
30 
31     if (reply.is_method_error())
32     {
33         log<level::ERR>("Failed to get managed objects",
34                         entry("PATH=%s", objPath.c_str()));
35         elog<InternalFailure>();
36     }
37 
38     reply.read(interfaces);
39     return interfaces;
40 }
41 
42 namespace network
43 {
44 
45 std::string resolveAddress(const std::string& address)
46 {
47     addrinfo hints{};
48     addrinfo* addr = nullptr;
49 
50     hints.ai_family = AF_UNSPEC;
51     hints.ai_socktype = SOCK_STREAM;
52     hints.ai_flags |= AI_CANONNAME;
53 
54     auto result = getaddrinfo(address.c_str(), NULL, &hints, &addr);
55     if (result)
56     {
57         log<level::ERR>("getaddrinfo failed",
58                         entry("ADDRESS=%s", address.c_str()));
59         elog<InternalFailure>();
60     }
61 
62     AddrPtr addrPtr{addr};
63     addr = nullptr;
64 
65     char ipaddress[INET6_ADDRSTRLEN]{0};
66     result = getnameinfo(addrPtr->ai_addr, addrPtr->ai_addrlen, ipaddress,
67                          sizeof(ipaddress), NULL, 0, NI_NUMERICHOST);
68     if (result)
69     {
70         log<level::ERR>("getnameinfo failed",
71                         entry("ADDRESS=%s", address.c_str()));
72         elog<InternalFailure>();
73     }
74 
75     unsigned char buf[sizeof(struct in6_addr)];
76     int isValid = inet_pton(AF_INET, ipaddress, buf);
77     if (isValid < 0)
78     {
79         log<level::ERR>("Invalid address",
80                         entry("ADDRESS=%s", address.c_str()));
81         elog<InternalFailure>();
82     }
83     if (isValid == 0)
84     {
85         int isValid6 = inet_pton(AF_INET6, ipaddress, buf);
86         if (isValid6 < 1)
87         {
88             log<level::ERR>("Invalid address",
89                             entry("ADDRESS=%s", address.c_str()));
90             elog<InternalFailure>();
91         }
92     }
93 
94     return ipaddress;
95 }
96 
97 namespace snmp
98 {
99 
100 static constexpr auto busName = "xyz.openbmc_project.Network.SNMP";
101 static constexpr auto root = "/xyz/openbmc_project/network/snmp/manager";
102 static constexpr auto clientIntf = "xyz.openbmc_project.Network.Client";
103 
104 /** @brief Gets the sdbus object for this process.
105  *  @return the bus object.
106  */
107 static auto& getBus()
108 {
109     static auto bus = sdbusplus::bus::new_default();
110     return bus;
111 }
112 
113 std::vector<std::string> getManagers()
114 {
115     std::vector<std::string> managers;
116     auto& bus = getBus();
117     auto objTree = phosphor::getManagedObjects(bus, busName, root);
118     for (const auto& objIter : objTree)
119     {
120         try
121         {
122             auto& intfMap = objIter.second;
123             auto& snmpClientProps = intfMap.at(clientIntf);
124             auto& address =
125                 std::get<std::string>(snmpClientProps.at("Address"));
126             auto& port = std::get<uint16_t>(snmpClientProps.at("Port"));
127             auto ipaddress = phosphor::network::resolveAddress(address);
128             auto mgr = std::move(ipaddress);
129             if (port > 0)
130             {
131                 mgr += ":";
132                 mgr += std::to_string(port);
133             }
134             managers.push_back(mgr);
135         }
136         catch (const std::exception& e)
137         {
138             log<level::ERR>(e.what());
139         }
140     }
141     return managers;
142 }
143 
144 } // namespace snmp
145 } // namespace network
146 } // namespace phosphor
147