blob: c9a7492cca56e35d92f4b5f880844abe804e9b35 [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
1423 std::string solService{};
1424 std::string solPathWitheEthName = solPath + ipmi::getChannelName(channel);
1425
1426 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1427 {
George Liu32e8f5d2024-07-17 19:52:25 +08001428 lg2::error("Set Sol Config - Invalid solInterface, service: {SERVICE}, "
1429 "object path: {OBJPATH}, interface: {INTERFACE}",
1430 "SERVICE", solService, "OBJPATH", solPathWitheEthName,
1431 "INTERFACE", solInterface);
Jian Zhang23f44652022-03-17 17:13:10 +08001432 return responseInvalidFieldRequest();
1433 }
1434
1435 switch (static_cast<SolConfParam>(parameter))
1436 {
1437 case SolConfParam::Progress:
1438 {
1439 uint8_t progress;
1440 if (req.unpack(progress) != 0 || !req.fullyUnpacked())
1441 {
1442 return responseReqDataLenInvalid();
1443 }
1444
1445 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1446 solInterface, "Progress", progress))
1447 {
1448 return responseUnspecifiedError();
1449 }
1450 break;
1451 }
1452 case SolConfParam::Enable:
1453 {
1454 bool enable;
1455 uint7_t reserved2;
1456
1457 if (req.unpack(enable, reserved2) != 0 || !req.fullyUnpacked())
1458 {
1459 return responseReqDataLenInvalid();
1460 }
1461
1462 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1463 solInterface, "Enable", enable))
1464 {
1465 return responseUnspecifiedError();
1466 }
1467 break;
1468 }
1469 case SolConfParam::Authentication:
1470 {
1471 uint4_t privilegeBits{};
1472 uint2_t reserved2{};
1473 bool forceAuth = false;
1474 bool forceEncrypt = false;
1475
1476 if (req.unpack(privilegeBits, reserved2, forceAuth, forceEncrypt) !=
1477 0 ||
1478 !req.fullyUnpacked())
1479 {
1480 return responseReqDataLenInvalid();
1481 }
1482
1483 uint8_t privilege = static_cast<uint8_t>(privilegeBits);
Jonathan Domana48bf772023-05-26 17:54:57 -07001484 if (privilege < static_cast<uint8_t>(Privilege::User) ||
Jian Zhang23f44652022-03-17 17:13:10 +08001485 privilege > static_cast<uint8_t>(Privilege::Oem))
1486 {
1487 return ipmi::responseInvalidFieldRequest();
1488 }
1489
1490 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1491 solInterface, "Privilege", privilege))
1492 {
1493 return responseUnspecifiedError();
1494 }
1495
1496 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1497 solInterface, "ForceEncryption",
1498 forceEncrypt))
1499 {
1500 return responseUnspecifiedError();
1501 }
1502
1503 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1504 solInterface, "ForceAuthentication",
1505 forceAuth))
1506 {
1507 return responseUnspecifiedError();
1508 }
1509 break;
1510 }
1511 case SolConfParam::Accumulate:
1512 {
1513 uint8_t interval;
1514 uint8_t threshold;
1515 if (req.unpack(interval, threshold) != 0 || !req.fullyUnpacked())
1516 {
1517 return responseReqDataLenInvalid();
1518 }
1519
1520 if (threshold == 0)
1521 {
1522 return responseInvalidFieldRequest();
1523 }
1524
1525 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1526 solInterface, "AccumulateIntervalMS",
1527 interval))
1528 {
1529 return responseUnspecifiedError();
1530 }
1531
1532 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1533 solInterface, "Threshold", threshold))
1534 {
1535 return responseUnspecifiedError();
1536 }
1537 break;
1538 }
1539 case SolConfParam::Retry:
1540 {
1541 uint3_t countBits;
1542 uint5_t reserved2;
1543 uint8_t interval;
1544
1545 if (req.unpack(countBits, reserved2, interval) != 0 ||
1546 !req.fullyUnpacked())
1547 {
1548 return responseReqDataLenInvalid();
1549 }
1550
1551 uint8_t count = static_cast<uint8_t>(countBits);
1552 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1553 solInterface, "RetryCount", count))
1554 {
1555 return responseUnspecifiedError();
1556 }
1557
1558 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1559 solInterface, "RetryIntervalMS",
1560 interval))
1561 {
1562 return responseUnspecifiedError();
1563 }
1564 break;
1565 }
1566 case SolConfParam::Port:
1567 {
George Liu8379dc92025-07-08 14:02:07 +08001568 return responseWriteReadParameter();
Jian Zhang23f44652022-03-17 17:13:10 +08001569 }
1570 case SolConfParam::NonVbitrate:
1571 case SolConfParam::Vbitrate:
1572 case SolConfParam::Channel:
1573 default:
George Liu8379dc92025-07-08 14:02:07 +08001574 return responseParamNotSupported();
Jian Zhang23f44652022-03-17 17:13:10 +08001575 }
1576 return responseSuccess();
1577}
1578
Patrick Williams1318a5e2024-08-16 15:19:54 -04001579RspType<message::Payload> getSolConfParams(
1580 Context::ptr ctx, uint4_t channelBits, uint3_t /*reserved*/, bool revOnly,
1581 uint8_t parameter, uint8_t /*set*/, uint8_t /*block*/)
Jian Zhang23f44652022-03-17 17:13:10 +08001582{
1583 message::Payload ret;
1584 constexpr uint8_t current_revision = 0x11;
1585 ret.pack(current_revision);
1586 if (revOnly)
1587 {
1588 return responseSuccess(std::move(ret));
1589 }
1590
1591 const uint8_t channel = convertCurrentChannelNum(
1592 static_cast<uint8_t>(channelBits), ctx->channel);
1593
1594 if (!isValidChannel(channel))
1595 {
George Liu32e8f5d2024-07-17 19:52:25 +08001596 lg2::error("Get Sol Config - Invalid channel in request");
Jian Zhang23f44652022-03-17 17:13:10 +08001597 return responseInvalidFieldRequest();
1598 }
1599
1600 std::string solService{};
1601 std::string solPathWitheEthName = solPath + ipmi::getChannelName(channel);
1602
1603 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1604 {
George Liu32e8f5d2024-07-17 19:52:25 +08001605 lg2::error("Set Sol Config - Invalid solInterface, service: {SERVICE}, "
1606 "object path: {OBJPATH}, interface: {INTERFACE}",
1607 "SERVICE", solService, "OBJPATH", solPathWitheEthName,
1608 "INTERFACE", solInterface);
Jian Zhang23f44652022-03-17 17:13:10 +08001609 return responseInvalidFieldRequest();
1610 }
1611
1612 switch (static_cast<SolConfParam>(parameter))
1613 {
1614 case SolConfParam::Progress:
1615 {
1616 uint8_t progress;
1617 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1618 solInterface, "Progress", progress))
1619 {
1620 return responseUnspecifiedError();
1621 }
1622 ret.pack(progress);
1623 return responseSuccess(std::move(ret));
1624 }
1625 case SolConfParam::Enable:
1626 {
1627 bool enable{};
1628 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1629 solInterface, "Enable", enable))
1630 {
1631 return responseUnspecifiedError();
1632 }
1633 ret.pack(enable, uint7_t{});
1634 return responseSuccess(std::move(ret));
1635 }
1636 case SolConfParam::Authentication:
1637 {
1638 // 4bits, cast when pack
1639 uint8_t privilege;
1640 bool forceAuth = false;
1641 bool forceEncrypt = false;
1642
1643 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1644 solInterface, "Privilege", privilege))
1645 {
1646 return responseUnspecifiedError();
1647 }
1648
1649 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1650 solInterface, "ForceAuthentication",
1651 forceAuth))
1652 {
1653 return responseUnspecifiedError();
1654 }
1655
1656 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1657 solInterface, "ForceEncryption",
1658 forceEncrypt))
1659 {
1660 return responseUnspecifiedError();
1661 }
1662 ret.pack(uint4_t{privilege}, uint2_t{}, forceAuth, forceEncrypt);
1663 return responseSuccess(std::move(ret));
1664 }
1665 case SolConfParam::Accumulate:
1666 {
1667 uint8_t interval{}, threshold{};
1668
1669 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1670 solInterface, "AccumulateIntervalMS",
1671 interval))
1672 {
1673 return responseUnspecifiedError();
1674 }
1675
1676 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1677 solInterface, "Threshold", threshold))
1678 {
1679 return responseUnspecifiedError();
1680 }
1681 ret.pack(interval, threshold);
1682 return responseSuccess(std::move(ret));
1683 }
1684 case SolConfParam::Retry:
1685 {
1686 // 3bits, cast when cast
1687 uint8_t count{};
1688 uint8_t interval{};
1689
1690 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1691 solInterface, "RetryCount", count))
1692 {
1693 return responseUnspecifiedError();
1694 }
1695
1696 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1697 solInterface, "RetryIntervalMS",
1698 interval))
1699 {
1700 return responseUnspecifiedError();
1701 }
1702 ret.pack(uint3_t{count}, uint5_t{}, interval);
1703 return responseSuccess(std::move(ret));
1704 }
1705 case SolConfParam::Port:
1706 {
1707 auto port = solDefaultPort;
1708 ret.pack(static_cast<uint16_t>(port));
1709 return responseSuccess(std::move(ret));
1710 }
1711 case SolConfParam::Channel:
1712 {
1713 ret.pack(channel);
1714 return responseSuccess(std::move(ret));
1715 }
1716 case SolConfParam::NonVbitrate:
Jonathan Domana48bf772023-05-26 17:54:57 -07001717 {
1718 uint64_t baudRate;
1719 uint8_t encodedBitRate = 0;
1720 if (ipmi::getDbusProperty(
1721 ctx, "xyz.openbmc_project.Console.default",
1722 "/xyz/openbmc_project/console/default",
1723 "xyz.openbmc_project.Console.UART", "Baud", baudRate))
1724 {
George Liu8379dc92025-07-08 14:02:07 +08001725 return responseParamNotSupported();
Jonathan Domana48bf772023-05-26 17:54:57 -07001726 }
1727 switch (baudRate)
1728 {
1729 case 9600:
1730 encodedBitRate = 0x06;
1731 break;
1732 case 19200:
1733 encodedBitRate = 0x07;
1734 break;
1735 case 38400:
1736 encodedBitRate = 0x08;
1737 break;
1738 case 57600:
1739 encodedBitRate = 0x09;
1740 break;
1741 case 115200:
1742 encodedBitRate = 0x0a;
1743 break;
1744 default:
1745 break;
1746 }
1747 ret.pack(encodedBitRate);
1748 return responseSuccess(std::move(ret));
1749 }
Jian Zhang23f44652022-03-17 17:13:10 +08001750 case SolConfParam::Vbitrate:
1751 default:
George Liu8379dc92025-07-08 14:02:07 +08001752 return responseParamNotSupported();
Jian Zhang23f44652022-03-17 17:13:10 +08001753 }
1754
George Liu8379dc92025-07-08 14:02:07 +08001755 return responseParamNotSupported();
Jian Zhang23f44652022-03-17 17:13:10 +08001756}
1757
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001758} // namespace transport
1759} // namespace ipmi
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301760
George Liu5087b072025-03-11 19:28:17 +08001761void registerNetFnTransportFunctions() __attribute__((constructor));
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301762
George Liu5087b072025-03-11 19:28:17 +08001763void registerNetFnTransportFunctions()
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001764{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001765 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1766 ipmi::transport::cmdSetLanConfigParameters,
1767 ipmi::Privilege::Admin, ipmi::transport::setLan);
1768 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1769 ipmi::transport::cmdGetLanConfigParameters,
Johnathan Mantey34698d52019-11-19 14:47:30 -08001770 ipmi::Privilege::Operator, ipmi::transport::getLan);
Jian Zhang23f44652022-03-17 17:13:10 +08001771 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1772 ipmi::transport::cmdSetSolConfigParameters,
1773 ipmi::Privilege::Admin,
1774 ipmi::transport::setSolConfParams);
1775 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1776 ipmi::transport::cmdGetSolConfigParameters,
1777 ipmi::Privilege::User,
1778 ipmi::transport::getSolConfParams);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001779}