xref: /openbmc/phosphor-networkd/src/util.cpp (revision 57dfea94549af7bb60ad1d420abc98900efb5891)
1324d260eSWilliam A. Kennington III #include "config.h"
2324d260eSWilliam A. Kennington III 
31bbe3d1eSWilliam A. Kennington III #include "util.hpp"
41bbe3d1eSWilliam A. Kennington III 
51bbe3d1eSWilliam A. Kennington III #include "config_parser.hpp"
61bbe3d1eSWilliam A. Kennington III #include "types.hpp"
71bbe3d1eSWilliam A. Kennington III 
81bbe3d1eSWilliam A. Kennington III #include <sys/wait.h>
91bbe3d1eSWilliam A. Kennington III 
101bbe3d1eSWilliam A. Kennington III #include <phosphor-logging/elog-errors.hpp>
11f78a415eSJagpal Singh Gill #include <phosphor-logging/lg2.hpp>
129b2a20d3SWilliam A. Kennington III #include <stdplus/numeric/str.hpp>
138664252aSWilliam A. Kennington III #include <stdplus/str/buf.hpp>
148664252aSWilliam A. Kennington III #include <stdplus/str/cat.hpp>
1589d734b9SPatrick Williams #include <xyz/openbmc_project/Common/error.hpp>
1689d734b9SPatrick Williams 
1789d734b9SPatrick Williams #include <cctype>
181bbe3d1eSWilliam A. Kennington III #include <string>
19feb7aab0SWilliam A. Kennington III #include <string_view>
201bbe3d1eSWilliam A. Kennington III 
211bbe3d1eSWilliam A. Kennington III namespace phosphor
221bbe3d1eSWilliam A. Kennington III {
231bbe3d1eSWilliam A. Kennington III namespace network
241bbe3d1eSWilliam A. Kennington III {
251bbe3d1eSWilliam A. Kennington III 
2669f4554bSWilliam A. Kennington III using std::literals::string_view_literals::operator""sv;
271bbe3d1eSWilliam A. Kennington III using namespace phosphor::logging;
281bbe3d1eSWilliam A. Kennington III using namespace sdbusplus::xyz::openbmc_project::Common::Error;
291bbe3d1eSWilliam A. Kennington III 
301bbe3d1eSWilliam A. Kennington III namespace internal
311bbe3d1eSWilliam A. Kennington III {
321bbe3d1eSWilliam A. Kennington III 
executeCommandinChildProcess(stdplus::zstring_view path,char ** args)338664252aSWilliam A. Kennington III void executeCommandinChildProcess(stdplus::zstring_view path, char** args)
341bbe3d1eSWilliam A. Kennington III {
351bbe3d1eSWilliam A. Kennington III     using namespace std::string_literals;
361bbe3d1eSWilliam A. Kennington III     pid_t pid = fork();
371bbe3d1eSWilliam A. Kennington III 
381bbe3d1eSWilliam A. Kennington III     if (pid == 0)
391bbe3d1eSWilliam A. Kennington III     {
4069f4554bSWilliam A. Kennington III         execv(path.c_str(), args);
4169f4554bSWilliam A. Kennington III         exit(255);
421bbe3d1eSWilliam A. Kennington III     }
431bbe3d1eSWilliam A. Kennington III     else if (pid < 0)
441bbe3d1eSWilliam A. Kennington III     {
451bbe3d1eSWilliam A. Kennington III         auto error = errno;
46f78a415eSJagpal Singh Gill         lg2::error("Error occurred during fork: {ERRNO}", "ERRNO", error);
471bbe3d1eSWilliam A. Kennington III         elog<InternalFailure>();
481bbe3d1eSWilliam A. Kennington III     }
491bbe3d1eSWilliam A. Kennington III     else if (pid > 0)
501bbe3d1eSWilliam A. Kennington III     {
5169f4554bSWilliam A. Kennington III         int status;
521bbe3d1eSWilliam A. Kennington III         while (waitpid(pid, &status, 0) == -1)
531bbe3d1eSWilliam A. Kennington III         {
541bbe3d1eSWilliam A. Kennington III             if (errno != EINTR)
5569f4554bSWilliam A. Kennington III             {
561bbe3d1eSWilliam A. Kennington III                 status = -1;
571bbe3d1eSWilliam A. Kennington III                 break;
581bbe3d1eSWilliam A. Kennington III             }
591bbe3d1eSWilliam A. Kennington III         }
601bbe3d1eSWilliam A. Kennington III 
611bbe3d1eSWilliam A. Kennington III         if (status < 0)
621bbe3d1eSWilliam A. Kennington III         {
638664252aSWilliam A. Kennington III             stdplus::StrBuf buf;
648664252aSWilliam A. Kennington III             stdplus::strAppend(buf, "`"sv, path, "`"sv);
6569f4554bSWilliam A. Kennington III             for (size_t i = 0; args[i] != nullptr; ++i)
661bbe3d1eSWilliam A. Kennington III             {
678664252aSWilliam A. Kennington III                 stdplus::strAppend(buf, " `"sv, args[i], "`"sv);
681bbe3d1eSWilliam A. Kennington III             }
6969f4554bSWilliam A. Kennington III             buf.push_back('\0');
70f78a415eSJagpal Singh Gill             lg2::error("Unable to execute the command {CMD}: {STATUS}", "CMD",
71f78a415eSJagpal Singh Gill                        buf.data(), "STATUS", status);
721bbe3d1eSWilliam A. Kennington III             elog<InternalFailure>();
731bbe3d1eSWilliam A. Kennington III         }
741bbe3d1eSWilliam A. Kennington III     }
751bbe3d1eSWilliam A. Kennington III }
761bbe3d1eSWilliam A. Kennington III 
771bbe3d1eSWilliam A. Kennington III /** @brief Get ignored interfaces from environment */
getIgnoredInterfacesEnv()781bbe3d1eSWilliam A. Kennington III std::string_view getIgnoredInterfacesEnv()
791bbe3d1eSWilliam A. Kennington III {
801bbe3d1eSWilliam A. Kennington III     auto r = std::getenv("IGNORED_INTERFACES");
811bbe3d1eSWilliam A. Kennington III     if (r == nullptr)
821bbe3d1eSWilliam A. Kennington III     {
831bbe3d1eSWilliam A. Kennington III         return "";
841bbe3d1eSWilliam A. Kennington III     }
851bbe3d1eSWilliam A. Kennington III     return r;
861bbe3d1eSWilliam A. Kennington III }
871bbe3d1eSWilliam A. Kennington III 
881bbe3d1eSWilliam A. Kennington III /** @brief Parse the comma separated interface names */
8995530ec9SWilliam A. Kennington III std::unordered_set<std::string_view>
parseInterfaces(std::string_view interfaces)9095530ec9SWilliam A. Kennington III     parseInterfaces(std::string_view interfaces)
911bbe3d1eSWilliam A. Kennington III {
9295530ec9SWilliam A. Kennington III     std::unordered_set<std::string_view> result;
931bbe3d1eSWilliam A. Kennington III     while (true)
941bbe3d1eSWilliam A. Kennington III     {
951bbe3d1eSWilliam A. Kennington III         auto sep = interfaces.find(',');
961bbe3d1eSWilliam A. Kennington III         auto interface = interfaces.substr(0, sep);
971bbe3d1eSWilliam A. Kennington III         while (!interface.empty() && std::isspace(interface.front()))
981bbe3d1eSWilliam A. Kennington III         {
991bbe3d1eSWilliam A. Kennington III             interface.remove_prefix(1);
1001bbe3d1eSWilliam A. Kennington III         }
1011bbe3d1eSWilliam A. Kennington III         while (!interface.empty() && std::isspace(interface.back()))
1021bbe3d1eSWilliam A. Kennington III         {
1031bbe3d1eSWilliam A. Kennington III             interface.remove_suffix(1);
1041bbe3d1eSWilliam A. Kennington III         }
1051bbe3d1eSWilliam A. Kennington III         if (!interface.empty())
1061bbe3d1eSWilliam A. Kennington III         {
1071bbe3d1eSWilliam A. Kennington III             result.insert(interface);
1081bbe3d1eSWilliam A. Kennington III         }
1091bbe3d1eSWilliam A. Kennington III         if (sep == interfaces.npos)
1101bbe3d1eSWilliam A. Kennington III         {
1111bbe3d1eSWilliam A. Kennington III             break;
1121bbe3d1eSWilliam A. Kennington III         }
1131bbe3d1eSWilliam A. Kennington III         interfaces = interfaces.substr(sep + 1);
1141bbe3d1eSWilliam A. Kennington III     }
1151bbe3d1eSWilliam A. Kennington III     return result;
1161bbe3d1eSWilliam A. Kennington III }
1171bbe3d1eSWilliam A. Kennington III 
1181bbe3d1eSWilliam A. Kennington III /** @brief Get the ignored interfaces */
getIgnoredInterfaces()11995530ec9SWilliam A. Kennington III const std::unordered_set<std::string_view>& getIgnoredInterfaces()
1201bbe3d1eSWilliam A. Kennington III {
1211bbe3d1eSWilliam A. Kennington III     static auto ignoredInterfaces = parseInterfaces(getIgnoredInterfacesEnv());
1221bbe3d1eSWilliam A. Kennington III     return ignoredInterfaces;
1231bbe3d1eSWilliam A. Kennington III }
1241bbe3d1eSWilliam A. Kennington III 
1251bbe3d1eSWilliam A. Kennington III } // namespace internal
1261bbe3d1eSWilliam A. Kennington III 
interfaceToUbootEthAddr(std::string_view intf)12769f4554bSWilliam A. Kennington III std::optional<std::string> interfaceToUbootEthAddr(std::string_view intf)
1281bbe3d1eSWilliam A. Kennington III {
12969f4554bSWilliam A. Kennington III     constexpr auto pfx = "eth"sv;
13069f4554bSWilliam A. Kennington III     if (!intf.starts_with(pfx))
1311bbe3d1eSWilliam A. Kennington III     {
1321bbe3d1eSWilliam A. Kennington III         return std::nullopt;
1331bbe3d1eSWilliam A. Kennington III     }
13469f4554bSWilliam A. Kennington III     intf.remove_prefix(pfx.size());
135d6bd8fbeSWilliam A. Kennington III     unsigned idx;
136d6bd8fbeSWilliam A. Kennington III     try
137d6bd8fbeSWilliam A. Kennington III     {
1389b2a20d3SWilliam A. Kennington III         idx = stdplus::StrToInt<10, unsigned>{}(intf);
139d6bd8fbeSWilliam A. Kennington III     }
140d6bd8fbeSWilliam A. Kennington III     catch (...)
1411bbe3d1eSWilliam A. Kennington III     {
1421bbe3d1eSWilliam A. Kennington III         return std::nullopt;
1431bbe3d1eSWilliam A. Kennington III     }
1441bbe3d1eSWilliam A. Kennington III     if (idx == 0)
1451bbe3d1eSWilliam A. Kennington III     {
1461bbe3d1eSWilliam A. Kennington III         return "ethaddr";
1471bbe3d1eSWilliam A. Kennington III     }
1488664252aSWilliam A. Kennington III     stdplus::ToStrHandle<stdplus::IntToStr<10, unsigned>> tsh;
1498664252aSWilliam A. Kennington III     return stdplus::strCat("eth"sv, tsh(idx), "addr"sv);
1501bbe3d1eSWilliam A. Kennington III }
1511bbe3d1eSWilliam A. Kennington III 
systemdParseDHCP(std::string_view str)152e94c9ffcSWilliam A. Kennington III static std::optional<DHCPVal> systemdParseDHCP(std::string_view str)
153e94c9ffcSWilliam A. Kennington III {
154e94c9ffcSWilliam A. Kennington III     if (config::icaseeq(str, "ipv4"))
155e94c9ffcSWilliam A. Kennington III     {
156e94c9ffcSWilliam A. Kennington III         return DHCPVal{.v4 = true, .v6 = false};
157e94c9ffcSWilliam A. Kennington III     }
158e94c9ffcSWilliam A. Kennington III     if (config::icaseeq(str, "ipv6"))
159e94c9ffcSWilliam A. Kennington III     {
160e94c9ffcSWilliam A. Kennington III         return DHCPVal{.v4 = false, .v6 = true};
161e94c9ffcSWilliam A. Kennington III     }
162e94c9ffcSWilliam A. Kennington III     if (auto b = config::parseBool(str); b)
163e94c9ffcSWilliam A. Kennington III     {
164e94c9ffcSWilliam A. Kennington III         return DHCPVal{.v4 = *b, .v6 = *b};
165e94c9ffcSWilliam A. Kennington III     }
166e94c9ffcSWilliam A. Kennington III     return std::nullopt;
167e94c9ffcSWilliam A. Kennington III }
168e94c9ffcSWilliam A. Kennington III 
systemdParseLast(const config::Parser & config,std::string_view section,std::string_view key,auto && fun)169e94c9ffcSWilliam A. Kennington III inline auto systemdParseLast(const config::Parser& config,
170e94c9ffcSWilliam A. Kennington III                              std::string_view section, std::string_view key,
171e94c9ffcSWilliam A. Kennington III                              auto&& fun)
172e94c9ffcSWilliam A. Kennington III {
1734a688fc1SWilliam A. Kennington III     if (!config.getFileExists())
17489d734b9SPatrick Williams     {}
1754a688fc1SWilliam A. Kennington III     else if (auto str = config.map.getLastValueString(section, key);
1764a688fc1SWilliam A. Kennington III              str == nullptr)
177e94c9ffcSWilliam A. Kennington III     {
1781d25ca4eSWilliam A. Kennington III         lg2::notice(
1791d25ca4eSWilliam A. Kennington III             "Unable to get the value of {CFG_SEC}[{CFG_KEY}] from {CFG_FILE}",
1801d25ca4eSWilliam A. Kennington III             "CFG_SEC", section, "CFG_KEY", key, "CFG_FILE",
181f78a415eSJagpal Singh Gill             config.getFilename());
182e94c9ffcSWilliam A. Kennington III     }
183e94c9ffcSWilliam A. Kennington III     else if (auto val = fun(*str); !val)
184e94c9ffcSWilliam A. Kennington III     {
1851d25ca4eSWilliam A. Kennington III         lg2::notice(
1861d25ca4eSWilliam A. Kennington III             "Invalid value of {CFG_SEC}[{CFG_KEY}] from {CFG_FILE}: {CFG_VAL}",
1871d25ca4eSWilliam A. Kennington III             "CFG_SEC", section, "CFG_KEY", key, "CFG_FILE",
1881d25ca4eSWilliam A. Kennington III             config.getFilename(), "CFG_VAL", *str);
189e94c9ffcSWilliam A. Kennington III     }
190e94c9ffcSWilliam A. Kennington III     else
191e94c9ffcSWilliam A. Kennington III     {
192e94c9ffcSWilliam A. Kennington III         return val;
193e94c9ffcSWilliam A. Kennington III     }
194e94c9ffcSWilliam A. Kennington III     return decltype(fun(std::string_view{}))(std::nullopt);
195e94c9ffcSWilliam A. Kennington III }
196e94c9ffcSWilliam A. Kennington III 
getIPv6AcceptRA(const config::Parser & config)197a520a39dSWilliam A. Kennington III bool getIPv6AcceptRA(const config::Parser& config)
1981bbe3d1eSWilliam A. Kennington III {
199324d260eSWilliam A. Kennington III #ifdef ENABLE_IPV6_ACCEPT_RA
200324d260eSWilliam A. Kennington III     constexpr bool def = true;
201324d260eSWilliam A. Kennington III #else
202324d260eSWilliam A. Kennington III     constexpr bool def = false;
203324d260eSWilliam A. Kennington III #endif
204e94c9ffcSWilliam A. Kennington III     return systemdParseLast(config, "Network", "IPv6AcceptRA",
205e94c9ffcSWilliam A. Kennington III                             config::parseBool)
206e94c9ffcSWilliam A. Kennington III         .value_or(def);
207a520a39dSWilliam A. Kennington III }
208a520a39dSWilliam A. Kennington III 
getDHCPValue(const config::Parser & config)2098060c0daSWilliam A. Kennington III DHCPVal getDHCPValue(const config::Parser& config)
210a520a39dSWilliam A. Kennington III {
211e94c9ffcSWilliam A. Kennington III     return systemdParseLast(config, "Network", "DHCP", systemdParseDHCP)
212e94c9ffcSWilliam A. Kennington III         .value_or(DHCPVal{.v4 = true, .v6 = true});
213e94c9ffcSWilliam A. Kennington III }
214324d260eSWilliam A. Kennington III 
getDHCPProp(const config::Parser & config,DHCPType dhcpType,std::string_view key)215*57dfea94SJishnu CM bool getDHCPProp(const config::Parser& config, DHCPType dhcpType,
216*57dfea94SJishnu CM                  std::string_view key)
217a520a39dSWilliam A. Kennington III {
218*57dfea94SJishnu CM     std::string_view type = (dhcpType == DHCPType::v4) ? "DHCPv4" : "DHCPv6";
219*57dfea94SJishnu CM 
220*57dfea94SJishnu CM     if (!config.map.contains(type))
221*57dfea94SJishnu CM     {
222*57dfea94SJishnu CM         type = "DHCP";
223*57dfea94SJishnu CM     }
224*57dfea94SJishnu CM 
225*57dfea94SJishnu CM     return systemdParseLast(config, type, key, config::parseBool)
226e94c9ffcSWilliam A. Kennington III         .value_or(true);
2271bbe3d1eSWilliam A. Kennington III }
2281bbe3d1eSWilliam A. Kennington III 
2291bbe3d1eSWilliam A. Kennington III } // namespace network
2301bbe3d1eSWilliam A. Kennington III } // namespace phosphor
231