blob: 6735ee62c58f3a4c2c1f7e2cd20d4d0e6fb16539 [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
William A. Kennington IIIc514d872019-04-06 18:19:38 -070056/** @brief Valid address origins for IPv4 */
57const std::unordered_set<IP::AddressOrigin> originsV4 = {
58 IP::AddressOrigin::Static,
59 IP::AddressOrigin::DHCP,
60};
61
Johnathan Manteyb87034e2019-09-16 10:50:50 -070062static constexpr uint8_t oemCmdStart = 192;
Johnathan Manteyb87034e2019-09-16 10:50:50 -070063
William A. Kennington IIIc72f3602023-10-19 03:51:37 -070064// Checks if the ifname is part of the networkd path
65// This assumes the path came from the network subtree PATH_ROOT
66bool ifnameInPath(std::string_view ifname, std::string_view path)
67{
68 constexpr auto rs = PATH_ROOT.size() + 1; // ROOT + separator
69 const auto is = rs + ifname.size(); // ROOT + sep + ifname
70 return path.size() > rs && path.substr(rs).starts_with(ifname) &&
Chandramohan839fa03352024-08-16 22:47:56 +053071 (path.size() == is || path[is] == '/' ||
72 path[is] == '_'); // handle VLAN IF uses '_' e.g.
73 // /xyz/openbmc_project/network/eth0_2
William A. Kennington IIIc72f3602023-10-19 03:51:37 -070074}
75
Patrick Williams69b4c282025-03-03 11:19:13 -050076std::optional<ChannelParams> maybeGetChannelParams(sdbusplus::bus_t& bus,
77 uint8_t channel)
William A. Kennington IIIc514d872019-04-06 18:19:38 -070078{
79 auto ifname = getChannelName(channel);
80 if (ifname.empty())
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080081 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -070082 return std::nullopt;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080083 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080084
William A. Kennington IIIc514d872019-04-06 18:19:38 -070085 // Enumerate all VLAN + ETHERNET interfaces
George Liuc1c7eac2024-02-04 17:24:19 +080086 std::vector<std::string> interfaces = {INTF_VLAN, INTF_ETHERNET};
Patrick Williams1318a5e2024-08-16 15:19:54 -040087 ipmi::ObjectTree objs =
88 ipmi::getSubTree(bus, interfaces, std::string{PATH_ROOT});
William A. Kennington IIIc514d872019-04-06 18:19:38 -070089
90 ChannelParams params;
91 for (const auto& [path, impls] : objs)
92 {
William A. Kennington IIIc72f3602023-10-19 03:51:37 -070093 if (!ifnameInPath(ifname, path))
William A. Kennington IIIc514d872019-04-06 18:19:38 -070094 {
95 continue;
96 }
97 for (const auto& [service, intfs] : impls)
98 {
99 bool vlan = false;
100 bool ethernet = false;
101 for (const auto& intf : intfs)
102 {
103 if (intf == INTF_VLAN)
104 {
105 vlan = true;
106 }
107 else if (intf == INTF_ETHERNET)
108 {
109 ethernet = true;
110 }
111 }
112 if (params.service.empty() && (vlan || ethernet))
113 {
114 params.service = service;
115 }
116 if (params.ifPath.empty() && !vlan && ethernet)
117 {
118 params.ifPath = path;
119 }
120 if (params.logicalPath.empty() && vlan)
121 {
122 params.logicalPath = path;
123 }
124 }
125 }
126
127 // We must have a path for the underlying interface
128 if (params.ifPath.empty())
129 {
130 return std::nullopt;
131 }
132 // We don't have a VLAN so the logical path is the same
133 if (params.logicalPath.empty())
134 {
135 params.logicalPath = params.ifPath;
136 }
137
138 params.id = channel;
139 params.ifname = std::move(ifname);
Willy Tu11d68892022-01-20 10:37:34 -0800140 return params;
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700141}
142
Patrick Williams5d82f472022-07-22 19:26:53 -0500143ChannelParams getChannelParams(sdbusplus::bus_t& bus, uint8_t channel)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700144{
145 auto params = maybeGetChannelParams(bus, channel);
146 if (!params)
147 {
George Liu32e8f5d2024-07-17 19:52:25 +0800148 lg2::error("Failed to get channel params: {CHANNEL}", "CHANNEL",
149 channel);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700150 elog<InternalFailure>();
151 }
152 return std::move(*params);
153}
154
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700155/** @brief Get / Set the Property value from phosphor-networkd EthernetInterface
156 */
157template <typename T>
158static T getEthProp(sdbusplus::bus_t& bus, const ChannelParams& params,
159 const std::string& prop)
160{
161 return std::get<T>(getDbusProperty(bus, params.service, params.logicalPath,
162 INTF_ETHERNET, prop));
163}
164template <typename T>
165static void setEthProp(sdbusplus::bus_t& bus, const ChannelParams& params,
166 const std::string& prop, const T& t)
167{
168 return setDbusProperty(bus, params.service, params.logicalPath,
169 INTF_ETHERNET, prop, t);
170}
171
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700172/** @brief Determines the MAC of the ethernet interface
173 *
174 * @param[in] bus - The bus object used for lookups
175 * @param[in] params - The parameters for the channel
176 * @return The configured mac address
177 */
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700178stdplus::EtherAddr getMACProperty(sdbusplus::bus_t& bus,
179 const ChannelParams& params)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700180{
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700181 auto prop = getDbusProperty(bus, params.service, params.ifPath, INTF_MAC,
182 "MACAddress");
183 return stdplus::fromStr<stdplus::EtherAddr>(std::get<std::string>(prop));
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700184}
185
186/** @brief Sets the system value for MAC address on the given interface
187 *
188 * @param[in] bus - The bus object used for lookups
189 * @param[in] params - The parameters for the channel
190 * @param[in] mac - MAC address to apply
191 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500192void setMACProperty(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700193 stdplus::EtherAddr mac)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700194{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700195 setDbusProperty(bus, params.service, params.ifPath, INTF_MAC, "MACAddress",
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700196 stdplus::toStr(mac));
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700197}
198
Patrick Williams5d82f472022-07-22 19:26:53 -0500199void deleteObjectIfExists(sdbusplus::bus_t& bus, const std::string& service,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700200 const std::string& path)
201{
202 if (path.empty())
203 {
204 return;
205 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530206 try
tomjose26e17732016-03-03 08:52:51 -0600207 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700208 auto req = bus.new_method_call(service.c_str(), path.c_str(),
209 ipmi::DELETE_INTERFACE, "Delete");
210 bus.call_noreply(req);
211 }
Patrick Williams5d82f472022-07-22 19:26:53 -0500212 catch (const sdbusplus::exception_t& e)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700213 {
Chandramohan839fa03352024-08-16 22:47:56 +0530214 // handle Delete Interface DBus errors
jayaprakash Mutyala84c49dc2020-05-18 23:12:13 +0000215 if (strcmp(e.name(),
216 "xyz.openbmc_project.Common.Error.InternalFailure") != 0 &&
Chandramohan839fa03352024-08-16 22:47:56 +0530217 strcmp(e.name(), "org.freedesktop.DBus.Error.UnknownObject") != 0 &&
218 strcmp(e.name(), "xyz.openbmc_project.Common.Error.NotAllowed") !=
219 0)
tomjose26e17732016-03-03 08:52:51 -0600220 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700221 // We want to rethrow real errors
222 throw;
tomjose26e17732016-03-03 08:52:51 -0600223 }
224 }
tomjose26e17732016-03-03 08:52:51 -0600225}
226
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700227/** @brief Sets the address info configured for the interface
228 * If a previous address path exists then it will be removed
229 * before the new address is added.
230 *
231 * @param[in] bus - The bus object used for lookups
232 * @param[in] params - The parameters for the channel
233 * @param[in] address - The address of the new IP
234 * @param[in] prefix - The prefix of the new IP
235 */
236template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500237void createIfAddr(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700238 typename AddrFamily<family>::addr address, uint8_t prefix)
Tom Josepha30c8d32018-03-22 02:15:03 +0530239{
Patrick Williams1318a5e2024-08-16 15:19:54 -0400240 auto newreq =
241 bus.new_method_call(params.service.c_str(), params.logicalPath.c_str(),
242 INTF_IP_CREATE, "IP");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700243 std::string protocol =
Willy Tu523e2d12023-09-05 11:36:48 -0700244 sdbusplus::common::xyz::openbmc_project::network::convertForMessage(
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700245 AddrFamily<family>::protocol);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700246 stdplus::ToStrHandle<stdplus::ToStr<typename AddrFamily<family>::addr>> tsh;
247 newreq.append(protocol, tsh(address), prefix, "");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700248 bus.call_noreply(newreq);
249}
Tom Josepha30c8d32018-03-22 02:15:03 +0530250
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700251/** @brief Trivial helper for getting the IPv4 address from getIfAddrs()
252 *
253 * @param[in] bus - The bus object used for lookups
254 * @param[in] params - The parameters for the channel
255 * @return The address and prefix if found
256 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500257auto getIfAddr4(sdbusplus::bus_t& bus, const ChannelParams& params)
Tom Josepha30c8d32018-03-22 02:15:03 +0530258{
Chanh Nguyen8bd9a9b2024-11-08 09:08:56 +0000259 std::optional<IfAddr<AF_INET>> ifaddr4 = std::nullopt;
260 IP::AddressOrigin src;
261
262 try
263 {
264 src = std::get<bool>(
265 getDbusProperty(bus, params.service, params.logicalPath,
266 INTF_ETHERNET, "DHCP4"))
267 ? IP::AddressOrigin::DHCP
268 : IP::AddressOrigin::Static;
269 }
270 catch (const sdbusplus::exception_t& e)
271 {
272 lg2::error("Failed to get IPv4 source");
273 return ifaddr4;
274 }
275
276 for (uint8_t i = 0; i < MAX_IPV4_ADDRESSES; ++i)
277 {
278 ifaddr4 = getIfAddr<AF_INET>(bus, params, i, originsV4);
Vince Changbefca3c2025-01-09 08:39:36 +0800279 if (ifaddr4 && src == ifaddr4->origin)
Chanh Nguyen8bd9a9b2024-11-08 09:08:56 +0000280 {
281 break;
282 }
283 else
284 {
285 ifaddr4 = std::nullopt;
286 }
287 }
288 return ifaddr4;
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700289}
Tom Josepha30c8d32018-03-22 02:15:03 +0530290
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700291/** @brief Reconfigures the IPv4 address info configured for the interface
292 *
293 * @param[in] bus - The bus object used for lookups
294 * @param[in] params - The parameters for the channel
295 * @param[in] address - The new address if specified
296 * @param[in] prefix - The new address prefix if specified
297 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500298void reconfigureIfAddr4(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700299 std::optional<stdplus::In4Addr> address,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700300 std::optional<uint8_t> prefix)
301{
302 auto ifaddr = getIfAddr4(bus, params);
303 if (!ifaddr && !address)
Tom Josepha30c8d32018-03-22 02:15:03 +0530304 {
George Liu32e8f5d2024-07-17 19:52:25 +0800305 lg2::error("Missing address for IPv4 assignment");
Tom Josepha30c8d32018-03-22 02:15:03 +0530306 elog<InternalFailure>();
307 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700308 uint8_t fallbackPrefix = AddrFamily<AF_INET>::defaultPrefix;
Vince Changbefca3c2025-01-09 08:39:36 +0800309 auto addr = stdplus::In4Addr{};
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700310 if (ifaddr)
Tom Josepha30c8d32018-03-22 02:15:03 +0530311 {
Vince Changbefca3c2025-01-09 08:39:36 +0800312 addr = ifaddr->address;
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700313 fallbackPrefix = ifaddr->prefix;
314 deleteObjectIfExists(bus, params.service, ifaddr->path);
315 }
Vince Changbefca3c2025-01-09 08:39:36 +0800316 addr = address.value_or(addr);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700317 if (addr != stdplus::In4Addr{})
Johnathan Manteycbfa6e12023-06-01 06:57:25 -0700318 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700319 createIfAddr<AF_INET>(bus, params, addr,
Johnathan Manteycbfa6e12023-06-01 06:57:25 -0700320 prefix.value_or(fallbackPrefix));
321 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700322}
323
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700324template <int family>
Patrick Williams69b4c282025-03-03 11:19:13 -0500325std::optional<IfNeigh<family>> findGatewayNeighbor(sdbusplus::bus_t& bus,
326 const ChannelParams& params,
327 ObjectLookupCache& neighbors)
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700328{
329 auto gateway = getGatewayProperty<family>(bus, params);
330 if (!gateway)
331 {
332 return std::nullopt;
333 }
334
335 return findStaticNeighbor<family>(bus, params, *gateway, neighbors);
336}
337
338template <int family>
Patrick Williams69b4c282025-03-03 11:19:13 -0500339std::optional<IfNeigh<family>> getGatewayNeighbor(sdbusplus::bus_t& bus,
340 const ChannelParams& params)
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700341{
342 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
343 return findGatewayNeighbor<family>(bus, params, neighbors);
344}
345
346template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500347void reconfigureGatewayMAC(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700348 stdplus::EtherAddr mac)
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700349{
350 auto gateway = getGatewayProperty<family>(bus, params);
351 if (!gateway)
352 {
George Liu32e8f5d2024-07-17 19:52:25 +0800353 lg2::error("Tried to set Gateway MAC without Gateway");
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700354 elog<InternalFailure>();
355 }
356
357 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
Patrick Williams1318a5e2024-08-16 15:19:54 -0400358 auto neighbor =
359 findStaticNeighbor<family>(bus, params, *gateway, neighbors);
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700360 if (neighbor)
361 {
362 deleteObjectIfExists(bus, params.service, neighbor->path);
363 }
364
365 createNeighbor<family>(bus, params, *gateway, mac);
366}
367
William A. Kennington III16064aa2019-04-13 17:44:53 -0700368/** @brief Deconfigures the IPv6 address info configured for the interface
369 *
370 * @param[in] bus - The bus object used for lookups
371 * @param[in] params - The parameters for the channel
372 * @param[in] idx - The address index to operate on
373 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500374void deconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III16064aa2019-04-13 17:44:53 -0700375 uint8_t idx)
376{
377 auto ifaddr = getIfAddr<AF_INET6>(bus, params, idx, originsV6Static);
378 if (ifaddr)
379 {
380 deleteObjectIfExists(bus, params.service, ifaddr->path);
381 }
382}
383
384/** @brief Reconfigures the IPv6 address info configured for the interface
385 *
386 * @param[in] bus - The bus object used for lookups
387 * @param[in] params - The parameters for the channel
388 * @param[in] idx - The address index to operate on
389 * @param[in] address - The new address
390 * @param[in] prefix - The new address prefix
391 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500392void reconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700393 uint8_t idx, stdplus::In6Addr address, uint8_t prefix)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700394{
395 deconfigureIfAddr6(bus, params, idx);
396 createIfAddr<AF_INET6>(bus, params, address, prefix);
397}
398
399/** @brief Converts the AddressOrigin into an IPv6Source
400 *
401 * @param[in] origin - The DBus Address Origin to convert
402 * @return The IPv6Source version of the origin
403 */
404IPv6Source originToSourceType(IP::AddressOrigin origin)
405{
406 switch (origin)
407 {
408 case IP::AddressOrigin::Static:
409 return IPv6Source::Static;
410 case IP::AddressOrigin::DHCP:
411 return IPv6Source::DHCP;
412 case IP::AddressOrigin::SLAAC:
413 return IPv6Source::SLAAC;
414 default:
415 {
Willy Tu523e2d12023-09-05 11:36:48 -0700416 auto originStr = sdbusplus::common::xyz::openbmc_project::network::
William A. Kennington III16064aa2019-04-13 17:44:53 -0700417 convertForMessage(origin);
George Liu32e8f5d2024-07-17 19:52:25 +0800418 lg2::error("Invalid IP::AddressOrigin conversion to IPv6Source, "
419 "origin: {ORIGIN}",
420 "ORIGIN", originStr);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700421 elog<InternalFailure>();
422 }
423 }
424}
425
426/** @brief Packs the IPMI message response with IPv6 address data
427 *
428 * @param[out] ret - The IPMI response payload to be packed
429 * @param[in] channel - The channel id corresponding to an ethernet interface
430 * @param[in] set - The set selector for determining address index
431 * @param[in] origins - Set of valid origins for address filtering
432 */
433void getLanIPv6Address(message::Payload& ret, uint8_t channel, uint8_t set,
434 const std::unordered_set<IP::AddressOrigin>& origins)
435{
436 auto source = IPv6Source::Static;
437 bool enabled = false;
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700438 stdplus::In6Addr addr{};
Johnathan Mantey5aae0922021-10-21 13:05:36 -0700439 uint8_t prefix{};
William A. Kennington III16064aa2019-04-13 17:44:53 -0700440 auto status = IPv6AddressStatus::Disabled;
441
442 auto ifaddr = channelCall<getIfAddr<AF_INET6>>(channel, set, origins);
443 if (ifaddr)
444 {
445 source = originToSourceType(ifaddr->origin);
Johnathan Mantey846af862021-10-21 12:48:54 -0700446 enabled = (origins == originsV6Static);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700447 addr = ifaddr->address;
448 prefix = ifaddr->prefix;
449 status = IPv6AddressStatus::Active;
450 }
451
452 ret.pack(set);
William A. Kennington III7a0e5df2021-05-19 13:31:29 -0700453 ret.pack(types::enum_cast<uint4_t>(source), uint3_t{}, enabled);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700454 ret.pack(stdplus::raw::asView<char>(addr));
William A. Kennington III16064aa2019-04-13 17:44:53 -0700455 ret.pack(prefix);
William A. Kennington III7a0e5df2021-05-19 13:31:29 -0700456 ret.pack(types::enum_cast<uint8_t>(status));
William A. Kennington III16064aa2019-04-13 17:44:53 -0700457}
458
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700459/** @brief Gets the vlan ID configured on the interface
460 *
461 * @param[in] bus - The bus object used for lookups
462 * @param[in] params - The parameters for the channel
463 * @return VLAN id or the standard 0 for no VLAN
464 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500465uint16_t getVLANProperty(sdbusplus::bus_t& bus, const ChannelParams& params)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700466{
467 // VLAN devices will always have a separate logical object
468 if (params.ifPath == params.logicalPath)
469 {
470 return 0;
471 }
472
473 auto vlan = std::get<uint32_t>(getDbusProperty(
474 bus, params.service, params.logicalPath, INTF_VLAN, "Id"));
475 if ((vlan & VLAN_VALUE_MASK) != vlan)
476 {
Vernon Maueryaf4a7752024-07-02 09:45:46 -0700477 lg2::error("networkd returned an invalid vlan: {VLAN} "
478 "(CH={CHANNEL}, IF={IFNAME})",
479 "CHANNEL", params.id, "IFNAME", params.ifname, "VLAN", vlan);
Tom Josepha30c8d32018-03-22 02:15:03 +0530480 elog<InternalFailure>();
481 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700482 return vlan;
Tom Josepha30c8d32018-03-22 02:15:03 +0530483}
484
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700485/** @brief Deletes all of the possible configuration parameters for a channel
486 *
487 * @param[in] bus - The bus object used for lookups
488 * @param[in] params - The parameters for the channel
489 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500490void deconfigureChannel(sdbusplus::bus_t& bus, ChannelParams& params)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500491{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700492 // Delete all objects associated with the interface
George Liuc1c7eac2024-02-04 17:24:19 +0800493 ObjectTree objs =
494 ipmi::getSubTree(bus, std::vector<std::string>{DELETE_INTERFACE},
495 std::string{PATH_ROOT});
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700496 for (const auto& [path, impls] : objs)
497 {
William A. Kennington IIIc72f3602023-10-19 03:51:37 -0700498 if (!ifnameInPath(params.ifname, path))
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700499 {
500 continue;
501 }
502 for (const auto& [service, intfs] : impls)
503 {
504 deleteObjectIfExists(bus, service, path);
505 }
506 // Update params to reflect the deletion of vlan
507 if (path == params.logicalPath)
508 {
509 params.logicalPath = params.ifPath;
510 }
511 }
512
513 // Clear out any settings on the lower physical interface
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700514 setEthProp(bus, params, "DHCP4", false);
515 setEthProp(bus, params, "DHCP6", false);
516 setEthProp(bus, params, "IPv6AcceptRA", false);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500517}
518
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700519/** @brief Creates a new VLAN on the specified interface
520 *
521 * @param[in] bus - The bus object used for lookups
522 * @param[in] params - The parameters for the channel
523 * @param[in] vlan - The id of the new vlan
524 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500525void createVLAN(sdbusplus::bus_t& bus, ChannelParams& params, uint16_t vlan)
Ratan Guptab8e99552017-07-27 07:07:48 +0530526{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700527 if (vlan == 0)
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530528 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700529 return;
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530530 }
531
William A. Kennington IIIc72f3602023-10-19 03:51:37 -0700532 auto req = bus.new_method_call(params.service.c_str(), PATH_ROOT.c_str(),
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700533 INTF_VLAN_CREATE, "VLAN");
534 req.append(params.ifname, static_cast<uint32_t>(vlan));
535 auto reply = bus.call(req);
536 sdbusplus::message::object_path newPath;
537 reply.read(newPath);
538 params.logicalPath = std::move(newPath);
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530539}
540
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700541/** @brief Performs the necessary reconfiguration to change the VLAN
542 *
543 * @param[in] bus - The bus object used for lookups
544 * @param[in] params - The parameters for the channel
545 * @param[in] vlan - The new vlan id to use
546 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500547void reconfigureVLAN(sdbusplus::bus_t& bus, ChannelParams& params,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700548 uint16_t vlan)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500549{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700550 // Unfortunatetly we don't have built-in functions to migrate our interface
551 // customizations to new VLAN interfaces, or have some kind of decoupling.
552 // We therefore must retain all of our old information, setup the new VLAN
553 // configuration, then restore the old info.
Nan Li3d0df912016-10-18 19:51:41 +0800554
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700555 // Save info from the old logical interface
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700556 bool dhcp4 = getEthProp<bool>(bus, params, "DHCP4");
557 bool dhcp6 = getEthProp<bool>(bus, params, "DHCP6");
558 bool ra = getEthProp<bool>(bus, params, "IPv6AcceptRA");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700559 ObjectLookupCache ips(bus, params, INTF_IP);
560 auto ifaddr4 = findIfAddr<AF_INET>(bus, params, 0, originsV4, ips);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700561 std::vector<IfAddr<AF_INET6>> ifaddrs6;
562 for (uint8_t i = 0; i < MAX_IPV6_STATIC_ADDRESSES; ++i)
563 {
Patrick Williams1318a5e2024-08-16 15:19:54 -0400564 auto ifaddr6 =
565 findIfAddr<AF_INET6>(bus, params, i, originsV6Static, ips);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700566 if (!ifaddr6)
567 {
568 break;
569 }
570 ifaddrs6.push_back(std::move(*ifaddr6));
571 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700572 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
573 auto neighbor4 = findGatewayNeighbor<AF_INET>(bus, params, neighbors);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700574 auto neighbor6 = findGatewayNeighbor<AF_INET6>(bus, params, neighbors);
Chandramohan839fa03352024-08-16 22:47:56 +0530575 // Make copy of params to retain the previous configs
576 ChannelParams parentIntParams = params;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500577
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700578 deconfigureChannel(bus, params);
579 createVLAN(bus, params, vlan);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500580
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700581 // Re-establish the saved settings
Chandramohan839fa03352024-08-16 22:47:56 +0530582 setEthProp(bus, parentIntParams, "DHCP4", dhcp4);
583 setEthProp(bus, parentIntParams, "DHCP6", dhcp6);
584 setEthProp(bus, parentIntParams, "IPv6AcceptRA", ra);
585
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700586 setEthProp(bus, params, "DHCP4", dhcp4);
587 setEthProp(bus, params, "DHCP6", dhcp6);
588 setEthProp(bus, params, "IPv6AcceptRA", ra);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700589 if (ifaddr4)
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800590 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700591 createIfAddr<AF_INET>(bus, params, ifaddr4->address, ifaddr4->prefix);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800592 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700593 for (const auto& ifaddr6 : ifaddrs6)
594 {
595 createIfAddr<AF_INET6>(bus, params, ifaddr6.address, ifaddr6.prefix);
596 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700597 if (neighbor4)
598 {
599 createNeighbor<AF_INET>(bus, params, neighbor4->ip, neighbor4->mac);
600 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700601 if (neighbor6)
602 {
603 createNeighbor<AF_INET6>(bus, params, neighbor6->ip, neighbor6->mac);
604 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700605}
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800606
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700607// We need to store this value so it can be returned to the client
608// It is volatile so safe to store in daemon memory.
609static std::unordered_map<uint8_t, SetStatus> setStatus;
610
611// Until we have good support for fixed versions of IPMI tool
612// we need to return the VLAN id for disabled VLANs. The value is only
613// used for verification that a disable operation succeeded and will only
614// be sent if our system indicates that vlans are disabled.
615static std::unordered_map<uint8_t, uint16_t> lastDisabledVlan;
616
617/** @brief Gets the set status for the channel if it exists
618 * Otherise populates and returns the default value.
619 *
620 * @param[in] channel - The channel id corresponding to an ethernet interface
621 * @return A reference to the SetStatus for the channel
622 */
623SetStatus& getSetStatus(uint8_t channel)
624{
625 auto it = setStatus.find(channel);
626 if (it != setStatus.end())
627 {
628 return it->second;
629 }
630 return setStatus[channel] = SetStatus::Complete;
631}
632
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700633/** @brief Unpacks the trivially copyable type from the message */
634template <typename T>
635static T unpackT(message::Payload& req)
636{
637 std::array<uint8_t, sizeof(T)> bytes;
638 if (req.unpack(bytes) != 0)
639 {
640 throw ccReqDataLenInvalid;
641 }
642 return stdplus::raw::copyFrom<T>(bytes);
643}
644
645/** @brief Ensure the message is fully unpacked */
646static void unpackFinal(message::Payload& req)
647{
648 if (!req.fullyUnpacked())
649 {
650 throw ccReqDataTruncated;
651 }
652}
653
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700654/**
655 * Define placeholder command handlers for the OEM Extension bytes for the Set
656 * LAN Configuration Parameters and Get LAN Configuration Parameters
657 * commands. Using "weak" linking allows the placeholder setLanOem/getLanOem
658 * functions below to be overridden.
659 * To create handlers for your own proprietary command set:
660 * Create/modify a phosphor-ipmi-host Bitbake append file within your Yocto
661 * recipe
662 * Create C++ file(s) that define IPMI handler functions matching the
663 * function names below (i.e. setLanOem). The default name for the
664 * transport IPMI commands is transporthandler_oem.cpp.
665 * Add:
Johnathan Manteyefe26682022-08-11 14:30:45 -0700666 * EXTRA_OEMESON:append = "-Dtransport-oem=enabled"
667 * Create a do_configure:prepend()/do_install:append() method in your
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700668 * bbappend file to copy the file to the build directory.
669 * Add:
670 * PROJECT_SRC_DIR := "${THISDIR}/${PN}"
671 * # Copy the "strong" functions into the working directory, overriding the
672 * # placeholder functions.
Johnathan Manteyefe26682022-08-11 14:30:45 -0700673 * do_configure:prepend(){
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700674 * cp -f ${PROJECT_SRC_DIR}/transporthandler_oem.cpp ${S}
675 * }
676 *
677 * # Clean up after complilation has completed
Johnathan Manteyefe26682022-08-11 14:30:45 -0700678 * do_install:append(){
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700679 * rm -f ${S}/transporthandler_oem.cpp
680 * }
681 *
682 */
683
684/**
685 * Define the placeholder OEM commands as having weak linkage. Create
686 * setLanOem, and getLanOem functions in the transporthandler_oem.cpp
687 * file. The functions defined there must not have the "weak" attribute
688 * applied to them.
689 */
690RspType<> setLanOem(uint8_t channel, uint8_t parameter, message::Payload& req)
691 __attribute__((weak));
Patrick Williams69b4c282025-03-03 11:19:13 -0500692RspType<message::Payload> getLanOem(uint8_t channel, uint8_t parameter,
693 uint8_t set, uint8_t block)
694 __attribute__((weak));
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700695
Willy Tu11d68892022-01-20 10:37:34 -0800696RspType<> setLanOem(uint8_t, uint8_t, message::Payload& req)
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700697{
698 req.trailingOk = true;
699 return response(ccParamNotSupported);
700}
701
Willy Tu11d68892022-01-20 10:37:34 -0800702RspType<message::Payload> getLanOem(uint8_t, uint8_t, uint8_t, uint8_t)
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700703{
704 return response(ccParamNotSupported);
705}
706
Jian Zhangcf19d142023-07-31 10:22:53 +0800707/**
708 * @brief is a valid LAN channel.
709 *
710 * This function checks whether the input channel is a valid LAN channel or not.
711 *
712 * @param[in] channel: the channel number.
713 * @return nullopt if the channel is invalid, false if the channel is not a LAN
714 * channel, true if the channel is a LAN channel.
715 **/
716std::optional<bool> isLanChannel(uint8_t channel)
717{
718 ChannelInfo chInfo;
719 auto cc = getChannelInfo(channel, chInfo);
720 if (cc != ccSuccess)
721 {
722 return std::nullopt;
723 }
724
725 return chInfo.mediumType ==
726 static_cast<uint8_t>(EChannelMediumType::lan8032);
727}
728
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700729RspType<> setLanInt(Context::ptr ctx, uint4_t channelBits, uint4_t reserved1,
730 uint8_t parameter, message::Payload& req)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700731{
vijayabharathix shettycc769252020-02-27 17:52:20 +0000732 const uint8_t channel = convertCurrentChannelNum(
733 static_cast<uint8_t>(channelBits), ctx->channel);
734 if (reserved1 || !isValidChannel(channel))
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700735 {
George Liu32e8f5d2024-07-17 19:52:25 +0800736 lg2::error("Set Lan - Invalid field in request");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700737 req.trailingOk = true;
738 return responseInvalidFieldRequest();
739 }
740
Jian Zhangcf19d142023-07-31 10:22:53 +0800741 if (!isLanChannel(channel).value_or(false))
742 {
George Liu32e8f5d2024-07-17 19:52:25 +0800743 lg2::error("Set Lan - Not a LAN channel");
Jian Zhangcf19d142023-07-31 10:22:53 +0800744 return responseInvalidFieldRequest();
745 }
746
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700747 switch (static_cast<LanParam>(parameter))
748 {
749 case LanParam::SetStatus:
750 {
751 uint2_t flag;
752 uint6_t rsvd;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700753 if (req.unpack(flag, rsvd) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700754 {
755 return responseReqDataLenInvalid();
756 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700757 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800758 if (rsvd)
759 {
760 return responseInvalidFieldRequest();
761 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700762 auto status = static_cast<SetStatus>(static_cast<uint8_t>(flag));
763 switch (status)
764 {
765 case SetStatus::Complete:
766 {
767 getSetStatus(channel) = status;
768 return responseSuccess();
769 }
770 case SetStatus::InProgress:
771 {
772 auto& storedStatus = getSetStatus(channel);
773 if (storedStatus == SetStatus::InProgress)
774 {
775 return response(ccParamSetLocked);
776 }
777 storedStatus = status;
778 return responseSuccess();
779 }
780 case SetStatus::Commit:
781 if (getSetStatus(channel) != SetStatus::InProgress)
782 {
783 return responseInvalidFieldRequest();
784 }
785 return responseSuccess();
786 }
787 return response(ccParamNotSupported);
788 }
789 case LanParam::AuthSupport:
790 {
791 req.trailingOk = true;
792 return response(ccParamReadOnly);
793 }
794 case LanParam::AuthEnables:
795 {
796 req.trailingOk = true;
Johnathan Mantey76ce9c72019-11-14 14:41:46 -0800797 return response(ccParamReadOnly);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700798 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800799 case LanParam::IP:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600800 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700801 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800802 {
803 return responseCommandNotAvailable();
804 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700805 auto ip = unpackT<stdplus::In4Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700806 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700807 channelCall<reconfigureIfAddr4>(channel, ip, std::nullopt);
808 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +0530809 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700810 case LanParam::IPSrc:
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530811 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700812 uint4_t flag;
813 uint4_t rsvd;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700814 if (req.unpack(flag, rsvd) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700815 {
816 return responseReqDataLenInvalid();
817 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700818 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800819 if (rsvd)
820 {
821 return responseInvalidFieldRequest();
822 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700823 switch (static_cast<IPSrc>(static_cast<uint8_t>(flag)))
824 {
825 case IPSrc::DHCP:
Johnathan Mantey65265362019-11-14 11:24:19 -0800826 // The IPSrc IPMI command is only for IPv4
827 // management. Modifying IPv6 state is done using
828 // a completely different Set LAN Configuration
829 // subcommand.
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700830 channelCall<setEthProp<bool>>(channel, "DHCP4", true);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700831 return responseSuccess();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700832 case IPSrc::Unspecified:
833 case IPSrc::Static:
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700834 channelCall<setEthProp<bool>>(channel, "DHCP4", false);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700835 return responseSuccess();
Rajashekar Gade Reddy8a860ea2019-12-24 11:31:19 +0530836 case IPSrc::BIOS:
837 case IPSrc::BMC:
Rajashekar Gade Reddy8a860ea2019-12-24 11:31:19 +0530838 return responseInvalidFieldRequest();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700839 }
840 return response(ccParamNotSupported);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530841 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800842 case LanParam::MAC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530843 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700844 auto mac = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700845 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700846 channelCall<setMACProperty>(channel, mac);
847 return responseSuccess();
Ratan Gupta533d03b2017-07-30 10:39:22 +0530848 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700849 case LanParam::SubnetMask:
Ratan Guptab8e99552017-07-27 07:07:48 +0530850 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700851 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800852 {
853 return responseCommandNotAvailable();
854 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700855 auto pfx = stdplus::maskToPfx(unpackT<stdplus::In4Addr>(req));
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700856 unpackFinal(req);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700857 channelCall<reconfigureIfAddr4>(channel, std::nullopt, pfx);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700858 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +0530859 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700860 case LanParam::Gateway1:
Ratan Guptab8e99552017-07-27 07:07:48 +0530861 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700862 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800863 {
864 return responseCommandNotAvailable();
865 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700866 auto gateway = unpackT<stdplus::In4Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700867 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700868 channelCall<setGatewayProperty<AF_INET>>(channel, gateway);
869 return responseSuccess();
870 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700871 case LanParam::Gateway1MAC:
872 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700873 auto gatewayMAC = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700874 unpackFinal(req);
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700875 channelCall<reconfigureGatewayMAC<AF_INET>>(channel, gatewayMAC);
876 return responseSuccess();
877 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700878 case LanParam::VLANId:
879 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700880 uint12_t vlanData;
881 uint3_t rsvd;
882 bool vlanEnable;
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530883
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700884 if (req.unpack(vlanData, rsvd, vlanEnable) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700885 {
886 return responseReqDataLenInvalid();
887 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700888 unpackFinal(req);
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530889
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700890 if (rsvd)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700891 {
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530892 return responseInvalidFieldRequest();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700893 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530894
895 uint16_t vlan = static_cast<uint16_t>(vlanData);
896
897 if (!vlanEnable)
898 {
899 lastDisabledVlan[channel] = vlan;
900 vlan = 0;
901 }
Jayaprakash Mutyala0d1d7ad2024-06-19 10:19:33 +0000902 else if (vlan == 0 || vlan == VLAN_VALUE_MASK)
903 {
904 return responseInvalidFieldRequest();
905 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530906
jayaprakash Mutyala84c49dc2020-05-18 23:12:13 +0000907 channelCall<reconfigureVLAN>(channel, vlan);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700908 return responseSuccess();
909 }
910 case LanParam::CiphersuiteSupport:
911 case LanParam::CiphersuiteEntries:
William A. Kennington III16064aa2019-04-13 17:44:53 -0700912 case LanParam::IPFamilySupport:
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700913 {
914 req.trailingOk = true;
915 return response(ccParamReadOnly);
Ratan Guptab8e99552017-07-27 07:07:48 +0530916 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700917 case LanParam::IPFamilyEnables:
918 {
919 uint8_t enables;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700920 if (req.unpack(enables) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700921 {
922 return responseReqDataLenInvalid();
923 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700924 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700925 switch (static_cast<IPFamilyEnables>(enables))
926 {
927 case IPFamilyEnables::DualStack:
928 return responseSuccess();
929 case IPFamilyEnables::IPv4Only:
930 case IPFamilyEnables::IPv6Only:
931 return response(ccParamNotSupported);
932 }
933 return response(ccParamNotSupported);
934 }
935 case LanParam::IPv6Status:
936 {
937 req.trailingOk = true;
938 return response(ccParamReadOnly);
939 }
940 case LanParam::IPv6StaticAddresses:
941 {
942 uint8_t set;
943 uint7_t rsvd;
944 bool enabled;
William A. Kennington III16064aa2019-04-13 17:44:53 -0700945 uint8_t prefix;
946 uint8_t status;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700947 if (req.unpack(set, rsvd, enabled) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700948 {
949 return responseReqDataLenInvalid();
950 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700951 auto ip = unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700952 if (req.unpack(prefix, status) != 0)
953 {
954 return responseReqDataLenInvalid();
955 }
956 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800957 if (rsvd)
958 {
959 return responseInvalidFieldRequest();
960 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700961 if (enabled)
962 {
Jiaqing Zhao6d4a44e2022-01-24 15:04:00 +0800963 if (prefix < MIN_IPV6_PREFIX_LENGTH ||
964 prefix > MAX_IPV6_PREFIX_LENGTH)
965 {
966 return responseParmOutOfRange();
967 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700968 channelCall<reconfigureIfAddr6>(channel, set, ip, prefix);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700969 }
970 else
971 {
972 channelCall<deconfigureIfAddr6>(channel, set);
973 }
974 return responseSuccess();
975 }
976 case LanParam::IPv6DynamicAddresses:
977 {
978 req.trailingOk = true;
979 return response(ccParamReadOnly);
980 }
981 case LanParam::IPv6RouterControl:
982 {
983 std::bitset<8> control;
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800984 constexpr uint8_t reservedRACCBits = 0xfc;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700985 if (req.unpack(control) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700986 {
987 return responseReqDataLenInvalid();
988 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700989 unpackFinal(req);
Patrick Williams1318a5e2024-08-16 15:19:54 -0400990 if (std::bitset<8> expected(
991 control & std::bitset<8>(reservedRACCBits));
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800992 expected.any())
William A. Kennington III16064aa2019-04-13 17:44:53 -0700993 {
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800994 return response(ccParamNotSupported);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700995 }
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800996
997 bool enableRA = control[IPv6RouterControlFlag::Dynamic];
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700998 channelCall<setEthProp<bool>>(channel, "IPv6AcceptRA", enableRA);
999 channelCall<setEthProp<bool>>(channel, "DHCP6", enableRA);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001000 return responseSuccess();
1001 }
1002 case LanParam::IPv6StaticRouter1IP:
1003 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001004 auto gateway = unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001005 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001006 channelCall<setGatewayProperty<AF_INET6>>(channel, gateway);
1007 return responseSuccess();
1008 }
1009 case LanParam::IPv6StaticRouter1MAC:
1010 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001011 auto mac = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001012 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001013 channelCall<reconfigureGatewayMAC<AF_INET6>>(channel, mac);
1014 return responseSuccess();
1015 }
1016 case LanParam::IPv6StaticRouter1PrefixLength:
1017 {
1018 uint8_t prefix;
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001019 if (req.unpack(prefix) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -07001020 {
1021 return responseReqDataLenInvalid();
1022 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001023 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001024 if (prefix != 0)
1025 {
1026 return responseInvalidFieldRequest();
1027 }
1028 return responseSuccess();
1029 }
1030 case LanParam::IPv6StaticRouter1PrefixValue:
1031 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001032 unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001033 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001034 // Accept any prefix value since our prefix length has to be 0
1035 return responseSuccess();
1036 }
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001037 case LanParam::cipherSuitePrivilegeLevels:
1038 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001039 uint8_t rsvd;
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001040 std::array<uint4_t, ipmi::maxCSRecords> cipherSuitePrivs;
1041
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001042 if (req.unpack(rsvd, cipherSuitePrivs))
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001043 {
1044 return responseReqDataLenInvalid();
1045 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001046 unpackFinal(req);
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001047
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001048 if (rsvd)
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001049 {
1050 return responseInvalidFieldRequest();
1051 }
1052
Patrick Williams1318a5e2024-08-16 15:19:54 -04001053 uint8_t resp =
1054 getCipherConfigObject(csPrivFileName, csPrivDefaultFileName)
1055 .setCSPrivilegeLevels(channel, cipherSuitePrivs);
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001056 if (!resp)
1057 {
1058 return responseSuccess();
1059 }
1060 else
1061 {
1062 req.trailingOk = true;
1063 return response(resp);
1064 }
1065 }
Ratan Guptab8e99552017-07-27 07:07:48 +05301066 }
vishwa1eaea4f2016-02-26 11:57:40 -06001067
PavanKumarIntel3771f5f2023-11-02 06:26:42 +00001068 if (parameter >= oemCmdStart)
Johnathan Manteyb87034e2019-09-16 10:50:50 -07001069 {
1070 return setLanOem(channel, parameter, req);
1071 }
1072
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001073 req.trailingOk = true;
1074 return response(ccParamNotSupported);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001075}
1076
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001077RspType<> setLan(Context::ptr ctx, uint4_t channelBits, uint4_t reserved1,
1078 uint8_t parameter, message::Payload& req)
1079{
1080 try
1081 {
1082 return setLanInt(ctx, channelBits, reserved1, parameter, req);
1083 }
1084 catch (ipmi::Cc cc)
1085 {
1086 return response(cc);
1087 }
1088 catch (const sdbusplus::exception_t& e)
1089 {
1090 if (std::string_view{InvalidArgument::errName} == e.name())
1091 {
1092 return responseInvalidFieldRequest();
1093 }
1094 throw;
1095 }
1096}
1097
vijayabharathix shettycc769252020-02-27 17:52:20 +00001098RspType<message::Payload> getLan(Context::ptr ctx, uint4_t channelBits,
1099 uint3_t reserved, bool revOnly,
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001100 uint8_t parameter, uint8_t set, uint8_t block)
Ratan Guptab8e99552017-07-27 07:07:48 +05301101{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001102 message::Payload ret;
1103 constexpr uint8_t current_revision = 0x11;
1104 ret.pack(current_revision);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001105
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001106 if (revOnly)
Suryakanth Sekare4054402019-08-08 15:16:52 +05301107 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001108 return responseSuccess(std::move(ret));
Suryakanth Sekare4054402019-08-08 15:16:52 +05301109 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001110
vijayabharathix shettycc769252020-02-27 17:52:20 +00001111 const uint8_t channel = convertCurrentChannelNum(
1112 static_cast<uint8_t>(channelBits), ctx->channel);
1113 if (reserved || !isValidChannel(channel))
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001114 {
George Liu32e8f5d2024-07-17 19:52:25 +08001115 lg2::error("Get Lan - Invalid field in request");
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001116 return responseInvalidFieldRequest();
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001117 }
1118
Jian Zhangcf19d142023-07-31 10:22:53 +08001119 if (!isLanChannel(channel).value_or(false))
1120 {
George Liu32e8f5d2024-07-17 19:52:25 +08001121 lg2::error("Set Lan - Not a LAN channel");
Jian Zhangcf19d142023-07-31 10:22:53 +08001122 return responseInvalidFieldRequest();
1123 }
1124
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001125 static std::vector<uint8_t> cipherList;
1126 static bool listInit = false;
1127 if (!listInit)
1128 {
1129 try
1130 {
1131 cipherList = cipher::getCipherList();
1132 listInit = true;
1133 }
1134 catch (const std::exception& e)
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -05001135 {}
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001136 }
1137
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001138 switch (static_cast<LanParam>(parameter))
Tom Josepha30c8d32018-03-22 02:15:03 +05301139 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001140 case LanParam::SetStatus:
Tom Josepha30c8d32018-03-22 02:15:03 +05301141 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001142 SetStatus status;
1143 try
1144 {
1145 status = setStatus.at(channel);
1146 }
1147 catch (const std::out_of_range&)
1148 {
1149 status = SetStatus::Complete;
1150 }
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001151 ret.pack(types::enum_cast<uint2_t>(status), uint6_t{});
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001152 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301153 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001154 case LanParam::AuthSupport:
Tom Josepha30c8d32018-03-22 02:15:03 +05301155 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001156 std::bitset<6> support;
1157 ret.pack(support, uint2_t{});
1158 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301159 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001160 case LanParam::AuthEnables:
vishwa1eaea4f2016-02-26 11:57:40 -06001161 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001162 std::bitset<6> enables;
1163 ret.pack(enables, uint2_t{}); // Callback
1164 ret.pack(enables, uint2_t{}); // User
1165 ret.pack(enables, uint2_t{}); // Operator
1166 ret.pack(enables, uint2_t{}); // Admin
1167 ret.pack(enables, uint2_t{}); // OEM
1168 return responseSuccess(std::move(ret));
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001169 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001170 case LanParam::IP:
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001171 {
1172 auto ifaddr = channelCall<getIfAddr4>(channel);
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001173 stdplus::In4Addr addr{};
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001174 if (ifaddr)
1175 {
1176 addr = ifaddr->address;
1177 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001178 ret.pack(stdplus::raw::asView<char>(addr));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001179 return responseSuccess(std::move(ret));
1180 }
1181 case LanParam::IPSrc:
1182 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001183 auto src = channelCall<getEthProp<bool>>(channel, "DHCP4")
1184 ? IPSrc::DHCP
1185 : IPSrc::Static;
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001186 ret.pack(types::enum_cast<uint4_t>(src), uint4_t{});
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001187 return responseSuccess(std::move(ret));
1188 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001189 case LanParam::MAC:
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001190 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001191 auto mac = channelCall<getMACProperty>(channel);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001192 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001193 return responseSuccess(std::move(ret));
1194 }
1195 case LanParam::SubnetMask:
1196 {
1197 auto ifaddr = channelCall<getIfAddr4>(channel);
1198 uint8_t prefix = AddrFamily<AF_INET>::defaultPrefix;
1199 if (ifaddr)
Ratan Guptab8e99552017-07-27 07:07:48 +05301200 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001201 prefix = ifaddr->prefix;
1202 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001203 auto netmask = stdplus::pfxToMask<stdplus::In4Addr>(prefix);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001204 ret.pack(stdplus::raw::asView<char>(netmask));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001205 return responseSuccess(std::move(ret));
1206 }
1207 case LanParam::Gateway1:
1208 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001209 auto gateway = channelCall<getGatewayProperty<AF_INET>>(channel);
1210 ret.pack(stdplus::raw::asView<char>(
1211 gateway.value_or(stdplus::In4Addr{})));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001212 return responseSuccess(std::move(ret));
1213 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001214 case LanParam::Gateway1MAC:
1215 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001216 stdplus::EtherAddr mac{};
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001217 auto neighbor = channelCall<getGatewayNeighbor<AF_INET>>(channel);
1218 if (neighbor)
1219 {
1220 mac = neighbor->mac;
1221 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001222 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001223 return responseSuccess(std::move(ret));
1224 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001225 case LanParam::VLANId:
1226 {
1227 uint16_t vlan = channelCall<getVLANProperty>(channel);
1228 if (vlan != 0)
1229 {
1230 vlan |= VLAN_ENABLE_FLAG;
Ratan Guptab8e99552017-07-27 07:07:48 +05301231 }
1232 else
1233 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001234 vlan = lastDisabledVlan[channel];
Ratan Guptab8e99552017-07-27 07:07:48 +05301235 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001236 ret.pack(vlan);
1237 return responseSuccess(std::move(ret));
Adriana Kobylak342df102016-02-10 13:48:16 -06001238 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001239 case LanParam::CiphersuiteSupport:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001240 {
srikanta mondal1d8579c2020-04-15 17:13:25 +00001241 if (getChannelSessionSupport(channel) ==
1242 EChannelSessSupported::none)
1243 {
1244 return responseInvalidFieldRequest();
1245 }
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001246 if (!listInit)
1247 {
1248 return responseUnspecifiedError();
1249 }
1250 ret.pack(static_cast<uint8_t>(cipherList.size() - 1));
1251 return responseSuccess(std::move(ret));
1252 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001253 case LanParam::CiphersuiteEntries:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001254 {
srikanta mondal1d8579c2020-04-15 17:13:25 +00001255 if (getChannelSessionSupport(channel) ==
1256 EChannelSessSupported::none)
1257 {
1258 return responseInvalidFieldRequest();
1259 }
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001260 if (!listInit)
1261 {
1262 return responseUnspecifiedError();
1263 }
1264 ret.pack(cipherList);
1265 return responseSuccess(std::move(ret));
1266 }
William A. Kennington III16064aa2019-04-13 17:44:53 -07001267 case LanParam::IPFamilySupport:
1268 {
1269 std::bitset<8> support;
1270 support[IPFamilySupportFlag::IPv6Only] = 0;
1271 support[IPFamilySupportFlag::DualStack] = 1;
1272 support[IPFamilySupportFlag::IPv6Alerts] = 1;
1273 ret.pack(support);
1274 return responseSuccess(std::move(ret));
1275 }
1276 case LanParam::IPFamilyEnables:
1277 {
1278 ret.pack(static_cast<uint8_t>(IPFamilyEnables::DualStack));
1279 return responseSuccess(std::move(ret));
1280 }
1281 case LanParam::IPv6Status:
1282 {
1283 ret.pack(MAX_IPV6_STATIC_ADDRESSES);
1284 ret.pack(MAX_IPV6_DYNAMIC_ADDRESSES);
1285 std::bitset<8> support;
1286 support[IPv6StatusFlag::DHCP] = 1;
1287 support[IPv6StatusFlag::SLAAC] = 1;
1288 ret.pack(support);
1289 return responseSuccess(std::move(ret));
1290 }
1291 case LanParam::IPv6StaticAddresses:
1292 {
1293 if (set >= MAX_IPV6_STATIC_ADDRESSES)
1294 {
1295 return responseParmOutOfRange();
1296 }
1297 getLanIPv6Address(ret, channel, set, originsV6Static);
1298 return responseSuccess(std::move(ret));
1299 }
1300 case LanParam::IPv6DynamicAddresses:
1301 {
1302 if (set >= MAX_IPV6_DYNAMIC_ADDRESSES)
1303 {
1304 return responseParmOutOfRange();
1305 }
1306 getLanIPv6Address(ret, channel, set, originsV6Dynamic);
1307 return responseSuccess(std::move(ret));
1308 }
1309 case LanParam::IPv6RouterControl:
1310 {
1311 std::bitset<8> control;
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001312 control[IPv6RouterControlFlag::Dynamic] =
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001313 channelCall<getEthProp<bool>>(channel, "IPv6AcceptRA");
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001314 control[IPv6RouterControlFlag::Static] = 1;
William A. Kennington III16064aa2019-04-13 17:44:53 -07001315 ret.pack(control);
1316 return responseSuccess(std::move(ret));
1317 }
1318 case LanParam::IPv6StaticRouter1IP:
1319 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001320 stdplus::In6Addr gateway{};
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001321 if (!channelCall<getEthProp<bool>>(channel, "IPv6AcceptRA"))
William A. Kennington III16064aa2019-04-13 17:44:53 -07001322 {
1323 gateway =
1324 channelCall<getGatewayProperty<AF_INET6>>(channel).value_or(
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001325 stdplus::In6Addr{});
William A. Kennington III16064aa2019-04-13 17:44:53 -07001326 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001327 ret.pack(stdplus::raw::asView<char>(gateway));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001328 return responseSuccess(std::move(ret));
1329 }
1330 case LanParam::IPv6StaticRouter1MAC:
1331 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001332 stdplus::EtherAddr mac{};
William A. Kennington III16064aa2019-04-13 17:44:53 -07001333 auto neighbor = channelCall<getGatewayNeighbor<AF_INET6>>(channel);
1334 if (neighbor)
1335 {
1336 mac = neighbor->mac;
1337 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001338 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001339 return responseSuccess(std::move(ret));
1340 }
1341 case LanParam::IPv6StaticRouter1PrefixLength:
1342 {
Jian Zhang796e8242024-02-01 14:07:34 +08001343 ret.pack(uint8_t{0});
William A. Kennington III16064aa2019-04-13 17:44:53 -07001344 return responseSuccess(std::move(ret));
1345 }
1346 case LanParam::IPv6StaticRouter1PrefixValue:
1347 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001348 ret.pack(stdplus::raw::asView<char>(stdplus::In6Addr{}));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001349 return responseSuccess(std::move(ret));
1350 }
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001351 case LanParam::cipherSuitePrivilegeLevels:
1352 {
1353 std::array<uint4_t, ipmi::maxCSRecords> csPrivilegeLevels;
1354
1355 uint8_t resp =
1356 getCipherConfigObject(csPrivFileName, csPrivDefaultFileName)
1357 .getCSPrivilegeLevels(channel, csPrivilegeLevels);
1358 if (!resp)
1359 {
1360 constexpr uint8_t reserved1 = 0x00;
1361 ret.pack(reserved1, csPrivilegeLevels);
1362 return responseSuccess(std::move(ret));
1363 }
1364 else
1365 {
1366 return response(resp);
1367 }
1368 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001369 }
1370
PavanKumarIntel3771f5f2023-11-02 06:26:42 +00001371 if (parameter >= oemCmdStart)
Johnathan Manteyb87034e2019-09-16 10:50:50 -07001372 {
1373 return getLanOem(channel, parameter, set, block);
1374 }
1375
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001376 return response(ccParamNotSupported);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001377}
1378
Jian Zhang23f44652022-03-17 17:13:10 +08001379constexpr const char* solInterface = "xyz.openbmc_project.Ipmi.SOL";
1380constexpr const char* solPath = "/xyz/openbmc_project/ipmi/sol/";
1381constexpr const uint16_t solDefaultPort = 623;
1382
1383RspType<> setSolConfParams(Context::ptr ctx, uint4_t channelBits,
Willy Tu11d68892022-01-20 10:37:34 -08001384 uint4_t /*reserved*/, uint8_t parameter,
Jian Zhang23f44652022-03-17 17:13:10 +08001385 message::Payload& req)
1386{
1387 const uint8_t channel = convertCurrentChannelNum(
1388 static_cast<uint8_t>(channelBits), ctx->channel);
1389
1390 if (!isValidChannel(channel))
1391 {
George Liu32e8f5d2024-07-17 19:52:25 +08001392 lg2::error("Set Sol Config - Invalid channel in request");
Jian Zhang23f44652022-03-17 17:13:10 +08001393 return responseInvalidFieldRequest();
1394 }
1395
1396 std::string solService{};
1397 std::string solPathWitheEthName = solPath + ipmi::getChannelName(channel);
1398
1399 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1400 {
George Liu32e8f5d2024-07-17 19:52:25 +08001401 lg2::error("Set Sol Config - Invalid solInterface, service: {SERVICE}, "
1402 "object path: {OBJPATH}, interface: {INTERFACE}",
1403 "SERVICE", solService, "OBJPATH", solPathWitheEthName,
1404 "INTERFACE", solInterface);
Jian Zhang23f44652022-03-17 17:13:10 +08001405 return responseInvalidFieldRequest();
1406 }
1407
1408 switch (static_cast<SolConfParam>(parameter))
1409 {
1410 case SolConfParam::Progress:
1411 {
1412 uint8_t progress;
1413 if (req.unpack(progress) != 0 || !req.fullyUnpacked())
1414 {
1415 return responseReqDataLenInvalid();
1416 }
1417
1418 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1419 solInterface, "Progress", progress))
1420 {
1421 return responseUnspecifiedError();
1422 }
1423 break;
1424 }
1425 case SolConfParam::Enable:
1426 {
1427 bool enable;
1428 uint7_t reserved2;
1429
1430 if (req.unpack(enable, reserved2) != 0 || !req.fullyUnpacked())
1431 {
1432 return responseReqDataLenInvalid();
1433 }
1434
1435 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1436 solInterface, "Enable", enable))
1437 {
1438 return responseUnspecifiedError();
1439 }
1440 break;
1441 }
1442 case SolConfParam::Authentication:
1443 {
1444 uint4_t privilegeBits{};
1445 uint2_t reserved2{};
1446 bool forceAuth = false;
1447 bool forceEncrypt = false;
1448
1449 if (req.unpack(privilegeBits, reserved2, forceAuth, forceEncrypt) !=
1450 0 ||
1451 !req.fullyUnpacked())
1452 {
1453 return responseReqDataLenInvalid();
1454 }
1455
1456 uint8_t privilege = static_cast<uint8_t>(privilegeBits);
Jonathan Domana48bf772023-05-26 17:54:57 -07001457 if (privilege < static_cast<uint8_t>(Privilege::User) ||
Jian Zhang23f44652022-03-17 17:13:10 +08001458 privilege > static_cast<uint8_t>(Privilege::Oem))
1459 {
1460 return ipmi::responseInvalidFieldRequest();
1461 }
1462
1463 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1464 solInterface, "Privilege", privilege))
1465 {
1466 return responseUnspecifiedError();
1467 }
1468
1469 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1470 solInterface, "ForceEncryption",
1471 forceEncrypt))
1472 {
1473 return responseUnspecifiedError();
1474 }
1475
1476 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1477 solInterface, "ForceAuthentication",
1478 forceAuth))
1479 {
1480 return responseUnspecifiedError();
1481 }
1482 break;
1483 }
1484 case SolConfParam::Accumulate:
1485 {
1486 uint8_t interval;
1487 uint8_t threshold;
1488 if (req.unpack(interval, threshold) != 0 || !req.fullyUnpacked())
1489 {
1490 return responseReqDataLenInvalid();
1491 }
1492
1493 if (threshold == 0)
1494 {
1495 return responseInvalidFieldRequest();
1496 }
1497
1498 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1499 solInterface, "AccumulateIntervalMS",
1500 interval))
1501 {
1502 return responseUnspecifiedError();
1503 }
1504
1505 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1506 solInterface, "Threshold", threshold))
1507 {
1508 return responseUnspecifiedError();
1509 }
1510 break;
1511 }
1512 case SolConfParam::Retry:
1513 {
1514 uint3_t countBits;
1515 uint5_t reserved2;
1516 uint8_t interval;
1517
1518 if (req.unpack(countBits, reserved2, interval) != 0 ||
1519 !req.fullyUnpacked())
1520 {
1521 return responseReqDataLenInvalid();
1522 }
1523
1524 uint8_t count = static_cast<uint8_t>(countBits);
1525 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1526 solInterface, "RetryCount", count))
1527 {
1528 return responseUnspecifiedError();
1529 }
1530
1531 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1532 solInterface, "RetryIntervalMS",
1533 interval))
1534 {
1535 return responseUnspecifiedError();
1536 }
1537 break;
1538 }
1539 case SolConfParam::Port:
1540 {
1541 return response(ipmiCCWriteReadParameter);
1542 }
1543 case SolConfParam::NonVbitrate:
1544 case SolConfParam::Vbitrate:
1545 case SolConfParam::Channel:
1546 default:
1547 return response(ipmiCCParamNotSupported);
1548 }
1549 return responseSuccess();
1550}
1551
Patrick Williams1318a5e2024-08-16 15:19:54 -04001552RspType<message::Payload> getSolConfParams(
1553 Context::ptr ctx, uint4_t channelBits, uint3_t /*reserved*/, bool revOnly,
1554 uint8_t parameter, uint8_t /*set*/, uint8_t /*block*/)
Jian Zhang23f44652022-03-17 17:13:10 +08001555{
1556 message::Payload ret;
1557 constexpr uint8_t current_revision = 0x11;
1558 ret.pack(current_revision);
1559 if (revOnly)
1560 {
1561 return responseSuccess(std::move(ret));
1562 }
1563
1564 const uint8_t channel = convertCurrentChannelNum(
1565 static_cast<uint8_t>(channelBits), ctx->channel);
1566
1567 if (!isValidChannel(channel))
1568 {
George Liu32e8f5d2024-07-17 19:52:25 +08001569 lg2::error("Get Sol Config - Invalid channel in request");
Jian Zhang23f44652022-03-17 17:13:10 +08001570 return responseInvalidFieldRequest();
1571 }
1572
1573 std::string solService{};
1574 std::string solPathWitheEthName = solPath + ipmi::getChannelName(channel);
1575
1576 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1577 {
George Liu32e8f5d2024-07-17 19:52:25 +08001578 lg2::error("Set Sol Config - Invalid solInterface, service: {SERVICE}, "
1579 "object path: {OBJPATH}, interface: {INTERFACE}",
1580 "SERVICE", solService, "OBJPATH", solPathWitheEthName,
1581 "INTERFACE", solInterface);
Jian Zhang23f44652022-03-17 17:13:10 +08001582 return responseInvalidFieldRequest();
1583 }
1584
1585 switch (static_cast<SolConfParam>(parameter))
1586 {
1587 case SolConfParam::Progress:
1588 {
1589 uint8_t progress;
1590 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1591 solInterface, "Progress", progress))
1592 {
1593 return responseUnspecifiedError();
1594 }
1595 ret.pack(progress);
1596 return responseSuccess(std::move(ret));
1597 }
1598 case SolConfParam::Enable:
1599 {
1600 bool enable{};
1601 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1602 solInterface, "Enable", enable))
1603 {
1604 return responseUnspecifiedError();
1605 }
1606 ret.pack(enable, uint7_t{});
1607 return responseSuccess(std::move(ret));
1608 }
1609 case SolConfParam::Authentication:
1610 {
1611 // 4bits, cast when pack
1612 uint8_t privilege;
1613 bool forceAuth = false;
1614 bool forceEncrypt = false;
1615
1616 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1617 solInterface, "Privilege", privilege))
1618 {
1619 return responseUnspecifiedError();
1620 }
1621
1622 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1623 solInterface, "ForceAuthentication",
1624 forceAuth))
1625 {
1626 return responseUnspecifiedError();
1627 }
1628
1629 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1630 solInterface, "ForceEncryption",
1631 forceEncrypt))
1632 {
1633 return responseUnspecifiedError();
1634 }
1635 ret.pack(uint4_t{privilege}, uint2_t{}, forceAuth, forceEncrypt);
1636 return responseSuccess(std::move(ret));
1637 }
1638 case SolConfParam::Accumulate:
1639 {
1640 uint8_t interval{}, threshold{};
1641
1642 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1643 solInterface, "AccumulateIntervalMS",
1644 interval))
1645 {
1646 return responseUnspecifiedError();
1647 }
1648
1649 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1650 solInterface, "Threshold", threshold))
1651 {
1652 return responseUnspecifiedError();
1653 }
1654 ret.pack(interval, threshold);
1655 return responseSuccess(std::move(ret));
1656 }
1657 case SolConfParam::Retry:
1658 {
1659 // 3bits, cast when cast
1660 uint8_t count{};
1661 uint8_t interval{};
1662
1663 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1664 solInterface, "RetryCount", count))
1665 {
1666 return responseUnspecifiedError();
1667 }
1668
1669 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1670 solInterface, "RetryIntervalMS",
1671 interval))
1672 {
1673 return responseUnspecifiedError();
1674 }
1675 ret.pack(uint3_t{count}, uint5_t{}, interval);
1676 return responseSuccess(std::move(ret));
1677 }
1678 case SolConfParam::Port:
1679 {
1680 auto port = solDefaultPort;
1681 ret.pack(static_cast<uint16_t>(port));
1682 return responseSuccess(std::move(ret));
1683 }
1684 case SolConfParam::Channel:
1685 {
1686 ret.pack(channel);
1687 return responseSuccess(std::move(ret));
1688 }
1689 case SolConfParam::NonVbitrate:
Jonathan Domana48bf772023-05-26 17:54:57 -07001690 {
1691 uint64_t baudRate;
1692 uint8_t encodedBitRate = 0;
1693 if (ipmi::getDbusProperty(
1694 ctx, "xyz.openbmc_project.Console.default",
1695 "/xyz/openbmc_project/console/default",
1696 "xyz.openbmc_project.Console.UART", "Baud", baudRate))
1697 {
Oskar Senft71d21a12024-08-13 17:01:26 -04001698 return response(ccParamNotSupported);
Jonathan Domana48bf772023-05-26 17:54:57 -07001699 }
1700 switch (baudRate)
1701 {
1702 case 9600:
1703 encodedBitRate = 0x06;
1704 break;
1705 case 19200:
1706 encodedBitRate = 0x07;
1707 break;
1708 case 38400:
1709 encodedBitRate = 0x08;
1710 break;
1711 case 57600:
1712 encodedBitRate = 0x09;
1713 break;
1714 case 115200:
1715 encodedBitRate = 0x0a;
1716 break;
1717 default:
1718 break;
1719 }
1720 ret.pack(encodedBitRate);
1721 return responseSuccess(std::move(ret));
1722 }
Jian Zhang23f44652022-03-17 17:13:10 +08001723 case SolConfParam::Vbitrate:
1724 default:
1725 return response(ipmiCCParamNotSupported);
1726 }
1727
1728 return response(ccParamNotSupported);
1729}
1730
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001731} // namespace transport
1732} // namespace ipmi
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301733
George Liu5087b072025-03-11 19:28:17 +08001734void registerNetFnTransportFunctions() __attribute__((constructor));
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301735
George Liu5087b072025-03-11 19:28:17 +08001736void registerNetFnTransportFunctions()
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001737{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001738 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1739 ipmi::transport::cmdSetLanConfigParameters,
1740 ipmi::Privilege::Admin, ipmi::transport::setLan);
1741 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1742 ipmi::transport::cmdGetLanConfigParameters,
Johnathan Mantey34698d52019-11-19 14:47:30 -08001743 ipmi::Privilege::Operator, ipmi::transport::getLan);
Jian Zhang23f44652022-03-17 17:13:10 +08001744 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1745 ipmi::transport::cmdSetSolConfigParameters,
1746 ipmi::Privilege::Admin,
1747 ipmi::transport::setSolConfParams);
1748 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1749 ipmi::transport::cmdGetSolConfigParameters,
1750 ipmi::Privilege::User,
1751 ipmi::transport::getSolConfParams);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001752}