blob: 14a1cb39b32b88d89ff350f9fa86e97067692906 [file] [log] [blame]
William A. Kennington III324d2602022-08-18 18:32:56 -07001#include "config.h"
2
Ratan Gupta3681a502017-06-17 19:20:04 +05303#include "util.hpp"
Ratan Gupta11cef802017-05-29 08:41:48 +05304
Patrick Venture189d44e2018-07-09 12:30:59 -07005#include "config_parser.hpp"
6#include "types.hpp"
Ratan Gupta8804feb2017-05-25 10:49:57 +05307
William A. Kennington III1c776022022-01-05 14:12:16 -08008#include <fmt/compile.h>
9#include <fmt/format.h>
Ratan Guptabc886292017-07-25 18:29:57 +053010#include <sys/wait.h>
Ratan Gupta3681a502017-06-17 19:20:04 +053011
Lei YU307554e2021-03-18 14:56:50 +080012#include <cctype>
Patrick Venture189d44e2018-07-09 12:30:59 -070013#include <phosphor-logging/elog-errors.hpp>
14#include <phosphor-logging/log.hpp>
15#include <string>
William A. Kennington IIIfeb7aab2022-10-03 17:21:44 -070016#include <string_view>
Patrick Venture189d44e2018-07-09 12:30:59 -070017#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta8804feb2017-05-25 10:49:57 +053018
19namespace phosphor
20{
21namespace network
22{
Ratan Guptabc886292017-07-25 18:29:57 +053023
William A. Kennington III69f45542022-09-24 23:28:14 -070024using std::literals::string_view_literals::operator""sv;
Ratan Gupta8804feb2017-05-25 10:49:57 +053025using namespace phosphor::logging;
Ratan Gupta11cef802017-05-29 08:41:48 +053026using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Ratan Gupta8804feb2017-05-25 10:49:57 +053027
Lei YU3894ce72021-03-18 14:53:42 +080028namespace internal
29{
30
William A. Kennington III69f45542022-09-24 23:28:14 -070031void executeCommandinChildProcess(stdplus::const_zstring path, char** args)
Lei YU3894ce72021-03-18 14:53:42 +080032{
33 using namespace std::string_literals;
34 pid_t pid = fork();
Lei YU3894ce72021-03-18 14:53:42 +080035
36 if (pid == 0)
37 {
William A. Kennington III69f45542022-09-24 23:28:14 -070038 execv(path.c_str(), args);
39 exit(255);
Lei YU3894ce72021-03-18 14:53:42 +080040 }
41 else if (pid < 0)
42 {
43 auto error = errno;
44 log<level::ERR>("Error occurred during fork", entry("ERRNO=%d", error));
45 elog<InternalFailure>();
46 }
47 else if (pid > 0)
48 {
William A. Kennington III69f45542022-09-24 23:28:14 -070049 int status;
Lei YU3894ce72021-03-18 14:53:42 +080050 while (waitpid(pid, &status, 0) == -1)
51 {
52 if (errno != EINTR)
William A. Kennington III69f45542022-09-24 23:28:14 -070053 {
Lei YU3894ce72021-03-18 14:53:42 +080054 status = -1;
55 break;
56 }
57 }
58
59 if (status < 0)
60 {
William A. Kennington III69f45542022-09-24 23:28:14 -070061 fmt::memory_buffer buf;
62 fmt::format_to(fmt::appender(buf), "`{}`", path);
63 for (size_t i = 0; args[i] != nullptr; ++i)
Lei YU3894ce72021-03-18 14:53:42 +080064 {
William A. Kennington III69f45542022-09-24 23:28:14 -070065 fmt::format_to(fmt::appender(buf), " `{}`", args[i]);
Lei YU3894ce72021-03-18 14:53:42 +080066 }
William A. Kennington III69f45542022-09-24 23:28:14 -070067 buf.push_back('\0');
Lei YU3894ce72021-03-18 14:53:42 +080068 log<level::ERR>("Unable to execute the command",
William A. Kennington III69f45542022-09-24 23:28:14 -070069 entry("CMD=%s", buf.data()),
Lei YU3894ce72021-03-18 14:53:42 +080070 entry("STATUS=%d", status));
71 elog<InternalFailure>();
72 }
73 }
74}
75
Lei YU307554e2021-03-18 14:56:50 +080076/** @brief Get ignored interfaces from environment */
William A. Kennington IIIee5b2c92021-04-28 02:31:28 -070077std::string_view getIgnoredInterfacesEnv()
Lei YU307554e2021-03-18 14:56:50 +080078{
79 auto r = std::getenv("IGNORED_INTERFACES");
80 if (r == nullptr)
81 {
William A. Kennington IIIee5b2c92021-04-28 02:31:28 -070082 return "";
Lei YU307554e2021-03-18 14:56:50 +080083 }
84 return r;
85}
86
87/** @brief Parse the comma separated interface names */
William A. Kennington III95530ec2022-08-19 01:44:39 -070088std::unordered_set<std::string_view>
89 parseInterfaces(std::string_view interfaces)
Lei YU307554e2021-03-18 14:56:50 +080090{
William A. Kennington III95530ec2022-08-19 01:44:39 -070091 std::unordered_set<std::string_view> result;
William A. Kennington IIIee5b2c92021-04-28 02:31:28 -070092 while (true)
Lei YU307554e2021-03-18 14:56:50 +080093 {
William A. Kennington IIIee5b2c92021-04-28 02:31:28 -070094 auto sep = interfaces.find(',');
95 auto interface = interfaces.substr(0, sep);
96 while (!interface.empty() && std::isspace(interface.front()))
Lei YU307554e2021-03-18 14:56:50 +080097 {
William A. Kennington IIIee5b2c92021-04-28 02:31:28 -070098 interface.remove_prefix(1);
Lei YU307554e2021-03-18 14:56:50 +080099 }
William A. Kennington IIIee5b2c92021-04-28 02:31:28 -0700100 while (!interface.empty() && std::isspace(interface.back()))
Lei YU307554e2021-03-18 14:56:50 +0800101 {
William A. Kennington IIIee5b2c92021-04-28 02:31:28 -0700102 interface.remove_suffix(1);
Lei YU307554e2021-03-18 14:56:50 +0800103 }
William A. Kennington IIIee5b2c92021-04-28 02:31:28 -0700104 if (!interface.empty())
105 {
106 result.insert(interface);
107 }
108 if (sep == interfaces.npos)
109 {
110 break;
111 }
112 interfaces = interfaces.substr(sep + 1);
Lei YU307554e2021-03-18 14:56:50 +0800113 }
114 return result;
115}
116
117/** @brief Get the ignored interfaces */
William A. Kennington III95530ec2022-08-19 01:44:39 -0700118const std::unordered_set<std::string_view>& getIgnoredInterfaces()
Lei YU307554e2021-03-18 14:56:50 +0800119{
120 static auto ignoredInterfaces = parseInterfaces(getIgnoredInterfacesEnv());
121 return ignoredInterfaces;
122}
123
Lei YU3894ce72021-03-18 14:53:42 +0800124} // namespace internal
Ratan Gupta8804feb2017-05-25 10:49:57 +0530125
William A. Kennington III69f45542022-09-24 23:28:14 -0700126std::optional<std::string> interfaceToUbootEthAddr(std::string_view intf)
William A. Kennington III7b9e8bd2019-04-23 19:31:31 -0700127{
William A. Kennington III69f45542022-09-24 23:28:14 -0700128 constexpr auto pfx = "eth"sv;
129 if (!intf.starts_with(pfx))
William A. Kennington III7b9e8bd2019-04-23 19:31:31 -0700130 {
131 return std::nullopt;
132 }
William A. Kennington III69f45542022-09-24 23:28:14 -0700133 intf.remove_prefix(pfx.size());
William A. Kennington IIId6bd8fb2022-11-17 18:10:06 -0800134 unsigned idx;
135 try
136 {
137 idx = DecodeInt<unsigned, 10>{}(intf);
138 }
139 catch (...)
William A. Kennington III7b9e8bd2019-04-23 19:31:31 -0700140 {
141 return std::nullopt;
142 }
143 if (idx == 0)
144 {
145 return "ethaddr";
146 }
William A. Kennington III69f45542022-09-24 23:28:14 -0700147 return fmt::format(FMT_COMPILE("eth{}addr"), idx);
William A. Kennington III7b9e8bd2019-04-23 19:31:31 -0700148}
149
William A. Kennington IIIe94c9ff2022-08-18 20:12:27 -0700150static std::optional<DHCPVal> systemdParseDHCP(std::string_view str)
151{
152 if (config::icaseeq(str, "ipv4"))
153 {
154 return DHCPVal{.v4 = true, .v6 = false};
155 }
156 if (config::icaseeq(str, "ipv6"))
157 {
158 return DHCPVal{.v4 = false, .v6 = true};
159 }
160 if (auto b = config::parseBool(str); b)
161 {
162 return DHCPVal{.v4 = *b, .v6 = *b};
163 }
164 return std::nullopt;
165}
166
167inline auto systemdParseLast(const config::Parser& config,
168 std::string_view section, std::string_view key,
169 auto&& fun)
170{
William A. Kennington III4a688fc2022-11-15 15:58:44 -0800171 if (!config.getFileExists())
172 {
173 }
174 else if (auto str = config.map.getLastValueString(section, key);
175 str == nullptr)
William A. Kennington IIIe94c9ff2022-08-18 20:12:27 -0700176 {
177 auto err = fmt::format("Unable to get the value of {}[{}] from {}",
178 section, key, config.getFilename().native());
179 log<level::NOTICE>(err.c_str(),
180 entry("FILE=%s", config.getFilename().c_str()));
181 }
182 else if (auto val = fun(*str); !val)
183 {
184 auto err = fmt::format("Invalid value of {}[{}] from {}: {}", section,
185 key, config.getFilename().native(), *str);
186 log<level::NOTICE>(err.c_str(), entry("VALUE=%s", str->c_str()),
187 entry("FILE=%s", config.getFilename().c_str()));
188 }
189 else
190 {
191 return val;
192 }
193 return decltype(fun(std::string_view{}))(std::nullopt);
194}
195
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700196bool getIPv6AcceptRA(const config::Parser& config)
Ratan Gupta56187e72017-08-13 09:40:14 +0530197{
William A. Kennington III324d2602022-08-18 18:32:56 -0700198#ifdef ENABLE_IPV6_ACCEPT_RA
199 constexpr bool def = true;
200#else
201 constexpr bool def = false;
202#endif
William A. Kennington IIIe94c9ff2022-08-18 20:12:27 -0700203 return systemdParseLast(config, "Network", "IPv6AcceptRA",
204 config::parseBool)
205 .value_or(def);
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700206}
207
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700208DHCPVal getDHCPValue(const config::Parser& config)
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700209{
William A. Kennington IIIe94c9ff2022-08-18 20:12:27 -0700210 return systemdParseLast(config, "Network", "DHCP", systemdParseDHCP)
211 .value_or(DHCPVal{.v4 = true, .v6 = true});
212}
William A. Kennington III324d2602022-08-18 18:32:56 -0700213
William A. Kennington IIIe94c9ff2022-08-18 20:12:27 -0700214bool getDHCPProp(const config::Parser& config, std::string_view key)
215{
216 return systemdParseLast(config, "DHCP", key, config::parseBool)
217 .value_or(true);
Ratan Gupta56187e72017-08-13 09:40:14 +0530218}
219
Ratan Guptabd303b12017-08-18 17:10:07 +0530220namespace mac_address
221{
222
William A. Kennington III1137a972019-04-20 20:49:58 -0700223bool isEmpty(const ether_addr& mac)
224{
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700225 return mac == ether_addr{};
William A. Kennington III1137a972019-04-20 20:49:58 -0700226}
227
228bool isMulticast(const ether_addr& mac)
229{
230 return mac.ether_addr_octet[0] & 0b1;
231}
232
233bool isUnicast(const ether_addr& mac)
234{
235 return !isEmpty(mac) && !isMulticast(mac);
236}
237
Gunnar Mills57d9c502018-09-14 14:42:34 -0500238} // namespace mac_address
239} // namespace network
240} // namespace phosphor