blob: d99c754c4a23e2064b66577b13a876e57448e542 [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{
Ed Tanous6d75e4d2025-07-29 10:22:02 -0700221 std::string macStr = stdplus::toStr(mac);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700222 setDbusProperty(bus, params.service, params.ifPath, INTF_MAC, "MACAddress",
Ed Tanous6d75e4d2025-07-29 10:22:02 -0700223 macStr);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700224}
225
Patrick Williams5d82f472022-07-22 19:26:53 -0500226void deleteObjectIfExists(sdbusplus::bus_t& bus, const std::string& service,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700227 const std::string& path)
228{
229 if (path.empty())
230 {
231 return;
232 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530233 try
tomjose26e17732016-03-03 08:52:51 -0600234 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700235 auto req = bus.new_method_call(service.c_str(), path.c_str(),
236 ipmi::DELETE_INTERFACE, "Delete");
237 bus.call_noreply(req);
238 }
Patrick Williams5d82f472022-07-22 19:26:53 -0500239 catch (const sdbusplus::exception_t& e)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700240 {
Chandramohan839fa03352024-08-16 22:47:56 +0530241 // handle Delete Interface DBus errors
jayaprakash Mutyala84c49dc2020-05-18 23:12:13 +0000242 if (strcmp(e.name(),
243 "xyz.openbmc_project.Common.Error.InternalFailure") != 0 &&
Chandramohan839fa03352024-08-16 22:47:56 +0530244 strcmp(e.name(), "org.freedesktop.DBus.Error.UnknownObject") != 0 &&
245 strcmp(e.name(), "xyz.openbmc_project.Common.Error.NotAllowed") !=
246 0)
tomjose26e17732016-03-03 08:52:51 -0600247 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700248 // We want to rethrow real errors
249 throw;
tomjose26e17732016-03-03 08:52:51 -0600250 }
251 }
tomjose26e17732016-03-03 08:52:51 -0600252}
253
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700254/** @brief Sets the address info configured for the interface
255 * If a previous address path exists then it will be removed
256 * before the new address is added.
257 *
258 * @param[in] bus - The bus object used for lookups
259 * @param[in] params - The parameters for the channel
260 * @param[in] address - The address of the new IP
261 * @param[in] prefix - The prefix of the new IP
262 */
263template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500264void createIfAddr(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700265 typename AddrFamily<family>::addr address, uint8_t prefix)
Tom Josepha30c8d32018-03-22 02:15:03 +0530266{
Patrick Williams1318a5e2024-08-16 15:19:54 -0400267 auto newreq =
268 bus.new_method_call(params.service.c_str(), params.logicalPath.c_str(),
269 INTF_IP_CREATE, "IP");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700270 std::string protocol =
Willy Tu523e2d12023-09-05 11:36:48 -0700271 sdbusplus::common::xyz::openbmc_project::network::convertForMessage(
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700272 AddrFamily<family>::protocol);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700273 stdplus::ToStrHandle<stdplus::ToStr<typename AddrFamily<family>::addr>> tsh;
274 newreq.append(protocol, tsh(address), prefix, "");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700275 bus.call_noreply(newreq);
276}
Tom Josepha30c8d32018-03-22 02:15:03 +0530277
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700278/** @brief Trivial helper for getting the IPv4 address from getIfAddrs()
279 *
280 * @param[in] bus - The bus object used for lookups
281 * @param[in] params - The parameters for the channel
282 * @return The address and prefix if found
283 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500284auto getIfAddr4(sdbusplus::bus_t& bus, const ChannelParams& params)
Tom Josepha30c8d32018-03-22 02:15:03 +0530285{
Chanh Nguyen8bd9a9b2024-11-08 09:08:56 +0000286 std::optional<IfAddr<AF_INET>> ifaddr4 = std::nullopt;
287 IP::AddressOrigin src;
288
289 try
290 {
291 src = std::get<bool>(
292 getDbusProperty(bus, params.service, params.logicalPath,
293 INTF_ETHERNET, "DHCP4"))
294 ? IP::AddressOrigin::DHCP
295 : IP::AddressOrigin::Static;
296 }
297 catch (const sdbusplus::exception_t& e)
298 {
299 lg2::error("Failed to get IPv4 source");
300 return ifaddr4;
301 }
302
303 for (uint8_t i = 0; i < MAX_IPV4_ADDRESSES; ++i)
304 {
305 ifaddr4 = getIfAddr<AF_INET>(bus, params, i, originsV4);
Vince Changbefca3c2025-01-09 08:39:36 +0800306 if (ifaddr4 && src == ifaddr4->origin)
Chanh Nguyen8bd9a9b2024-11-08 09:08:56 +0000307 {
308 break;
309 }
310 else
311 {
312 ifaddr4 = std::nullopt;
313 }
314 }
315 return ifaddr4;
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700316}
Tom Josepha30c8d32018-03-22 02:15:03 +0530317
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700318/** @brief Reconfigures the IPv4 address info configured for the interface
319 *
320 * @param[in] bus - The bus object used for lookups
321 * @param[in] params - The parameters for the channel
322 * @param[in] address - The new address if specified
323 * @param[in] prefix - The new address prefix if specified
324 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500325void reconfigureIfAddr4(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700326 std::optional<stdplus::In4Addr> address,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700327 std::optional<uint8_t> prefix)
328{
329 auto ifaddr = getIfAddr4(bus, params);
330 if (!ifaddr && !address)
Tom Josepha30c8d32018-03-22 02:15:03 +0530331 {
George Liu32e8f5d2024-07-17 19:52:25 +0800332 lg2::error("Missing address for IPv4 assignment");
Tom Josepha30c8d32018-03-22 02:15:03 +0530333 elog<InternalFailure>();
334 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700335 uint8_t fallbackPrefix = AddrFamily<AF_INET>::defaultPrefix;
Vince Changbefca3c2025-01-09 08:39:36 +0800336 auto addr = stdplus::In4Addr{};
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700337 if (ifaddr)
Tom Josepha30c8d32018-03-22 02:15:03 +0530338 {
Vince Changbefca3c2025-01-09 08:39:36 +0800339 addr = ifaddr->address;
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700340 fallbackPrefix = ifaddr->prefix;
341 deleteObjectIfExists(bus, params.service, ifaddr->path);
342 }
Vince Changbefca3c2025-01-09 08:39:36 +0800343 addr = address.value_or(addr);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700344 if (addr != stdplus::In4Addr{})
Johnathan Manteycbfa6e12023-06-01 06:57:25 -0700345 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700346 createIfAddr<AF_INET>(bus, params, addr,
Johnathan Manteycbfa6e12023-06-01 06:57:25 -0700347 prefix.value_or(fallbackPrefix));
348 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700349}
350
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700351template <int family>
Patrick Williams69b4c282025-03-03 11:19:13 -0500352std::optional<IfNeigh<family>> findGatewayNeighbor(sdbusplus::bus_t& bus,
353 const ChannelParams& params,
354 ObjectLookupCache& neighbors)
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700355{
356 auto gateway = getGatewayProperty<family>(bus, params);
357 if (!gateway)
358 {
359 return std::nullopt;
360 }
361
362 return findStaticNeighbor<family>(bus, params, *gateway, neighbors);
363}
364
365template <int family>
Patrick Williams69b4c282025-03-03 11:19:13 -0500366std::optional<IfNeigh<family>> getGatewayNeighbor(sdbusplus::bus_t& bus,
367 const ChannelParams& params)
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700368{
369 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
370 return findGatewayNeighbor<family>(bus, params, neighbors);
371}
372
373template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500374void reconfigureGatewayMAC(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700375 stdplus::EtherAddr mac)
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700376{
377 auto gateway = getGatewayProperty<family>(bus, params);
378 if (!gateway)
379 {
George Liu32e8f5d2024-07-17 19:52:25 +0800380 lg2::error("Tried to set Gateway MAC without Gateway");
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700381 elog<InternalFailure>();
382 }
383
384 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
Patrick Williams1318a5e2024-08-16 15:19:54 -0400385 auto neighbor =
386 findStaticNeighbor<family>(bus, params, *gateway, neighbors);
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700387 if (neighbor)
388 {
389 deleteObjectIfExists(bus, params.service, neighbor->path);
390 }
391
392 createNeighbor<family>(bus, params, *gateway, mac);
393}
394
William A. Kennington III16064aa2019-04-13 17:44:53 -0700395/** @brief Deconfigures the IPv6 address info configured for the interface
396 *
397 * @param[in] bus - The bus object used for lookups
398 * @param[in] params - The parameters for the channel
399 * @param[in] idx - The address index to operate on
400 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500401void deconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III16064aa2019-04-13 17:44:53 -0700402 uint8_t idx)
403{
404 auto ifaddr = getIfAddr<AF_INET6>(bus, params, idx, originsV6Static);
405 if (ifaddr)
406 {
407 deleteObjectIfExists(bus, params.service, ifaddr->path);
408 }
409}
410
411/** @brief Reconfigures the IPv6 address info configured for the interface
412 *
413 * @param[in] bus - The bus object used for lookups
414 * @param[in] params - The parameters for the channel
415 * @param[in] idx - The address index to operate on
416 * @param[in] address - The new address
417 * @param[in] prefix - The new address prefix
418 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500419void reconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700420 uint8_t idx, stdplus::In6Addr address, uint8_t prefix)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700421{
422 deconfigureIfAddr6(bus, params, idx);
423 createIfAddr<AF_INET6>(bus, params, address, prefix);
424}
425
426/** @brief Converts the AddressOrigin into an IPv6Source
427 *
428 * @param[in] origin - The DBus Address Origin to convert
429 * @return The IPv6Source version of the origin
430 */
431IPv6Source originToSourceType(IP::AddressOrigin origin)
432{
433 switch (origin)
434 {
435 case IP::AddressOrigin::Static:
436 return IPv6Source::Static;
437 case IP::AddressOrigin::DHCP:
438 return IPv6Source::DHCP;
439 case IP::AddressOrigin::SLAAC:
440 return IPv6Source::SLAAC;
441 default:
442 {
Willy Tu523e2d12023-09-05 11:36:48 -0700443 auto originStr = sdbusplus::common::xyz::openbmc_project::network::
William A. Kennington III16064aa2019-04-13 17:44:53 -0700444 convertForMessage(origin);
George Liu32e8f5d2024-07-17 19:52:25 +0800445 lg2::error("Invalid IP::AddressOrigin conversion to IPv6Source, "
446 "origin: {ORIGIN}",
447 "ORIGIN", originStr);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700448 elog<InternalFailure>();
449 }
450 }
451}
452
453/** @brief Packs the IPMI message response with IPv6 address data
454 *
455 * @param[out] ret - The IPMI response payload to be packed
456 * @param[in] channel - The channel id corresponding to an ethernet interface
457 * @param[in] set - The set selector for determining address index
458 * @param[in] origins - Set of valid origins for address filtering
459 */
460void getLanIPv6Address(message::Payload& ret, uint8_t channel, uint8_t set,
461 const std::unordered_set<IP::AddressOrigin>& origins)
462{
463 auto source = IPv6Source::Static;
464 bool enabled = false;
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700465 stdplus::In6Addr addr{};
Johnathan Mantey5aae0922021-10-21 13:05:36 -0700466 uint8_t prefix{};
William A. Kennington III16064aa2019-04-13 17:44:53 -0700467 auto status = IPv6AddressStatus::Disabled;
468
469 auto ifaddr = channelCall<getIfAddr<AF_INET6>>(channel, set, origins);
470 if (ifaddr)
471 {
472 source = originToSourceType(ifaddr->origin);
Johnathan Mantey846af862021-10-21 12:48:54 -0700473 enabled = (origins == originsV6Static);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700474 addr = ifaddr->address;
475 prefix = ifaddr->prefix;
476 status = IPv6AddressStatus::Active;
477 }
478
479 ret.pack(set);
William A. Kennington III7a0e5df2021-05-19 13:31:29 -0700480 ret.pack(types::enum_cast<uint4_t>(source), uint3_t{}, enabled);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700481 ret.pack(stdplus::raw::asView<char>(addr));
William A. Kennington III16064aa2019-04-13 17:44:53 -0700482 ret.pack(prefix);
William A. Kennington III7a0e5df2021-05-19 13:31:29 -0700483 ret.pack(types::enum_cast<uint8_t>(status));
William A. Kennington III16064aa2019-04-13 17:44:53 -0700484}
485
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700486/** @brief Gets the vlan ID configured on the interface
487 *
488 * @param[in] bus - The bus object used for lookups
489 * @param[in] params - The parameters for the channel
490 * @return VLAN id or the standard 0 for no VLAN
491 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500492uint16_t getVLANProperty(sdbusplus::bus_t& bus, const ChannelParams& params)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700493{
494 // VLAN devices will always have a separate logical object
495 if (params.ifPath == params.logicalPath)
496 {
497 return 0;
498 }
499
500 auto vlan = std::get<uint32_t>(getDbusProperty(
501 bus, params.service, params.logicalPath, INTF_VLAN, "Id"));
502 if ((vlan & VLAN_VALUE_MASK) != vlan)
503 {
Vernon Maueryaf4a7752024-07-02 09:45:46 -0700504 lg2::error("networkd returned an invalid vlan: {VLAN} "
505 "(CH={CHANNEL}, IF={IFNAME})",
506 "CHANNEL", params.id, "IFNAME", params.ifname, "VLAN", vlan);
Tom Josepha30c8d32018-03-22 02:15:03 +0530507 elog<InternalFailure>();
508 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700509 return vlan;
Tom Josepha30c8d32018-03-22 02:15:03 +0530510}
511
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700512/** @brief Deletes all of the possible configuration parameters for a channel
513 *
514 * @param[in] bus - The bus object used for lookups
515 * @param[in] params - The parameters for the channel
516 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500517void deconfigureChannel(sdbusplus::bus_t& bus, ChannelParams& params)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500518{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700519 // Delete all objects associated with the interface
George Liuc1c7eac2024-02-04 17:24:19 +0800520 ObjectTree objs =
521 ipmi::getSubTree(bus, std::vector<std::string>{DELETE_INTERFACE},
522 std::string{PATH_ROOT});
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700523 for (const auto& [path, impls] : objs)
524 {
William A. Kennington IIIc72f3602023-10-19 03:51:37 -0700525 if (!ifnameInPath(params.ifname, path))
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700526 {
527 continue;
528 }
529 for (const auto& [service, intfs] : impls)
530 {
531 deleteObjectIfExists(bus, service, path);
532 }
533 // Update params to reflect the deletion of vlan
534 if (path == params.logicalPath)
535 {
536 params.logicalPath = params.ifPath;
537 }
538 }
539
540 // Clear out any settings on the lower physical interface
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700541 setEthProp(bus, params, "DHCP4", false);
542 setEthProp(bus, params, "DHCP6", false);
543 setEthProp(bus, params, "IPv6AcceptRA", false);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500544}
545
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700546/** @brief Creates a new VLAN on the specified interface
547 *
548 * @param[in] bus - The bus object used for lookups
549 * @param[in] params - The parameters for the channel
550 * @param[in] vlan - The id of the new vlan
551 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500552void createVLAN(sdbusplus::bus_t& bus, ChannelParams& params, uint16_t vlan)
Ratan Guptab8e99552017-07-27 07:07:48 +0530553{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700554 if (vlan == 0)
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530555 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700556 return;
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530557 }
558
William A. Kennington IIIc72f3602023-10-19 03:51:37 -0700559 auto req = bus.new_method_call(params.service.c_str(), PATH_ROOT.c_str(),
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700560 INTF_VLAN_CREATE, "VLAN");
561 req.append(params.ifname, static_cast<uint32_t>(vlan));
562 auto reply = bus.call(req);
563 sdbusplus::message::object_path newPath;
564 reply.read(newPath);
565 params.logicalPath = std::move(newPath);
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530566}
567
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700568/** @brief Performs the necessary reconfiguration to change the VLAN
569 *
570 * @param[in] bus - The bus object used for lookups
571 * @param[in] params - The parameters for the channel
572 * @param[in] vlan - The new vlan id to use
573 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500574void reconfigureVLAN(sdbusplus::bus_t& bus, ChannelParams& params,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700575 uint16_t vlan)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500576{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700577 // Unfortunatetly we don't have built-in functions to migrate our interface
578 // customizations to new VLAN interfaces, or have some kind of decoupling.
579 // We therefore must retain all of our old information, setup the new VLAN
580 // configuration, then restore the old info.
Nan Li3d0df912016-10-18 19:51:41 +0800581
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700582 // Save info from the old logical interface
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700583 bool dhcp4 = getEthProp<bool>(bus, params, "DHCP4");
584 bool dhcp6 = getEthProp<bool>(bus, params, "DHCP6");
585 bool ra = getEthProp<bool>(bus, params, "IPv6AcceptRA");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700586 ObjectLookupCache ips(bus, params, INTF_IP);
587 auto ifaddr4 = findIfAddr<AF_INET>(bus, params, 0, originsV4, ips);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700588 std::vector<IfAddr<AF_INET6>> ifaddrs6;
589 for (uint8_t i = 0; i < MAX_IPV6_STATIC_ADDRESSES; ++i)
590 {
Patrick Williams1318a5e2024-08-16 15:19:54 -0400591 auto ifaddr6 =
592 findIfAddr<AF_INET6>(bus, params, i, originsV6Static, ips);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700593 if (!ifaddr6)
594 {
595 break;
596 }
597 ifaddrs6.push_back(std::move(*ifaddr6));
598 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700599 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
600 auto neighbor4 = findGatewayNeighbor<AF_INET>(bus, params, neighbors);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700601 auto neighbor6 = findGatewayNeighbor<AF_INET6>(bus, params, neighbors);
Chandramohan839fa03352024-08-16 22:47:56 +0530602 // Make copy of params to retain the previous configs
603 ChannelParams parentIntParams = params;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500604
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700605 deconfigureChannel(bus, params);
606 createVLAN(bus, params, vlan);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500607
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700608 // Re-establish the saved settings
Chandramohan839fa03352024-08-16 22:47:56 +0530609 setEthProp(bus, parentIntParams, "DHCP4", dhcp4);
610 setEthProp(bus, parentIntParams, "DHCP6", dhcp6);
611 setEthProp(bus, parentIntParams, "IPv6AcceptRA", ra);
612
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700613 setEthProp(bus, params, "DHCP4", dhcp4);
614 setEthProp(bus, params, "DHCP6", dhcp6);
615 setEthProp(bus, params, "IPv6AcceptRA", ra);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700616 if (ifaddr4)
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800617 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700618 createIfAddr<AF_INET>(bus, params, ifaddr4->address, ifaddr4->prefix);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800619 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700620 for (const auto& ifaddr6 : ifaddrs6)
621 {
622 createIfAddr<AF_INET6>(bus, params, ifaddr6.address, ifaddr6.prefix);
623 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700624 if (neighbor4)
625 {
626 createNeighbor<AF_INET>(bus, params, neighbor4->ip, neighbor4->mac);
627 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700628 if (neighbor6)
629 {
630 createNeighbor<AF_INET6>(bus, params, neighbor6->ip, neighbor6->mac);
631 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700632}
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800633
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700634// We need to store this value so it can be returned to the client
635// It is volatile so safe to store in daemon memory.
636static std::unordered_map<uint8_t, SetStatus> setStatus;
637
638// Until we have good support for fixed versions of IPMI tool
639// we need to return the VLAN id for disabled VLANs. The value is only
640// used for verification that a disable operation succeeded and will only
641// be sent if our system indicates that vlans are disabled.
642static std::unordered_map<uint8_t, uint16_t> lastDisabledVlan;
643
644/** @brief Gets the set status for the channel if it exists
645 * Otherise populates and returns the default value.
646 *
647 * @param[in] channel - The channel id corresponding to an ethernet interface
648 * @return A reference to the SetStatus for the channel
649 */
650SetStatus& getSetStatus(uint8_t channel)
651{
652 auto it = setStatus.find(channel);
653 if (it != setStatus.end())
654 {
655 return it->second;
656 }
657 return setStatus[channel] = SetStatus::Complete;
658}
659
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700660/** @brief Unpacks the trivially copyable type from the message */
661template <typename T>
662static T unpackT(message::Payload& req)
663{
664 std::array<uint8_t, sizeof(T)> bytes;
665 if (req.unpack(bytes) != 0)
666 {
667 throw ccReqDataLenInvalid;
668 }
669 return stdplus::raw::copyFrom<T>(bytes);
670}
671
672/** @brief Ensure the message is fully unpacked */
673static void unpackFinal(message::Payload& req)
674{
675 if (!req.fullyUnpacked())
676 {
677 throw ccReqDataTruncated;
678 }
679}
680
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700681/**
682 * Define placeholder command handlers for the OEM Extension bytes for the Set
683 * LAN Configuration Parameters and Get LAN Configuration Parameters
684 * commands. Using "weak" linking allows the placeholder setLanOem/getLanOem
685 * functions below to be overridden.
686 * To create handlers for your own proprietary command set:
687 * Create/modify a phosphor-ipmi-host Bitbake append file within your Yocto
688 * recipe
689 * Create C++ file(s) that define IPMI handler functions matching the
690 * function names below (i.e. setLanOem). The default name for the
691 * transport IPMI commands is transporthandler_oem.cpp.
692 * Add:
Johnathan Manteyefe26682022-08-11 14:30:45 -0700693 * EXTRA_OEMESON:append = "-Dtransport-oem=enabled"
694 * Create a do_configure:prepend()/do_install:append() method in your
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700695 * bbappend file to copy the file to the build directory.
696 * Add:
697 * PROJECT_SRC_DIR := "${THISDIR}/${PN}"
698 * # Copy the "strong" functions into the working directory, overriding the
699 * # placeholder functions.
Johnathan Manteyefe26682022-08-11 14:30:45 -0700700 * do_configure:prepend(){
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700701 * cp -f ${PROJECT_SRC_DIR}/transporthandler_oem.cpp ${S}
702 * }
703 *
704 * # Clean up after complilation has completed
Johnathan Manteyefe26682022-08-11 14:30:45 -0700705 * do_install:append(){
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700706 * rm -f ${S}/transporthandler_oem.cpp
707 * }
708 *
709 */
710
711/**
712 * Define the placeholder OEM commands as having weak linkage. Create
713 * setLanOem, and getLanOem functions in the transporthandler_oem.cpp
714 * file. The functions defined there must not have the "weak" attribute
715 * applied to them.
716 */
717RspType<> setLanOem(uint8_t channel, uint8_t parameter, message::Payload& req)
718 __attribute__((weak));
Patrick Williams69b4c282025-03-03 11:19:13 -0500719RspType<message::Payload> getLanOem(uint8_t channel, uint8_t parameter,
720 uint8_t set, uint8_t block)
721 __attribute__((weak));
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700722
Willy Tu11d68892022-01-20 10:37:34 -0800723RspType<> setLanOem(uint8_t, uint8_t, message::Payload& req)
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700724{
725 req.trailingOk = true;
George Liu8379dc92025-07-08 14:02:07 +0800726 return responseParamNotSupported();
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700727}
728
Willy Tu11d68892022-01-20 10:37:34 -0800729RspType<message::Payload> getLanOem(uint8_t, uint8_t, uint8_t, uint8_t)
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700730{
George Liu8379dc92025-07-08 14:02:07 +0800731 return responseParamNotSupported();
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700732}
733
Jian Zhangcf19d142023-07-31 10:22:53 +0800734/**
735 * @brief is a valid LAN channel.
736 *
737 * This function checks whether the input channel is a valid LAN channel or not.
738 *
739 * @param[in] channel: the channel number.
740 * @return nullopt if the channel is invalid, false if the channel is not a LAN
741 * channel, true if the channel is a LAN channel.
742 **/
743std::optional<bool> isLanChannel(uint8_t channel)
744{
745 ChannelInfo chInfo;
746 auto cc = getChannelInfo(channel, chInfo);
747 if (cc != ccSuccess)
748 {
749 return std::nullopt;
750 }
751
752 return chInfo.mediumType ==
753 static_cast<uint8_t>(EChannelMediumType::lan8032);
754}
755
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700756RspType<> setLanInt(Context::ptr ctx, uint4_t channelBits, uint4_t reserved1,
757 uint8_t parameter, message::Payload& req)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700758{
vijayabharathix shettycc769252020-02-27 17:52:20 +0000759 const uint8_t channel = convertCurrentChannelNum(
760 static_cast<uint8_t>(channelBits), ctx->channel);
761 if (reserved1 || !isValidChannel(channel))
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700762 {
George Liu32e8f5d2024-07-17 19:52:25 +0800763 lg2::error("Set Lan - Invalid field in request");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700764 req.trailingOk = true;
765 return responseInvalidFieldRequest();
766 }
767
Jian Zhangcf19d142023-07-31 10:22:53 +0800768 if (!isLanChannel(channel).value_or(false))
769 {
George Liu32e8f5d2024-07-17 19:52:25 +0800770 lg2::error("Set Lan - Not a LAN channel");
Jian Zhangcf19d142023-07-31 10:22:53 +0800771 return responseInvalidFieldRequest();
772 }
773
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700774 switch (static_cast<LanParam>(parameter))
775 {
776 case LanParam::SetStatus:
777 {
778 uint2_t flag;
779 uint6_t rsvd;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700780 if (req.unpack(flag, rsvd) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700781 {
782 return responseReqDataLenInvalid();
783 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700784 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800785 if (rsvd)
786 {
787 return responseInvalidFieldRequest();
788 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700789 auto status = static_cast<SetStatus>(static_cast<uint8_t>(flag));
790 switch (status)
791 {
792 case SetStatus::Complete:
793 {
794 getSetStatus(channel) = status;
795 return responseSuccess();
796 }
797 case SetStatus::InProgress:
798 {
799 auto& storedStatus = getSetStatus(channel);
800 if (storedStatus == SetStatus::InProgress)
801 {
George Liu8379dc92025-07-08 14:02:07 +0800802 return responseParamSetLocked();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700803 }
804 storedStatus = status;
805 return responseSuccess();
806 }
807 case SetStatus::Commit:
808 if (getSetStatus(channel) != SetStatus::InProgress)
809 {
810 return responseInvalidFieldRequest();
811 }
812 return responseSuccess();
813 }
George Liu8379dc92025-07-08 14:02:07 +0800814 return responseParamNotSupported();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700815 }
816 case LanParam::AuthSupport:
817 {
818 req.trailingOk = true;
George Liu8379dc92025-07-08 14:02:07 +0800819 return responseParamReadOnly();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700820 }
821 case LanParam::AuthEnables:
822 {
823 req.trailingOk = true;
George Liu8379dc92025-07-08 14:02:07 +0800824 return responseParamReadOnly();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700825 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800826 case LanParam::IP:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600827 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700828 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800829 {
830 return responseCommandNotAvailable();
831 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700832 auto ip = unpackT<stdplus::In4Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700833 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700834 channelCall<reconfigureIfAddr4>(channel, ip, std::nullopt);
835 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +0530836 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700837 case LanParam::IPSrc:
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530838 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700839 uint4_t flag;
840 uint4_t rsvd;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700841 if (req.unpack(flag, rsvd) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700842 {
843 return responseReqDataLenInvalid();
844 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700845 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800846 if (rsvd)
847 {
848 return responseInvalidFieldRequest();
849 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700850 switch (static_cast<IPSrc>(static_cast<uint8_t>(flag)))
851 {
852 case IPSrc::DHCP:
Johnathan Mantey65265362019-11-14 11:24:19 -0800853 // The IPSrc IPMI command is only for IPv4
854 // management. Modifying IPv6 state is done using
855 // a completely different Set LAN Configuration
856 // subcommand.
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700857 channelCall<setEthProp<bool>>(channel, "DHCP4", true);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700858 return responseSuccess();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700859 case IPSrc::Unspecified:
860 case IPSrc::Static:
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700861 channelCall<setEthProp<bool>>(channel, "DHCP4", false);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700862 return responseSuccess();
Rajashekar Gade Reddy8a860ea2019-12-24 11:31:19 +0530863 case IPSrc::BIOS:
864 case IPSrc::BMC:
Rajashekar Gade Reddy8a860ea2019-12-24 11:31:19 +0530865 return responseInvalidFieldRequest();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700866 }
George Liu8379dc92025-07-08 14:02:07 +0800867 return responseParamNotSupported();
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530868 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800869 case LanParam::MAC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530870 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700871 auto mac = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700872 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700873 channelCall<setMACProperty>(channel, mac);
874 return responseSuccess();
Ratan Gupta533d03b2017-07-30 10:39:22 +0530875 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700876 case LanParam::SubnetMask:
Ratan Guptab8e99552017-07-27 07:07:48 +0530877 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700878 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800879 {
880 return responseCommandNotAvailable();
881 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700882 auto pfx = stdplus::maskToPfx(unpackT<stdplus::In4Addr>(req));
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700883 unpackFinal(req);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700884 channelCall<reconfigureIfAddr4>(channel, std::nullopt, pfx);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700885 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +0530886 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700887 case LanParam::Gateway1:
Ratan Guptab8e99552017-07-27 07:07:48 +0530888 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700889 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800890 {
891 return responseCommandNotAvailable();
892 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700893 auto gateway = unpackT<stdplus::In4Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700894 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700895 channelCall<setGatewayProperty<AF_INET>>(channel, gateway);
896 return responseSuccess();
897 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700898 case LanParam::Gateway1MAC:
899 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700900 auto gatewayMAC = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700901 unpackFinal(req);
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700902 channelCall<reconfigureGatewayMAC<AF_INET>>(channel, gatewayMAC);
903 return responseSuccess();
904 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700905 case LanParam::VLANId:
906 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700907 uint12_t vlanData;
908 uint3_t rsvd;
909 bool vlanEnable;
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530910
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700911 if (req.unpack(vlanData, rsvd, vlanEnable) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700912 {
913 return responseReqDataLenInvalid();
914 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700915 unpackFinal(req);
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530916
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700917 if (rsvd)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700918 {
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530919 return responseInvalidFieldRequest();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700920 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530921
922 uint16_t vlan = static_cast<uint16_t>(vlanData);
923
924 if (!vlanEnable)
925 {
926 lastDisabledVlan[channel] = vlan;
927 vlan = 0;
928 }
Jayaprakash Mutyala0d1d7ad2024-06-19 10:19:33 +0000929 else if (vlan == 0 || vlan == VLAN_VALUE_MASK)
930 {
931 return responseInvalidFieldRequest();
932 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530933
jayaprakash Mutyala84c49dc2020-05-18 23:12:13 +0000934 channelCall<reconfigureVLAN>(channel, vlan);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700935 return responseSuccess();
936 }
937 case LanParam::CiphersuiteSupport:
938 case LanParam::CiphersuiteEntries:
William A. Kennington III16064aa2019-04-13 17:44:53 -0700939 case LanParam::IPFamilySupport:
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700940 {
941 req.trailingOk = true;
George Liu8379dc92025-07-08 14:02:07 +0800942 return responseParamReadOnly();
Ratan Guptab8e99552017-07-27 07:07:48 +0530943 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700944 case LanParam::IPFamilyEnables:
945 {
946 uint8_t enables;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700947 if (req.unpack(enables) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700948 {
949 return responseReqDataLenInvalid();
950 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700951 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700952 switch (static_cast<IPFamilyEnables>(enables))
953 {
954 case IPFamilyEnables::DualStack:
955 return responseSuccess();
956 case IPFamilyEnables::IPv4Only:
957 case IPFamilyEnables::IPv6Only:
George Liu8379dc92025-07-08 14:02:07 +0800958 return responseParamNotSupported();
William A. Kennington III16064aa2019-04-13 17:44:53 -0700959 }
George Liu8379dc92025-07-08 14:02:07 +0800960 return responseParamNotSupported();
William A. Kennington III16064aa2019-04-13 17:44:53 -0700961 }
962 case LanParam::IPv6Status:
963 {
964 req.trailingOk = true;
George Liu8379dc92025-07-08 14:02:07 +0800965 return responseParamReadOnly();
William A. Kennington III16064aa2019-04-13 17:44:53 -0700966 }
967 case LanParam::IPv6StaticAddresses:
968 {
969 uint8_t set;
970 uint7_t rsvd;
971 bool enabled;
William A. Kennington III16064aa2019-04-13 17:44:53 -0700972 uint8_t prefix;
973 uint8_t status;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700974 if (req.unpack(set, rsvd, enabled) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700975 {
976 return responseReqDataLenInvalid();
977 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700978 auto ip = unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700979 if (req.unpack(prefix, status) != 0)
980 {
981 return responseReqDataLenInvalid();
982 }
983 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800984 if (rsvd)
985 {
986 return responseInvalidFieldRequest();
987 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700988 if (enabled)
989 {
Jiaqing Zhao6d4a44e2022-01-24 15:04:00 +0800990 if (prefix < MIN_IPV6_PREFIX_LENGTH ||
991 prefix > MAX_IPV6_PREFIX_LENGTH)
992 {
993 return responseParmOutOfRange();
994 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700995 channelCall<reconfigureIfAddr6>(channel, set, ip, prefix);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700996 }
997 else
998 {
999 channelCall<deconfigureIfAddr6>(channel, set);
1000 }
1001 return responseSuccess();
1002 }
1003 case LanParam::IPv6DynamicAddresses:
1004 {
1005 req.trailingOk = true;
George Liu8379dc92025-07-08 14:02:07 +08001006 return responseParamReadOnly();
William A. Kennington III16064aa2019-04-13 17:44:53 -07001007 }
1008 case LanParam::IPv6RouterControl:
1009 {
1010 std::bitset<8> control;
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001011 constexpr uint8_t reservedRACCBits = 0xfc;
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001012 if (req.unpack(control) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -07001013 {
1014 return responseReqDataLenInvalid();
1015 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001016 unpackFinal(req);
Patrick Williams1318a5e2024-08-16 15:19:54 -04001017 if (std::bitset<8> expected(
1018 control & std::bitset<8>(reservedRACCBits));
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001019 expected.any())
William A. Kennington III16064aa2019-04-13 17:44:53 -07001020 {
George Liu8379dc92025-07-08 14:02:07 +08001021 return responseParamNotSupported();
William A. Kennington III16064aa2019-04-13 17:44:53 -07001022 }
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001023
1024 bool enableRA = control[IPv6RouterControlFlag::Dynamic];
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001025 channelCall<setEthProp<bool>>(channel, "IPv6AcceptRA", enableRA);
1026 channelCall<setEthProp<bool>>(channel, "DHCP6", enableRA);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001027 return responseSuccess();
1028 }
1029 case LanParam::IPv6StaticRouter1IP:
1030 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001031 auto gateway = unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001032 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001033 channelCall<setGatewayProperty<AF_INET6>>(channel, gateway);
1034 return responseSuccess();
1035 }
1036 case LanParam::IPv6StaticRouter1MAC:
1037 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001038 auto mac = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001039 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001040 channelCall<reconfigureGatewayMAC<AF_INET6>>(channel, mac);
1041 return responseSuccess();
1042 }
1043 case LanParam::IPv6StaticRouter1PrefixLength:
1044 {
1045 uint8_t prefix;
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001046 if (req.unpack(prefix) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -07001047 {
1048 return responseReqDataLenInvalid();
1049 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001050 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001051 if (prefix != 0)
1052 {
1053 return responseInvalidFieldRequest();
1054 }
1055 return responseSuccess();
1056 }
1057 case LanParam::IPv6StaticRouter1PrefixValue:
1058 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001059 unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001060 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001061 // Accept any prefix value since our prefix length has to be 0
1062 return responseSuccess();
1063 }
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001064 case LanParam::cipherSuitePrivilegeLevels:
1065 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001066 uint8_t rsvd;
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001067 std::array<uint4_t, ipmi::maxCSRecords> cipherSuitePrivs;
1068
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001069 if (req.unpack(rsvd, cipherSuitePrivs))
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001070 {
1071 return responseReqDataLenInvalid();
1072 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001073 unpackFinal(req);
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001074
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001075 if (rsvd)
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001076 {
1077 return responseInvalidFieldRequest();
1078 }
1079
Patrick Williams1318a5e2024-08-16 15:19:54 -04001080 uint8_t resp =
1081 getCipherConfigObject(csPrivFileName, csPrivDefaultFileName)
1082 .setCSPrivilegeLevels(channel, cipherSuitePrivs);
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001083 if (!resp)
1084 {
1085 return responseSuccess();
1086 }
1087 else
1088 {
1089 req.trailingOk = true;
1090 return response(resp);
1091 }
1092 }
Ratan Guptab8e99552017-07-27 07:07:48 +05301093 }
vishwa1eaea4f2016-02-26 11:57:40 -06001094
PavanKumarIntel3771f5f2023-11-02 06:26:42 +00001095 if (parameter >= oemCmdStart)
Johnathan Manteyb87034e2019-09-16 10:50:50 -07001096 {
1097 return setLanOem(channel, parameter, req);
1098 }
1099
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001100 req.trailingOk = true;
George Liu8379dc92025-07-08 14:02:07 +08001101 return responseParamNotSupported();
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001102}
1103
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001104RspType<> setLan(Context::ptr ctx, uint4_t channelBits, uint4_t reserved1,
1105 uint8_t parameter, message::Payload& req)
1106{
1107 try
1108 {
1109 return setLanInt(ctx, channelBits, reserved1, parameter, req);
1110 }
1111 catch (ipmi::Cc cc)
1112 {
1113 return response(cc);
1114 }
1115 catch (const sdbusplus::exception_t& e)
1116 {
1117 if (std::string_view{InvalidArgument::errName} == e.name())
1118 {
1119 return responseInvalidFieldRequest();
1120 }
1121 throw;
1122 }
1123}
1124
vijayabharathix shettycc769252020-02-27 17:52:20 +00001125RspType<message::Payload> getLan(Context::ptr ctx, uint4_t channelBits,
1126 uint3_t reserved, bool revOnly,
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001127 uint8_t parameter, uint8_t set, uint8_t block)
Ratan Guptab8e99552017-07-27 07:07:48 +05301128{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001129 message::Payload ret;
1130 constexpr uint8_t current_revision = 0x11;
1131 ret.pack(current_revision);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001132
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001133 if (revOnly)
Suryakanth Sekare4054402019-08-08 15:16:52 +05301134 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001135 return responseSuccess(std::move(ret));
Suryakanth Sekare4054402019-08-08 15:16:52 +05301136 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001137
vijayabharathix shettycc769252020-02-27 17:52:20 +00001138 const uint8_t channel = convertCurrentChannelNum(
1139 static_cast<uint8_t>(channelBits), ctx->channel);
1140 if (reserved || !isValidChannel(channel))
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001141 {
George Liu32e8f5d2024-07-17 19:52:25 +08001142 lg2::error("Get Lan - Invalid field in request");
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001143 return responseInvalidFieldRequest();
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001144 }
1145
Jian Zhangcf19d142023-07-31 10:22:53 +08001146 if (!isLanChannel(channel).value_or(false))
1147 {
George Liu32e8f5d2024-07-17 19:52:25 +08001148 lg2::error("Set Lan - Not a LAN channel");
Jian Zhangcf19d142023-07-31 10:22:53 +08001149 return responseInvalidFieldRequest();
1150 }
1151
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001152 static std::vector<uint8_t> cipherList;
1153 static bool listInit = false;
1154 if (!listInit)
1155 {
1156 try
1157 {
1158 cipherList = cipher::getCipherList();
1159 listInit = true;
1160 }
1161 catch (const std::exception& e)
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -05001162 {}
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001163 }
1164
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001165 switch (static_cast<LanParam>(parameter))
Tom Josepha30c8d32018-03-22 02:15:03 +05301166 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001167 case LanParam::SetStatus:
Tom Josepha30c8d32018-03-22 02:15:03 +05301168 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001169 SetStatus status;
1170 try
1171 {
1172 status = setStatus.at(channel);
1173 }
1174 catch (const std::out_of_range&)
1175 {
1176 status = SetStatus::Complete;
1177 }
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001178 ret.pack(types::enum_cast<uint2_t>(status), uint6_t{});
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001179 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301180 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001181 case LanParam::AuthSupport:
Tom Josepha30c8d32018-03-22 02:15:03 +05301182 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001183 std::bitset<6> support;
1184 ret.pack(support, uint2_t{});
1185 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301186 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001187 case LanParam::AuthEnables:
vishwa1eaea4f2016-02-26 11:57:40 -06001188 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001189 std::bitset<6> enables;
1190 ret.pack(enables, uint2_t{}); // Callback
1191 ret.pack(enables, uint2_t{}); // User
1192 ret.pack(enables, uint2_t{}); // Operator
1193 ret.pack(enables, uint2_t{}); // Admin
1194 ret.pack(enables, uint2_t{}); // OEM
1195 return responseSuccess(std::move(ret));
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001196 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001197 case LanParam::IP:
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001198 {
1199 auto ifaddr = channelCall<getIfAddr4>(channel);
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001200 stdplus::In4Addr addr{};
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001201 if (ifaddr)
1202 {
1203 addr = ifaddr->address;
1204 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001205 ret.pack(stdplus::raw::asView<char>(addr));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001206 return responseSuccess(std::move(ret));
1207 }
1208 case LanParam::IPSrc:
1209 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001210 auto src = channelCall<getEthProp<bool>>(channel, "DHCP4")
1211 ? IPSrc::DHCP
1212 : IPSrc::Static;
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001213 ret.pack(types::enum_cast<uint4_t>(src), uint4_t{});
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001214 return responseSuccess(std::move(ret));
1215 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001216 case LanParam::MAC:
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001217 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001218 auto mac = channelCall<getMACProperty>(channel);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001219 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001220 return responseSuccess(std::move(ret));
1221 }
1222 case LanParam::SubnetMask:
1223 {
1224 auto ifaddr = channelCall<getIfAddr4>(channel);
1225 uint8_t prefix = AddrFamily<AF_INET>::defaultPrefix;
1226 if (ifaddr)
Ratan Guptab8e99552017-07-27 07:07:48 +05301227 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001228 prefix = ifaddr->prefix;
1229 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001230 auto netmask = stdplus::pfxToMask<stdplus::In4Addr>(prefix);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001231 ret.pack(stdplus::raw::asView<char>(netmask));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001232 return responseSuccess(std::move(ret));
1233 }
1234 case LanParam::Gateway1:
1235 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001236 auto gateway = channelCall<getGatewayProperty<AF_INET>>(channel);
1237 ret.pack(stdplus::raw::asView<char>(
1238 gateway.value_or(stdplus::In4Addr{})));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001239 return responseSuccess(std::move(ret));
1240 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001241 case LanParam::Gateway1MAC:
1242 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001243 stdplus::EtherAddr mac{};
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001244 auto neighbor = channelCall<getGatewayNeighbor<AF_INET>>(channel);
1245 if (neighbor)
1246 {
1247 mac = neighbor->mac;
1248 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001249 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001250 return responseSuccess(std::move(ret));
1251 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001252 case LanParam::VLANId:
1253 {
1254 uint16_t vlan = channelCall<getVLANProperty>(channel);
1255 if (vlan != 0)
1256 {
1257 vlan |= VLAN_ENABLE_FLAG;
Ratan Guptab8e99552017-07-27 07:07:48 +05301258 }
1259 else
1260 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001261 vlan = lastDisabledVlan[channel];
Ratan Guptab8e99552017-07-27 07:07:48 +05301262 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001263 ret.pack(vlan);
1264 return responseSuccess(std::move(ret));
Adriana Kobylak342df102016-02-10 13:48:16 -06001265 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001266 case LanParam::CiphersuiteSupport:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001267 {
srikanta mondal1d8579c2020-04-15 17:13:25 +00001268 if (getChannelSessionSupport(channel) ==
1269 EChannelSessSupported::none)
1270 {
1271 return responseInvalidFieldRequest();
1272 }
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001273 if (!listInit)
1274 {
1275 return responseUnspecifiedError();
1276 }
1277 ret.pack(static_cast<uint8_t>(cipherList.size() - 1));
1278 return responseSuccess(std::move(ret));
1279 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001280 case LanParam::CiphersuiteEntries:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001281 {
srikanta mondal1d8579c2020-04-15 17:13:25 +00001282 if (getChannelSessionSupport(channel) ==
1283 EChannelSessSupported::none)
1284 {
1285 return responseInvalidFieldRequest();
1286 }
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001287 if (!listInit)
1288 {
1289 return responseUnspecifiedError();
1290 }
1291 ret.pack(cipherList);
1292 return responseSuccess(std::move(ret));
1293 }
William A. Kennington III16064aa2019-04-13 17:44:53 -07001294 case LanParam::IPFamilySupport:
1295 {
1296 std::bitset<8> support;
1297 support[IPFamilySupportFlag::IPv6Only] = 0;
1298 support[IPFamilySupportFlag::DualStack] = 1;
1299 support[IPFamilySupportFlag::IPv6Alerts] = 1;
1300 ret.pack(support);
1301 return responseSuccess(std::move(ret));
1302 }
1303 case LanParam::IPFamilyEnables:
1304 {
1305 ret.pack(static_cast<uint8_t>(IPFamilyEnables::DualStack));
1306 return responseSuccess(std::move(ret));
1307 }
1308 case LanParam::IPv6Status:
1309 {
1310 ret.pack(MAX_IPV6_STATIC_ADDRESSES);
1311 ret.pack(MAX_IPV6_DYNAMIC_ADDRESSES);
1312 std::bitset<8> support;
1313 support[IPv6StatusFlag::DHCP] = 1;
1314 support[IPv6StatusFlag::SLAAC] = 1;
1315 ret.pack(support);
1316 return responseSuccess(std::move(ret));
1317 }
1318 case LanParam::IPv6StaticAddresses:
1319 {
1320 if (set >= MAX_IPV6_STATIC_ADDRESSES)
1321 {
1322 return responseParmOutOfRange();
1323 }
1324 getLanIPv6Address(ret, channel, set, originsV6Static);
1325 return responseSuccess(std::move(ret));
1326 }
1327 case LanParam::IPv6DynamicAddresses:
1328 {
1329 if (set >= MAX_IPV6_DYNAMIC_ADDRESSES)
1330 {
1331 return responseParmOutOfRange();
1332 }
1333 getLanIPv6Address(ret, channel, set, originsV6Dynamic);
1334 return responseSuccess(std::move(ret));
1335 }
1336 case LanParam::IPv6RouterControl:
1337 {
1338 std::bitset<8> control;
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001339 control[IPv6RouterControlFlag::Dynamic] =
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001340 channelCall<getEthProp<bool>>(channel, "IPv6AcceptRA");
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001341 control[IPv6RouterControlFlag::Static] = 1;
William A. Kennington III16064aa2019-04-13 17:44:53 -07001342 ret.pack(control);
1343 return responseSuccess(std::move(ret));
1344 }
1345 case LanParam::IPv6StaticRouter1IP:
1346 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001347 stdplus::In6Addr gateway{};
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001348 if (!channelCall<getEthProp<bool>>(channel, "IPv6AcceptRA"))
William A. Kennington III16064aa2019-04-13 17:44:53 -07001349 {
1350 gateway =
1351 channelCall<getGatewayProperty<AF_INET6>>(channel).value_or(
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001352 stdplus::In6Addr{});
William A. Kennington III16064aa2019-04-13 17:44:53 -07001353 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001354 ret.pack(stdplus::raw::asView<char>(gateway));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001355 return responseSuccess(std::move(ret));
1356 }
1357 case LanParam::IPv6StaticRouter1MAC:
1358 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001359 stdplus::EtherAddr mac{};
William A. Kennington III16064aa2019-04-13 17:44:53 -07001360 auto neighbor = channelCall<getGatewayNeighbor<AF_INET6>>(channel);
1361 if (neighbor)
1362 {
1363 mac = neighbor->mac;
1364 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001365 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001366 return responseSuccess(std::move(ret));
1367 }
1368 case LanParam::IPv6StaticRouter1PrefixLength:
1369 {
Jian Zhang796e8242024-02-01 14:07:34 +08001370 ret.pack(uint8_t{0});
William A. Kennington III16064aa2019-04-13 17:44:53 -07001371 return responseSuccess(std::move(ret));
1372 }
1373 case LanParam::IPv6StaticRouter1PrefixValue:
1374 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001375 ret.pack(stdplus::raw::asView<char>(stdplus::In6Addr{}));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001376 return responseSuccess(std::move(ret));
1377 }
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001378 case LanParam::cipherSuitePrivilegeLevels:
1379 {
1380 std::array<uint4_t, ipmi::maxCSRecords> csPrivilegeLevels;
1381
1382 uint8_t resp =
1383 getCipherConfigObject(csPrivFileName, csPrivDefaultFileName)
1384 .getCSPrivilegeLevels(channel, csPrivilegeLevels);
1385 if (!resp)
1386 {
1387 constexpr uint8_t reserved1 = 0x00;
1388 ret.pack(reserved1, csPrivilegeLevels);
1389 return responseSuccess(std::move(ret));
1390 }
1391 else
1392 {
1393 return response(resp);
1394 }
1395 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001396 }
1397
PavanKumarIntel3771f5f2023-11-02 06:26:42 +00001398 if (parameter >= oemCmdStart)
Johnathan Manteyb87034e2019-09-16 10:50:50 -07001399 {
1400 return getLanOem(channel, parameter, set, block);
1401 }
1402
George Liu8379dc92025-07-08 14:02:07 +08001403 return responseParamNotSupported();
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001404}
1405
Jian Zhang23f44652022-03-17 17:13:10 +08001406constexpr const char* solInterface = "xyz.openbmc_project.Ipmi.SOL";
1407constexpr const char* solPath = "/xyz/openbmc_project/ipmi/sol/";
1408constexpr const uint16_t solDefaultPort = 623;
1409
1410RspType<> setSolConfParams(Context::ptr ctx, uint4_t channelBits,
Willy Tu11d68892022-01-20 10:37:34 -08001411 uint4_t /*reserved*/, uint8_t parameter,
Jian Zhang23f44652022-03-17 17:13:10 +08001412 message::Payload& req)
1413{
1414 const uint8_t channel = convertCurrentChannelNum(
1415 static_cast<uint8_t>(channelBits), ctx->channel);
1416
1417 if (!isValidChannel(channel))
1418 {
George Liu32e8f5d2024-07-17 19:52:25 +08001419 lg2::error("Set Sol Config - Invalid channel in request");
Jian Zhang23f44652022-03-17 17:13:10 +08001420 return responseInvalidFieldRequest();
1421 }
1422
Prithvi Pai1dd18d22025-09-19 14:27:03 +05301423 auto channelName = ipmi::getChannelName(channel);
1424 if (channelName.empty())
1425 {
1426 lg2::error("Channel name does not exist for channel {CHANNEL}",
1427 "CHANNEL", channel);
1428 return responseInvalidFieldRequest();
1429 }
1430
Jian Zhang23f44652022-03-17 17:13:10 +08001431 std::string solService{};
Prithvi Pai1dd18d22025-09-19 14:27:03 +05301432 std::string solPathWitheEthName = solPath + channelName;
Jian Zhang23f44652022-03-17 17:13:10 +08001433
1434 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1435 {
George Liu32e8f5d2024-07-17 19:52:25 +08001436 lg2::error("Set Sol Config - Invalid solInterface, service: {SERVICE}, "
1437 "object path: {OBJPATH}, interface: {INTERFACE}",
1438 "SERVICE", solService, "OBJPATH", solPathWitheEthName,
1439 "INTERFACE", solInterface);
Jian Zhang23f44652022-03-17 17:13:10 +08001440 return responseInvalidFieldRequest();
1441 }
1442
1443 switch (static_cast<SolConfParam>(parameter))
1444 {
1445 case SolConfParam::Progress:
1446 {
1447 uint8_t progress;
1448 if (req.unpack(progress) != 0 || !req.fullyUnpacked())
1449 {
1450 return responseReqDataLenInvalid();
1451 }
1452
1453 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1454 solInterface, "Progress", progress))
1455 {
1456 return responseUnspecifiedError();
1457 }
1458 break;
1459 }
1460 case SolConfParam::Enable:
1461 {
1462 bool enable;
1463 uint7_t reserved2;
1464
1465 if (req.unpack(enable, reserved2) != 0 || !req.fullyUnpacked())
1466 {
1467 return responseReqDataLenInvalid();
1468 }
1469
1470 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1471 solInterface, "Enable", enable))
1472 {
1473 return responseUnspecifiedError();
1474 }
1475 break;
1476 }
1477 case SolConfParam::Authentication:
1478 {
1479 uint4_t privilegeBits{};
1480 uint2_t reserved2{};
1481 bool forceAuth = false;
1482 bool forceEncrypt = false;
1483
1484 if (req.unpack(privilegeBits, reserved2, forceAuth, forceEncrypt) !=
1485 0 ||
1486 !req.fullyUnpacked())
1487 {
1488 return responseReqDataLenInvalid();
1489 }
1490
1491 uint8_t privilege = static_cast<uint8_t>(privilegeBits);
Jonathan Domana48bf772023-05-26 17:54:57 -07001492 if (privilege < static_cast<uint8_t>(Privilege::User) ||
Jian Zhang23f44652022-03-17 17:13:10 +08001493 privilege > static_cast<uint8_t>(Privilege::Oem))
1494 {
1495 return ipmi::responseInvalidFieldRequest();
1496 }
1497
1498 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1499 solInterface, "Privilege", privilege))
1500 {
1501 return responseUnspecifiedError();
1502 }
1503
1504 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1505 solInterface, "ForceEncryption",
1506 forceEncrypt))
1507 {
1508 return responseUnspecifiedError();
1509 }
1510
1511 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1512 solInterface, "ForceAuthentication",
1513 forceAuth))
1514 {
1515 return responseUnspecifiedError();
1516 }
1517 break;
1518 }
1519 case SolConfParam::Accumulate:
1520 {
1521 uint8_t interval;
1522 uint8_t threshold;
1523 if (req.unpack(interval, threshold) != 0 || !req.fullyUnpacked())
1524 {
1525 return responseReqDataLenInvalid();
1526 }
1527
1528 if (threshold == 0)
1529 {
1530 return responseInvalidFieldRequest();
1531 }
1532
1533 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1534 solInterface, "AccumulateIntervalMS",
1535 interval))
1536 {
1537 return responseUnspecifiedError();
1538 }
1539
1540 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1541 solInterface, "Threshold", threshold))
1542 {
1543 return responseUnspecifiedError();
1544 }
1545 break;
1546 }
1547 case SolConfParam::Retry:
1548 {
1549 uint3_t countBits;
1550 uint5_t reserved2;
1551 uint8_t interval;
1552
1553 if (req.unpack(countBits, reserved2, interval) != 0 ||
1554 !req.fullyUnpacked())
1555 {
1556 return responseReqDataLenInvalid();
1557 }
1558
1559 uint8_t count = static_cast<uint8_t>(countBits);
1560 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1561 solInterface, "RetryCount", count))
1562 {
1563 return responseUnspecifiedError();
1564 }
1565
1566 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1567 solInterface, "RetryIntervalMS",
1568 interval))
1569 {
1570 return responseUnspecifiedError();
1571 }
1572 break;
1573 }
1574 case SolConfParam::Port:
1575 {
George Liu8379dc92025-07-08 14:02:07 +08001576 return responseWriteReadParameter();
Jian Zhang23f44652022-03-17 17:13:10 +08001577 }
1578 case SolConfParam::NonVbitrate:
1579 case SolConfParam::Vbitrate:
1580 case SolConfParam::Channel:
1581 default:
George Liu8379dc92025-07-08 14:02:07 +08001582 return responseParamNotSupported();
Jian Zhang23f44652022-03-17 17:13:10 +08001583 }
1584 return responseSuccess();
1585}
1586
Patrick Williams1318a5e2024-08-16 15:19:54 -04001587RspType<message::Payload> getSolConfParams(
1588 Context::ptr ctx, uint4_t channelBits, uint3_t /*reserved*/, bool revOnly,
1589 uint8_t parameter, uint8_t /*set*/, uint8_t /*block*/)
Jian Zhang23f44652022-03-17 17:13:10 +08001590{
1591 message::Payload ret;
1592 constexpr uint8_t current_revision = 0x11;
1593 ret.pack(current_revision);
1594 if (revOnly)
1595 {
1596 return responseSuccess(std::move(ret));
1597 }
1598
1599 const uint8_t channel = convertCurrentChannelNum(
1600 static_cast<uint8_t>(channelBits), ctx->channel);
1601
1602 if (!isValidChannel(channel))
1603 {
George Liu32e8f5d2024-07-17 19:52:25 +08001604 lg2::error("Get Sol Config - Invalid channel in request");
Jian Zhang23f44652022-03-17 17:13:10 +08001605 return responseInvalidFieldRequest();
1606 }
1607
Prithvi Pai1dd18d22025-09-19 14:27:03 +05301608 auto channelName = ipmi::getChannelName(channel);
1609 if (channelName.empty())
1610 {
1611 lg2::error("Channel name does not exist for channel {CHANNEL}",
1612 "CHANNEL", channel);
1613 return responseInvalidFieldRequest();
1614 }
1615
Jian Zhang23f44652022-03-17 17:13:10 +08001616 std::string solService{};
Prithvi Pai1dd18d22025-09-19 14:27:03 +05301617 std::string solPathWitheEthName = solPath + channelName;
Jian Zhang23f44652022-03-17 17:13:10 +08001618
1619 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1620 {
George Liu32e8f5d2024-07-17 19:52:25 +08001621 lg2::error("Set Sol Config - Invalid solInterface, service: {SERVICE}, "
1622 "object path: {OBJPATH}, interface: {INTERFACE}",
1623 "SERVICE", solService, "OBJPATH", solPathWitheEthName,
1624 "INTERFACE", solInterface);
Jian Zhang23f44652022-03-17 17:13:10 +08001625 return responseInvalidFieldRequest();
1626 }
1627
1628 switch (static_cast<SolConfParam>(parameter))
1629 {
1630 case SolConfParam::Progress:
1631 {
1632 uint8_t progress;
1633 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1634 solInterface, "Progress", progress))
1635 {
1636 return responseUnspecifiedError();
1637 }
1638 ret.pack(progress);
1639 return responseSuccess(std::move(ret));
1640 }
1641 case SolConfParam::Enable:
1642 {
1643 bool enable{};
1644 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1645 solInterface, "Enable", enable))
1646 {
1647 return responseUnspecifiedError();
1648 }
1649 ret.pack(enable, uint7_t{});
1650 return responseSuccess(std::move(ret));
1651 }
1652 case SolConfParam::Authentication:
1653 {
1654 // 4bits, cast when pack
1655 uint8_t privilege;
1656 bool forceAuth = false;
1657 bool forceEncrypt = false;
1658
1659 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1660 solInterface, "Privilege", privilege))
1661 {
1662 return responseUnspecifiedError();
1663 }
1664
1665 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1666 solInterface, "ForceAuthentication",
1667 forceAuth))
1668 {
1669 return responseUnspecifiedError();
1670 }
1671
1672 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1673 solInterface, "ForceEncryption",
1674 forceEncrypt))
1675 {
1676 return responseUnspecifiedError();
1677 }
1678 ret.pack(uint4_t{privilege}, uint2_t{}, forceAuth, forceEncrypt);
1679 return responseSuccess(std::move(ret));
1680 }
1681 case SolConfParam::Accumulate:
1682 {
1683 uint8_t interval{}, threshold{};
1684
1685 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1686 solInterface, "AccumulateIntervalMS",
1687 interval))
1688 {
1689 return responseUnspecifiedError();
1690 }
1691
1692 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1693 solInterface, "Threshold", threshold))
1694 {
1695 return responseUnspecifiedError();
1696 }
1697 ret.pack(interval, threshold);
1698 return responseSuccess(std::move(ret));
1699 }
1700 case SolConfParam::Retry:
1701 {
1702 // 3bits, cast when cast
1703 uint8_t count{};
1704 uint8_t interval{};
1705
1706 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1707 solInterface, "RetryCount", count))
1708 {
1709 return responseUnspecifiedError();
1710 }
1711
1712 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1713 solInterface, "RetryIntervalMS",
1714 interval))
1715 {
1716 return responseUnspecifiedError();
1717 }
1718 ret.pack(uint3_t{count}, uint5_t{}, interval);
1719 return responseSuccess(std::move(ret));
1720 }
1721 case SolConfParam::Port:
1722 {
1723 auto port = solDefaultPort;
1724 ret.pack(static_cast<uint16_t>(port));
1725 return responseSuccess(std::move(ret));
1726 }
1727 case SolConfParam::Channel:
1728 {
1729 ret.pack(channel);
1730 return responseSuccess(std::move(ret));
1731 }
1732 case SolConfParam::NonVbitrate:
Jonathan Domana48bf772023-05-26 17:54:57 -07001733 {
1734 uint64_t baudRate;
1735 uint8_t encodedBitRate = 0;
1736 if (ipmi::getDbusProperty(
1737 ctx, "xyz.openbmc_project.Console.default",
1738 "/xyz/openbmc_project/console/default",
1739 "xyz.openbmc_project.Console.UART", "Baud", baudRate))
1740 {
George Liu8379dc92025-07-08 14:02:07 +08001741 return responseParamNotSupported();
Jonathan Domana48bf772023-05-26 17:54:57 -07001742 }
1743 switch (baudRate)
1744 {
1745 case 9600:
1746 encodedBitRate = 0x06;
1747 break;
1748 case 19200:
1749 encodedBitRate = 0x07;
1750 break;
1751 case 38400:
1752 encodedBitRate = 0x08;
1753 break;
1754 case 57600:
1755 encodedBitRate = 0x09;
1756 break;
1757 case 115200:
1758 encodedBitRate = 0x0a;
1759 break;
1760 default:
1761 break;
1762 }
1763 ret.pack(encodedBitRate);
1764 return responseSuccess(std::move(ret));
1765 }
Jian Zhang23f44652022-03-17 17:13:10 +08001766 case SolConfParam::Vbitrate:
1767 default:
George Liu8379dc92025-07-08 14:02:07 +08001768 return responseParamNotSupported();
Jian Zhang23f44652022-03-17 17:13:10 +08001769 }
1770
George Liu8379dc92025-07-08 14:02:07 +08001771 return responseParamNotSupported();
Jian Zhang23f44652022-03-17 17:13:10 +08001772}
1773
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001774} // namespace transport
1775} // namespace ipmi
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301776
George Liu5087b072025-03-11 19:28:17 +08001777void registerNetFnTransportFunctions() __attribute__((constructor));
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301778
George Liu5087b072025-03-11 19:28:17 +08001779void registerNetFnTransportFunctions()
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001780{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001781 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1782 ipmi::transport::cmdSetLanConfigParameters,
1783 ipmi::Privilege::Admin, ipmi::transport::setLan);
1784 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1785 ipmi::transport::cmdGetLanConfigParameters,
Johnathan Mantey34698d52019-11-19 14:47:30 -08001786 ipmi::Privilege::Operator, ipmi::transport::getLan);
Jian Zhang23f44652022-03-17 17:13:10 +08001787 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1788 ipmi::transport::cmdSetSolConfigParameters,
1789 ipmi::Privilege::Admin,
1790 ipmi::transport::setSolConfParams);
1791 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1792 ipmi::transport::cmdGetSolConfigParameters,
1793 ipmi::Privilege::User,
1794 ipmi::transport::getSolConfParams);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001795}