blob: df4e39678b5fd401baeb419fbd4113ec7d61bd55 [file] [log] [blame]
Patrick Venture690a2342020-05-17 11:51:31 -07001#include "transporthandler.hpp"
2
George Liuc1c7eac2024-02-04 17:24:19 +08003#include <ipmid/utils.hpp>
George Liu32e8f5d2024-07-17 19:52:25 +08004#include <phosphor-logging/lg2.hpp>
William A. Kennington III726f2bd2023-06-21 01:11:40 -07005#include <stdplus/net/addr/subnet.hpp>
William A. Kennington III7a3831b2023-06-21 01:10:49 -07006#include <stdplus/raw.hpp>
7
8#include <array>
William A. Kennington III726f2bd2023-06-21 01:11:40 -07009#include <fstream>
William A. Kennington III7a3831b2023-06-21 01:10:49 -070010
William A. Kennington IIIc514d872019-04-06 18:19:38 -070011using phosphor::logging::elog;
Willy Tu523e2d12023-09-05 11:36:48 -070012using sdbusplus::error::xyz::openbmc_project::common::InternalFailure;
William A. Kennington III7a3831b2023-06-21 01:10:49 -070013using sdbusplus::error::xyz::openbmc_project::common::InvalidArgument;
Willy Tu523e2d12023-09-05 11:36:48 -070014using sdbusplus::server::xyz::openbmc_project::network::EthernetInterface;
15using sdbusplus::server::xyz::openbmc_project::network::IP;
16using sdbusplus::server::xyz::openbmc_project::network::Neighbor;
William A. Kennington IIIc514d872019-04-06 18:19:38 -070017
Johnathan Manteyaffadb52019-10-07 10:13:53 -070018namespace cipher
19{
20
21std::vector<uint8_t> getCipherList()
22{
23 std::vector<uint8_t> cipherList;
24
25 std::ifstream jsonFile(cipher::configFile);
26 if (!jsonFile.is_open())
27 {
George Liu32e8f5d2024-07-17 19:52:25 +080028 lg2::error("Channel Cipher suites file not found");
Johnathan Manteyaffadb52019-10-07 10:13:53 -070029 elog<InternalFailure>();
30 }
31
32 auto data = Json::parse(jsonFile, nullptr, false);
33 if (data.is_discarded())
34 {
George Liu32e8f5d2024-07-17 19:52:25 +080035 lg2::error("Parsing channel cipher suites JSON failed");
Johnathan Manteyaffadb52019-10-07 10:13:53 -070036 elog<InternalFailure>();
37 }
38
39 // Byte 1 is reserved
40 cipherList.push_back(0x00);
41
42 for (const auto& record : data)
43 {
44 cipherList.push_back(record.value(cipher, 0));
45 }
46
47 return cipherList;
48}
49} // namespace cipher
50
51namespace ipmi
52{
53namespace transport
54{
55
George Liu8379dc92025-07-08 14:02:07 +080056// LAN Handler specific response codes
57constexpr Cc ccParamNotSupported = 0x80;
58constexpr Cc ccParamSetLocked = 0x81;
59constexpr Cc ccParamReadOnly = 0x82;
60constexpr Cc ccWriteReadParameter = 0x82;
61
62static inline auto responseParamNotSupported()
63{
64 return response(ccParamNotSupported);
65}
66
67static inline auto responseParamSetLocked()
68{
69 return response(ccParamSetLocked);
70}
71
72static inline auto responseParamReadOnly()
73{
74 return response(ccParamReadOnly);
75}
76
77static inline auto responseWriteReadParameter()
78{
79 return response(ccWriteReadParameter);
80}
81
William A. Kennington IIIc514d872019-04-06 18:19:38 -070082/** @brief Valid address origins for IPv4 */
83const std::unordered_set<IP::AddressOrigin> originsV4 = {
84 IP::AddressOrigin::Static,
85 IP::AddressOrigin::DHCP,
86};
87
Johnathan Manteyb87034e2019-09-16 10:50:50 -070088static constexpr uint8_t oemCmdStart = 192;
Johnathan Manteyb87034e2019-09-16 10:50:50 -070089
William A. Kennington IIIc72f3602023-10-19 03:51:37 -070090// Checks if the ifname is part of the networkd path
91// This assumes the path came from the network subtree PATH_ROOT
92bool ifnameInPath(std::string_view ifname, std::string_view path)
93{
94 constexpr auto rs = PATH_ROOT.size() + 1; // ROOT + separator
95 const auto is = rs + ifname.size(); // ROOT + sep + ifname
96 return path.size() > rs && path.substr(rs).starts_with(ifname) &&
Chandramohan839fa03352024-08-16 22:47:56 +053097 (path.size() == is || path[is] == '/' ||
98 path[is] == '_'); // handle VLAN IF uses '_' e.g.
99 // /xyz/openbmc_project/network/eth0_2
William A. Kennington IIIc72f3602023-10-19 03:51:37 -0700100}
101
Patrick Williams69b4c282025-03-03 11:19:13 -0500102std::optional<ChannelParams> maybeGetChannelParams(sdbusplus::bus_t& bus,
103 uint8_t channel)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700104{
105 auto ifname = getChannelName(channel);
106 if (ifname.empty())
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800107 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700108 return std::nullopt;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800109 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800110
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700111 // Enumerate all VLAN + ETHERNET interfaces
George Liuc1c7eac2024-02-04 17:24:19 +0800112 std::vector<std::string> interfaces = {INTF_VLAN, INTF_ETHERNET};
Patrick Williams1318a5e2024-08-16 15:19:54 -0400113 ipmi::ObjectTree objs =
114 ipmi::getSubTree(bus, interfaces, std::string{PATH_ROOT});
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700115
116 ChannelParams params;
117 for (const auto& [path, impls] : objs)
118 {
William A. Kennington IIIc72f3602023-10-19 03:51:37 -0700119 if (!ifnameInPath(ifname, path))
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700120 {
121 continue;
122 }
123 for (const auto& [service, intfs] : impls)
124 {
125 bool vlan = false;
126 bool ethernet = false;
127 for (const auto& intf : intfs)
128 {
129 if (intf == INTF_VLAN)
130 {
131 vlan = true;
132 }
133 else if (intf == INTF_ETHERNET)
134 {
135 ethernet = true;
136 }
137 }
138 if (params.service.empty() && (vlan || ethernet))
139 {
140 params.service = service;
141 }
142 if (params.ifPath.empty() && !vlan && ethernet)
143 {
144 params.ifPath = path;
145 }
146 if (params.logicalPath.empty() && vlan)
147 {
148 params.logicalPath = path;
149 }
150 }
151 }
152
153 // We must have a path for the underlying interface
154 if (params.ifPath.empty())
155 {
156 return std::nullopt;
157 }
158 // We don't have a VLAN so the logical path is the same
159 if (params.logicalPath.empty())
160 {
161 params.logicalPath = params.ifPath;
162 }
163
164 params.id = channel;
165 params.ifname = std::move(ifname);
Willy Tu11d68892022-01-20 10:37:34 -0800166 return params;
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700167}
168
Patrick Williams5d82f472022-07-22 19:26:53 -0500169ChannelParams getChannelParams(sdbusplus::bus_t& bus, uint8_t channel)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700170{
171 auto params = maybeGetChannelParams(bus, channel);
172 if (!params)
173 {
George Liu32e8f5d2024-07-17 19:52:25 +0800174 lg2::error("Failed to get channel params: {CHANNEL}", "CHANNEL",
175 channel);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700176 elog<InternalFailure>();
177 }
178 return std::move(*params);
179}
180
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700181/** @brief Get / Set the Property value from phosphor-networkd EthernetInterface
182 */
183template <typename T>
184static T getEthProp(sdbusplus::bus_t& bus, const ChannelParams& params,
185 const std::string& prop)
186{
187 return std::get<T>(getDbusProperty(bus, params.service, params.logicalPath,
188 INTF_ETHERNET, prop));
189}
190template <typename T>
191static void setEthProp(sdbusplus::bus_t& bus, const ChannelParams& params,
192 const std::string& prop, const T& t)
193{
194 return setDbusProperty(bus, params.service, params.logicalPath,
195 INTF_ETHERNET, prop, t);
196}
197
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700198/** @brief Determines the MAC of the ethernet interface
199 *
200 * @param[in] bus - The bus object used for lookups
201 * @param[in] params - The parameters for the channel
202 * @return The configured mac address
203 */
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700204stdplus::EtherAddr getMACProperty(sdbusplus::bus_t& bus,
205 const ChannelParams& params)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700206{
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700207 auto prop = getDbusProperty(bus, params.service, params.ifPath, INTF_MAC,
208 "MACAddress");
209 return stdplus::fromStr<stdplus::EtherAddr>(std::get<std::string>(prop));
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700210}
211
212/** @brief Sets the system value for MAC address on the given interface
213 *
214 * @param[in] bus - The bus object used for lookups
215 * @param[in] params - The parameters for the channel
216 * @param[in] mac - MAC address to apply
217 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500218void setMACProperty(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700219 stdplus::EtherAddr mac)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700220{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700221 setDbusProperty(bus, params.service, params.ifPath, INTF_MAC, "MACAddress",
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700222 stdplus::toStr(mac));
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700223}
224
Patrick Williams5d82f472022-07-22 19:26:53 -0500225void deleteObjectIfExists(sdbusplus::bus_t& bus, const std::string& service,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700226 const std::string& path)
227{
228 if (path.empty())
229 {
230 return;
231 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530232 try
tomjose26e17732016-03-03 08:52:51 -0600233 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700234 auto req = bus.new_method_call(service.c_str(), path.c_str(),
235 ipmi::DELETE_INTERFACE, "Delete");
236 bus.call_noreply(req);
237 }
Patrick Williams5d82f472022-07-22 19:26:53 -0500238 catch (const sdbusplus::exception_t& e)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700239 {
Chandramohan839fa03352024-08-16 22:47:56 +0530240 // handle Delete Interface DBus errors
jayaprakash Mutyala84c49dc2020-05-18 23:12:13 +0000241 if (strcmp(e.name(),
242 "xyz.openbmc_project.Common.Error.InternalFailure") != 0 &&
Chandramohan839fa03352024-08-16 22:47:56 +0530243 strcmp(e.name(), "org.freedesktop.DBus.Error.UnknownObject") != 0 &&
244 strcmp(e.name(), "xyz.openbmc_project.Common.Error.NotAllowed") !=
245 0)
tomjose26e17732016-03-03 08:52:51 -0600246 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700247 // We want to rethrow real errors
248 throw;
tomjose26e17732016-03-03 08:52:51 -0600249 }
250 }
tomjose26e17732016-03-03 08:52:51 -0600251}
252
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700253/** @brief Sets the address info configured for the interface
254 * If a previous address path exists then it will be removed
255 * before the new address is added.
256 *
257 * @param[in] bus - The bus object used for lookups
258 * @param[in] params - The parameters for the channel
259 * @param[in] address - The address of the new IP
260 * @param[in] prefix - The prefix of the new IP
261 */
262template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500263void createIfAddr(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700264 typename AddrFamily<family>::addr address, uint8_t prefix)
Tom Josepha30c8d32018-03-22 02:15:03 +0530265{
Patrick Williams1318a5e2024-08-16 15:19:54 -0400266 auto newreq =
267 bus.new_method_call(params.service.c_str(), params.logicalPath.c_str(),
268 INTF_IP_CREATE, "IP");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700269 std::string protocol =
Willy Tu523e2d12023-09-05 11:36:48 -0700270 sdbusplus::common::xyz::openbmc_project::network::convertForMessage(
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700271 AddrFamily<family>::protocol);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700272 stdplus::ToStrHandle<stdplus::ToStr<typename AddrFamily<family>::addr>> tsh;
273 newreq.append(protocol, tsh(address), prefix, "");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700274 bus.call_noreply(newreq);
275}
Tom Josepha30c8d32018-03-22 02:15:03 +0530276
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700277/** @brief Trivial helper for getting the IPv4 address from getIfAddrs()
278 *
279 * @param[in] bus - The bus object used for lookups
280 * @param[in] params - The parameters for the channel
281 * @return The address and prefix if found
282 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500283auto getIfAddr4(sdbusplus::bus_t& bus, const ChannelParams& params)
Tom Josepha30c8d32018-03-22 02:15:03 +0530284{
Chanh Nguyen8bd9a9b2024-11-08 09:08:56 +0000285 std::optional<IfAddr<AF_INET>> ifaddr4 = std::nullopt;
286 IP::AddressOrigin src;
287
288 try
289 {
290 src = std::get<bool>(
291 getDbusProperty(bus, params.service, params.logicalPath,
292 INTF_ETHERNET, "DHCP4"))
293 ? IP::AddressOrigin::DHCP
294 : IP::AddressOrigin::Static;
295 }
296 catch (const sdbusplus::exception_t& e)
297 {
298 lg2::error("Failed to get IPv4 source");
299 return ifaddr4;
300 }
301
302 for (uint8_t i = 0; i < MAX_IPV4_ADDRESSES; ++i)
303 {
304 ifaddr4 = getIfAddr<AF_INET>(bus, params, i, originsV4);
Vince Changbefca3c2025-01-09 08:39:36 +0800305 if (ifaddr4 && src == ifaddr4->origin)
Chanh Nguyen8bd9a9b2024-11-08 09:08:56 +0000306 {
307 break;
308 }
309 else
310 {
311 ifaddr4 = std::nullopt;
312 }
313 }
314 return ifaddr4;
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700315}
Tom Josepha30c8d32018-03-22 02:15:03 +0530316
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700317/** @brief Reconfigures the IPv4 address info configured for the interface
318 *
319 * @param[in] bus - The bus object used for lookups
320 * @param[in] params - The parameters for the channel
321 * @param[in] address - The new address if specified
322 * @param[in] prefix - The new address prefix if specified
323 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500324void reconfigureIfAddr4(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700325 std::optional<stdplus::In4Addr> address,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700326 std::optional<uint8_t> prefix)
327{
328 auto ifaddr = getIfAddr4(bus, params);
329 if (!ifaddr && !address)
Tom Josepha30c8d32018-03-22 02:15:03 +0530330 {
George Liu32e8f5d2024-07-17 19:52:25 +0800331 lg2::error("Missing address for IPv4 assignment");
Tom Josepha30c8d32018-03-22 02:15:03 +0530332 elog<InternalFailure>();
333 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700334 uint8_t fallbackPrefix = AddrFamily<AF_INET>::defaultPrefix;
Vince Changbefca3c2025-01-09 08:39:36 +0800335 auto addr = stdplus::In4Addr{};
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700336 if (ifaddr)
Tom Josepha30c8d32018-03-22 02:15:03 +0530337 {
Vince Changbefca3c2025-01-09 08:39:36 +0800338 addr = ifaddr->address;
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700339 fallbackPrefix = ifaddr->prefix;
340 deleteObjectIfExists(bus, params.service, ifaddr->path);
341 }
Vince Changbefca3c2025-01-09 08:39:36 +0800342 addr = address.value_or(addr);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700343 if (addr != stdplus::In4Addr{})
Johnathan Manteycbfa6e12023-06-01 06:57:25 -0700344 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700345 createIfAddr<AF_INET>(bus, params, addr,
Johnathan Manteycbfa6e12023-06-01 06:57:25 -0700346 prefix.value_or(fallbackPrefix));
347 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700348}
349
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700350template <int family>
Patrick Williams69b4c282025-03-03 11:19:13 -0500351std::optional<IfNeigh<family>> findGatewayNeighbor(sdbusplus::bus_t& bus,
352 const ChannelParams& params,
353 ObjectLookupCache& neighbors)
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700354{
355 auto gateway = getGatewayProperty<family>(bus, params);
356 if (!gateway)
357 {
358 return std::nullopt;
359 }
360
361 return findStaticNeighbor<family>(bus, params, *gateway, neighbors);
362}
363
364template <int family>
Patrick Williams69b4c282025-03-03 11:19:13 -0500365std::optional<IfNeigh<family>> getGatewayNeighbor(sdbusplus::bus_t& bus,
366 const ChannelParams& params)
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700367{
368 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
369 return findGatewayNeighbor<family>(bus, params, neighbors);
370}
371
372template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500373void reconfigureGatewayMAC(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700374 stdplus::EtherAddr mac)
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700375{
376 auto gateway = getGatewayProperty<family>(bus, params);
377 if (!gateway)
378 {
George Liu32e8f5d2024-07-17 19:52:25 +0800379 lg2::error("Tried to set Gateway MAC without Gateway");
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700380 elog<InternalFailure>();
381 }
382
383 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
Patrick Williams1318a5e2024-08-16 15:19:54 -0400384 auto neighbor =
385 findStaticNeighbor<family>(bus, params, *gateway, neighbors);
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700386 if (neighbor)
387 {
388 deleteObjectIfExists(bus, params.service, neighbor->path);
389 }
390
391 createNeighbor<family>(bus, params, *gateway, mac);
392}
393
William A. Kennington III16064aa2019-04-13 17:44:53 -0700394/** @brief Deconfigures the IPv6 address info configured for the interface
395 *
396 * @param[in] bus - The bus object used for lookups
397 * @param[in] params - The parameters for the channel
398 * @param[in] idx - The address index to operate on
399 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500400void deconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III16064aa2019-04-13 17:44:53 -0700401 uint8_t idx)
402{
403 auto ifaddr = getIfAddr<AF_INET6>(bus, params, idx, originsV6Static);
404 if (ifaddr)
405 {
406 deleteObjectIfExists(bus, params.service, ifaddr->path);
407 }
408}
409
410/** @brief Reconfigures the IPv6 address info configured for the interface
411 *
412 * @param[in] bus - The bus object used for lookups
413 * @param[in] params - The parameters for the channel
414 * @param[in] idx - The address index to operate on
415 * @param[in] address - The new address
416 * @param[in] prefix - The new address prefix
417 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500418void reconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700419 uint8_t idx, stdplus::In6Addr address, uint8_t prefix)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700420{
421 deconfigureIfAddr6(bus, params, idx);
422 createIfAddr<AF_INET6>(bus, params, address, prefix);
423}
424
425/** @brief Converts the AddressOrigin into an IPv6Source
426 *
427 * @param[in] origin - The DBus Address Origin to convert
428 * @return The IPv6Source version of the origin
429 */
430IPv6Source originToSourceType(IP::AddressOrigin origin)
431{
432 switch (origin)
433 {
434 case IP::AddressOrigin::Static:
435 return IPv6Source::Static;
436 case IP::AddressOrigin::DHCP:
437 return IPv6Source::DHCP;
438 case IP::AddressOrigin::SLAAC:
439 return IPv6Source::SLAAC;
440 default:
441 {
Willy Tu523e2d12023-09-05 11:36:48 -0700442 auto originStr = sdbusplus::common::xyz::openbmc_project::network::
William A. Kennington III16064aa2019-04-13 17:44:53 -0700443 convertForMessage(origin);
George Liu32e8f5d2024-07-17 19:52:25 +0800444 lg2::error("Invalid IP::AddressOrigin conversion to IPv6Source, "
445 "origin: {ORIGIN}",
446 "ORIGIN", originStr);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700447 elog<InternalFailure>();
448 }
449 }
450}
451
452/** @brief Packs the IPMI message response with IPv6 address data
453 *
454 * @param[out] ret - The IPMI response payload to be packed
455 * @param[in] channel - The channel id corresponding to an ethernet interface
456 * @param[in] set - The set selector for determining address index
457 * @param[in] origins - Set of valid origins for address filtering
458 */
459void getLanIPv6Address(message::Payload& ret, uint8_t channel, uint8_t set,
460 const std::unordered_set<IP::AddressOrigin>& origins)
461{
462 auto source = IPv6Source::Static;
463 bool enabled = false;
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700464 stdplus::In6Addr addr{};
Johnathan Mantey5aae0922021-10-21 13:05:36 -0700465 uint8_t prefix{};
William A. Kennington III16064aa2019-04-13 17:44:53 -0700466 auto status = IPv6AddressStatus::Disabled;
467
468 auto ifaddr = channelCall<getIfAddr<AF_INET6>>(channel, set, origins);
469 if (ifaddr)
470 {
471 source = originToSourceType(ifaddr->origin);
Johnathan Mantey846af862021-10-21 12:48:54 -0700472 enabled = (origins == originsV6Static);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700473 addr = ifaddr->address;
474 prefix = ifaddr->prefix;
475 status = IPv6AddressStatus::Active;
476 }
477
478 ret.pack(set);
William A. Kennington III7a0e5df2021-05-19 13:31:29 -0700479 ret.pack(types::enum_cast<uint4_t>(source), uint3_t{}, enabled);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700480 ret.pack(stdplus::raw::asView<char>(addr));
William A. Kennington III16064aa2019-04-13 17:44:53 -0700481 ret.pack(prefix);
William A. Kennington III7a0e5df2021-05-19 13:31:29 -0700482 ret.pack(types::enum_cast<uint8_t>(status));
William A. Kennington III16064aa2019-04-13 17:44:53 -0700483}
484
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700485/** @brief Gets the vlan ID configured on the interface
486 *
487 * @param[in] bus - The bus object used for lookups
488 * @param[in] params - The parameters for the channel
489 * @return VLAN id or the standard 0 for no VLAN
490 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500491uint16_t getVLANProperty(sdbusplus::bus_t& bus, const ChannelParams& params)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700492{
493 // VLAN devices will always have a separate logical object
494 if (params.ifPath == params.logicalPath)
495 {
496 return 0;
497 }
498
499 auto vlan = std::get<uint32_t>(getDbusProperty(
500 bus, params.service, params.logicalPath, INTF_VLAN, "Id"));
501 if ((vlan & VLAN_VALUE_MASK) != vlan)
502 {
Vernon Maueryaf4a7752024-07-02 09:45:46 -0700503 lg2::error("networkd returned an invalid vlan: {VLAN} "
504 "(CH={CHANNEL}, IF={IFNAME})",
505 "CHANNEL", params.id, "IFNAME", params.ifname, "VLAN", vlan);
Tom Josepha30c8d32018-03-22 02:15:03 +0530506 elog<InternalFailure>();
507 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700508 return vlan;
Tom Josepha30c8d32018-03-22 02:15:03 +0530509}
510
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700511/** @brief Deletes all of the possible configuration parameters for a channel
512 *
513 * @param[in] bus - The bus object used for lookups
514 * @param[in] params - The parameters for the channel
515 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500516void deconfigureChannel(sdbusplus::bus_t& bus, ChannelParams& params)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500517{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700518 // Delete all objects associated with the interface
George Liuc1c7eac2024-02-04 17:24:19 +0800519 ObjectTree objs =
520 ipmi::getSubTree(bus, std::vector<std::string>{DELETE_INTERFACE},
521 std::string{PATH_ROOT});
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700522 for (const auto& [path, impls] : objs)
523 {
William A. Kennington IIIc72f3602023-10-19 03:51:37 -0700524 if (!ifnameInPath(params.ifname, path))
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700525 {
526 continue;
527 }
528 for (const auto& [service, intfs] : impls)
529 {
530 deleteObjectIfExists(bus, service, path);
531 }
532 // Update params to reflect the deletion of vlan
533 if (path == params.logicalPath)
534 {
535 params.logicalPath = params.ifPath;
536 }
537 }
538
539 // Clear out any settings on the lower physical interface
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700540 setEthProp(bus, params, "DHCP4", false);
541 setEthProp(bus, params, "DHCP6", false);
542 setEthProp(bus, params, "IPv6AcceptRA", false);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500543}
544
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700545/** @brief Creates a new VLAN on the specified interface
546 *
547 * @param[in] bus - The bus object used for lookups
548 * @param[in] params - The parameters for the channel
549 * @param[in] vlan - The id of the new vlan
550 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500551void createVLAN(sdbusplus::bus_t& bus, ChannelParams& params, uint16_t vlan)
Ratan Guptab8e99552017-07-27 07:07:48 +0530552{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700553 if (vlan == 0)
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530554 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700555 return;
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530556 }
557
William A. Kennington IIIc72f3602023-10-19 03:51:37 -0700558 auto req = bus.new_method_call(params.service.c_str(), PATH_ROOT.c_str(),
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700559 INTF_VLAN_CREATE, "VLAN");
560 req.append(params.ifname, static_cast<uint32_t>(vlan));
561 auto reply = bus.call(req);
562 sdbusplus::message::object_path newPath;
563 reply.read(newPath);
564 params.logicalPath = std::move(newPath);
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530565}
566
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700567/** @brief Performs the necessary reconfiguration to change the VLAN
568 *
569 * @param[in] bus - The bus object used for lookups
570 * @param[in] params - The parameters for the channel
571 * @param[in] vlan - The new vlan id to use
572 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500573void reconfigureVLAN(sdbusplus::bus_t& bus, ChannelParams& params,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700574 uint16_t vlan)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500575{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700576 // Unfortunatetly we don't have built-in functions to migrate our interface
577 // customizations to new VLAN interfaces, or have some kind of decoupling.
578 // We therefore must retain all of our old information, setup the new VLAN
579 // configuration, then restore the old info.
Nan Li3d0df912016-10-18 19:51:41 +0800580
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700581 // Save info from the old logical interface
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700582 bool dhcp4 = getEthProp<bool>(bus, params, "DHCP4");
583 bool dhcp6 = getEthProp<bool>(bus, params, "DHCP6");
584 bool ra = getEthProp<bool>(bus, params, "IPv6AcceptRA");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700585 ObjectLookupCache ips(bus, params, INTF_IP);
586 auto ifaddr4 = findIfAddr<AF_INET>(bus, params, 0, originsV4, ips);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700587 std::vector<IfAddr<AF_INET6>> ifaddrs6;
588 for (uint8_t i = 0; i < MAX_IPV6_STATIC_ADDRESSES; ++i)
589 {
Patrick Williams1318a5e2024-08-16 15:19:54 -0400590 auto ifaddr6 =
591 findIfAddr<AF_INET6>(bus, params, i, originsV6Static, ips);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700592 if (!ifaddr6)
593 {
594 break;
595 }
596 ifaddrs6.push_back(std::move(*ifaddr6));
597 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700598 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
599 auto neighbor4 = findGatewayNeighbor<AF_INET>(bus, params, neighbors);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700600 auto neighbor6 = findGatewayNeighbor<AF_INET6>(bus, params, neighbors);
Chandramohan839fa03352024-08-16 22:47:56 +0530601 // Make copy of params to retain the previous configs
602 ChannelParams parentIntParams = params;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500603
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700604 deconfigureChannel(bus, params);
605 createVLAN(bus, params, vlan);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500606
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700607 // Re-establish the saved settings
Chandramohan839fa03352024-08-16 22:47:56 +0530608 setEthProp(bus, parentIntParams, "DHCP4", dhcp4);
609 setEthProp(bus, parentIntParams, "DHCP6", dhcp6);
610 setEthProp(bus, parentIntParams, "IPv6AcceptRA", ra);
611
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700612 setEthProp(bus, params, "DHCP4", dhcp4);
613 setEthProp(bus, params, "DHCP6", dhcp6);
614 setEthProp(bus, params, "IPv6AcceptRA", ra);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700615 if (ifaddr4)
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800616 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700617 createIfAddr<AF_INET>(bus, params, ifaddr4->address, ifaddr4->prefix);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800618 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700619 for (const auto& ifaddr6 : ifaddrs6)
620 {
621 createIfAddr<AF_INET6>(bus, params, ifaddr6.address, ifaddr6.prefix);
622 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700623 if (neighbor4)
624 {
625 createNeighbor<AF_INET>(bus, params, neighbor4->ip, neighbor4->mac);
626 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700627 if (neighbor6)
628 {
629 createNeighbor<AF_INET6>(bus, params, neighbor6->ip, neighbor6->mac);
630 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700631}
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800632
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700633// We need to store this value so it can be returned to the client
634// It is volatile so safe to store in daemon memory.
635static std::unordered_map<uint8_t, SetStatus> setStatus;
636
637// Until we have good support for fixed versions of IPMI tool
638// we need to return the VLAN id for disabled VLANs. The value is only
639// used for verification that a disable operation succeeded and will only
640// be sent if our system indicates that vlans are disabled.
641static std::unordered_map<uint8_t, uint16_t> lastDisabledVlan;
642
643/** @brief Gets the set status for the channel if it exists
644 * Otherise populates and returns the default value.
645 *
646 * @param[in] channel - The channel id corresponding to an ethernet interface
647 * @return A reference to the SetStatus for the channel
648 */
649SetStatus& getSetStatus(uint8_t channel)
650{
651 auto it = setStatus.find(channel);
652 if (it != setStatus.end())
653 {
654 return it->second;
655 }
656 return setStatus[channel] = SetStatus::Complete;
657}
658
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700659/** @brief Unpacks the trivially copyable type from the message */
660template <typename T>
661static T unpackT(message::Payload& req)
662{
663 std::array<uint8_t, sizeof(T)> bytes;
664 if (req.unpack(bytes) != 0)
665 {
666 throw ccReqDataLenInvalid;
667 }
668 return stdplus::raw::copyFrom<T>(bytes);
669}
670
671/** @brief Ensure the message is fully unpacked */
672static void unpackFinal(message::Payload& req)
673{
674 if (!req.fullyUnpacked())
675 {
676 throw ccReqDataTruncated;
677 }
678}
679
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700680/**
681 * Define placeholder command handlers for the OEM Extension bytes for the Set
682 * LAN Configuration Parameters and Get LAN Configuration Parameters
683 * commands. Using "weak" linking allows the placeholder setLanOem/getLanOem
684 * functions below to be overridden.
685 * To create handlers for your own proprietary command set:
686 * Create/modify a phosphor-ipmi-host Bitbake append file within your Yocto
687 * recipe
688 * Create C++ file(s) that define IPMI handler functions matching the
689 * function names below (i.e. setLanOem). The default name for the
690 * transport IPMI commands is transporthandler_oem.cpp.
691 * Add:
Johnathan Manteyefe26682022-08-11 14:30:45 -0700692 * EXTRA_OEMESON:append = "-Dtransport-oem=enabled"
693 * Create a do_configure:prepend()/do_install:append() method in your
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700694 * bbappend file to copy the file to the build directory.
695 * Add:
696 * PROJECT_SRC_DIR := "${THISDIR}/${PN}"
697 * # Copy the "strong" functions into the working directory, overriding the
698 * # placeholder functions.
Johnathan Manteyefe26682022-08-11 14:30:45 -0700699 * do_configure:prepend(){
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700700 * cp -f ${PROJECT_SRC_DIR}/transporthandler_oem.cpp ${S}
701 * }
702 *
703 * # Clean up after complilation has completed
Johnathan Manteyefe26682022-08-11 14:30:45 -0700704 * do_install:append(){
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700705 * rm -f ${S}/transporthandler_oem.cpp
706 * }
707 *
708 */
709
710/**
711 * Define the placeholder OEM commands as having weak linkage. Create
712 * setLanOem, and getLanOem functions in the transporthandler_oem.cpp
713 * file. The functions defined there must not have the "weak" attribute
714 * applied to them.
715 */
716RspType<> setLanOem(uint8_t channel, uint8_t parameter, message::Payload& req)
717 __attribute__((weak));
Patrick Williams69b4c282025-03-03 11:19:13 -0500718RspType<message::Payload> getLanOem(uint8_t channel, uint8_t parameter,
719 uint8_t set, uint8_t block)
720 __attribute__((weak));
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700721
Willy Tu11d68892022-01-20 10:37:34 -0800722RspType<> setLanOem(uint8_t, uint8_t, message::Payload& req)
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700723{
724 req.trailingOk = true;
George Liu8379dc92025-07-08 14:02:07 +0800725 return responseParamNotSupported();
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700726}
727
Willy Tu11d68892022-01-20 10:37:34 -0800728RspType<message::Payload> getLanOem(uint8_t, uint8_t, uint8_t, uint8_t)
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700729{
George Liu8379dc92025-07-08 14:02:07 +0800730 return responseParamNotSupported();
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700731}
732
Jian Zhangcf19d142023-07-31 10:22:53 +0800733/**
734 * @brief is a valid LAN channel.
735 *
736 * This function checks whether the input channel is a valid LAN channel or not.
737 *
738 * @param[in] channel: the channel number.
739 * @return nullopt if the channel is invalid, false if the channel is not a LAN
740 * channel, true if the channel is a LAN channel.
741 **/
742std::optional<bool> isLanChannel(uint8_t channel)
743{
744 ChannelInfo chInfo;
745 auto cc = getChannelInfo(channel, chInfo);
746 if (cc != ccSuccess)
747 {
748 return std::nullopt;
749 }
750
751 return chInfo.mediumType ==
752 static_cast<uint8_t>(EChannelMediumType::lan8032);
753}
754
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700755RspType<> setLanInt(Context::ptr ctx, uint4_t channelBits, uint4_t reserved1,
756 uint8_t parameter, message::Payload& req)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700757{
vijayabharathix shettycc769252020-02-27 17:52:20 +0000758 const uint8_t channel = convertCurrentChannelNum(
759 static_cast<uint8_t>(channelBits), ctx->channel);
760 if (reserved1 || !isValidChannel(channel))
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700761 {
George Liu32e8f5d2024-07-17 19:52:25 +0800762 lg2::error("Set Lan - Invalid field in request");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700763 req.trailingOk = true;
764 return responseInvalidFieldRequest();
765 }
766
Jian Zhangcf19d142023-07-31 10:22:53 +0800767 if (!isLanChannel(channel).value_or(false))
768 {
George Liu32e8f5d2024-07-17 19:52:25 +0800769 lg2::error("Set Lan - Not a LAN channel");
Jian Zhangcf19d142023-07-31 10:22:53 +0800770 return responseInvalidFieldRequest();
771 }
772
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700773 switch (static_cast<LanParam>(parameter))
774 {
775 case LanParam::SetStatus:
776 {
777 uint2_t flag;
778 uint6_t rsvd;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700779 if (req.unpack(flag, rsvd) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700780 {
781 return responseReqDataLenInvalid();
782 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700783 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800784 if (rsvd)
785 {
786 return responseInvalidFieldRequest();
787 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700788 auto status = static_cast<SetStatus>(static_cast<uint8_t>(flag));
789 switch (status)
790 {
791 case SetStatus::Complete:
792 {
793 getSetStatus(channel) = status;
794 return responseSuccess();
795 }
796 case SetStatus::InProgress:
797 {
798 auto& storedStatus = getSetStatus(channel);
799 if (storedStatus == SetStatus::InProgress)
800 {
George Liu8379dc92025-07-08 14:02:07 +0800801 return responseParamSetLocked();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700802 }
803 storedStatus = status;
804 return responseSuccess();
805 }
806 case SetStatus::Commit:
807 if (getSetStatus(channel) != SetStatus::InProgress)
808 {
809 return responseInvalidFieldRequest();
810 }
811 return responseSuccess();
812 }
George Liu8379dc92025-07-08 14:02:07 +0800813 return responseParamNotSupported();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700814 }
815 case LanParam::AuthSupport:
816 {
817 req.trailingOk = true;
George Liu8379dc92025-07-08 14:02:07 +0800818 return responseParamReadOnly();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700819 }
820 case LanParam::AuthEnables:
821 {
822 req.trailingOk = true;
George Liu8379dc92025-07-08 14:02:07 +0800823 return responseParamReadOnly();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700824 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800825 case LanParam::IP:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600826 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700827 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800828 {
829 return responseCommandNotAvailable();
830 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700831 auto ip = unpackT<stdplus::In4Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700832 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700833 channelCall<reconfigureIfAddr4>(channel, ip, std::nullopt);
834 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +0530835 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700836 case LanParam::IPSrc:
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530837 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700838 uint4_t flag;
839 uint4_t rsvd;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700840 if (req.unpack(flag, rsvd) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700841 {
842 return responseReqDataLenInvalid();
843 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700844 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800845 if (rsvd)
846 {
847 return responseInvalidFieldRequest();
848 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700849 switch (static_cast<IPSrc>(static_cast<uint8_t>(flag)))
850 {
851 case IPSrc::DHCP:
Johnathan Mantey65265362019-11-14 11:24:19 -0800852 // The IPSrc IPMI command is only for IPv4
853 // management. Modifying IPv6 state is done using
854 // a completely different Set LAN Configuration
855 // subcommand.
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700856 channelCall<setEthProp<bool>>(channel, "DHCP4", true);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700857 return responseSuccess();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700858 case IPSrc::Unspecified:
859 case IPSrc::Static:
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700860 channelCall<setEthProp<bool>>(channel, "DHCP4", false);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700861 return responseSuccess();
Rajashekar Gade Reddy8a860ea2019-12-24 11:31:19 +0530862 case IPSrc::BIOS:
863 case IPSrc::BMC:
Rajashekar Gade Reddy8a860ea2019-12-24 11:31:19 +0530864 return responseInvalidFieldRequest();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700865 }
George Liu8379dc92025-07-08 14:02:07 +0800866 return responseParamNotSupported();
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530867 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800868 case LanParam::MAC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530869 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700870 auto mac = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700871 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700872 channelCall<setMACProperty>(channel, mac);
873 return responseSuccess();
Ratan Gupta533d03b2017-07-30 10:39:22 +0530874 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700875 case LanParam::SubnetMask:
Ratan Guptab8e99552017-07-27 07:07:48 +0530876 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700877 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800878 {
879 return responseCommandNotAvailable();
880 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700881 auto pfx = stdplus::maskToPfx(unpackT<stdplus::In4Addr>(req));
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700882 unpackFinal(req);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700883 channelCall<reconfigureIfAddr4>(channel, std::nullopt, pfx);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700884 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +0530885 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700886 case LanParam::Gateway1:
Ratan Guptab8e99552017-07-27 07:07:48 +0530887 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700888 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800889 {
890 return responseCommandNotAvailable();
891 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700892 auto gateway = unpackT<stdplus::In4Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700893 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700894 channelCall<setGatewayProperty<AF_INET>>(channel, gateway);
895 return responseSuccess();
896 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700897 case LanParam::Gateway1MAC:
898 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700899 auto gatewayMAC = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700900 unpackFinal(req);
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700901 channelCall<reconfigureGatewayMAC<AF_INET>>(channel, gatewayMAC);
902 return responseSuccess();
903 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700904 case LanParam::VLANId:
905 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700906 uint12_t vlanData;
907 uint3_t rsvd;
908 bool vlanEnable;
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530909
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700910 if (req.unpack(vlanData, rsvd, vlanEnable) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700911 {
912 return responseReqDataLenInvalid();
913 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700914 unpackFinal(req);
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530915
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700916 if (rsvd)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700917 {
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530918 return responseInvalidFieldRequest();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700919 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530920
921 uint16_t vlan = static_cast<uint16_t>(vlanData);
922
923 if (!vlanEnable)
924 {
925 lastDisabledVlan[channel] = vlan;
926 vlan = 0;
927 }
Jayaprakash Mutyala0d1d7ad2024-06-19 10:19:33 +0000928 else if (vlan == 0 || vlan == VLAN_VALUE_MASK)
929 {
930 return responseInvalidFieldRequest();
931 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530932
jayaprakash Mutyala84c49dc2020-05-18 23:12:13 +0000933 channelCall<reconfigureVLAN>(channel, vlan);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700934 return responseSuccess();
935 }
936 case LanParam::CiphersuiteSupport:
937 case LanParam::CiphersuiteEntries:
William A. Kennington III16064aa2019-04-13 17:44:53 -0700938 case LanParam::IPFamilySupport:
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700939 {
940 req.trailingOk = true;
George Liu8379dc92025-07-08 14:02:07 +0800941 return responseParamReadOnly();
Ratan Guptab8e99552017-07-27 07:07:48 +0530942 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700943 case LanParam::IPFamilyEnables:
944 {
945 uint8_t enables;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700946 if (req.unpack(enables) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700947 {
948 return responseReqDataLenInvalid();
949 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700950 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700951 switch (static_cast<IPFamilyEnables>(enables))
952 {
953 case IPFamilyEnables::DualStack:
954 return responseSuccess();
955 case IPFamilyEnables::IPv4Only:
956 case IPFamilyEnables::IPv6Only:
George Liu8379dc92025-07-08 14:02:07 +0800957 return responseParamNotSupported();
William A. Kennington III16064aa2019-04-13 17:44:53 -0700958 }
George Liu8379dc92025-07-08 14:02:07 +0800959 return responseParamNotSupported();
William A. Kennington III16064aa2019-04-13 17:44:53 -0700960 }
961 case LanParam::IPv6Status:
962 {
963 req.trailingOk = true;
George Liu8379dc92025-07-08 14:02:07 +0800964 return responseParamReadOnly();
William A. Kennington III16064aa2019-04-13 17:44:53 -0700965 }
966 case LanParam::IPv6StaticAddresses:
967 {
968 uint8_t set;
969 uint7_t rsvd;
970 bool enabled;
William A. Kennington III16064aa2019-04-13 17:44:53 -0700971 uint8_t prefix;
972 uint8_t status;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700973 if (req.unpack(set, rsvd, enabled) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700974 {
975 return responseReqDataLenInvalid();
976 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700977 auto ip = unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700978 if (req.unpack(prefix, status) != 0)
979 {
980 return responseReqDataLenInvalid();
981 }
982 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800983 if (rsvd)
984 {
985 return responseInvalidFieldRequest();
986 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700987 if (enabled)
988 {
Jiaqing Zhao6d4a44e2022-01-24 15:04:00 +0800989 if (prefix < MIN_IPV6_PREFIX_LENGTH ||
990 prefix > MAX_IPV6_PREFIX_LENGTH)
991 {
992 return responseParmOutOfRange();
993 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700994 channelCall<reconfigureIfAddr6>(channel, set, ip, prefix);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700995 }
996 else
997 {
998 channelCall<deconfigureIfAddr6>(channel, set);
999 }
1000 return responseSuccess();
1001 }
1002 case LanParam::IPv6DynamicAddresses:
1003 {
1004 req.trailingOk = true;
George Liu8379dc92025-07-08 14:02:07 +08001005 return responseParamReadOnly();
William A. Kennington III16064aa2019-04-13 17:44:53 -07001006 }
1007 case LanParam::IPv6RouterControl:
1008 {
1009 std::bitset<8> control;
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001010 constexpr uint8_t reservedRACCBits = 0xfc;
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001011 if (req.unpack(control) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -07001012 {
1013 return responseReqDataLenInvalid();
1014 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001015 unpackFinal(req);
Patrick Williams1318a5e2024-08-16 15:19:54 -04001016 if (std::bitset<8> expected(
1017 control & std::bitset<8>(reservedRACCBits));
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001018 expected.any())
William A. Kennington III16064aa2019-04-13 17:44:53 -07001019 {
George Liu8379dc92025-07-08 14:02:07 +08001020 return responseParamNotSupported();
William A. Kennington III16064aa2019-04-13 17:44:53 -07001021 }
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001022
1023 bool enableRA = control[IPv6RouterControlFlag::Dynamic];
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001024 channelCall<setEthProp<bool>>(channel, "IPv6AcceptRA", enableRA);
1025 channelCall<setEthProp<bool>>(channel, "DHCP6", enableRA);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001026 return responseSuccess();
1027 }
1028 case LanParam::IPv6StaticRouter1IP:
1029 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001030 auto gateway = unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001031 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001032 channelCall<setGatewayProperty<AF_INET6>>(channel, gateway);
1033 return responseSuccess();
1034 }
1035 case LanParam::IPv6StaticRouter1MAC:
1036 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001037 auto mac = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001038 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001039 channelCall<reconfigureGatewayMAC<AF_INET6>>(channel, mac);
1040 return responseSuccess();
1041 }
1042 case LanParam::IPv6StaticRouter1PrefixLength:
1043 {
1044 uint8_t prefix;
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001045 if (req.unpack(prefix) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -07001046 {
1047 return responseReqDataLenInvalid();
1048 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001049 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001050 if (prefix != 0)
1051 {
1052 return responseInvalidFieldRequest();
1053 }
1054 return responseSuccess();
1055 }
1056 case LanParam::IPv6StaticRouter1PrefixValue:
1057 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001058 unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001059 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001060 // Accept any prefix value since our prefix length has to be 0
1061 return responseSuccess();
1062 }
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001063 case LanParam::cipherSuitePrivilegeLevels:
1064 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001065 uint8_t rsvd;
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001066 std::array<uint4_t, ipmi::maxCSRecords> cipherSuitePrivs;
1067
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001068 if (req.unpack(rsvd, cipherSuitePrivs))
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001069 {
1070 return responseReqDataLenInvalid();
1071 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001072 unpackFinal(req);
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001073
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001074 if (rsvd)
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001075 {
1076 return responseInvalidFieldRequest();
1077 }
1078
Patrick Williams1318a5e2024-08-16 15:19:54 -04001079 uint8_t resp =
1080 getCipherConfigObject(csPrivFileName, csPrivDefaultFileName)
1081 .setCSPrivilegeLevels(channel, cipherSuitePrivs);
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001082 if (!resp)
1083 {
1084 return responseSuccess();
1085 }
1086 else
1087 {
1088 req.trailingOk = true;
1089 return response(resp);
1090 }
1091 }
Ratan Guptab8e99552017-07-27 07:07:48 +05301092 }
vishwa1eaea4f2016-02-26 11:57:40 -06001093
PavanKumarIntel3771f5f2023-11-02 06:26:42 +00001094 if (parameter >= oemCmdStart)
Johnathan Manteyb87034e2019-09-16 10:50:50 -07001095 {
1096 return setLanOem(channel, parameter, req);
1097 }
1098
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001099 req.trailingOk = true;
George Liu8379dc92025-07-08 14:02:07 +08001100 return responseParamNotSupported();
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001101}
1102
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001103RspType<> setLan(Context::ptr ctx, uint4_t channelBits, uint4_t reserved1,
1104 uint8_t parameter, message::Payload& req)
1105{
1106 try
1107 {
1108 return setLanInt(ctx, channelBits, reserved1, parameter, req);
1109 }
1110 catch (ipmi::Cc cc)
1111 {
1112 return response(cc);
1113 }
1114 catch (const sdbusplus::exception_t& e)
1115 {
1116 if (std::string_view{InvalidArgument::errName} == e.name())
1117 {
1118 return responseInvalidFieldRequest();
1119 }
1120 throw;
1121 }
1122}
1123
vijayabharathix shettycc769252020-02-27 17:52:20 +00001124RspType<message::Payload> getLan(Context::ptr ctx, uint4_t channelBits,
1125 uint3_t reserved, bool revOnly,
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001126 uint8_t parameter, uint8_t set, uint8_t block)
Ratan Guptab8e99552017-07-27 07:07:48 +05301127{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001128 message::Payload ret;
1129 constexpr uint8_t current_revision = 0x11;
1130 ret.pack(current_revision);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001131
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001132 if (revOnly)
Suryakanth Sekare4054402019-08-08 15:16:52 +05301133 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001134 return responseSuccess(std::move(ret));
Suryakanth Sekare4054402019-08-08 15:16:52 +05301135 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001136
vijayabharathix shettycc769252020-02-27 17:52:20 +00001137 const uint8_t channel = convertCurrentChannelNum(
1138 static_cast<uint8_t>(channelBits), ctx->channel);
1139 if (reserved || !isValidChannel(channel))
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001140 {
George Liu32e8f5d2024-07-17 19:52:25 +08001141 lg2::error("Get Lan - Invalid field in request");
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001142 return responseInvalidFieldRequest();
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001143 }
1144
Jian Zhangcf19d142023-07-31 10:22:53 +08001145 if (!isLanChannel(channel).value_or(false))
1146 {
George Liu32e8f5d2024-07-17 19:52:25 +08001147 lg2::error("Set Lan - Not a LAN channel");
Jian Zhangcf19d142023-07-31 10:22:53 +08001148 return responseInvalidFieldRequest();
1149 }
1150
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001151 static std::vector<uint8_t> cipherList;
1152 static bool listInit = false;
1153 if (!listInit)
1154 {
1155 try
1156 {
1157 cipherList = cipher::getCipherList();
1158 listInit = true;
1159 }
1160 catch (const std::exception& e)
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -05001161 {}
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001162 }
1163
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001164 switch (static_cast<LanParam>(parameter))
Tom Josepha30c8d32018-03-22 02:15:03 +05301165 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001166 case LanParam::SetStatus:
Tom Josepha30c8d32018-03-22 02:15:03 +05301167 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001168 SetStatus status;
1169 try
1170 {
1171 status = setStatus.at(channel);
1172 }
1173 catch (const std::out_of_range&)
1174 {
1175 status = SetStatus::Complete;
1176 }
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001177 ret.pack(types::enum_cast<uint2_t>(status), uint6_t{});
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001178 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301179 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001180 case LanParam::AuthSupport:
Tom Josepha30c8d32018-03-22 02:15:03 +05301181 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001182 std::bitset<6> support;
1183 ret.pack(support, uint2_t{});
1184 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301185 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001186 case LanParam::AuthEnables:
vishwa1eaea4f2016-02-26 11:57:40 -06001187 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001188 std::bitset<6> enables;
1189 ret.pack(enables, uint2_t{}); // Callback
1190 ret.pack(enables, uint2_t{}); // User
1191 ret.pack(enables, uint2_t{}); // Operator
1192 ret.pack(enables, uint2_t{}); // Admin
1193 ret.pack(enables, uint2_t{}); // OEM
1194 return responseSuccess(std::move(ret));
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001195 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001196 case LanParam::IP:
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001197 {
1198 auto ifaddr = channelCall<getIfAddr4>(channel);
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001199 stdplus::In4Addr addr{};
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001200 if (ifaddr)
1201 {
1202 addr = ifaddr->address;
1203 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001204 ret.pack(stdplus::raw::asView<char>(addr));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001205 return responseSuccess(std::move(ret));
1206 }
1207 case LanParam::IPSrc:
1208 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001209 auto src = channelCall<getEthProp<bool>>(channel, "DHCP4")
1210 ? IPSrc::DHCP
1211 : IPSrc::Static;
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001212 ret.pack(types::enum_cast<uint4_t>(src), uint4_t{});
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001213 return responseSuccess(std::move(ret));
1214 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001215 case LanParam::MAC:
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001216 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001217 auto mac = channelCall<getMACProperty>(channel);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001218 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001219 return responseSuccess(std::move(ret));
1220 }
1221 case LanParam::SubnetMask:
1222 {
1223 auto ifaddr = channelCall<getIfAddr4>(channel);
1224 uint8_t prefix = AddrFamily<AF_INET>::defaultPrefix;
1225 if (ifaddr)
Ratan Guptab8e99552017-07-27 07:07:48 +05301226 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001227 prefix = ifaddr->prefix;
1228 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001229 auto netmask = stdplus::pfxToMask<stdplus::In4Addr>(prefix);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001230 ret.pack(stdplus::raw::asView<char>(netmask));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001231 return responseSuccess(std::move(ret));
1232 }
1233 case LanParam::Gateway1:
1234 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001235 auto gateway = channelCall<getGatewayProperty<AF_INET>>(channel);
1236 ret.pack(stdplus::raw::asView<char>(
1237 gateway.value_or(stdplus::In4Addr{})));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001238 return responseSuccess(std::move(ret));
1239 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001240 case LanParam::Gateway1MAC:
1241 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001242 stdplus::EtherAddr mac{};
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001243 auto neighbor = channelCall<getGatewayNeighbor<AF_INET>>(channel);
1244 if (neighbor)
1245 {
1246 mac = neighbor->mac;
1247 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001248 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001249 return responseSuccess(std::move(ret));
1250 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001251 case LanParam::VLANId:
1252 {
1253 uint16_t vlan = channelCall<getVLANProperty>(channel);
1254 if (vlan != 0)
1255 {
1256 vlan |= VLAN_ENABLE_FLAG;
Ratan Guptab8e99552017-07-27 07:07:48 +05301257 }
1258 else
1259 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001260 vlan = lastDisabledVlan[channel];
Ratan Guptab8e99552017-07-27 07:07:48 +05301261 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001262 ret.pack(vlan);
1263 return responseSuccess(std::move(ret));
Adriana Kobylak342df102016-02-10 13:48:16 -06001264 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001265 case LanParam::CiphersuiteSupport:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001266 {
srikanta mondal1d8579c2020-04-15 17:13:25 +00001267 if (getChannelSessionSupport(channel) ==
1268 EChannelSessSupported::none)
1269 {
1270 return responseInvalidFieldRequest();
1271 }
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001272 if (!listInit)
1273 {
1274 return responseUnspecifiedError();
1275 }
1276 ret.pack(static_cast<uint8_t>(cipherList.size() - 1));
1277 return responseSuccess(std::move(ret));
1278 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001279 case LanParam::CiphersuiteEntries:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001280 {
srikanta mondal1d8579c2020-04-15 17:13:25 +00001281 if (getChannelSessionSupport(channel) ==
1282 EChannelSessSupported::none)
1283 {
1284 return responseInvalidFieldRequest();
1285 }
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001286 if (!listInit)
1287 {
1288 return responseUnspecifiedError();
1289 }
1290 ret.pack(cipherList);
1291 return responseSuccess(std::move(ret));
1292 }
William A. Kennington III16064aa2019-04-13 17:44:53 -07001293 case LanParam::IPFamilySupport:
1294 {
1295 std::bitset<8> support;
1296 support[IPFamilySupportFlag::IPv6Only] = 0;
1297 support[IPFamilySupportFlag::DualStack] = 1;
1298 support[IPFamilySupportFlag::IPv6Alerts] = 1;
1299 ret.pack(support);
1300 return responseSuccess(std::move(ret));
1301 }
1302 case LanParam::IPFamilyEnables:
1303 {
1304 ret.pack(static_cast<uint8_t>(IPFamilyEnables::DualStack));
1305 return responseSuccess(std::move(ret));
1306 }
1307 case LanParam::IPv6Status:
1308 {
1309 ret.pack(MAX_IPV6_STATIC_ADDRESSES);
1310 ret.pack(MAX_IPV6_DYNAMIC_ADDRESSES);
1311 std::bitset<8> support;
1312 support[IPv6StatusFlag::DHCP] = 1;
1313 support[IPv6StatusFlag::SLAAC] = 1;
1314 ret.pack(support);
1315 return responseSuccess(std::move(ret));
1316 }
1317 case LanParam::IPv6StaticAddresses:
1318 {
1319 if (set >= MAX_IPV6_STATIC_ADDRESSES)
1320 {
1321 return responseParmOutOfRange();
1322 }
1323 getLanIPv6Address(ret, channel, set, originsV6Static);
1324 return responseSuccess(std::move(ret));
1325 }
1326 case LanParam::IPv6DynamicAddresses:
1327 {
1328 if (set >= MAX_IPV6_DYNAMIC_ADDRESSES)
1329 {
1330 return responseParmOutOfRange();
1331 }
1332 getLanIPv6Address(ret, channel, set, originsV6Dynamic);
1333 return responseSuccess(std::move(ret));
1334 }
1335 case LanParam::IPv6RouterControl:
1336 {
1337 std::bitset<8> control;
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001338 control[IPv6RouterControlFlag::Dynamic] =
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001339 channelCall<getEthProp<bool>>(channel, "IPv6AcceptRA");
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001340 control[IPv6RouterControlFlag::Static] = 1;
William A. Kennington III16064aa2019-04-13 17:44:53 -07001341 ret.pack(control);
1342 return responseSuccess(std::move(ret));
1343 }
1344 case LanParam::IPv6StaticRouter1IP:
1345 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001346 stdplus::In6Addr gateway{};
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001347 if (!channelCall<getEthProp<bool>>(channel, "IPv6AcceptRA"))
William A. Kennington III16064aa2019-04-13 17:44:53 -07001348 {
1349 gateway =
1350 channelCall<getGatewayProperty<AF_INET6>>(channel).value_or(
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001351 stdplus::In6Addr{});
William A. Kennington III16064aa2019-04-13 17:44:53 -07001352 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001353 ret.pack(stdplus::raw::asView<char>(gateway));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001354 return responseSuccess(std::move(ret));
1355 }
1356 case LanParam::IPv6StaticRouter1MAC:
1357 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001358 stdplus::EtherAddr mac{};
William A. Kennington III16064aa2019-04-13 17:44:53 -07001359 auto neighbor = channelCall<getGatewayNeighbor<AF_INET6>>(channel);
1360 if (neighbor)
1361 {
1362 mac = neighbor->mac;
1363 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001364 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001365 return responseSuccess(std::move(ret));
1366 }
1367 case LanParam::IPv6StaticRouter1PrefixLength:
1368 {
Jian Zhang796e8242024-02-01 14:07:34 +08001369 ret.pack(uint8_t{0});
William A. Kennington III16064aa2019-04-13 17:44:53 -07001370 return responseSuccess(std::move(ret));
1371 }
1372 case LanParam::IPv6StaticRouter1PrefixValue:
1373 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001374 ret.pack(stdplus::raw::asView<char>(stdplus::In6Addr{}));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001375 return responseSuccess(std::move(ret));
1376 }
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001377 case LanParam::cipherSuitePrivilegeLevels:
1378 {
1379 std::array<uint4_t, ipmi::maxCSRecords> csPrivilegeLevels;
1380
1381 uint8_t resp =
1382 getCipherConfigObject(csPrivFileName, csPrivDefaultFileName)
1383 .getCSPrivilegeLevels(channel, csPrivilegeLevels);
1384 if (!resp)
1385 {
1386 constexpr uint8_t reserved1 = 0x00;
1387 ret.pack(reserved1, csPrivilegeLevels);
1388 return responseSuccess(std::move(ret));
1389 }
1390 else
1391 {
1392 return response(resp);
1393 }
1394 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001395 }
1396
PavanKumarIntel3771f5f2023-11-02 06:26:42 +00001397 if (parameter >= oemCmdStart)
Johnathan Manteyb87034e2019-09-16 10:50:50 -07001398 {
1399 return getLanOem(channel, parameter, set, block);
1400 }
1401
George Liu8379dc92025-07-08 14:02:07 +08001402 return responseParamNotSupported();
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001403}
1404
Jian Zhang23f44652022-03-17 17:13:10 +08001405constexpr const char* solInterface = "xyz.openbmc_project.Ipmi.SOL";
1406constexpr const char* solPath = "/xyz/openbmc_project/ipmi/sol/";
1407constexpr const uint16_t solDefaultPort = 623;
1408
1409RspType<> setSolConfParams(Context::ptr ctx, uint4_t channelBits,
Willy Tu11d68892022-01-20 10:37:34 -08001410 uint4_t /*reserved*/, uint8_t parameter,
Jian Zhang23f44652022-03-17 17:13:10 +08001411 message::Payload& req)
1412{
1413 const uint8_t channel = convertCurrentChannelNum(
1414 static_cast<uint8_t>(channelBits), ctx->channel);
1415
1416 if (!isValidChannel(channel))
1417 {
George Liu32e8f5d2024-07-17 19:52:25 +08001418 lg2::error("Set Sol Config - Invalid channel in request");
Jian Zhang23f44652022-03-17 17:13:10 +08001419 return responseInvalidFieldRequest();
1420 }
1421
1422 std::string solService{};
1423 std::string solPathWitheEthName = solPath + ipmi::getChannelName(channel);
1424
1425 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1426 {
George Liu32e8f5d2024-07-17 19:52:25 +08001427 lg2::error("Set Sol Config - Invalid solInterface, service: {SERVICE}, "
1428 "object path: {OBJPATH}, interface: {INTERFACE}",
1429 "SERVICE", solService, "OBJPATH", solPathWitheEthName,
1430 "INTERFACE", solInterface);
Jian Zhang23f44652022-03-17 17:13:10 +08001431 return responseInvalidFieldRequest();
1432 }
1433
1434 switch (static_cast<SolConfParam>(parameter))
1435 {
1436 case SolConfParam::Progress:
1437 {
1438 uint8_t progress;
1439 if (req.unpack(progress) != 0 || !req.fullyUnpacked())
1440 {
1441 return responseReqDataLenInvalid();
1442 }
1443
1444 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1445 solInterface, "Progress", progress))
1446 {
1447 return responseUnspecifiedError();
1448 }
1449 break;
1450 }
1451 case SolConfParam::Enable:
1452 {
1453 bool enable;
1454 uint7_t reserved2;
1455
1456 if (req.unpack(enable, reserved2) != 0 || !req.fullyUnpacked())
1457 {
1458 return responseReqDataLenInvalid();
1459 }
1460
1461 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1462 solInterface, "Enable", enable))
1463 {
1464 return responseUnspecifiedError();
1465 }
1466 break;
1467 }
1468 case SolConfParam::Authentication:
1469 {
1470 uint4_t privilegeBits{};
1471 uint2_t reserved2{};
1472 bool forceAuth = false;
1473 bool forceEncrypt = false;
1474
1475 if (req.unpack(privilegeBits, reserved2, forceAuth, forceEncrypt) !=
1476 0 ||
1477 !req.fullyUnpacked())
1478 {
1479 return responseReqDataLenInvalid();
1480 }
1481
1482 uint8_t privilege = static_cast<uint8_t>(privilegeBits);
Jonathan Domana48bf772023-05-26 17:54:57 -07001483 if (privilege < static_cast<uint8_t>(Privilege::User) ||
Jian Zhang23f44652022-03-17 17:13:10 +08001484 privilege > static_cast<uint8_t>(Privilege::Oem))
1485 {
1486 return ipmi::responseInvalidFieldRequest();
1487 }
1488
1489 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1490 solInterface, "Privilege", privilege))
1491 {
1492 return responseUnspecifiedError();
1493 }
1494
1495 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1496 solInterface, "ForceEncryption",
1497 forceEncrypt))
1498 {
1499 return responseUnspecifiedError();
1500 }
1501
1502 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1503 solInterface, "ForceAuthentication",
1504 forceAuth))
1505 {
1506 return responseUnspecifiedError();
1507 }
1508 break;
1509 }
1510 case SolConfParam::Accumulate:
1511 {
1512 uint8_t interval;
1513 uint8_t threshold;
1514 if (req.unpack(interval, threshold) != 0 || !req.fullyUnpacked())
1515 {
1516 return responseReqDataLenInvalid();
1517 }
1518
1519 if (threshold == 0)
1520 {
1521 return responseInvalidFieldRequest();
1522 }
1523
1524 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1525 solInterface, "AccumulateIntervalMS",
1526 interval))
1527 {
1528 return responseUnspecifiedError();
1529 }
1530
1531 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1532 solInterface, "Threshold", threshold))
1533 {
1534 return responseUnspecifiedError();
1535 }
1536 break;
1537 }
1538 case SolConfParam::Retry:
1539 {
1540 uint3_t countBits;
1541 uint5_t reserved2;
1542 uint8_t interval;
1543
1544 if (req.unpack(countBits, reserved2, interval) != 0 ||
1545 !req.fullyUnpacked())
1546 {
1547 return responseReqDataLenInvalid();
1548 }
1549
1550 uint8_t count = static_cast<uint8_t>(countBits);
1551 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1552 solInterface, "RetryCount", count))
1553 {
1554 return responseUnspecifiedError();
1555 }
1556
1557 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1558 solInterface, "RetryIntervalMS",
1559 interval))
1560 {
1561 return responseUnspecifiedError();
1562 }
1563 break;
1564 }
1565 case SolConfParam::Port:
1566 {
George Liu8379dc92025-07-08 14:02:07 +08001567 return responseWriteReadParameter();
Jian Zhang23f44652022-03-17 17:13:10 +08001568 }
1569 case SolConfParam::NonVbitrate:
1570 case SolConfParam::Vbitrate:
1571 case SolConfParam::Channel:
1572 default:
George Liu8379dc92025-07-08 14:02:07 +08001573 return responseParamNotSupported();
Jian Zhang23f44652022-03-17 17:13:10 +08001574 }
1575 return responseSuccess();
1576}
1577
Patrick Williams1318a5e2024-08-16 15:19:54 -04001578RspType<message::Payload> getSolConfParams(
1579 Context::ptr ctx, uint4_t channelBits, uint3_t /*reserved*/, bool revOnly,
1580 uint8_t parameter, uint8_t /*set*/, uint8_t /*block*/)
Jian Zhang23f44652022-03-17 17:13:10 +08001581{
1582 message::Payload ret;
1583 constexpr uint8_t current_revision = 0x11;
1584 ret.pack(current_revision);
1585 if (revOnly)
1586 {
1587 return responseSuccess(std::move(ret));
1588 }
1589
1590 const uint8_t channel = convertCurrentChannelNum(
1591 static_cast<uint8_t>(channelBits), ctx->channel);
1592
1593 if (!isValidChannel(channel))
1594 {
George Liu32e8f5d2024-07-17 19:52:25 +08001595 lg2::error("Get Sol Config - Invalid channel in request");
Jian Zhang23f44652022-03-17 17:13:10 +08001596 return responseInvalidFieldRequest();
1597 }
1598
1599 std::string solService{};
1600 std::string solPathWitheEthName = solPath + ipmi::getChannelName(channel);
1601
1602 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1603 {
George Liu32e8f5d2024-07-17 19:52:25 +08001604 lg2::error("Set Sol Config - Invalid solInterface, service: {SERVICE}, "
1605 "object path: {OBJPATH}, interface: {INTERFACE}",
1606 "SERVICE", solService, "OBJPATH", solPathWitheEthName,
1607 "INTERFACE", solInterface);
Jian Zhang23f44652022-03-17 17:13:10 +08001608 return responseInvalidFieldRequest();
1609 }
1610
1611 switch (static_cast<SolConfParam>(parameter))
1612 {
1613 case SolConfParam::Progress:
1614 {
1615 uint8_t progress;
1616 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1617 solInterface, "Progress", progress))
1618 {
1619 return responseUnspecifiedError();
1620 }
1621 ret.pack(progress);
1622 return responseSuccess(std::move(ret));
1623 }
1624 case SolConfParam::Enable:
1625 {
1626 bool enable{};
1627 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1628 solInterface, "Enable", enable))
1629 {
1630 return responseUnspecifiedError();
1631 }
1632 ret.pack(enable, uint7_t{});
1633 return responseSuccess(std::move(ret));
1634 }
1635 case SolConfParam::Authentication:
1636 {
1637 // 4bits, cast when pack
1638 uint8_t privilege;
1639 bool forceAuth = false;
1640 bool forceEncrypt = false;
1641
1642 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1643 solInterface, "Privilege", privilege))
1644 {
1645 return responseUnspecifiedError();
1646 }
1647
1648 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1649 solInterface, "ForceAuthentication",
1650 forceAuth))
1651 {
1652 return responseUnspecifiedError();
1653 }
1654
1655 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1656 solInterface, "ForceEncryption",
1657 forceEncrypt))
1658 {
1659 return responseUnspecifiedError();
1660 }
1661 ret.pack(uint4_t{privilege}, uint2_t{}, forceAuth, forceEncrypt);
1662 return responseSuccess(std::move(ret));
1663 }
1664 case SolConfParam::Accumulate:
1665 {
1666 uint8_t interval{}, threshold{};
1667
1668 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1669 solInterface, "AccumulateIntervalMS",
1670 interval))
1671 {
1672 return responseUnspecifiedError();
1673 }
1674
1675 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1676 solInterface, "Threshold", threshold))
1677 {
1678 return responseUnspecifiedError();
1679 }
1680 ret.pack(interval, threshold);
1681 return responseSuccess(std::move(ret));
1682 }
1683 case SolConfParam::Retry:
1684 {
1685 // 3bits, cast when cast
1686 uint8_t count{};
1687 uint8_t interval{};
1688
1689 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1690 solInterface, "RetryCount", count))
1691 {
1692 return responseUnspecifiedError();
1693 }
1694
1695 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1696 solInterface, "RetryIntervalMS",
1697 interval))
1698 {
1699 return responseUnspecifiedError();
1700 }
1701 ret.pack(uint3_t{count}, uint5_t{}, interval);
1702 return responseSuccess(std::move(ret));
1703 }
1704 case SolConfParam::Port:
1705 {
1706 auto port = solDefaultPort;
1707 ret.pack(static_cast<uint16_t>(port));
1708 return responseSuccess(std::move(ret));
1709 }
1710 case SolConfParam::Channel:
1711 {
1712 ret.pack(channel);
1713 return responseSuccess(std::move(ret));
1714 }
1715 case SolConfParam::NonVbitrate:
Jonathan Domana48bf772023-05-26 17:54:57 -07001716 {
1717 uint64_t baudRate;
1718 uint8_t encodedBitRate = 0;
1719 if (ipmi::getDbusProperty(
1720 ctx, "xyz.openbmc_project.Console.default",
1721 "/xyz/openbmc_project/console/default",
1722 "xyz.openbmc_project.Console.UART", "Baud", baudRate))
1723 {
George Liu8379dc92025-07-08 14:02:07 +08001724 return responseParamNotSupported();
Jonathan Domana48bf772023-05-26 17:54:57 -07001725 }
1726 switch (baudRate)
1727 {
1728 case 9600:
1729 encodedBitRate = 0x06;
1730 break;
1731 case 19200:
1732 encodedBitRate = 0x07;
1733 break;
1734 case 38400:
1735 encodedBitRate = 0x08;
1736 break;
1737 case 57600:
1738 encodedBitRate = 0x09;
1739 break;
1740 case 115200:
1741 encodedBitRate = 0x0a;
1742 break;
1743 default:
1744 break;
1745 }
1746 ret.pack(encodedBitRate);
1747 return responseSuccess(std::move(ret));
1748 }
Jian Zhang23f44652022-03-17 17:13:10 +08001749 case SolConfParam::Vbitrate:
1750 default:
George Liu8379dc92025-07-08 14:02:07 +08001751 return responseParamNotSupported();
Jian Zhang23f44652022-03-17 17:13:10 +08001752 }
1753
George Liu8379dc92025-07-08 14:02:07 +08001754 return responseParamNotSupported();
Jian Zhang23f44652022-03-17 17:13:10 +08001755}
1756
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001757} // namespace transport
1758} // namespace ipmi
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301759
George Liu5087b072025-03-11 19:28:17 +08001760void registerNetFnTransportFunctions() __attribute__((constructor));
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301761
George Liu5087b072025-03-11 19:28:17 +08001762void registerNetFnTransportFunctions()
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001763{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001764 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1765 ipmi::transport::cmdSetLanConfigParameters,
1766 ipmi::Privilege::Admin, ipmi::transport::setLan);
1767 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1768 ipmi::transport::cmdGetLanConfigParameters,
Johnathan Mantey34698d52019-11-19 14:47:30 -08001769 ipmi::Privilege::Operator, ipmi::transport::getLan);
Jian Zhang23f44652022-03-17 17:13:10 +08001770 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1771 ipmi::transport::cmdSetSolConfigParameters,
1772 ipmi::Privilege::Admin,
1773 ipmi::transport::setSolConfParams);
1774 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1775 ipmi::transport::cmdGetSolConfigParameters,
1776 ipmi::Privilege::User,
1777 ipmi::transport::getSolConfParams);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001778}