blob: dc602afd35580cc020277d77e8995337b75cf380 [file] [log] [blame]
Patrick Venture690a2342020-05-17 11:51:31 -07001#include "transporthandler.hpp"
2
William A. Kennington III726f2bd2023-06-21 01:11:40 -07003#include <stdplus/net/addr/subnet.hpp>
William A. Kennington III7a3831b2023-06-21 01:10:49 -07004#include <stdplus/raw.hpp>
5
6#include <array>
William A. Kennington III726f2bd2023-06-21 01:11:40 -07007#include <fstream>
William A. Kennington III7a3831b2023-06-21 01:10:49 -07008
William A. Kennington IIIc514d872019-04-06 18:19:38 -07009using phosphor::logging::commit;
10using phosphor::logging::elog;
11using phosphor::logging::entry;
12using phosphor::logging::level;
13using phosphor::logging::log;
Willy Tu523e2d12023-09-05 11:36:48 -070014using sdbusplus::error::xyz::openbmc_project::common::InternalFailure;
William A. Kennington III7a3831b2023-06-21 01:10:49 -070015using sdbusplus::error::xyz::openbmc_project::common::InvalidArgument;
Willy Tu523e2d12023-09-05 11:36:48 -070016using sdbusplus::server::xyz::openbmc_project::network::EthernetInterface;
17using sdbusplus::server::xyz::openbmc_project::network::IP;
18using sdbusplus::server::xyz::openbmc_project::network::Neighbor;
William A. Kennington IIIc514d872019-04-06 18:19:38 -070019
Johnathan Manteyaffadb52019-10-07 10:13:53 -070020namespace cipher
21{
22
23std::vector<uint8_t> getCipherList()
24{
25 std::vector<uint8_t> cipherList;
26
27 std::ifstream jsonFile(cipher::configFile);
28 if (!jsonFile.is_open())
29 {
30 log<level::ERR>("Channel Cipher suites file not found");
31 elog<InternalFailure>();
32 }
33
34 auto data = Json::parse(jsonFile, nullptr, false);
35 if (data.is_discarded())
36 {
37 log<level::ERR>("Parsing channel cipher suites JSON failed");
38 elog<InternalFailure>();
39 }
40
41 // Byte 1 is reserved
42 cipherList.push_back(0x00);
43
44 for (const auto& record : data)
45 {
46 cipherList.push_back(record.value(cipher, 0));
47 }
48
49 return cipherList;
50}
51} // namespace cipher
52
53namespace ipmi
54{
55namespace transport
56{
57
William A. Kennington IIIc514d872019-04-06 18:19:38 -070058/** @brief Valid address origins for IPv4 */
59const std::unordered_set<IP::AddressOrigin> originsV4 = {
60 IP::AddressOrigin::Static,
61 IP::AddressOrigin::DHCP,
62};
63
Johnathan Manteyb87034e2019-09-16 10:50:50 -070064static constexpr uint8_t oemCmdStart = 192;
65static constexpr uint8_t oemCmdEnd = 255;
66
Patrick Williams5d82f472022-07-22 19:26:53 -050067std::optional<ChannelParams> maybeGetChannelParams(sdbusplus::bus_t& bus,
William A. Kennington IIIc514d872019-04-06 18:19:38 -070068 uint8_t channel)
69{
70 auto ifname = getChannelName(channel);
71 if (ifname.empty())
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080072 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -070073 return std::nullopt;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080074 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080075
William A. Kennington IIIc514d872019-04-06 18:19:38 -070076 // Enumerate all VLAN + ETHERNET interfaces
77 auto req = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF,
78 "GetSubTree");
79 req.append(PATH_ROOT, 0,
80 std::vector<std::string>{INTF_VLAN, INTF_ETHERNET});
81 auto reply = bus.call(req);
82 ObjectTree objs;
83 reply.read(objs);
84
85 ChannelParams params;
86 for (const auto& [path, impls] : objs)
87 {
88 if (path.find(ifname) == path.npos)
89 {
90 continue;
91 }
92 for (const auto& [service, intfs] : impls)
93 {
94 bool vlan = false;
95 bool ethernet = false;
96 for (const auto& intf : intfs)
97 {
98 if (intf == INTF_VLAN)
99 {
100 vlan = true;
101 }
102 else if (intf == INTF_ETHERNET)
103 {
104 ethernet = true;
105 }
106 }
107 if (params.service.empty() && (vlan || ethernet))
108 {
109 params.service = service;
110 }
111 if (params.ifPath.empty() && !vlan && ethernet)
112 {
113 params.ifPath = path;
114 }
115 if (params.logicalPath.empty() && vlan)
116 {
117 params.logicalPath = path;
118 }
119 }
120 }
121
122 // We must have a path for the underlying interface
123 if (params.ifPath.empty())
124 {
125 return std::nullopt;
126 }
127 // We don't have a VLAN so the logical path is the same
128 if (params.logicalPath.empty())
129 {
130 params.logicalPath = params.ifPath;
131 }
132
133 params.id = channel;
134 params.ifname = std::move(ifname);
Willy Tu11d68892022-01-20 10:37:34 -0800135 return params;
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700136}
137
Patrick Williams5d82f472022-07-22 19:26:53 -0500138ChannelParams getChannelParams(sdbusplus::bus_t& bus, uint8_t channel)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700139{
140 auto params = maybeGetChannelParams(bus, channel);
141 if (!params)
142 {
143 log<level::ERR>("Failed to get channel params",
144 entry("CHANNEL=%" PRIu8, channel));
145 elog<InternalFailure>();
146 }
147 return std::move(*params);
148}
149
150/** @brief Wraps the phosphor logging method to insert some additional metadata
151 *
152 * @param[in] params - The parameters for the channel
153 * ...
154 */
155template <auto level, typename... Args>
156auto logWithChannel(const ChannelParams& params, Args&&... args)
157{
158 return log<level>(std::forward<Args>(args)...,
159 entry("CHANNEL=%d", params.id),
160 entry("IFNAME=%s", params.ifname.c_str()));
161}
162template <auto level, typename... Args>
163auto logWithChannel(const std::optional<ChannelParams>& params, Args&&... args)
164{
165 if (params)
166 {
167 return logWithChannel<level>(*params, std::forward<Args>(args)...);
168 }
169 return log<level>(std::forward<Args>(args)...);
170}
171
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700172/** @brief Get / Set the Property value from phosphor-networkd EthernetInterface
173 */
174template <typename T>
175static T getEthProp(sdbusplus::bus_t& bus, const ChannelParams& params,
176 const std::string& prop)
177{
178 return std::get<T>(getDbusProperty(bus, params.service, params.logicalPath,
179 INTF_ETHERNET, prop));
180}
181template <typename T>
182static void setEthProp(sdbusplus::bus_t& bus, const ChannelParams& params,
183 const std::string& prop, const T& t)
184{
185 return setDbusProperty(bus, params.service, params.logicalPath,
186 INTF_ETHERNET, prop, t);
187}
188
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700189/** @brief Determines the MAC of the ethernet interface
190 *
191 * @param[in] bus - The bus object used for lookups
192 * @param[in] params - The parameters for the channel
193 * @return The configured mac address
194 */
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700195stdplus::EtherAddr getMACProperty(sdbusplus::bus_t& bus,
196 const ChannelParams& params)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700197{
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700198 auto prop = getDbusProperty(bus, params.service, params.ifPath, INTF_MAC,
199 "MACAddress");
200 return stdplus::fromStr<stdplus::EtherAddr>(std::get<std::string>(prop));
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700201}
202
203/** @brief Sets the system value for MAC address on the given interface
204 *
205 * @param[in] bus - The bus object used for lookups
206 * @param[in] params - The parameters for the channel
207 * @param[in] mac - MAC address to apply
208 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500209void setMACProperty(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700210 stdplus::EtherAddr mac)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700211{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700212 setDbusProperty(bus, params.service, params.ifPath, INTF_MAC, "MACAddress",
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700213 stdplus::toStr(mac));
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700214}
215
Patrick Williams5d82f472022-07-22 19:26:53 -0500216void deleteObjectIfExists(sdbusplus::bus_t& bus, const std::string& service,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700217 const std::string& path)
218{
219 if (path.empty())
220 {
221 return;
222 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530223 try
tomjose26e17732016-03-03 08:52:51 -0600224 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700225 auto req = bus.new_method_call(service.c_str(), path.c_str(),
226 ipmi::DELETE_INTERFACE, "Delete");
227 bus.call_noreply(req);
228 }
Patrick Williams5d82f472022-07-22 19:26:53 -0500229 catch (const sdbusplus::exception_t& e)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700230 {
jayaprakash Mutyala84c49dc2020-05-18 23:12:13 +0000231 if (strcmp(e.name(),
232 "xyz.openbmc_project.Common.Error.InternalFailure") != 0 &&
233 strcmp(e.name(), "org.freedesktop.DBus.Error.UnknownObject") != 0)
tomjose26e17732016-03-03 08:52:51 -0600234 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700235 // We want to rethrow real errors
236 throw;
tomjose26e17732016-03-03 08:52:51 -0600237 }
238 }
tomjose26e17732016-03-03 08:52:51 -0600239}
240
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700241/** @brief Sets the address info configured for the interface
242 * If a previous address path exists then it will be removed
243 * before the new address is added.
244 *
245 * @param[in] bus - The bus object used for lookups
246 * @param[in] params - The parameters for the channel
247 * @param[in] address - The address of the new IP
248 * @param[in] prefix - The prefix of the new IP
249 */
250template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500251void createIfAddr(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700252 typename AddrFamily<family>::addr address, uint8_t prefix)
Tom Josepha30c8d32018-03-22 02:15:03 +0530253{
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500254 auto newreq = bus.new_method_call(params.service.c_str(),
255 params.logicalPath.c_str(),
256 INTF_IP_CREATE, "IP");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700257 std::string protocol =
Willy Tu523e2d12023-09-05 11:36:48 -0700258 sdbusplus::common::xyz::openbmc_project::network::convertForMessage(
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700259 AddrFamily<family>::protocol);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700260 stdplus::ToStrHandle<stdplus::ToStr<typename AddrFamily<family>::addr>> tsh;
261 newreq.append(protocol, tsh(address), prefix, "");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700262 bus.call_noreply(newreq);
263}
Tom Josepha30c8d32018-03-22 02:15:03 +0530264
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700265/** @brief Trivial helper for getting the IPv4 address from getIfAddrs()
266 *
267 * @param[in] bus - The bus object used for lookups
268 * @param[in] params - The parameters for the channel
269 * @return The address and prefix if found
270 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500271auto getIfAddr4(sdbusplus::bus_t& bus, const ChannelParams& params)
Tom Josepha30c8d32018-03-22 02:15:03 +0530272{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700273 return getIfAddr<AF_INET>(bus, params, 0, originsV4);
274}
Tom Josepha30c8d32018-03-22 02:15:03 +0530275
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700276/** @brief Reconfigures the IPv4 address info configured for the interface
277 *
278 * @param[in] bus - The bus object used for lookups
279 * @param[in] params - The parameters for the channel
280 * @param[in] address - The new address if specified
281 * @param[in] prefix - The new address prefix if specified
282 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500283void reconfigureIfAddr4(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700284 std::optional<stdplus::In4Addr> address,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700285 std::optional<uint8_t> prefix)
286{
287 auto ifaddr = getIfAddr4(bus, params);
288 if (!ifaddr && !address)
Tom Josepha30c8d32018-03-22 02:15:03 +0530289 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700290 log<level::ERR>("Missing address for IPv4 assignment");
Tom Josepha30c8d32018-03-22 02:15:03 +0530291 elog<InternalFailure>();
292 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700293 uint8_t fallbackPrefix = AddrFamily<AF_INET>::defaultPrefix;
294 if (ifaddr)
Tom Josepha30c8d32018-03-22 02:15:03 +0530295 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700296 fallbackPrefix = ifaddr->prefix;
297 deleteObjectIfExists(bus, params.service, ifaddr->path);
298 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700299 auto addr = address.value_or(ifaddr->address);
300 if (addr != stdplus::In4Addr{})
Johnathan Manteycbfa6e12023-06-01 06:57:25 -0700301 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700302 createIfAddr<AF_INET>(bus, params, addr,
Johnathan Manteycbfa6e12023-06-01 06:57:25 -0700303 prefix.value_or(fallbackPrefix));
304 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700305}
306
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700307template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500308std::optional<IfNeigh<family>> findGatewayNeighbor(sdbusplus::bus_t& bus,
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700309 const ChannelParams& params,
310 ObjectLookupCache& neighbors)
311{
312 auto gateway = getGatewayProperty<family>(bus, params);
313 if (!gateway)
314 {
315 return std::nullopt;
316 }
317
318 return findStaticNeighbor<family>(bus, params, *gateway, neighbors);
319}
320
321template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500322std::optional<IfNeigh<family>> getGatewayNeighbor(sdbusplus::bus_t& bus,
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700323 const ChannelParams& params)
324{
325 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
326 return findGatewayNeighbor<family>(bus, params, neighbors);
327}
328
329template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500330void reconfigureGatewayMAC(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700331 stdplus::EtherAddr mac)
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700332{
333 auto gateway = getGatewayProperty<family>(bus, params);
334 if (!gateway)
335 {
336 log<level::ERR>("Tried to set Gateway MAC without Gateway");
337 elog<InternalFailure>();
338 }
339
340 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500341 auto neighbor = findStaticNeighbor<family>(bus, params, *gateway,
342 neighbors);
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700343 if (neighbor)
344 {
345 deleteObjectIfExists(bus, params.service, neighbor->path);
346 }
347
348 createNeighbor<family>(bus, params, *gateway, mac);
349}
350
William A. Kennington III16064aa2019-04-13 17:44:53 -0700351/** @brief Deconfigures the IPv6 address info configured for the interface
352 *
353 * @param[in] bus - The bus object used for lookups
354 * @param[in] params - The parameters for the channel
355 * @param[in] idx - The address index to operate on
356 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500357void deconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III16064aa2019-04-13 17:44:53 -0700358 uint8_t idx)
359{
360 auto ifaddr = getIfAddr<AF_INET6>(bus, params, idx, originsV6Static);
361 if (ifaddr)
362 {
363 deleteObjectIfExists(bus, params.service, ifaddr->path);
364 }
365}
366
367/** @brief Reconfigures the IPv6 address info configured for the interface
368 *
369 * @param[in] bus - The bus object used for lookups
370 * @param[in] params - The parameters for the channel
371 * @param[in] idx - The address index to operate on
372 * @param[in] address - The new address
373 * @param[in] prefix - The new address prefix
374 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500375void reconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700376 uint8_t idx, stdplus::In6Addr address, uint8_t prefix)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700377{
378 deconfigureIfAddr6(bus, params, idx);
379 createIfAddr<AF_INET6>(bus, params, address, prefix);
380}
381
382/** @brief Converts the AddressOrigin into an IPv6Source
383 *
384 * @param[in] origin - The DBus Address Origin to convert
385 * @return The IPv6Source version of the origin
386 */
387IPv6Source originToSourceType(IP::AddressOrigin origin)
388{
389 switch (origin)
390 {
391 case IP::AddressOrigin::Static:
392 return IPv6Source::Static;
393 case IP::AddressOrigin::DHCP:
394 return IPv6Source::DHCP;
395 case IP::AddressOrigin::SLAAC:
396 return IPv6Source::SLAAC;
397 default:
398 {
Willy Tu523e2d12023-09-05 11:36:48 -0700399 auto originStr = sdbusplus::common::xyz::openbmc_project::network::
William A. Kennington III16064aa2019-04-13 17:44:53 -0700400 convertForMessage(origin);
401 log<level::ERR>(
402 "Invalid IP::AddressOrigin conversion to IPv6Source",
403 entry("ORIGIN=%s", originStr.c_str()));
404 elog<InternalFailure>();
405 }
406 }
407}
408
409/** @brief Packs the IPMI message response with IPv6 address data
410 *
411 * @param[out] ret - The IPMI response payload to be packed
412 * @param[in] channel - The channel id corresponding to an ethernet interface
413 * @param[in] set - The set selector for determining address index
414 * @param[in] origins - Set of valid origins for address filtering
415 */
416void getLanIPv6Address(message::Payload& ret, uint8_t channel, uint8_t set,
417 const std::unordered_set<IP::AddressOrigin>& origins)
418{
419 auto source = IPv6Source::Static;
420 bool enabled = false;
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700421 stdplus::In6Addr addr{};
Johnathan Mantey5aae0922021-10-21 13:05:36 -0700422 uint8_t prefix{};
William A. Kennington III16064aa2019-04-13 17:44:53 -0700423 auto status = IPv6AddressStatus::Disabled;
424
425 auto ifaddr = channelCall<getIfAddr<AF_INET6>>(channel, set, origins);
426 if (ifaddr)
427 {
428 source = originToSourceType(ifaddr->origin);
Johnathan Mantey846af862021-10-21 12:48:54 -0700429 enabled = (origins == originsV6Static);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700430 addr = ifaddr->address;
431 prefix = ifaddr->prefix;
432 status = IPv6AddressStatus::Active;
433 }
434
435 ret.pack(set);
William A. Kennington III7a0e5df2021-05-19 13:31:29 -0700436 ret.pack(types::enum_cast<uint4_t>(source), uint3_t{}, enabled);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700437 ret.pack(stdplus::raw::asView<char>(addr));
William A. Kennington III16064aa2019-04-13 17:44:53 -0700438 ret.pack(prefix);
William A. Kennington III7a0e5df2021-05-19 13:31:29 -0700439 ret.pack(types::enum_cast<uint8_t>(status));
William A. Kennington III16064aa2019-04-13 17:44:53 -0700440}
441
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700442/** @brief Gets the vlan ID configured on the interface
443 *
444 * @param[in] bus - The bus object used for lookups
445 * @param[in] params - The parameters for the channel
446 * @return VLAN id or the standard 0 for no VLAN
447 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500448uint16_t getVLANProperty(sdbusplus::bus_t& bus, const ChannelParams& params)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700449{
450 // VLAN devices will always have a separate logical object
451 if (params.ifPath == params.logicalPath)
452 {
453 return 0;
454 }
455
456 auto vlan = std::get<uint32_t>(getDbusProperty(
457 bus, params.service, params.logicalPath, INTF_VLAN, "Id"));
458 if ((vlan & VLAN_VALUE_MASK) != vlan)
459 {
460 logWithChannel<level::ERR>(params, "networkd returned an invalid vlan",
461 entry("VLAN=%" PRIu32, vlan));
Tom Josepha30c8d32018-03-22 02:15:03 +0530462 elog<InternalFailure>();
463 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700464 return vlan;
Tom Josepha30c8d32018-03-22 02:15:03 +0530465}
466
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700467/** @brief Deletes all of the possible configuration parameters for a channel
468 *
469 * @param[in] bus - The bus object used for lookups
470 * @param[in] params - The parameters for the channel
471 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500472void deconfigureChannel(sdbusplus::bus_t& bus, ChannelParams& params)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500473{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700474 // Delete all objects associated with the interface
475 auto objreq = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF,
476 "GetSubTree");
477 objreq.append(PATH_ROOT, 0, std::vector<std::string>{DELETE_INTERFACE});
478 auto objreply = bus.call(objreq);
479 ObjectTree objs;
480 objreply.read(objs);
481 for (const auto& [path, impls] : objs)
482 {
483 if (path.find(params.ifname) == path.npos)
484 {
485 continue;
486 }
487 for (const auto& [service, intfs] : impls)
488 {
489 deleteObjectIfExists(bus, service, path);
490 }
491 // Update params to reflect the deletion of vlan
492 if (path == params.logicalPath)
493 {
494 params.logicalPath = params.ifPath;
495 }
496 }
497
498 // Clear out any settings on the lower physical interface
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700499 setEthProp(bus, params, "DHCP4", false);
500 setEthProp(bus, params, "DHCP6", false);
501 setEthProp(bus, params, "IPv6AcceptRA", false);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500502}
503
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700504/** @brief Creates a new VLAN on the specified interface
505 *
506 * @param[in] bus - The bus object used for lookups
507 * @param[in] params - The parameters for the channel
508 * @param[in] vlan - The id of the new vlan
509 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500510void createVLAN(sdbusplus::bus_t& bus, ChannelParams& params, uint16_t vlan)
Ratan Guptab8e99552017-07-27 07:07:48 +0530511{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700512 if (vlan == 0)
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530513 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700514 return;
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530515 }
516
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700517 auto req = bus.new_method_call(params.service.c_str(), PATH_ROOT,
518 INTF_VLAN_CREATE, "VLAN");
519 req.append(params.ifname, static_cast<uint32_t>(vlan));
520 auto reply = bus.call(req);
521 sdbusplus::message::object_path newPath;
522 reply.read(newPath);
523 params.logicalPath = std::move(newPath);
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530524}
525
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700526/** @brief Performs the necessary reconfiguration to change the VLAN
527 *
528 * @param[in] bus - The bus object used for lookups
529 * @param[in] params - The parameters for the channel
530 * @param[in] vlan - The new vlan id to use
531 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500532void reconfigureVLAN(sdbusplus::bus_t& bus, ChannelParams& params,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700533 uint16_t vlan)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500534{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700535 // Unfortunatetly we don't have built-in functions to migrate our interface
536 // customizations to new VLAN interfaces, or have some kind of decoupling.
537 // We therefore must retain all of our old information, setup the new VLAN
538 // configuration, then restore the old info.
Nan Li3d0df912016-10-18 19:51:41 +0800539
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700540 // Save info from the old logical interface
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700541 bool dhcp4 = getEthProp<bool>(bus, params, "DHCP4");
542 bool dhcp6 = getEthProp<bool>(bus, params, "DHCP6");
543 bool ra = getEthProp<bool>(bus, params, "IPv6AcceptRA");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700544 ObjectLookupCache ips(bus, params, INTF_IP);
545 auto ifaddr4 = findIfAddr<AF_INET>(bus, params, 0, originsV4, ips);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700546 std::vector<IfAddr<AF_INET6>> ifaddrs6;
547 for (uint8_t i = 0; i < MAX_IPV6_STATIC_ADDRESSES; ++i)
548 {
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500549 auto ifaddr6 = findIfAddr<AF_INET6>(bus, params, i, originsV6Static,
550 ips);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700551 if (!ifaddr6)
552 {
553 break;
554 }
555 ifaddrs6.push_back(std::move(*ifaddr6));
556 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700557 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
558 auto neighbor4 = findGatewayNeighbor<AF_INET>(bus, params, neighbors);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700559 auto neighbor6 = findGatewayNeighbor<AF_INET6>(bus, params, neighbors);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500560
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700561 deconfigureChannel(bus, params);
562 createVLAN(bus, params, vlan);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500563
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700564 // Re-establish the saved settings
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700565 setEthProp(bus, params, "DHCP4", dhcp4);
566 setEthProp(bus, params, "DHCP6", dhcp6);
567 setEthProp(bus, params, "IPv6AcceptRA", ra);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700568 if (ifaddr4)
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800569 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700570 createIfAddr<AF_INET>(bus, params, ifaddr4->address, ifaddr4->prefix);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800571 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700572 for (const auto& ifaddr6 : ifaddrs6)
573 {
574 createIfAddr<AF_INET6>(bus, params, ifaddr6.address, ifaddr6.prefix);
575 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700576 if (neighbor4)
577 {
578 createNeighbor<AF_INET>(bus, params, neighbor4->ip, neighbor4->mac);
579 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700580 if (neighbor6)
581 {
582 createNeighbor<AF_INET6>(bus, params, neighbor6->ip, neighbor6->mac);
583 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700584}
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800585
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700586// We need to store this value so it can be returned to the client
587// It is volatile so safe to store in daemon memory.
588static std::unordered_map<uint8_t, SetStatus> setStatus;
589
590// Until we have good support for fixed versions of IPMI tool
591// we need to return the VLAN id for disabled VLANs. The value is only
592// used for verification that a disable operation succeeded and will only
593// be sent if our system indicates that vlans are disabled.
594static std::unordered_map<uint8_t, uint16_t> lastDisabledVlan;
595
596/** @brief Gets the set status for the channel if it exists
597 * Otherise populates and returns the default value.
598 *
599 * @param[in] channel - The channel id corresponding to an ethernet interface
600 * @return A reference to the SetStatus for the channel
601 */
602SetStatus& getSetStatus(uint8_t channel)
603{
604 auto it = setStatus.find(channel);
605 if (it != setStatus.end())
606 {
607 return it->second;
608 }
609 return setStatus[channel] = SetStatus::Complete;
610}
611
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700612/** @brief Unpacks the trivially copyable type from the message */
613template <typename T>
614static T unpackT(message::Payload& req)
615{
616 std::array<uint8_t, sizeof(T)> bytes;
617 if (req.unpack(bytes) != 0)
618 {
619 throw ccReqDataLenInvalid;
620 }
621 return stdplus::raw::copyFrom<T>(bytes);
622}
623
624/** @brief Ensure the message is fully unpacked */
625static void unpackFinal(message::Payload& req)
626{
627 if (!req.fullyUnpacked())
628 {
629 throw ccReqDataTruncated;
630 }
631}
632
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700633/**
634 * Define placeholder command handlers for the OEM Extension bytes for the Set
635 * LAN Configuration Parameters and Get LAN Configuration Parameters
636 * commands. Using "weak" linking allows the placeholder setLanOem/getLanOem
637 * functions below to be overridden.
638 * To create handlers for your own proprietary command set:
639 * Create/modify a phosphor-ipmi-host Bitbake append file within your Yocto
640 * recipe
641 * Create C++ file(s) that define IPMI handler functions matching the
642 * function names below (i.e. setLanOem). The default name for the
643 * transport IPMI commands is transporthandler_oem.cpp.
644 * Add:
Johnathan Manteyefe26682022-08-11 14:30:45 -0700645 * EXTRA_OEMESON:append = "-Dtransport-oem=enabled"
646 * Create a do_configure:prepend()/do_install:append() method in your
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700647 * bbappend file to copy the file to the build directory.
648 * Add:
649 * PROJECT_SRC_DIR := "${THISDIR}/${PN}"
650 * # Copy the "strong" functions into the working directory, overriding the
651 * # placeholder functions.
Johnathan Manteyefe26682022-08-11 14:30:45 -0700652 * do_configure:prepend(){
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700653 * cp -f ${PROJECT_SRC_DIR}/transporthandler_oem.cpp ${S}
654 * }
655 *
656 * # Clean up after complilation has completed
Johnathan Manteyefe26682022-08-11 14:30:45 -0700657 * do_install:append(){
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700658 * rm -f ${S}/transporthandler_oem.cpp
659 * }
660 *
661 */
662
663/**
664 * Define the placeholder OEM commands as having weak linkage. Create
665 * setLanOem, and getLanOem functions in the transporthandler_oem.cpp
666 * file. The functions defined there must not have the "weak" attribute
667 * applied to them.
668 */
669RspType<> setLanOem(uint8_t channel, uint8_t parameter, message::Payload& req)
670 __attribute__((weak));
671RspType<message::Payload> getLanOem(uint8_t channel, uint8_t parameter,
672 uint8_t set, uint8_t block)
673 __attribute__((weak));
674
Willy Tu11d68892022-01-20 10:37:34 -0800675RspType<> setLanOem(uint8_t, uint8_t, message::Payload& req)
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700676{
677 req.trailingOk = true;
678 return response(ccParamNotSupported);
679}
680
Willy Tu11d68892022-01-20 10:37:34 -0800681RspType<message::Payload> getLanOem(uint8_t, uint8_t, uint8_t, uint8_t)
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700682{
683 return response(ccParamNotSupported);
684}
685
Jian Zhangcf19d142023-07-31 10:22:53 +0800686/**
687 * @brief is a valid LAN channel.
688 *
689 * This function checks whether the input channel is a valid LAN channel or not.
690 *
691 * @param[in] channel: the channel number.
692 * @return nullopt if the channel is invalid, false if the channel is not a LAN
693 * channel, true if the channel is a LAN channel.
694 **/
695std::optional<bool> isLanChannel(uint8_t channel)
696{
697 ChannelInfo chInfo;
698 auto cc = getChannelInfo(channel, chInfo);
699 if (cc != ccSuccess)
700 {
701 return std::nullopt;
702 }
703
704 return chInfo.mediumType ==
705 static_cast<uint8_t>(EChannelMediumType::lan8032);
706}
707
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700708RspType<> setLanInt(Context::ptr ctx, uint4_t channelBits, uint4_t reserved1,
709 uint8_t parameter, message::Payload& req)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700710{
vijayabharathix shettycc769252020-02-27 17:52:20 +0000711 const uint8_t channel = convertCurrentChannelNum(
712 static_cast<uint8_t>(channelBits), ctx->channel);
713 if (reserved1 || !isValidChannel(channel))
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700714 {
vijayabharathix shettycc769252020-02-27 17:52:20 +0000715 log<level::ERR>("Set Lan - Invalid field in request");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700716 req.trailingOk = true;
717 return responseInvalidFieldRequest();
718 }
719
Jian Zhangcf19d142023-07-31 10:22:53 +0800720 if (!isLanChannel(channel).value_or(false))
721 {
722 log<level::ERR>("Set Lan - Not a LAN channel");
723 return responseInvalidFieldRequest();
724 }
725
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700726 switch (static_cast<LanParam>(parameter))
727 {
728 case LanParam::SetStatus:
729 {
730 uint2_t flag;
731 uint6_t rsvd;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700732 if (req.unpack(flag, rsvd) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700733 {
734 return responseReqDataLenInvalid();
735 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700736 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800737 if (rsvd)
738 {
739 return responseInvalidFieldRequest();
740 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700741 auto status = static_cast<SetStatus>(static_cast<uint8_t>(flag));
742 switch (status)
743 {
744 case SetStatus::Complete:
745 {
746 getSetStatus(channel) = status;
747 return responseSuccess();
748 }
749 case SetStatus::InProgress:
750 {
751 auto& storedStatus = getSetStatus(channel);
752 if (storedStatus == SetStatus::InProgress)
753 {
754 return response(ccParamSetLocked);
755 }
756 storedStatus = status;
757 return responseSuccess();
758 }
759 case SetStatus::Commit:
760 if (getSetStatus(channel) != SetStatus::InProgress)
761 {
762 return responseInvalidFieldRequest();
763 }
764 return responseSuccess();
765 }
766 return response(ccParamNotSupported);
767 }
768 case LanParam::AuthSupport:
769 {
770 req.trailingOk = true;
771 return response(ccParamReadOnly);
772 }
773 case LanParam::AuthEnables:
774 {
775 req.trailingOk = true;
Johnathan Mantey76ce9c72019-11-14 14:41:46 -0800776 return response(ccParamReadOnly);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700777 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800778 case LanParam::IP:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600779 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700780 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800781 {
782 return responseCommandNotAvailable();
783 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700784 auto ip = unpackT<stdplus::In4Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700785 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700786 channelCall<reconfigureIfAddr4>(channel, ip, std::nullopt);
787 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +0530788 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700789 case LanParam::IPSrc:
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530790 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700791 uint4_t flag;
792 uint4_t rsvd;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700793 if (req.unpack(flag, rsvd) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700794 {
795 return responseReqDataLenInvalid();
796 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700797 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800798 if (rsvd)
799 {
800 return responseInvalidFieldRequest();
801 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700802 switch (static_cast<IPSrc>(static_cast<uint8_t>(flag)))
803 {
804 case IPSrc::DHCP:
Johnathan Mantey65265362019-11-14 11:24:19 -0800805 // The IPSrc IPMI command is only for IPv4
806 // management. Modifying IPv6 state is done using
807 // a completely different Set LAN Configuration
808 // subcommand.
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700809 channelCall<setEthProp<bool>>(channel, "DHCP4", true);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700810 return responseSuccess();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700811 case IPSrc::Unspecified:
812 case IPSrc::Static:
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700813 channelCall<setEthProp<bool>>(channel, "DHCP4", false);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700814 return responseSuccess();
Rajashekar Gade Reddy8a860ea2019-12-24 11:31:19 +0530815 case IPSrc::BIOS:
816 case IPSrc::BMC:
Rajashekar Gade Reddy8a860ea2019-12-24 11:31:19 +0530817 return responseInvalidFieldRequest();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700818 }
819 return response(ccParamNotSupported);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530820 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800821 case LanParam::MAC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530822 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700823 auto mac = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700824 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700825 channelCall<setMACProperty>(channel, mac);
826 return responseSuccess();
Ratan Gupta533d03b2017-07-30 10:39:22 +0530827 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700828 case LanParam::SubnetMask:
Ratan Guptab8e99552017-07-27 07:07:48 +0530829 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700830 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800831 {
832 return responseCommandNotAvailable();
833 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700834 auto pfx = stdplus::maskToPfx(unpackT<stdplus::In4Addr>(req));
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700835 unpackFinal(req);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700836 channelCall<reconfigureIfAddr4>(channel, std::nullopt, pfx);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700837 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +0530838 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700839 case LanParam::Gateway1:
Ratan Guptab8e99552017-07-27 07:07:48 +0530840 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700841 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800842 {
843 return responseCommandNotAvailable();
844 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700845 auto gateway = unpackT<stdplus::In4Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700846 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700847 channelCall<setGatewayProperty<AF_INET>>(channel, gateway);
848 return responseSuccess();
849 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700850 case LanParam::Gateway1MAC:
851 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700852 auto gatewayMAC = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700853 unpackFinal(req);
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700854 channelCall<reconfigureGatewayMAC<AF_INET>>(channel, gatewayMAC);
855 return responseSuccess();
856 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700857 case LanParam::VLANId:
858 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700859 uint12_t vlanData;
860 uint3_t rsvd;
861 bool vlanEnable;
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530862
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700863 if (req.unpack(vlanData, rsvd, vlanEnable) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700864 {
865 return responseReqDataLenInvalid();
866 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700867 unpackFinal(req);
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530868
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700869 if (rsvd)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700870 {
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530871 return responseInvalidFieldRequest();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700872 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530873
874 uint16_t vlan = static_cast<uint16_t>(vlanData);
875
876 if (!vlanEnable)
877 {
878 lastDisabledVlan[channel] = vlan;
879 vlan = 0;
880 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530881
jayaprakash Mutyala84c49dc2020-05-18 23:12:13 +0000882 channelCall<reconfigureVLAN>(channel, vlan);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700883 return responseSuccess();
884 }
885 case LanParam::CiphersuiteSupport:
886 case LanParam::CiphersuiteEntries:
William A. Kennington III16064aa2019-04-13 17:44:53 -0700887 case LanParam::IPFamilySupport:
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700888 {
889 req.trailingOk = true;
890 return response(ccParamReadOnly);
Ratan Guptab8e99552017-07-27 07:07:48 +0530891 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700892 case LanParam::IPFamilyEnables:
893 {
894 uint8_t enables;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700895 if (req.unpack(enables) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700896 {
897 return responseReqDataLenInvalid();
898 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700899 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700900 switch (static_cast<IPFamilyEnables>(enables))
901 {
902 case IPFamilyEnables::DualStack:
903 return responseSuccess();
904 case IPFamilyEnables::IPv4Only:
905 case IPFamilyEnables::IPv6Only:
906 return response(ccParamNotSupported);
907 }
908 return response(ccParamNotSupported);
909 }
910 case LanParam::IPv6Status:
911 {
912 req.trailingOk = true;
913 return response(ccParamReadOnly);
914 }
915 case LanParam::IPv6StaticAddresses:
916 {
917 uint8_t set;
918 uint7_t rsvd;
919 bool enabled;
William A. Kennington III16064aa2019-04-13 17:44:53 -0700920 uint8_t prefix;
921 uint8_t status;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700922 if (req.unpack(set, rsvd, enabled) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700923 {
924 return responseReqDataLenInvalid();
925 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700926 auto ip = unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700927 if (req.unpack(prefix, status) != 0)
928 {
929 return responseReqDataLenInvalid();
930 }
931 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800932 if (rsvd)
933 {
934 return responseInvalidFieldRequest();
935 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700936 if (enabled)
937 {
Jiaqing Zhao6d4a44e2022-01-24 15:04:00 +0800938 if (prefix < MIN_IPV6_PREFIX_LENGTH ||
939 prefix > MAX_IPV6_PREFIX_LENGTH)
940 {
941 return responseParmOutOfRange();
942 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700943 channelCall<reconfigureIfAddr6>(channel, set, ip, prefix);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700944 }
945 else
946 {
947 channelCall<deconfigureIfAddr6>(channel, set);
948 }
949 return responseSuccess();
950 }
951 case LanParam::IPv6DynamicAddresses:
952 {
953 req.trailingOk = true;
954 return response(ccParamReadOnly);
955 }
956 case LanParam::IPv6RouterControl:
957 {
958 std::bitset<8> control;
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800959 constexpr uint8_t reservedRACCBits = 0xfc;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700960 if (req.unpack(control) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700961 {
962 return responseReqDataLenInvalid();
963 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700964 unpackFinal(req);
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800965 if (std::bitset<8> expected(control &
966 std::bitset<8>(reservedRACCBits));
967 expected.any())
William A. Kennington III16064aa2019-04-13 17:44:53 -0700968 {
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800969 return response(ccParamNotSupported);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700970 }
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800971
972 bool enableRA = control[IPv6RouterControlFlag::Dynamic];
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700973 channelCall<setEthProp<bool>>(channel, "IPv6AcceptRA", enableRA);
974 channelCall<setEthProp<bool>>(channel, "DHCP6", enableRA);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700975 return responseSuccess();
976 }
977 case LanParam::IPv6StaticRouter1IP:
978 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700979 auto gateway = unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700980 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700981 channelCall<setGatewayProperty<AF_INET6>>(channel, gateway);
982 return responseSuccess();
983 }
984 case LanParam::IPv6StaticRouter1MAC:
985 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700986 auto mac = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700987 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700988 channelCall<reconfigureGatewayMAC<AF_INET6>>(channel, mac);
989 return responseSuccess();
990 }
991 case LanParam::IPv6StaticRouter1PrefixLength:
992 {
993 uint8_t prefix;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700994 if (req.unpack(prefix) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700995 {
996 return responseReqDataLenInvalid();
997 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700998 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700999 if (prefix != 0)
1000 {
1001 return responseInvalidFieldRequest();
1002 }
1003 return responseSuccess();
1004 }
1005 case LanParam::IPv6StaticRouter1PrefixValue:
1006 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001007 unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001008 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001009 // Accept any prefix value since our prefix length has to be 0
1010 return responseSuccess();
1011 }
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001012 case LanParam::cipherSuitePrivilegeLevels:
1013 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001014 uint8_t rsvd;
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001015 std::array<uint4_t, ipmi::maxCSRecords> cipherSuitePrivs;
1016
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001017 if (req.unpack(rsvd, cipherSuitePrivs))
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001018 {
1019 return responseReqDataLenInvalid();
1020 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001021 unpackFinal(req);
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001022
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001023 if (rsvd)
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001024 {
1025 return responseInvalidFieldRequest();
1026 }
1027
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -05001028 uint8_t resp = getCipherConfigObject(csPrivFileName,
1029 csPrivDefaultFileName)
1030 .setCSPrivilegeLevels(channel, cipherSuitePrivs);
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001031 if (!resp)
1032 {
1033 return responseSuccess();
1034 }
1035 else
1036 {
1037 req.trailingOk = true;
1038 return response(resp);
1039 }
1040 }
Ratan Guptab8e99552017-07-27 07:07:48 +05301041 }
vishwa1eaea4f2016-02-26 11:57:40 -06001042
Johnathan Manteyb87034e2019-09-16 10:50:50 -07001043 if ((parameter >= oemCmdStart) && (parameter <= oemCmdEnd))
1044 {
1045 return setLanOem(channel, parameter, req);
1046 }
1047
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001048 req.trailingOk = true;
1049 return response(ccParamNotSupported);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001050}
1051
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001052RspType<> setLan(Context::ptr ctx, uint4_t channelBits, uint4_t reserved1,
1053 uint8_t parameter, message::Payload& req)
1054{
1055 try
1056 {
1057 return setLanInt(ctx, channelBits, reserved1, parameter, req);
1058 }
1059 catch (ipmi::Cc cc)
1060 {
1061 return response(cc);
1062 }
1063 catch (const sdbusplus::exception_t& e)
1064 {
1065 if (std::string_view{InvalidArgument::errName} == e.name())
1066 {
1067 return responseInvalidFieldRequest();
1068 }
1069 throw;
1070 }
1071}
1072
vijayabharathix shettycc769252020-02-27 17:52:20 +00001073RspType<message::Payload> getLan(Context::ptr ctx, uint4_t channelBits,
1074 uint3_t reserved, bool revOnly,
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001075 uint8_t parameter, uint8_t set, uint8_t block)
Ratan Guptab8e99552017-07-27 07:07:48 +05301076{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001077 message::Payload ret;
1078 constexpr uint8_t current_revision = 0x11;
1079 ret.pack(current_revision);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001080
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001081 if (revOnly)
Suryakanth Sekare4054402019-08-08 15:16:52 +05301082 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001083 return responseSuccess(std::move(ret));
Suryakanth Sekare4054402019-08-08 15:16:52 +05301084 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001085
vijayabharathix shettycc769252020-02-27 17:52:20 +00001086 const uint8_t channel = convertCurrentChannelNum(
1087 static_cast<uint8_t>(channelBits), ctx->channel);
1088 if (reserved || !isValidChannel(channel))
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001089 {
vijayabharathix shettycc769252020-02-27 17:52:20 +00001090 log<level::ERR>("Get Lan - Invalid field in request");
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001091 return responseInvalidFieldRequest();
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001092 }
1093
Jian Zhangcf19d142023-07-31 10:22:53 +08001094 if (!isLanChannel(channel).value_or(false))
1095 {
1096 log<level::ERR>("Set Lan - Not a LAN channel");
1097 return responseInvalidFieldRequest();
1098 }
1099
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001100 static std::vector<uint8_t> cipherList;
1101 static bool listInit = false;
1102 if (!listInit)
1103 {
1104 try
1105 {
1106 cipherList = cipher::getCipherList();
1107 listInit = true;
1108 }
1109 catch (const std::exception& e)
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -05001110 {}
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001111 }
1112
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001113 switch (static_cast<LanParam>(parameter))
Tom Josepha30c8d32018-03-22 02:15:03 +05301114 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001115 case LanParam::SetStatus:
Tom Josepha30c8d32018-03-22 02:15:03 +05301116 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001117 SetStatus status;
1118 try
1119 {
1120 status = setStatus.at(channel);
1121 }
1122 catch (const std::out_of_range&)
1123 {
1124 status = SetStatus::Complete;
1125 }
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001126 ret.pack(types::enum_cast<uint2_t>(status), uint6_t{});
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001127 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301128 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001129 case LanParam::AuthSupport:
Tom Josepha30c8d32018-03-22 02:15:03 +05301130 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001131 std::bitset<6> support;
1132 ret.pack(support, uint2_t{});
1133 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301134 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001135 case LanParam::AuthEnables:
vishwa1eaea4f2016-02-26 11:57:40 -06001136 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001137 std::bitset<6> enables;
1138 ret.pack(enables, uint2_t{}); // Callback
1139 ret.pack(enables, uint2_t{}); // User
1140 ret.pack(enables, uint2_t{}); // Operator
1141 ret.pack(enables, uint2_t{}); // Admin
1142 ret.pack(enables, uint2_t{}); // OEM
1143 return responseSuccess(std::move(ret));
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001144 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001145 case LanParam::IP:
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001146 {
1147 auto ifaddr = channelCall<getIfAddr4>(channel);
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001148 stdplus::In4Addr addr{};
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001149 if (ifaddr)
1150 {
1151 addr = ifaddr->address;
1152 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001153 ret.pack(stdplus::raw::asView<char>(addr));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001154 return responseSuccess(std::move(ret));
1155 }
1156 case LanParam::IPSrc:
1157 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001158 auto src = channelCall<getEthProp<bool>>(channel, "DHCP4")
1159 ? IPSrc::DHCP
1160 : IPSrc::Static;
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001161 ret.pack(types::enum_cast<uint4_t>(src), uint4_t{});
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001162 return responseSuccess(std::move(ret));
1163 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001164 case LanParam::MAC:
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001165 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001166 auto mac = channelCall<getMACProperty>(channel);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001167 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001168 return responseSuccess(std::move(ret));
1169 }
1170 case LanParam::SubnetMask:
1171 {
1172 auto ifaddr = channelCall<getIfAddr4>(channel);
1173 uint8_t prefix = AddrFamily<AF_INET>::defaultPrefix;
1174 if (ifaddr)
Ratan Guptab8e99552017-07-27 07:07:48 +05301175 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001176 prefix = ifaddr->prefix;
1177 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001178 auto netmask = stdplus::pfxToMask<stdplus::In4Addr>(prefix);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001179 ret.pack(stdplus::raw::asView<char>(netmask));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001180 return responseSuccess(std::move(ret));
1181 }
1182 case LanParam::Gateway1:
1183 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001184 auto gateway = channelCall<getGatewayProperty<AF_INET>>(channel);
1185 ret.pack(stdplus::raw::asView<char>(
1186 gateway.value_or(stdplus::In4Addr{})));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001187 return responseSuccess(std::move(ret));
1188 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001189 case LanParam::Gateway1MAC:
1190 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001191 stdplus::EtherAddr mac{};
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001192 auto neighbor = channelCall<getGatewayNeighbor<AF_INET>>(channel);
1193 if (neighbor)
1194 {
1195 mac = neighbor->mac;
1196 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001197 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001198 return responseSuccess(std::move(ret));
1199 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001200 case LanParam::VLANId:
1201 {
1202 uint16_t vlan = channelCall<getVLANProperty>(channel);
1203 if (vlan != 0)
1204 {
1205 vlan |= VLAN_ENABLE_FLAG;
Ratan Guptab8e99552017-07-27 07:07:48 +05301206 }
1207 else
1208 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001209 vlan = lastDisabledVlan[channel];
Ratan Guptab8e99552017-07-27 07:07:48 +05301210 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001211 ret.pack(vlan);
1212 return responseSuccess(std::move(ret));
Adriana Kobylak342df102016-02-10 13:48:16 -06001213 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001214 case LanParam::CiphersuiteSupport:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001215 {
srikanta mondal1d8579c2020-04-15 17:13:25 +00001216 if (getChannelSessionSupport(channel) ==
1217 EChannelSessSupported::none)
1218 {
1219 return responseInvalidFieldRequest();
1220 }
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001221 if (!listInit)
1222 {
1223 return responseUnspecifiedError();
1224 }
1225 ret.pack(static_cast<uint8_t>(cipherList.size() - 1));
1226 return responseSuccess(std::move(ret));
1227 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001228 case LanParam::CiphersuiteEntries:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001229 {
srikanta mondal1d8579c2020-04-15 17:13:25 +00001230 if (getChannelSessionSupport(channel) ==
1231 EChannelSessSupported::none)
1232 {
1233 return responseInvalidFieldRequest();
1234 }
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001235 if (!listInit)
1236 {
1237 return responseUnspecifiedError();
1238 }
1239 ret.pack(cipherList);
1240 return responseSuccess(std::move(ret));
1241 }
William A. Kennington III16064aa2019-04-13 17:44:53 -07001242 case LanParam::IPFamilySupport:
1243 {
1244 std::bitset<8> support;
1245 support[IPFamilySupportFlag::IPv6Only] = 0;
1246 support[IPFamilySupportFlag::DualStack] = 1;
1247 support[IPFamilySupportFlag::IPv6Alerts] = 1;
1248 ret.pack(support);
1249 return responseSuccess(std::move(ret));
1250 }
1251 case LanParam::IPFamilyEnables:
1252 {
1253 ret.pack(static_cast<uint8_t>(IPFamilyEnables::DualStack));
1254 return responseSuccess(std::move(ret));
1255 }
1256 case LanParam::IPv6Status:
1257 {
1258 ret.pack(MAX_IPV6_STATIC_ADDRESSES);
1259 ret.pack(MAX_IPV6_DYNAMIC_ADDRESSES);
1260 std::bitset<8> support;
1261 support[IPv6StatusFlag::DHCP] = 1;
1262 support[IPv6StatusFlag::SLAAC] = 1;
1263 ret.pack(support);
1264 return responseSuccess(std::move(ret));
1265 }
1266 case LanParam::IPv6StaticAddresses:
1267 {
1268 if (set >= MAX_IPV6_STATIC_ADDRESSES)
1269 {
1270 return responseParmOutOfRange();
1271 }
1272 getLanIPv6Address(ret, channel, set, originsV6Static);
1273 return responseSuccess(std::move(ret));
1274 }
1275 case LanParam::IPv6DynamicAddresses:
1276 {
1277 if (set >= MAX_IPV6_DYNAMIC_ADDRESSES)
1278 {
1279 return responseParmOutOfRange();
1280 }
1281 getLanIPv6Address(ret, channel, set, originsV6Dynamic);
1282 return responseSuccess(std::move(ret));
1283 }
1284 case LanParam::IPv6RouterControl:
1285 {
1286 std::bitset<8> control;
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001287 control[IPv6RouterControlFlag::Dynamic] =
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001288 channelCall<getEthProp<bool>>(channel, "IPv6AcceptRA");
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001289 control[IPv6RouterControlFlag::Static] = 1;
William A. Kennington III16064aa2019-04-13 17:44:53 -07001290 ret.pack(control);
1291 return responseSuccess(std::move(ret));
1292 }
1293 case LanParam::IPv6StaticRouter1IP:
1294 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001295 stdplus::In6Addr gateway{};
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001296 if (!channelCall<getEthProp<bool>>(channel, "IPv6AcceptRA"))
William A. Kennington III16064aa2019-04-13 17:44:53 -07001297 {
1298 gateway =
1299 channelCall<getGatewayProperty<AF_INET6>>(channel).value_or(
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001300 stdplus::In6Addr{});
William A. Kennington III16064aa2019-04-13 17:44:53 -07001301 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001302 ret.pack(stdplus::raw::asView<char>(gateway));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001303 return responseSuccess(std::move(ret));
1304 }
1305 case LanParam::IPv6StaticRouter1MAC:
1306 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001307 stdplus::EtherAddr mac{};
William A. Kennington III16064aa2019-04-13 17:44:53 -07001308 auto neighbor = channelCall<getGatewayNeighbor<AF_INET6>>(channel);
1309 if (neighbor)
1310 {
1311 mac = neighbor->mac;
1312 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001313 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001314 return responseSuccess(std::move(ret));
1315 }
1316 case LanParam::IPv6StaticRouter1PrefixLength:
1317 {
1318 ret.pack(UINT8_C(0));
1319 return responseSuccess(std::move(ret));
1320 }
1321 case LanParam::IPv6StaticRouter1PrefixValue:
1322 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001323 ret.pack(stdplus::raw::asView<char>(stdplus::In6Addr{}));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001324 return responseSuccess(std::move(ret));
1325 }
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001326 case LanParam::cipherSuitePrivilegeLevels:
1327 {
1328 std::array<uint4_t, ipmi::maxCSRecords> csPrivilegeLevels;
1329
1330 uint8_t resp =
1331 getCipherConfigObject(csPrivFileName, csPrivDefaultFileName)
1332 .getCSPrivilegeLevels(channel, csPrivilegeLevels);
1333 if (!resp)
1334 {
1335 constexpr uint8_t reserved1 = 0x00;
1336 ret.pack(reserved1, csPrivilegeLevels);
1337 return responseSuccess(std::move(ret));
1338 }
1339 else
1340 {
1341 return response(resp);
1342 }
1343 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001344 }
1345
Johnathan Manteyb87034e2019-09-16 10:50:50 -07001346 if ((parameter >= oemCmdStart) && (parameter <= oemCmdEnd))
1347 {
1348 return getLanOem(channel, parameter, set, block);
1349 }
1350
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001351 return response(ccParamNotSupported);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001352}
1353
Jian Zhang23f44652022-03-17 17:13:10 +08001354constexpr const char* solInterface = "xyz.openbmc_project.Ipmi.SOL";
1355constexpr const char* solPath = "/xyz/openbmc_project/ipmi/sol/";
1356constexpr const uint16_t solDefaultPort = 623;
1357
1358RspType<> setSolConfParams(Context::ptr ctx, uint4_t channelBits,
Willy Tu11d68892022-01-20 10:37:34 -08001359 uint4_t /*reserved*/, uint8_t parameter,
Jian Zhang23f44652022-03-17 17:13:10 +08001360 message::Payload& req)
1361{
1362 const uint8_t channel = convertCurrentChannelNum(
1363 static_cast<uint8_t>(channelBits), ctx->channel);
1364
1365 if (!isValidChannel(channel))
1366 {
1367 log<level::ERR>("Set Sol Config - Invalid channel in request");
1368 return responseInvalidFieldRequest();
1369 }
1370
1371 std::string solService{};
1372 std::string solPathWitheEthName = solPath + ipmi::getChannelName(channel);
1373
1374 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1375 {
1376 log<level::ERR>("Set Sol Config - Invalid solInterface",
1377 entry("SERVICE=%s", solService.c_str()),
1378 entry("OBJPATH=%s", solPathWitheEthName.c_str()),
1379 entry("INTERFACE=%s", solInterface));
1380 return responseInvalidFieldRequest();
1381 }
1382
1383 switch (static_cast<SolConfParam>(parameter))
1384 {
1385 case SolConfParam::Progress:
1386 {
1387 uint8_t progress;
1388 if (req.unpack(progress) != 0 || !req.fullyUnpacked())
1389 {
1390 return responseReqDataLenInvalid();
1391 }
1392
1393 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1394 solInterface, "Progress", progress))
1395 {
1396 return responseUnspecifiedError();
1397 }
1398 break;
1399 }
1400 case SolConfParam::Enable:
1401 {
1402 bool enable;
1403 uint7_t reserved2;
1404
1405 if (req.unpack(enable, reserved2) != 0 || !req.fullyUnpacked())
1406 {
1407 return responseReqDataLenInvalid();
1408 }
1409
1410 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1411 solInterface, "Enable", enable))
1412 {
1413 return responseUnspecifiedError();
1414 }
1415 break;
1416 }
1417 case SolConfParam::Authentication:
1418 {
1419 uint4_t privilegeBits{};
1420 uint2_t reserved2{};
1421 bool forceAuth = false;
1422 bool forceEncrypt = false;
1423
1424 if (req.unpack(privilegeBits, reserved2, forceAuth, forceEncrypt) !=
1425 0 ||
1426 !req.fullyUnpacked())
1427 {
1428 return responseReqDataLenInvalid();
1429 }
1430
1431 uint8_t privilege = static_cast<uint8_t>(privilegeBits);
Jonathan Domana48bf772023-05-26 17:54:57 -07001432 if (privilege < static_cast<uint8_t>(Privilege::User) ||
Jian Zhang23f44652022-03-17 17:13:10 +08001433 privilege > static_cast<uint8_t>(Privilege::Oem))
1434 {
1435 return ipmi::responseInvalidFieldRequest();
1436 }
1437
1438 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1439 solInterface, "Privilege", privilege))
1440 {
1441 return responseUnspecifiedError();
1442 }
1443
1444 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1445 solInterface, "ForceEncryption",
1446 forceEncrypt))
1447 {
1448 return responseUnspecifiedError();
1449 }
1450
1451 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1452 solInterface, "ForceAuthentication",
1453 forceAuth))
1454 {
1455 return responseUnspecifiedError();
1456 }
1457 break;
1458 }
1459 case SolConfParam::Accumulate:
1460 {
1461 uint8_t interval;
1462 uint8_t threshold;
1463 if (req.unpack(interval, threshold) != 0 || !req.fullyUnpacked())
1464 {
1465 return responseReqDataLenInvalid();
1466 }
1467
1468 if (threshold == 0)
1469 {
1470 return responseInvalidFieldRequest();
1471 }
1472
1473 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1474 solInterface, "AccumulateIntervalMS",
1475 interval))
1476 {
1477 return responseUnspecifiedError();
1478 }
1479
1480 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1481 solInterface, "Threshold", threshold))
1482 {
1483 return responseUnspecifiedError();
1484 }
1485 break;
1486 }
1487 case SolConfParam::Retry:
1488 {
1489 uint3_t countBits;
1490 uint5_t reserved2;
1491 uint8_t interval;
1492
1493 if (req.unpack(countBits, reserved2, interval) != 0 ||
1494 !req.fullyUnpacked())
1495 {
1496 return responseReqDataLenInvalid();
1497 }
1498
1499 uint8_t count = static_cast<uint8_t>(countBits);
1500 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1501 solInterface, "RetryCount", count))
1502 {
1503 return responseUnspecifiedError();
1504 }
1505
1506 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1507 solInterface, "RetryIntervalMS",
1508 interval))
1509 {
1510 return responseUnspecifiedError();
1511 }
1512 break;
1513 }
1514 case SolConfParam::Port:
1515 {
1516 return response(ipmiCCWriteReadParameter);
1517 }
1518 case SolConfParam::NonVbitrate:
1519 case SolConfParam::Vbitrate:
1520 case SolConfParam::Channel:
1521 default:
1522 return response(ipmiCCParamNotSupported);
1523 }
1524 return responseSuccess();
1525}
1526
1527RspType<message::Payload> getSolConfParams(Context::ptr ctx,
1528 uint4_t channelBits,
Willy Tu11d68892022-01-20 10:37:34 -08001529 uint3_t /*reserved*/, bool revOnly,
1530 uint8_t parameter, uint8_t /*set*/,
1531 uint8_t /*block*/)
Jian Zhang23f44652022-03-17 17:13:10 +08001532{
1533 message::Payload ret;
1534 constexpr uint8_t current_revision = 0x11;
1535 ret.pack(current_revision);
1536 if (revOnly)
1537 {
1538 return responseSuccess(std::move(ret));
1539 }
1540
1541 const uint8_t channel = convertCurrentChannelNum(
1542 static_cast<uint8_t>(channelBits), ctx->channel);
1543
1544 if (!isValidChannel(channel))
1545 {
1546 log<level::ERR>("Get Sol Config - Invalid channel in request");
1547 return responseInvalidFieldRequest();
1548 }
1549
1550 std::string solService{};
1551 std::string solPathWitheEthName = solPath + ipmi::getChannelName(channel);
1552
1553 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1554 {
1555 log<level::ERR>("Set Sol Config - Invalid solInterface",
1556 entry("SERVICE=%s", solService.c_str()),
1557 entry("OBJPATH=%s", solPathWitheEthName.c_str()),
1558 entry("INTERFACE=%s", solInterface));
1559 return responseInvalidFieldRequest();
1560 }
1561
1562 switch (static_cast<SolConfParam>(parameter))
1563 {
1564 case SolConfParam::Progress:
1565 {
1566 uint8_t progress;
1567 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1568 solInterface, "Progress", progress))
1569 {
1570 return responseUnspecifiedError();
1571 }
1572 ret.pack(progress);
1573 return responseSuccess(std::move(ret));
1574 }
1575 case SolConfParam::Enable:
1576 {
1577 bool enable{};
1578 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1579 solInterface, "Enable", enable))
1580 {
1581 return responseUnspecifiedError();
1582 }
1583 ret.pack(enable, uint7_t{});
1584 return responseSuccess(std::move(ret));
1585 }
1586 case SolConfParam::Authentication:
1587 {
1588 // 4bits, cast when pack
1589 uint8_t privilege;
1590 bool forceAuth = false;
1591 bool forceEncrypt = false;
1592
1593 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1594 solInterface, "Privilege", privilege))
1595 {
1596 return responseUnspecifiedError();
1597 }
1598
1599 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1600 solInterface, "ForceAuthentication",
1601 forceAuth))
1602 {
1603 return responseUnspecifiedError();
1604 }
1605
1606 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1607 solInterface, "ForceEncryption",
1608 forceEncrypt))
1609 {
1610 return responseUnspecifiedError();
1611 }
1612 ret.pack(uint4_t{privilege}, uint2_t{}, forceAuth, forceEncrypt);
1613 return responseSuccess(std::move(ret));
1614 }
1615 case SolConfParam::Accumulate:
1616 {
1617 uint8_t interval{}, threshold{};
1618
1619 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1620 solInterface, "AccumulateIntervalMS",
1621 interval))
1622 {
1623 return responseUnspecifiedError();
1624 }
1625
1626 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1627 solInterface, "Threshold", threshold))
1628 {
1629 return responseUnspecifiedError();
1630 }
1631 ret.pack(interval, threshold);
1632 return responseSuccess(std::move(ret));
1633 }
1634 case SolConfParam::Retry:
1635 {
1636 // 3bits, cast when cast
1637 uint8_t count{};
1638 uint8_t interval{};
1639
1640 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1641 solInterface, "RetryCount", count))
1642 {
1643 return responseUnspecifiedError();
1644 }
1645
1646 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1647 solInterface, "RetryIntervalMS",
1648 interval))
1649 {
1650 return responseUnspecifiedError();
1651 }
1652 ret.pack(uint3_t{count}, uint5_t{}, interval);
1653 return responseSuccess(std::move(ret));
1654 }
1655 case SolConfParam::Port:
1656 {
1657 auto port = solDefaultPort;
1658 ret.pack(static_cast<uint16_t>(port));
1659 return responseSuccess(std::move(ret));
1660 }
1661 case SolConfParam::Channel:
1662 {
1663 ret.pack(channel);
1664 return responseSuccess(std::move(ret));
1665 }
1666 case SolConfParam::NonVbitrate:
Jonathan Domana48bf772023-05-26 17:54:57 -07001667 {
1668 uint64_t baudRate;
1669 uint8_t encodedBitRate = 0;
1670 if (ipmi::getDbusProperty(
1671 ctx, "xyz.openbmc_project.Console.default",
1672 "/xyz/openbmc_project/console/default",
1673 "xyz.openbmc_project.Console.UART", "Baud", baudRate))
1674 {
1675 return ipmi::responseUnspecifiedError();
1676 }
1677 switch (baudRate)
1678 {
1679 case 9600:
1680 encodedBitRate = 0x06;
1681 break;
1682 case 19200:
1683 encodedBitRate = 0x07;
1684 break;
1685 case 38400:
1686 encodedBitRate = 0x08;
1687 break;
1688 case 57600:
1689 encodedBitRate = 0x09;
1690 break;
1691 case 115200:
1692 encodedBitRate = 0x0a;
1693 break;
1694 default:
1695 break;
1696 }
1697 ret.pack(encodedBitRate);
1698 return responseSuccess(std::move(ret));
1699 }
Jian Zhang23f44652022-03-17 17:13:10 +08001700 case SolConfParam::Vbitrate:
1701 default:
1702 return response(ipmiCCParamNotSupported);
1703 }
1704
1705 return response(ccParamNotSupported);
1706}
1707
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001708} // namespace transport
1709} // namespace ipmi
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301710
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001711void register_netfn_transport_functions() __attribute__((constructor));
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301712
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001713void register_netfn_transport_functions()
1714{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001715 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1716 ipmi::transport::cmdSetLanConfigParameters,
1717 ipmi::Privilege::Admin, ipmi::transport::setLan);
1718 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1719 ipmi::transport::cmdGetLanConfigParameters,
Johnathan Mantey34698d52019-11-19 14:47:30 -08001720 ipmi::Privilege::Operator, ipmi::transport::getLan);
Jian Zhang23f44652022-03-17 17:13:10 +08001721 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1722 ipmi::transport::cmdSetSolConfigParameters,
1723 ipmi::Privilege::Admin,
1724 ipmi::transport::setSolConfParams);
1725 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1726 ipmi::transport::cmdGetSolConfigParameters,
1727 ipmi::Privilege::User,
1728 ipmi::transport::getSolConfParams);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001729}