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