xref: /openbmc/phosphor-snmp/snmp_util.cpp (revision 87d3edd6)
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 
getManagedObjects(sdbusplus::bus_t & bus,const std::string & service,const std::string & objPath)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 
resolveAddress(const std::string & address)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  */
getBus()108 static auto& getBus()
109 {
110     static auto bus = sdbusplus::bus::new_default();
111     return bus;
112 }
113 
getManagers()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