blob: db164e6744e6352b858f90ac8117028aa7e76a94 [file] [log] [blame]
Ratan Gupta3681a502017-06-17 19:20:04 +05301#include "util.hpp"
Ratan Gupta11cef802017-05-29 08:41:48 +05302
Patrick Venture189d44e2018-07-09 12:30:59 -07003#include "config_parser.hpp"
4#include "types.hpp"
Ratan Gupta8804feb2017-05-25 10:49:57 +05305
Ratan Gupta3681a502017-06-17 19:20:04 +05306#include <arpa/inet.h>
7#include <dirent.h>
8#include <net/if.h>
Ratan Guptabc886292017-07-25 18:29:57 +05309#include <sys/wait.h>
Ratan Gupta3681a502017-06-17 19:20:04 +053010
Ratan Gupta8804feb2017-05-25 10:49:57 +053011#include <algorithm>
Ratan Gupta56187e72017-08-13 09:40:14 +053012#include <experimental/filesystem>
Patrick Venture189d44e2018-07-09 12:30:59 -070013#include <iostream>
14#include <list>
15#include <phosphor-logging/elog-errors.hpp>
16#include <phosphor-logging/log.hpp>
William A. Kennington III5058f572019-01-30 17:18:14 -080017#include <stdexcept>
Patrick Venture189d44e2018-07-09 12:30:59 -070018#include <string>
19#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta8804feb2017-05-25 10:49:57 +053020
21namespace phosphor
22{
23namespace network
24{
Ratan Guptabc886292017-07-25 18:29:57 +053025
Ratan Gupta8804feb2017-05-25 10:49:57 +053026namespace
27{
28
29using namespace phosphor::logging;
Ratan Gupta11cef802017-05-29 08:41:48 +053030using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Ratan Gupta56187e72017-08-13 09:40:14 +053031namespace fs = std::experimental::filesystem;
Ratan Gupta8804feb2017-05-25 10:49:57 +053032
33uint8_t toV6Cidr(const std::string& subnetMask)
34{
35 uint8_t pos = 0;
36 uint8_t prevPos = 0;
37 uint8_t cidr = 0;
Gunnar Mills57d9c502018-09-14 14:42:34 -050038 uint16_t buff{};
Ratan Gupta8804feb2017-05-25 10:49:57 +053039 do
40 {
Gunnar Mills57d9c502018-09-14 14:42:34 -050041 // subnet mask look like ffff:ffff::
Ratan Gupta8804feb2017-05-25 10:49:57 +053042 // or ffff:c000::
Gunnar Mills57d9c502018-09-14 14:42:34 -050043 pos = subnetMask.find(":", prevPos);
Ratan Gupta8804feb2017-05-25 10:49:57 +053044 if (pos == std::string::npos)
45 {
46 break;
47 }
48
49 auto str = subnetMask.substr(prevPos, (pos - prevPos));
50 prevPos = pos + 1;
51
52 // String length is 0
53 if (!str.length())
54 {
55 return cidr;
56 }
Gunnar Mills57d9c502018-09-14 14:42:34 -050057 // converts it into number.
Ratan Gupta8804feb2017-05-25 10:49:57 +053058 if (sscanf(str.c_str(), "%hx", &buff) <= 0)
59 {
60 log<level::ERR>("Invalid Mask",
Joseph Reynolds02653ca2018-05-10 15:55:09 -050061 entry("SUBNETMASK=%s", subnetMask.c_str()));
Ratan Gupta8804feb2017-05-25 10:49:57 +053062
63 return 0;
64 }
65
66 // convert the number into bitset
67 // and check for how many ones are there.
68 // if we don't have all the ones then make
69 // sure that all the ones should be left justify.
70
71 if (__builtin_popcount(buff) != 16)
72 {
Gunnar Mills57d9c502018-09-14 14:42:34 -050073 if (((sizeof(buff) * 8) - (__builtin_ctz(buff))) !=
74 __builtin_popcount(buff))
Ratan Gupta8804feb2017-05-25 10:49:57 +053075 {
76 log<level::ERR>("Invalid Mask",
Joseph Reynolds02653ca2018-05-10 15:55:09 -050077 entry("SUBNETMASK=%s", subnetMask.c_str()));
Ratan Gupta8804feb2017-05-25 10:49:57 +053078
79 return 0;
80 }
81 cidr += __builtin_popcount(buff);
82 return cidr;
83 }
84
85 cidr += 16;
Gunnar Mills57d9c502018-09-14 14:42:34 -050086 } while (1);
Ratan Gupta8804feb2017-05-25 10:49:57 +053087
88 return cidr;
89}
Gunnar Mills57d9c502018-09-14 14:42:34 -050090} // anonymous namespace
Ratan Gupta8804feb2017-05-25 10:49:57 +053091
92uint8_t toCidr(int addressFamily, const std::string& subnetMask)
93{
94 if (addressFamily == AF_INET6)
95 {
96 return toV6Cidr(subnetMask);
97 }
98
99 uint32_t buff;
100
101 auto rc = inet_pton(addressFamily, subnetMask.c_str(), &buff);
102 if (rc <= 0)
103 {
104 log<level::ERR>("inet_pton failed:",
Joseph Reynolds02653ca2018-05-10 15:55:09 -0500105 entry("SUBNETMASK=%s", subnetMask.c_str()));
Ratan Gupta8804feb2017-05-25 10:49:57 +0530106 return 0;
107 }
108
109 buff = be32toh(buff);
110 // total no of bits - total no of leading zero == total no of ones
Gunnar Mills57d9c502018-09-14 14:42:34 -0500111 if (((sizeof(buff) * 8) - (__builtin_ctz(buff))) ==
112 __builtin_popcount(buff))
Ratan Gupta8804feb2017-05-25 10:49:57 +0530113 {
114 return __builtin_popcount(buff);
115 }
116 else
117 {
118 log<level::ERR>("Invalid Mask",
Joseph Reynolds02653ca2018-05-10 15:55:09 -0500119 entry("SUBNETMASK=%s", subnetMask.c_str()));
Ratan Gupta8804feb2017-05-25 10:49:57 +0530120 return 0;
121 }
122}
123
124std::string toMask(int addressFamily, uint8_t prefix)
125{
126 if (addressFamily == AF_INET6)
127 {
Gunnar Mills57d9c502018-09-14 14:42:34 -0500128 // TODO:- conversion for v6
Ratan Gupta8804feb2017-05-25 10:49:57 +0530129 return "";
130 }
131
132 if (prefix < 1 || prefix > 30)
133 {
Gunnar Mills57d9c502018-09-14 14:42:34 -0500134 log<level::ERR>("Invalid Prefix", entry("PREFIX=%d", prefix));
Ratan Gupta8804feb2017-05-25 10:49:57 +0530135 return "";
136 }
137 /* Create the netmask from the number of bits */
138 unsigned long mask = 0;
Gunnar Mills57d9c502018-09-14 14:42:34 -0500139 for (auto i = 0; i < prefix; i++)
Ratan Gupta8804feb2017-05-25 10:49:57 +0530140 {
141 mask |= 1 << (31 - i);
142 }
143 struct in_addr netmask;
144 netmask.s_addr = htonl(mask);
145 return inet_ntoa(netmask);
146}
147
Ratan Gupta11cef802017-05-29 08:41:48 +0530148std::string getNetworkID(int addressFamily, const std::string& ipaddress,
Ratan Guptabc886292017-07-25 18:29:57 +0530149 uint8_t prefix)
Ratan Gupta11cef802017-05-29 08:41:48 +0530150{
151 unsigned char* pntMask = nullptr;
152 unsigned char* pntNetwork = nullptr;
Gunnar Mills57d9c502018-09-14 14:42:34 -0500153 int bit{};
154 int offset{};
155 struct in6_addr netmask
156 {
157 };
Ratan Gupta11cef802017-05-29 08:41:48 +0530158 const u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
Gunnar Mills57d9c502018-09-14 14:42:34 -0500159 0xf8, 0xfc, 0xfe, 0xff};
Ratan Gupta11cef802017-05-29 08:41:48 +0530160
161 pntMask = reinterpret_cast<unsigned char*>(&netmask);
162
163 offset = prefix / 8;
164 bit = prefix % 8;
165
166 while (offset--)
167 {
168 *pntMask++ = 0xff;
169 }
170
171 if (bit)
172 {
173 *pntMask = maskbit[bit];
174 }
175
176 // convert ipaddres string into network address
177 struct in6_addr ipaddressNetwork;
178 if (inet_pton(addressFamily, ipaddress.c_str(), &ipaddressNetwork) <= 0)
179 {
180 log<level::ERR>("inet_pton failure",
Ratan Guptabc886292017-07-25 18:29:57 +0530181 entry("IPADDRESS=%s", ipaddress.c_str()));
Ratan Gupta450b3462018-11-27 15:05:54 +0530182 elog<InternalFailure>();
Ratan Gupta11cef802017-05-29 08:41:48 +0530183
184 return "";
185 }
186
187 // Now bit wise and gets you the network address
188 pntMask = reinterpret_cast<unsigned char*>(&netmask);
189 pntNetwork = reinterpret_cast<unsigned char*>(&ipaddressNetwork);
190
Gunnar Mills57d9c502018-09-14 14:42:34 -0500191 for (int i = 0; i < 16; i++)
Ratan Gupta11cef802017-05-29 08:41:48 +0530192 {
193 pntNetwork[i] = pntNetwork[i] & pntMask[i];
194 }
195
Gunnar Mills57d9c502018-09-14 14:42:34 -0500196 // convert the network address into string fomat.
197 char networkString[INET6_ADDRSTRLEN] = {0};
Ratan Gupta11cef802017-05-29 08:41:48 +0530198 if (inet_ntop(addressFamily, &ipaddressNetwork, networkString,
199 INET6_ADDRSTRLEN) == NULL)
200 {
201 log<level::ERR>("inet_ntop failure");
Ratan Gupta450b3462018-11-27 15:05:54 +0530202 elog<InternalFailure>();
Ratan Gupta11cef802017-05-29 08:41:48 +0530203 }
204 return networkString;
205}
206
William A. Kennington III5058f572019-01-30 17:18:14 -0800207std::string toString(const InAddrAny& addr)
208{
209 std::string ip;
210 if (std::holds_alternative<struct in_addr>(addr))
211 {
212 const auto& v = std::get<struct in_addr>(addr);
213 ip.resize(INET_ADDRSTRLEN);
214 if (inet_ntop(AF_INET, &v, ip.data(), ip.size()) == NULL)
215 {
216 throw std::runtime_error("Failed to convert IP4 to string");
217 }
218 }
219 else if (std::holds_alternative<struct in6_addr>(addr))
220 {
221 const auto& v = std::get<struct in6_addr>(addr);
222 ip.resize(INET6_ADDRSTRLEN);
223 if (inet_ntop(AF_INET6, &v, ip.data(), ip.size()) == NULL)
224 {
225 throw std::runtime_error("Failed to convert IP6 to string");
226 }
227 }
228 else
229 {
230 throw std::runtime_error("Invalid addr type");
231 }
232 ip.resize(strlen(ip.c_str()));
233 return ip;
234}
235
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500236bool isLinkLocalIP(const std::string& address)
Ratan Gupta8804feb2017-05-25 10:49:57 +0530237{
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500238 return address.find(IPV4_PREFIX) == 0 || address.find(IPV6_PREFIX) == 0;
239}
240
241bool isValidIP(int addressFamily, const std::string& address)
242{
243 unsigned char buf[sizeof(struct in6_addr)];
244
245 return inet_pton(addressFamily, address.c_str(), buf) > 0;
246}
247
248bool isValidPrefix(int addressFamily, uint8_t prefixLength)
249{
250 if (addressFamily == AF_INET)
251 {
252 if (prefixLength < IPV4_MIN_PREFIX_LENGTH ||
253 prefixLength > IPV4_MAX_PREFIX_LENGTH)
254 {
255 return false;
256 }
257 }
258
259 if (addressFamily == AF_INET6)
260 {
261 if (prefixLength < IPV4_MIN_PREFIX_LENGTH ||
262 prefixLength > IPV6_MAX_PREFIX_LENGTH)
263 {
264 return false;
265 }
266 }
267
268 return true;
Ratan Gupta8804feb2017-05-25 10:49:57 +0530269}
270
Ratan Gupta3681a502017-06-17 19:20:04 +0530271IntfAddrMap getInterfaceAddrs()
272{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500273 IntfAddrMap intfMap{};
Ratan Gupta3681a502017-06-17 19:20:04 +0530274 struct ifaddrs* ifaddr = nullptr;
275
276 // attempt to fill struct with ifaddrs
277 if (getifaddrs(&ifaddr) == -1)
278 {
279 auto error = errno;
280 log<level::ERR>("Error occurred during the getifaddrs call",
281 entry("ERRNO=%s", strerror(error)));
282 elog<InternalFailure>();
283 }
284
285 AddrPtr ifaddrPtr(ifaddr);
286 ifaddr = nullptr;
287
Gunnar Mills57d9c502018-09-14 14:42:34 -0500288 std::string intfName{};
Ratan Gupta3681a502017-06-17 19:20:04 +0530289
290 for (ifaddrs* ifa = ifaddrPtr.get(); ifa != nullptr; ifa = ifa->ifa_next)
291 {
292 // walk interfaces
293 if (ifa->ifa_addr == nullptr)
294 {
295 continue;
296 }
297
298 // get only INET interfaces not ipv6
299 if (ifa->ifa_addr->sa_family == AF_INET ||
300 ifa->ifa_addr->sa_family == AF_INET6)
301 {
302 // if loopback, or not running ignore
303 if ((ifa->ifa_flags & IFF_LOOPBACK) ||
304 !(ifa->ifa_flags & IFF_RUNNING))
305 {
306 continue;
307 }
Ratan Gupta3681a502017-06-17 19:20:04 +0530308 intfName = ifa->ifa_name;
Gunnar Mills57d9c502018-09-14 14:42:34 -0500309 AddrInfo info{};
310 char ip[INET6_ADDRSTRLEN] = {0};
311 char subnetMask[INET6_ADDRSTRLEN] = {0};
Ratan Gupta3681a502017-06-17 19:20:04 +0530312
313 if (ifa->ifa_addr->sa_family == AF_INET)
314 {
315
316 inet_ntop(ifa->ifa_addr->sa_family,
317 &(((struct sockaddr_in*)(ifa->ifa_addr))->sin_addr),
Gunnar Mills57d9c502018-09-14 14:42:34 -0500318 ip, sizeof(ip));
Ratan Gupta3681a502017-06-17 19:20:04 +0530319
Gunnar Mills57d9c502018-09-14 14:42:34 -0500320 inet_ntop(
321 ifa->ifa_addr->sa_family,
322 &(((struct sockaddr_in*)(ifa->ifa_netmask))->sin_addr),
323 subnetMask, sizeof(subnetMask));
Ratan Gupta3681a502017-06-17 19:20:04 +0530324 }
325 else
326 {
327 inet_ntop(ifa->ifa_addr->sa_family,
328 &(((struct sockaddr_in6*)(ifa->ifa_addr))->sin6_addr),
Gunnar Mills57d9c502018-09-14 14:42:34 -0500329 ip, sizeof(ip));
Ratan Gupta3681a502017-06-17 19:20:04 +0530330
Gunnar Mills57d9c502018-09-14 14:42:34 -0500331 inet_ntop(
332 ifa->ifa_addr->sa_family,
333 &(((struct sockaddr_in6*)(ifa->ifa_netmask))->sin6_addr),
334 subnetMask, sizeof(subnetMask));
Ratan Gupta3681a502017-06-17 19:20:04 +0530335 }
336
337 info.addrType = ifa->ifa_addr->sa_family;
338 info.ipaddress = ip;
339 info.prefix = toCidr(info.addrType, std::string(subnetMask));
David Cobbley269501c2018-05-25 15:55:56 -0700340 intfMap[intfName].push_back(info);
Ratan Gupta3681a502017-06-17 19:20:04 +0530341 }
342 }
Ratan Gupta3681a502017-06-17 19:20:04 +0530343 return intfMap;
344}
345
Ratan Guptafd4b0f02017-09-16 06:01:24 +0530346InterfaceList getInterfaces()
347{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500348 InterfaceList interfaces{};
Ratan Guptafd4b0f02017-09-16 06:01:24 +0530349 struct ifaddrs* ifaddr = nullptr;
350
351 // attempt to fill struct with ifaddrs
352 if (getifaddrs(&ifaddr) == -1)
353 {
354 auto error = errno;
355 log<level::ERR>("Error occurred during the getifaddrs call",
356 entry("ERRNO=%d", error));
357 elog<InternalFailure>();
358 }
359
360 AddrPtr ifaddrPtr(ifaddr);
361 ifaddr = nullptr;
362
363 for (ifaddrs* ifa = ifaddrPtr.get(); ifa != nullptr; ifa = ifa->ifa_next)
364 {
365 // walk interfaces
366 // if loopback, or not running ignore
Gunnar Mills57d9c502018-09-14 14:42:34 -0500367 if ((ifa->ifa_flags & IFF_LOOPBACK) || !(ifa->ifa_flags & IFF_RUNNING))
Ratan Guptafd4b0f02017-09-16 06:01:24 +0530368 {
369 continue;
370 }
371 interfaces.emplace(ifa->ifa_name);
372 }
373 return interfaces;
374}
375
Ratan Guptabc886292017-07-25 18:29:57 +0530376void deleteInterface(const std::string& intf)
377{
378 pid_t pid = fork();
Gunnar Mills57d9c502018-09-14 14:42:34 -0500379 int status{};
Ratan Guptabc886292017-07-25 18:29:57 +0530380
381 if (pid == 0)
382 {
383
384 execl("/sbin/ip", "ip", "link", "delete", "dev", intf.c_str(), nullptr);
385 auto error = errno;
Gunnar Mills57d9c502018-09-14 14:42:34 -0500386 log<level::ERR>("Couldn't delete the device", entry("ERRNO=%d", error),
Ratan Guptabc886292017-07-25 18:29:57 +0530387 entry("INTF=%s", intf.c_str()));
388 elog<InternalFailure>();
389 }
390 else if (pid < 0)
391 {
392 auto error = errno;
Gunnar Mills57d9c502018-09-14 14:42:34 -0500393 log<level::ERR>("Error occurred during fork", entry("ERRNO=%d", error));
Ratan Guptabc886292017-07-25 18:29:57 +0530394 elog<InternalFailure>();
395 }
396 else if (pid > 0)
397 {
398 while (waitpid(pid, &status, 0) == -1)
399 {
400 if (errno != EINTR)
Gunnar Mills57d9c502018-09-14 14:42:34 -0500401 { /* Error other than EINTR */
Ratan Guptabc886292017-07-25 18:29:57 +0530402 status = -1;
403 break;
404 }
405 }
406
Gunnar Mills57d9c502018-09-14 14:42:34 -0500407 if (status < 0)
Ratan Guptabc886292017-07-25 18:29:57 +0530408 {
409 log<level::ERR>("Unable to delete the interface",
Joseph Reynolds02653ca2018-05-10 15:55:09 -0500410 entry("INTF=%s", intf.c_str()),
411 entry("STATUS=%d", status));
Ratan Guptabc886292017-07-25 18:29:57 +0530412 elog<InternalFailure>();
413 }
414 }
415}
416
Ratan Gupta56187e72017-08-13 09:40:14 +0530417bool getDHCPValue(const std::string& confDir, const std::string& intf)
418{
419 bool dhcp = false;
420 // Get the interface mode value from systemd conf
Gunnar Mills57d9c502018-09-14 14:42:34 -0500421 // using namespace std::string_literals;
Ratan Gupta56187e72017-08-13 09:40:14 +0530422 fs::path confPath = confDir;
423 std::string fileName = systemd::config::networkFilePrefix + intf +
424 systemd::config::networkFileSuffix;
425 confPath /= fileName;
426
Ratan Guptac27170a2017-11-22 15:44:42 +0530427 auto rc = config::ReturnCode::SUCCESS;
428 config::ValueList values;
429 config::Parser parser(confPath.string());
430
431 std::tie(rc, values) = parser.getValues("Network", "DHCP");
432 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta56187e72017-08-13 09:40:14 +0530433 {
Ratan Guptac27170a2017-11-22 15:44:42 +0530434 log<level::DEBUG>("Unable to get the value for Network[DHCP]",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500435 entry("RC=%d", rc));
Ratan Guptac27170a2017-11-22 15:44:42 +0530436 return dhcp;
Ratan Gupta56187e72017-08-13 09:40:14 +0530437 }
Ratan Guptac27170a2017-11-22 15:44:42 +0530438 // There will be only single value for DHCP key.
439 if (values[0] == "true")
Ratan Gupta56187e72017-08-13 09:40:14 +0530440 {
Ratan Guptac27170a2017-11-22 15:44:42 +0530441 dhcp = true;
Ratan Gupta56187e72017-08-13 09:40:14 +0530442 }
443 return dhcp;
444}
445
Ratan Guptabd303b12017-08-18 17:10:07 +0530446namespace internal
447{
Ratan Gupta56187e72017-08-13 09:40:14 +0530448
Ratan Guptabd303b12017-08-18 17:10:07 +0530449void executeCommandinChildProcess(const char* path, char** args)
450{
451 using namespace std::string_literals;
452 pid_t pid = fork();
Gunnar Mills57d9c502018-09-14 14:42:34 -0500453 int status{};
Ratan Guptabd303b12017-08-18 17:10:07 +0530454
455 if (pid == 0)
456 {
457 execv(path, args);
458 auto error = errno;
459 // create the command from var args.
460 std::string command = path + " "s;
461
Gunnar Mills57d9c502018-09-14 14:42:34 -0500462 for (int i = 0; args[i]; i++)
Ratan Guptabd303b12017-08-18 17:10:07 +0530463 {
Gunnar Mills57d9c502018-09-14 14:42:34 -0500464 command += args[i] + " "s;
Ratan Guptabd303b12017-08-18 17:10:07 +0530465 }
466
467 log<level::ERR>("Couldn't exceute the command",
468 entry("ERRNO=%d", error),
469 entry("CMD=%s", command.c_str()));
470 elog<InternalFailure>();
471 }
472 else if (pid < 0)
473 {
474 auto error = errno;
Gunnar Mills57d9c502018-09-14 14:42:34 -0500475 log<level::ERR>("Error occurred during fork", entry("ERRNO=%d", error));
Ratan Guptabd303b12017-08-18 17:10:07 +0530476 elog<InternalFailure>();
477 }
478 else if (pid > 0)
479 {
480 while (waitpid(pid, &status, 0) == -1)
481 {
482 if (errno != EINTR)
Gunnar Mills57d9c502018-09-14 14:42:34 -0500483 { // Error other than EINTR
Ratan Guptabd303b12017-08-18 17:10:07 +0530484 status = -1;
485 break;
486 }
487 }
488
Gunnar Mills57d9c502018-09-14 14:42:34 -0500489 if (status < 0)
Ratan Guptabd303b12017-08-18 17:10:07 +0530490 {
491 std::string command = path + " "s;
Gunnar Mills57d9c502018-09-14 14:42:34 -0500492 for (int i = 0; args[i]; i++)
Ratan Guptabd303b12017-08-18 17:10:07 +0530493 {
494 command += args[i] + " "s;
495 }
496
497 log<level::ERR>("Unable to execute the command",
Joseph Reynolds02653ca2018-05-10 15:55:09 -0500498 entry("CMD=%s", command.c_str()),
499 entry("STATUS=%d", status));
Ratan Guptabd303b12017-08-18 17:10:07 +0530500 elog<InternalFailure>();
501 }
502 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530503}
Gunnar Mills57d9c502018-09-14 14:42:34 -0500504} // namespace internal
Ratan Guptabd303b12017-08-18 17:10:07 +0530505
506namespace mac_address
507{
508
509constexpr auto mapperBus = "xyz.openbmc_project.ObjectMapper";
510constexpr auto mapperObj = "/xyz/openbmc_project/object_mapper";
511constexpr auto mapperIntf = "xyz.openbmc_project.ObjectMapper";
512constexpr auto propIntf = "org.freedesktop.DBus.Properties";
513constexpr auto methodGet = "Get";
514
515using DbusObjectPath = std::string;
516using DbusService = std::string;
517using DbusInterface = std::string;
Gunnar Mills57d9c502018-09-14 14:42:34 -0500518using ObjectTree =
519 std::map<DbusObjectPath, std::map<DbusService, std::vector<DbusInterface>>>;
Ratan Guptabd303b12017-08-18 17:10:07 +0530520
521constexpr auto invBus = "xyz.openbmc_project.Inventory.Manager";
522constexpr auto invNetworkIntf =
Gunnar Mills57d9c502018-09-14 14:42:34 -0500523 "xyz.openbmc_project.Inventory.Item.NetworkInterface";
Ratan Guptabd303b12017-08-18 17:10:07 +0530524constexpr auto invRoot = "/xyz/openbmc_project/inventory";
525
526std::string getfromInventory(sdbusplus::bus::bus& bus)
527{
528 std::vector<DbusInterface> interfaces;
529 interfaces.emplace_back(invNetworkIntf);
530
531 auto depth = 0;
532
Gunnar Mills57d9c502018-09-14 14:42:34 -0500533 auto mapperCall =
534 bus.new_method_call(mapperBus, mapperObj, mapperIntf, "GetSubTree");
Ratan Guptabd303b12017-08-18 17:10:07 +0530535
536 mapperCall.append(invRoot, depth, interfaces);
537
538 auto mapperReply = bus.call(mapperCall);
539 if (mapperReply.is_method_error())
540 {
541 log<level::ERR>("Error in mapper call");
542 elog<InternalFailure>();
543 }
544
545 ObjectTree objectTree;
546 mapperReply.read(objectTree);
547
548 if (objectTree.empty())
549 {
550 log<level::ERR>("No Object has implemented the interface",
551 entry("INTERFACE=%s", invNetworkIntf));
552 elog<InternalFailure>();
553 }
554
Gunnar Millsa251a782017-09-26 16:49:08 -0500555 // It is expected that only one object has implemented this interface.
Ratan Guptabd303b12017-08-18 17:10:07 +0530556
557 auto objPath = objectTree.begin()->first;
558 auto service = objectTree.begin()->second.begin()->first;
559
560 sdbusplus::message::variant<std::string> value;
561
Gunnar Mills57d9c502018-09-14 14:42:34 -0500562 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
563 propIntf, methodGet);
Ratan Guptabd303b12017-08-18 17:10:07 +0530564
565 method.append(invNetworkIntf, "MACAddress");
566
567 auto reply = bus.call(method);
568 if (reply.is_method_error())
569 {
Gunnar Mills57d9c502018-09-14 14:42:34 -0500570 log<level::ERR>("Failed to get MACAddress",
Ratan Guptabd303b12017-08-18 17:10:07 +0530571 entry("PATH=%s", objPath.c_str()),
572 entry("INTERFACE=%s", invNetworkIntf));
573 elog<InternalFailure>();
574 }
575
576 reply.read(value);
William A. Kennington III79e44152018-11-06 16:46:01 -0800577 return sdbusplus::message::variant_ns::get<std::string>(value);
Ratan Guptabd303b12017-08-18 17:10:07 +0530578}
579
William A. Kennington IIId27410f2019-01-30 17:15:43 -0800580std::string toString(const MacAddr& mac)
581{
582 std::string str;
583 str.reserve(mac.size() * 3);
584 for (size_t i = 0; i < mac.size(); ++i)
585 {
586 str.push_back(internal::toHex(mac[i] >> 4));
587 str.push_back(internal::toHex(mac[i]));
588 str.push_back(':');
589 }
590 // Remove trailing semicolon
591 str.pop_back();
592 return str;
593}
594
Gunnar Mills57d9c502018-09-14 14:42:34 -0500595} // namespace mac_address
596} // namespace network
597} // namespace phosphor