blob: 772925e4521e0e951ed66ea066161a9729710b80 [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) &&
71 (path.size() == is || path[is] == '/');
72}
73
Patrick Williams1318a5e2024-08-16 15:19:54 -040074std::optional<ChannelParams>
75 maybeGetChannelParams(sdbusplus::bus_t& bus, uint8_t channel)
William A. Kennington IIIc514d872019-04-06 18:19:38 -070076{
77 auto ifname = getChannelName(channel);
78 if (ifname.empty())
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080079 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -070080 return std::nullopt;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080081 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080082
William A. Kennington IIIc514d872019-04-06 18:19:38 -070083 // Enumerate all VLAN + ETHERNET interfaces
George Liuc1c7eac2024-02-04 17:24:19 +080084 std::vector<std::string> interfaces = {INTF_VLAN, INTF_ETHERNET};
Patrick Williams1318a5e2024-08-16 15:19:54 -040085 ipmi::ObjectTree objs =
86 ipmi::getSubTree(bus, interfaces, std::string{PATH_ROOT});
William A. Kennington IIIc514d872019-04-06 18:19:38 -070087
88 ChannelParams params;
89 for (const auto& [path, impls] : objs)
90 {
William A. Kennington IIIc72f3602023-10-19 03:51:37 -070091 if (!ifnameInPath(ifname, path))
William A. Kennington IIIc514d872019-04-06 18:19:38 -070092 {
93 continue;
94 }
95 for (const auto& [service, intfs] : impls)
96 {
97 bool vlan = false;
98 bool ethernet = false;
99 for (const auto& intf : intfs)
100 {
101 if (intf == INTF_VLAN)
102 {
103 vlan = true;
104 }
105 else if (intf == INTF_ETHERNET)
106 {
107 ethernet = true;
108 }
109 }
110 if (params.service.empty() && (vlan || ethernet))
111 {
112 params.service = service;
113 }
114 if (params.ifPath.empty() && !vlan && ethernet)
115 {
116 params.ifPath = path;
117 }
118 if (params.logicalPath.empty() && vlan)
119 {
120 params.logicalPath = path;
121 }
122 }
123 }
124
125 // We must have a path for the underlying interface
126 if (params.ifPath.empty())
127 {
128 return std::nullopt;
129 }
130 // We don't have a VLAN so the logical path is the same
131 if (params.logicalPath.empty())
132 {
133 params.logicalPath = params.ifPath;
134 }
135
136 params.id = channel;
137 params.ifname = std::move(ifname);
Willy Tu11d68892022-01-20 10:37:34 -0800138 return params;
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700139}
140
Patrick Williams5d82f472022-07-22 19:26:53 -0500141ChannelParams getChannelParams(sdbusplus::bus_t& bus, uint8_t channel)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700142{
143 auto params = maybeGetChannelParams(bus, channel);
144 if (!params)
145 {
George Liu32e8f5d2024-07-17 19:52:25 +0800146 lg2::error("Failed to get channel params: {CHANNEL}", "CHANNEL",
147 channel);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700148 elog<InternalFailure>();
149 }
150 return std::move(*params);
151}
152
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700153/** @brief Get / Set the Property value from phosphor-networkd EthernetInterface
154 */
155template <typename T>
156static T getEthProp(sdbusplus::bus_t& bus, const ChannelParams& params,
157 const std::string& prop)
158{
159 return std::get<T>(getDbusProperty(bus, params.service, params.logicalPath,
160 INTF_ETHERNET, prop));
161}
162template <typename T>
163static void setEthProp(sdbusplus::bus_t& bus, const ChannelParams& params,
164 const std::string& prop, const T& t)
165{
166 return setDbusProperty(bus, params.service, params.logicalPath,
167 INTF_ETHERNET, prop, t);
168}
169
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700170/** @brief Determines the MAC of the ethernet interface
171 *
172 * @param[in] bus - The bus object used for lookups
173 * @param[in] params - The parameters for the channel
174 * @return The configured mac address
175 */
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700176stdplus::EtherAddr getMACProperty(sdbusplus::bus_t& bus,
177 const ChannelParams& params)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700178{
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700179 auto prop = getDbusProperty(bus, params.service, params.ifPath, INTF_MAC,
180 "MACAddress");
181 return stdplus::fromStr<stdplus::EtherAddr>(std::get<std::string>(prop));
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700182}
183
184/** @brief Sets the system value for MAC address on the given interface
185 *
186 * @param[in] bus - The bus object used for lookups
187 * @param[in] params - The parameters for the channel
188 * @param[in] mac - MAC address to apply
189 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500190void setMACProperty(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700191 stdplus::EtherAddr mac)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700192{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700193 setDbusProperty(bus, params.service, params.ifPath, INTF_MAC, "MACAddress",
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700194 stdplus::toStr(mac));
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700195}
196
Patrick Williams5d82f472022-07-22 19:26:53 -0500197void deleteObjectIfExists(sdbusplus::bus_t& bus, const std::string& service,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700198 const std::string& path)
199{
200 if (path.empty())
201 {
202 return;
203 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530204 try
tomjose26e17732016-03-03 08:52:51 -0600205 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700206 auto req = bus.new_method_call(service.c_str(), path.c_str(),
207 ipmi::DELETE_INTERFACE, "Delete");
208 bus.call_noreply(req);
209 }
Patrick Williams5d82f472022-07-22 19:26:53 -0500210 catch (const sdbusplus::exception_t& e)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700211 {
jayaprakash Mutyala84c49dc2020-05-18 23:12:13 +0000212 if (strcmp(e.name(),
213 "xyz.openbmc_project.Common.Error.InternalFailure") != 0 &&
214 strcmp(e.name(), "org.freedesktop.DBus.Error.UnknownObject") != 0)
tomjose26e17732016-03-03 08:52:51 -0600215 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700216 // We want to rethrow real errors
217 throw;
tomjose26e17732016-03-03 08:52:51 -0600218 }
219 }
tomjose26e17732016-03-03 08:52:51 -0600220}
221
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700222/** @brief Sets the address info configured for the interface
223 * If a previous address path exists then it will be removed
224 * before the new address is added.
225 *
226 * @param[in] bus - The bus object used for lookups
227 * @param[in] params - The parameters for the channel
228 * @param[in] address - The address of the new IP
229 * @param[in] prefix - The prefix of the new IP
230 */
231template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500232void createIfAddr(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700233 typename AddrFamily<family>::addr address, uint8_t prefix)
Tom Josepha30c8d32018-03-22 02:15:03 +0530234{
Patrick Williams1318a5e2024-08-16 15:19:54 -0400235 auto newreq =
236 bus.new_method_call(params.service.c_str(), params.logicalPath.c_str(),
237 INTF_IP_CREATE, "IP");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700238 std::string protocol =
Willy Tu523e2d12023-09-05 11:36:48 -0700239 sdbusplus::common::xyz::openbmc_project::network::convertForMessage(
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700240 AddrFamily<family>::protocol);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700241 stdplus::ToStrHandle<stdplus::ToStr<typename AddrFamily<family>::addr>> tsh;
242 newreq.append(protocol, tsh(address), prefix, "");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700243 bus.call_noreply(newreq);
244}
Tom Josepha30c8d32018-03-22 02:15:03 +0530245
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700246/** @brief Trivial helper for getting the IPv4 address from getIfAddrs()
247 *
248 * @param[in] bus - The bus object used for lookups
249 * @param[in] params - The parameters for the channel
250 * @return The address and prefix if found
251 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500252auto getIfAddr4(sdbusplus::bus_t& bus, const ChannelParams& params)
Tom Josepha30c8d32018-03-22 02:15:03 +0530253{
Chanh Nguyen8bd9a9b2024-11-08 09:08:56 +0000254 std::optional<IfAddr<AF_INET>> ifaddr4 = std::nullopt;
255 IP::AddressOrigin src;
256
257 try
258 {
259 src = std::get<bool>(
260 getDbusProperty(bus, params.service, params.logicalPath,
261 INTF_ETHERNET, "DHCP4"))
262 ? IP::AddressOrigin::DHCP
263 : IP::AddressOrigin::Static;
264 }
265 catch (const sdbusplus::exception_t& e)
266 {
267 lg2::error("Failed to get IPv4 source");
268 return ifaddr4;
269 }
270
271 for (uint8_t i = 0; i < MAX_IPV4_ADDRESSES; ++i)
272 {
273 ifaddr4 = getIfAddr<AF_INET>(bus, params, i, originsV4);
274 if (src == ifaddr4->origin)
275 {
276 break;
277 }
278 else
279 {
280 ifaddr4 = std::nullopt;
281 }
282 }
283 return ifaddr4;
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700284}
Tom Josepha30c8d32018-03-22 02:15:03 +0530285
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700286/** @brief Reconfigures the IPv4 address info configured for the interface
287 *
288 * @param[in] bus - The bus object used for lookups
289 * @param[in] params - The parameters for the channel
290 * @param[in] address - The new address if specified
291 * @param[in] prefix - The new address prefix if specified
292 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500293void reconfigureIfAddr4(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700294 std::optional<stdplus::In4Addr> address,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700295 std::optional<uint8_t> prefix)
296{
297 auto ifaddr = getIfAddr4(bus, params);
298 if (!ifaddr && !address)
Tom Josepha30c8d32018-03-22 02:15:03 +0530299 {
George Liu32e8f5d2024-07-17 19:52:25 +0800300 lg2::error("Missing address for IPv4 assignment");
Tom Josepha30c8d32018-03-22 02:15:03 +0530301 elog<InternalFailure>();
302 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700303 uint8_t fallbackPrefix = AddrFamily<AF_INET>::defaultPrefix;
304 if (ifaddr)
Tom Josepha30c8d32018-03-22 02:15:03 +0530305 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700306 fallbackPrefix = ifaddr->prefix;
307 deleteObjectIfExists(bus, params.service, ifaddr->path);
308 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700309 auto addr = address.value_or(ifaddr->address);
310 if (addr != stdplus::In4Addr{})
Johnathan Manteycbfa6e12023-06-01 06:57:25 -0700311 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700312 createIfAddr<AF_INET>(bus, params, addr,
Johnathan Manteycbfa6e12023-06-01 06:57:25 -0700313 prefix.value_or(fallbackPrefix));
314 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700315}
316
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700317template <int family>
Patrick Williams1318a5e2024-08-16 15:19:54 -0400318std::optional<IfNeigh<family>>
319 findGatewayNeighbor(sdbusplus::bus_t& bus, const ChannelParams& params,
320 ObjectLookupCache& neighbors)
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700321{
322 auto gateway = getGatewayProperty<family>(bus, params);
323 if (!gateway)
324 {
325 return std::nullopt;
326 }
327
328 return findStaticNeighbor<family>(bus, params, *gateway, neighbors);
329}
330
331template <int family>
Patrick Williams1318a5e2024-08-16 15:19:54 -0400332std::optional<IfNeigh<family>>
333 getGatewayNeighbor(sdbusplus::bus_t& bus, const ChannelParams& params)
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700334{
335 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
336 return findGatewayNeighbor<family>(bus, params, neighbors);
337}
338
339template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500340void reconfigureGatewayMAC(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700341 stdplus::EtherAddr mac)
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700342{
343 auto gateway = getGatewayProperty<family>(bus, params);
344 if (!gateway)
345 {
George Liu32e8f5d2024-07-17 19:52:25 +0800346 lg2::error("Tried to set Gateway MAC without Gateway");
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700347 elog<InternalFailure>();
348 }
349
350 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
Patrick Williams1318a5e2024-08-16 15:19:54 -0400351 auto neighbor =
352 findStaticNeighbor<family>(bus, params, *gateway, neighbors);
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700353 if (neighbor)
354 {
355 deleteObjectIfExists(bus, params.service, neighbor->path);
356 }
357
358 createNeighbor<family>(bus, params, *gateway, mac);
359}
360
William A. Kennington III16064aa2019-04-13 17:44:53 -0700361/** @brief Deconfigures the IPv6 address info configured for the interface
362 *
363 * @param[in] bus - The bus object used for lookups
364 * @param[in] params - The parameters for the channel
365 * @param[in] idx - The address index to operate on
366 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500367void deconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III16064aa2019-04-13 17:44:53 -0700368 uint8_t idx)
369{
370 auto ifaddr = getIfAddr<AF_INET6>(bus, params, idx, originsV6Static);
371 if (ifaddr)
372 {
373 deleteObjectIfExists(bus, params.service, ifaddr->path);
374 }
375}
376
377/** @brief Reconfigures the IPv6 address info configured for the interface
378 *
379 * @param[in] bus - The bus object used for lookups
380 * @param[in] params - The parameters for the channel
381 * @param[in] idx - The address index to operate on
382 * @param[in] address - The new address
383 * @param[in] prefix - The new address prefix
384 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500385void reconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700386 uint8_t idx, stdplus::In6Addr address, uint8_t prefix)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700387{
388 deconfigureIfAddr6(bus, params, idx);
389 createIfAddr<AF_INET6>(bus, params, address, prefix);
390}
391
392/** @brief Converts the AddressOrigin into an IPv6Source
393 *
394 * @param[in] origin - The DBus Address Origin to convert
395 * @return The IPv6Source version of the origin
396 */
397IPv6Source originToSourceType(IP::AddressOrigin origin)
398{
399 switch (origin)
400 {
401 case IP::AddressOrigin::Static:
402 return IPv6Source::Static;
403 case IP::AddressOrigin::DHCP:
404 return IPv6Source::DHCP;
405 case IP::AddressOrigin::SLAAC:
406 return IPv6Source::SLAAC;
407 default:
408 {
Willy Tu523e2d12023-09-05 11:36:48 -0700409 auto originStr = sdbusplus::common::xyz::openbmc_project::network::
William A. Kennington III16064aa2019-04-13 17:44:53 -0700410 convertForMessage(origin);
George Liu32e8f5d2024-07-17 19:52:25 +0800411 lg2::error("Invalid IP::AddressOrigin conversion to IPv6Source, "
412 "origin: {ORIGIN}",
413 "ORIGIN", originStr);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700414 elog<InternalFailure>();
415 }
416 }
417}
418
419/** @brief Packs the IPMI message response with IPv6 address data
420 *
421 * @param[out] ret - The IPMI response payload to be packed
422 * @param[in] channel - The channel id corresponding to an ethernet interface
423 * @param[in] set - The set selector for determining address index
424 * @param[in] origins - Set of valid origins for address filtering
425 */
426void getLanIPv6Address(message::Payload& ret, uint8_t channel, uint8_t set,
427 const std::unordered_set<IP::AddressOrigin>& origins)
428{
429 auto source = IPv6Source::Static;
430 bool enabled = false;
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700431 stdplus::In6Addr addr{};
Johnathan Mantey5aae0922021-10-21 13:05:36 -0700432 uint8_t prefix{};
William A. Kennington III16064aa2019-04-13 17:44:53 -0700433 auto status = IPv6AddressStatus::Disabled;
434
435 auto ifaddr = channelCall<getIfAddr<AF_INET6>>(channel, set, origins);
436 if (ifaddr)
437 {
438 source = originToSourceType(ifaddr->origin);
Johnathan Mantey846af862021-10-21 12:48:54 -0700439 enabled = (origins == originsV6Static);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700440 addr = ifaddr->address;
441 prefix = ifaddr->prefix;
442 status = IPv6AddressStatus::Active;
443 }
444
445 ret.pack(set);
William A. Kennington III7a0e5df2021-05-19 13:31:29 -0700446 ret.pack(types::enum_cast<uint4_t>(source), uint3_t{}, enabled);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700447 ret.pack(stdplus::raw::asView<char>(addr));
William A. Kennington III16064aa2019-04-13 17:44:53 -0700448 ret.pack(prefix);
William A. Kennington III7a0e5df2021-05-19 13:31:29 -0700449 ret.pack(types::enum_cast<uint8_t>(status));
William A. Kennington III16064aa2019-04-13 17:44:53 -0700450}
451
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700452/** @brief Gets the vlan ID configured on the interface
453 *
454 * @param[in] bus - The bus object used for lookups
455 * @param[in] params - The parameters for the channel
456 * @return VLAN id or the standard 0 for no VLAN
457 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500458uint16_t getVLANProperty(sdbusplus::bus_t& bus, const ChannelParams& params)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700459{
460 // VLAN devices will always have a separate logical object
461 if (params.ifPath == params.logicalPath)
462 {
463 return 0;
464 }
465
466 auto vlan = std::get<uint32_t>(getDbusProperty(
467 bus, params.service, params.logicalPath, INTF_VLAN, "Id"));
468 if ((vlan & VLAN_VALUE_MASK) != vlan)
469 {
Vernon Maueryaf4a7752024-07-02 09:45:46 -0700470 lg2::error("networkd returned an invalid vlan: {VLAN} "
471 "(CH={CHANNEL}, IF={IFNAME})",
472 "CHANNEL", params.id, "IFNAME", params.ifname, "VLAN", vlan);
Tom Josepha30c8d32018-03-22 02:15:03 +0530473 elog<InternalFailure>();
474 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700475 return vlan;
Tom Josepha30c8d32018-03-22 02:15:03 +0530476}
477
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700478/** @brief Deletes all of the possible configuration parameters for a channel
479 *
480 * @param[in] bus - The bus object used for lookups
481 * @param[in] params - The parameters for the channel
482 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500483void deconfigureChannel(sdbusplus::bus_t& bus, ChannelParams& params)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500484{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700485 // Delete all objects associated with the interface
George Liuc1c7eac2024-02-04 17:24:19 +0800486 ObjectTree objs =
487 ipmi::getSubTree(bus, std::vector<std::string>{DELETE_INTERFACE},
488 std::string{PATH_ROOT});
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700489 for (const auto& [path, impls] : objs)
490 {
William A. Kennington IIIc72f3602023-10-19 03:51:37 -0700491 if (!ifnameInPath(params.ifname, path))
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700492 {
493 continue;
494 }
495 for (const auto& [service, intfs] : impls)
496 {
497 deleteObjectIfExists(bus, service, path);
498 }
499 // Update params to reflect the deletion of vlan
500 if (path == params.logicalPath)
501 {
502 params.logicalPath = params.ifPath;
503 }
504 }
505
506 // Clear out any settings on the lower physical interface
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700507 setEthProp(bus, params, "DHCP4", false);
508 setEthProp(bus, params, "DHCP6", false);
509 setEthProp(bus, params, "IPv6AcceptRA", false);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500510}
511
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700512/** @brief Creates a new VLAN on the specified interface
513 *
514 * @param[in] bus - The bus object used for lookups
515 * @param[in] params - The parameters for the channel
516 * @param[in] vlan - The id of the new vlan
517 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500518void createVLAN(sdbusplus::bus_t& bus, ChannelParams& params, uint16_t vlan)
Ratan Guptab8e99552017-07-27 07:07:48 +0530519{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700520 if (vlan == 0)
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530521 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700522 return;
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530523 }
524
William A. Kennington IIIc72f3602023-10-19 03:51:37 -0700525 auto req = bus.new_method_call(params.service.c_str(), PATH_ROOT.c_str(),
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700526 INTF_VLAN_CREATE, "VLAN");
527 req.append(params.ifname, static_cast<uint32_t>(vlan));
528 auto reply = bus.call(req);
529 sdbusplus::message::object_path newPath;
530 reply.read(newPath);
531 params.logicalPath = std::move(newPath);
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530532}
533
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700534/** @brief Performs the necessary reconfiguration to change the VLAN
535 *
536 * @param[in] bus - The bus object used for lookups
537 * @param[in] params - The parameters for the channel
538 * @param[in] vlan - The new vlan id to use
539 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500540void reconfigureVLAN(sdbusplus::bus_t& bus, ChannelParams& params,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700541 uint16_t vlan)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500542{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700543 // Unfortunatetly we don't have built-in functions to migrate our interface
544 // customizations to new VLAN interfaces, or have some kind of decoupling.
545 // We therefore must retain all of our old information, setup the new VLAN
546 // configuration, then restore the old info.
Nan Li3d0df912016-10-18 19:51:41 +0800547
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700548 // Save info from the old logical interface
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700549 bool dhcp4 = getEthProp<bool>(bus, params, "DHCP4");
550 bool dhcp6 = getEthProp<bool>(bus, params, "DHCP6");
551 bool ra = getEthProp<bool>(bus, params, "IPv6AcceptRA");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700552 ObjectLookupCache ips(bus, params, INTF_IP);
553 auto ifaddr4 = findIfAddr<AF_INET>(bus, params, 0, originsV4, ips);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700554 std::vector<IfAddr<AF_INET6>> ifaddrs6;
555 for (uint8_t i = 0; i < MAX_IPV6_STATIC_ADDRESSES; ++i)
556 {
Patrick Williams1318a5e2024-08-16 15:19:54 -0400557 auto ifaddr6 =
558 findIfAddr<AF_INET6>(bus, params, i, originsV6Static, ips);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700559 if (!ifaddr6)
560 {
561 break;
562 }
563 ifaddrs6.push_back(std::move(*ifaddr6));
564 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700565 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
566 auto neighbor4 = findGatewayNeighbor<AF_INET>(bus, params, neighbors);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700567 auto neighbor6 = findGatewayNeighbor<AF_INET6>(bus, params, neighbors);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500568
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700569 deconfigureChannel(bus, params);
570 createVLAN(bus, params, vlan);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500571
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700572 // Re-establish the saved settings
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700573 setEthProp(bus, params, "DHCP4", dhcp4);
574 setEthProp(bus, params, "DHCP6", dhcp6);
575 setEthProp(bus, params, "IPv6AcceptRA", ra);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700576 if (ifaddr4)
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800577 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700578 createIfAddr<AF_INET>(bus, params, ifaddr4->address, ifaddr4->prefix);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800579 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700580 for (const auto& ifaddr6 : ifaddrs6)
581 {
582 createIfAddr<AF_INET6>(bus, params, ifaddr6.address, ifaddr6.prefix);
583 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700584 if (neighbor4)
585 {
586 createNeighbor<AF_INET>(bus, params, neighbor4->ip, neighbor4->mac);
587 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700588 if (neighbor6)
589 {
590 createNeighbor<AF_INET6>(bus, params, neighbor6->ip, neighbor6->mac);
591 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700592}
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800593
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700594// We need to store this value so it can be returned to the client
595// It is volatile so safe to store in daemon memory.
596static std::unordered_map<uint8_t, SetStatus> setStatus;
597
598// Until we have good support for fixed versions of IPMI tool
599// we need to return the VLAN id for disabled VLANs. The value is only
600// used for verification that a disable operation succeeded and will only
601// be sent if our system indicates that vlans are disabled.
602static std::unordered_map<uint8_t, uint16_t> lastDisabledVlan;
603
604/** @brief Gets the set status for the channel if it exists
605 * Otherise populates and returns the default value.
606 *
607 * @param[in] channel - The channel id corresponding to an ethernet interface
608 * @return A reference to the SetStatus for the channel
609 */
610SetStatus& getSetStatus(uint8_t channel)
611{
612 auto it = setStatus.find(channel);
613 if (it != setStatus.end())
614 {
615 return it->second;
616 }
617 return setStatus[channel] = SetStatus::Complete;
618}
619
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700620/** @brief Unpacks the trivially copyable type from the message */
621template <typename T>
622static T unpackT(message::Payload& req)
623{
624 std::array<uint8_t, sizeof(T)> bytes;
625 if (req.unpack(bytes) != 0)
626 {
627 throw ccReqDataLenInvalid;
628 }
629 return stdplus::raw::copyFrom<T>(bytes);
630}
631
632/** @brief Ensure the message is fully unpacked */
633static void unpackFinal(message::Payload& req)
634{
635 if (!req.fullyUnpacked())
636 {
637 throw ccReqDataTruncated;
638 }
639}
640
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700641/**
642 * Define placeholder command handlers for the OEM Extension bytes for the Set
643 * LAN Configuration Parameters and Get LAN Configuration Parameters
644 * commands. Using "weak" linking allows the placeholder setLanOem/getLanOem
645 * functions below to be overridden.
646 * To create handlers for your own proprietary command set:
647 * Create/modify a phosphor-ipmi-host Bitbake append file within your Yocto
648 * recipe
649 * Create C++ file(s) that define IPMI handler functions matching the
650 * function names below (i.e. setLanOem). The default name for the
651 * transport IPMI commands is transporthandler_oem.cpp.
652 * Add:
Johnathan Manteyefe26682022-08-11 14:30:45 -0700653 * EXTRA_OEMESON:append = "-Dtransport-oem=enabled"
654 * Create a do_configure:prepend()/do_install:append() method in your
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700655 * bbappend file to copy the file to the build directory.
656 * Add:
657 * PROJECT_SRC_DIR := "${THISDIR}/${PN}"
658 * # Copy the "strong" functions into the working directory, overriding the
659 * # placeholder functions.
Johnathan Manteyefe26682022-08-11 14:30:45 -0700660 * do_configure:prepend(){
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700661 * cp -f ${PROJECT_SRC_DIR}/transporthandler_oem.cpp ${S}
662 * }
663 *
664 * # Clean up after complilation has completed
Johnathan Manteyefe26682022-08-11 14:30:45 -0700665 * do_install:append(){
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700666 * rm -f ${S}/transporthandler_oem.cpp
667 * }
668 *
669 */
670
671/**
672 * Define the placeholder OEM commands as having weak linkage. Create
673 * setLanOem, and getLanOem functions in the transporthandler_oem.cpp
674 * file. The functions defined there must not have the "weak" attribute
675 * applied to them.
676 */
677RspType<> setLanOem(uint8_t channel, uint8_t parameter, message::Payload& req)
678 __attribute__((weak));
Patrick Williams1318a5e2024-08-16 15:19:54 -0400679RspType<message::Payload>
680 getLanOem(uint8_t channel, uint8_t parameter, uint8_t set, uint8_t block)
681 __attribute__((weak));
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700682
Willy Tu11d68892022-01-20 10:37:34 -0800683RspType<> setLanOem(uint8_t, uint8_t, message::Payload& req)
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700684{
685 req.trailingOk = true;
686 return response(ccParamNotSupported);
687}
688
Willy Tu11d68892022-01-20 10:37:34 -0800689RspType<message::Payload> getLanOem(uint8_t, uint8_t, uint8_t, uint8_t)
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700690{
691 return response(ccParamNotSupported);
692}
693
Jian Zhangcf19d142023-07-31 10:22:53 +0800694/**
695 * @brief is a valid LAN channel.
696 *
697 * This function checks whether the input channel is a valid LAN channel or not.
698 *
699 * @param[in] channel: the channel number.
700 * @return nullopt if the channel is invalid, false if the channel is not a LAN
701 * channel, true if the channel is a LAN channel.
702 **/
703std::optional<bool> isLanChannel(uint8_t channel)
704{
705 ChannelInfo chInfo;
706 auto cc = getChannelInfo(channel, chInfo);
707 if (cc != ccSuccess)
708 {
709 return std::nullopt;
710 }
711
712 return chInfo.mediumType ==
713 static_cast<uint8_t>(EChannelMediumType::lan8032);
714}
715
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700716RspType<> setLanInt(Context::ptr ctx, uint4_t channelBits, uint4_t reserved1,
717 uint8_t parameter, message::Payload& req)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700718{
vijayabharathix shettycc769252020-02-27 17:52:20 +0000719 const uint8_t channel = convertCurrentChannelNum(
720 static_cast<uint8_t>(channelBits), ctx->channel);
721 if (reserved1 || !isValidChannel(channel))
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700722 {
George Liu32e8f5d2024-07-17 19:52:25 +0800723 lg2::error("Set Lan - Invalid field in request");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700724 req.trailingOk = true;
725 return responseInvalidFieldRequest();
726 }
727
Jian Zhangcf19d142023-07-31 10:22:53 +0800728 if (!isLanChannel(channel).value_or(false))
729 {
George Liu32e8f5d2024-07-17 19:52:25 +0800730 lg2::error("Set Lan - Not a LAN channel");
Jian Zhangcf19d142023-07-31 10:22:53 +0800731 return responseInvalidFieldRequest();
732 }
733
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700734 switch (static_cast<LanParam>(parameter))
735 {
736 case LanParam::SetStatus:
737 {
738 uint2_t flag;
739 uint6_t rsvd;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700740 if (req.unpack(flag, rsvd) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700741 {
742 return responseReqDataLenInvalid();
743 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700744 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800745 if (rsvd)
746 {
747 return responseInvalidFieldRequest();
748 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700749 auto status = static_cast<SetStatus>(static_cast<uint8_t>(flag));
750 switch (status)
751 {
752 case SetStatus::Complete:
753 {
754 getSetStatus(channel) = status;
755 return responseSuccess();
756 }
757 case SetStatus::InProgress:
758 {
759 auto& storedStatus = getSetStatus(channel);
760 if (storedStatus == SetStatus::InProgress)
761 {
762 return response(ccParamSetLocked);
763 }
764 storedStatus = status;
765 return responseSuccess();
766 }
767 case SetStatus::Commit:
768 if (getSetStatus(channel) != SetStatus::InProgress)
769 {
770 return responseInvalidFieldRequest();
771 }
772 return responseSuccess();
773 }
774 return response(ccParamNotSupported);
775 }
776 case LanParam::AuthSupport:
777 {
778 req.trailingOk = true;
779 return response(ccParamReadOnly);
780 }
781 case LanParam::AuthEnables:
782 {
783 req.trailingOk = true;
Johnathan Mantey76ce9c72019-11-14 14:41:46 -0800784 return response(ccParamReadOnly);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700785 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800786 case LanParam::IP:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600787 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700788 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800789 {
790 return responseCommandNotAvailable();
791 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700792 auto ip = unpackT<stdplus::In4Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700793 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700794 channelCall<reconfigureIfAddr4>(channel, ip, std::nullopt);
795 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +0530796 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700797 case LanParam::IPSrc:
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530798 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700799 uint4_t flag;
800 uint4_t rsvd;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700801 if (req.unpack(flag, rsvd) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700802 {
803 return responseReqDataLenInvalid();
804 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700805 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800806 if (rsvd)
807 {
808 return responseInvalidFieldRequest();
809 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700810 switch (static_cast<IPSrc>(static_cast<uint8_t>(flag)))
811 {
812 case IPSrc::DHCP:
Johnathan Mantey65265362019-11-14 11:24:19 -0800813 // The IPSrc IPMI command is only for IPv4
814 // management. Modifying IPv6 state is done using
815 // a completely different Set LAN Configuration
816 // subcommand.
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700817 channelCall<setEthProp<bool>>(channel, "DHCP4", true);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700818 return responseSuccess();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700819 case IPSrc::Unspecified:
820 case IPSrc::Static:
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700821 channelCall<setEthProp<bool>>(channel, "DHCP4", false);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700822 return responseSuccess();
Rajashekar Gade Reddy8a860ea2019-12-24 11:31:19 +0530823 case IPSrc::BIOS:
824 case IPSrc::BMC:
Rajashekar Gade Reddy8a860ea2019-12-24 11:31:19 +0530825 return responseInvalidFieldRequest();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700826 }
827 return response(ccParamNotSupported);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530828 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800829 case LanParam::MAC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530830 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700831 auto mac = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700832 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700833 channelCall<setMACProperty>(channel, mac);
834 return responseSuccess();
Ratan Gupta533d03b2017-07-30 10:39:22 +0530835 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700836 case LanParam::SubnetMask:
Ratan Guptab8e99552017-07-27 07:07:48 +0530837 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700838 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800839 {
840 return responseCommandNotAvailable();
841 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700842 auto pfx = stdplus::maskToPfx(unpackT<stdplus::In4Addr>(req));
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700843 unpackFinal(req);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700844 channelCall<reconfigureIfAddr4>(channel, std::nullopt, pfx);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700845 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +0530846 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700847 case LanParam::Gateway1:
Ratan Guptab8e99552017-07-27 07:07:48 +0530848 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700849 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800850 {
851 return responseCommandNotAvailable();
852 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700853 auto gateway = unpackT<stdplus::In4Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700854 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700855 channelCall<setGatewayProperty<AF_INET>>(channel, gateway);
856 return responseSuccess();
857 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700858 case LanParam::Gateway1MAC:
859 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700860 auto gatewayMAC = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700861 unpackFinal(req);
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700862 channelCall<reconfigureGatewayMAC<AF_INET>>(channel, gatewayMAC);
863 return responseSuccess();
864 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700865 case LanParam::VLANId:
866 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700867 uint12_t vlanData;
868 uint3_t rsvd;
869 bool vlanEnable;
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530870
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700871 if (req.unpack(vlanData, rsvd, vlanEnable) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700872 {
873 return responseReqDataLenInvalid();
874 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700875 unpackFinal(req);
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530876
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700877 if (rsvd)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700878 {
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530879 return responseInvalidFieldRequest();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700880 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530881
882 uint16_t vlan = static_cast<uint16_t>(vlanData);
883
884 if (!vlanEnable)
885 {
886 lastDisabledVlan[channel] = vlan;
887 vlan = 0;
888 }
Jayaprakash Mutyala0d1d7ad2024-06-19 10:19:33 +0000889 else if (vlan == 0 || vlan == VLAN_VALUE_MASK)
890 {
891 return responseInvalidFieldRequest();
892 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530893
jayaprakash Mutyala84c49dc2020-05-18 23:12:13 +0000894 channelCall<reconfigureVLAN>(channel, vlan);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700895 return responseSuccess();
896 }
897 case LanParam::CiphersuiteSupport:
898 case LanParam::CiphersuiteEntries:
William A. Kennington III16064aa2019-04-13 17:44:53 -0700899 case LanParam::IPFamilySupport:
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700900 {
901 req.trailingOk = true;
902 return response(ccParamReadOnly);
Ratan Guptab8e99552017-07-27 07:07:48 +0530903 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700904 case LanParam::IPFamilyEnables:
905 {
906 uint8_t enables;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700907 if (req.unpack(enables) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700908 {
909 return responseReqDataLenInvalid();
910 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700911 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700912 switch (static_cast<IPFamilyEnables>(enables))
913 {
914 case IPFamilyEnables::DualStack:
915 return responseSuccess();
916 case IPFamilyEnables::IPv4Only:
917 case IPFamilyEnables::IPv6Only:
918 return response(ccParamNotSupported);
919 }
920 return response(ccParamNotSupported);
921 }
922 case LanParam::IPv6Status:
923 {
924 req.trailingOk = true;
925 return response(ccParamReadOnly);
926 }
927 case LanParam::IPv6StaticAddresses:
928 {
929 uint8_t set;
930 uint7_t rsvd;
931 bool enabled;
William A. Kennington III16064aa2019-04-13 17:44:53 -0700932 uint8_t prefix;
933 uint8_t status;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700934 if (req.unpack(set, rsvd, enabled) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700935 {
936 return responseReqDataLenInvalid();
937 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700938 auto ip = unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700939 if (req.unpack(prefix, status) != 0)
940 {
941 return responseReqDataLenInvalid();
942 }
943 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800944 if (rsvd)
945 {
946 return responseInvalidFieldRequest();
947 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700948 if (enabled)
949 {
Jiaqing Zhao6d4a44e2022-01-24 15:04:00 +0800950 if (prefix < MIN_IPV6_PREFIX_LENGTH ||
951 prefix > MAX_IPV6_PREFIX_LENGTH)
952 {
953 return responseParmOutOfRange();
954 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700955 channelCall<reconfigureIfAddr6>(channel, set, ip, prefix);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700956 }
957 else
958 {
959 channelCall<deconfigureIfAddr6>(channel, set);
960 }
961 return responseSuccess();
962 }
963 case LanParam::IPv6DynamicAddresses:
964 {
965 req.trailingOk = true;
966 return response(ccParamReadOnly);
967 }
968 case LanParam::IPv6RouterControl:
969 {
970 std::bitset<8> control;
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800971 constexpr uint8_t reservedRACCBits = 0xfc;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700972 if (req.unpack(control) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700973 {
974 return responseReqDataLenInvalid();
975 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700976 unpackFinal(req);
Patrick Williams1318a5e2024-08-16 15:19:54 -0400977 if (std::bitset<8> expected(
978 control & std::bitset<8>(reservedRACCBits));
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800979 expected.any())
William A. Kennington III16064aa2019-04-13 17:44:53 -0700980 {
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800981 return response(ccParamNotSupported);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700982 }
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800983
984 bool enableRA = control[IPv6RouterControlFlag::Dynamic];
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700985 channelCall<setEthProp<bool>>(channel, "IPv6AcceptRA", enableRA);
986 channelCall<setEthProp<bool>>(channel, "DHCP6", enableRA);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700987 return responseSuccess();
988 }
989 case LanParam::IPv6StaticRouter1IP:
990 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700991 auto gateway = unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700992 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700993 channelCall<setGatewayProperty<AF_INET6>>(channel, gateway);
994 return responseSuccess();
995 }
996 case LanParam::IPv6StaticRouter1MAC:
997 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700998 auto mac = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700999 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001000 channelCall<reconfigureGatewayMAC<AF_INET6>>(channel, mac);
1001 return responseSuccess();
1002 }
1003 case LanParam::IPv6StaticRouter1PrefixLength:
1004 {
1005 uint8_t prefix;
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001006 if (req.unpack(prefix) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -07001007 {
1008 return responseReqDataLenInvalid();
1009 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001010 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001011 if (prefix != 0)
1012 {
1013 return responseInvalidFieldRequest();
1014 }
1015 return responseSuccess();
1016 }
1017 case LanParam::IPv6StaticRouter1PrefixValue:
1018 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001019 unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001020 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001021 // Accept any prefix value since our prefix length has to be 0
1022 return responseSuccess();
1023 }
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001024 case LanParam::cipherSuitePrivilegeLevels:
1025 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001026 uint8_t rsvd;
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001027 std::array<uint4_t, ipmi::maxCSRecords> cipherSuitePrivs;
1028
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001029 if (req.unpack(rsvd, cipherSuitePrivs))
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001030 {
1031 return responseReqDataLenInvalid();
1032 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001033 unpackFinal(req);
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001034
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001035 if (rsvd)
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001036 {
1037 return responseInvalidFieldRequest();
1038 }
1039
Patrick Williams1318a5e2024-08-16 15:19:54 -04001040 uint8_t resp =
1041 getCipherConfigObject(csPrivFileName, csPrivDefaultFileName)
1042 .setCSPrivilegeLevels(channel, cipherSuitePrivs);
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001043 if (!resp)
1044 {
1045 return responseSuccess();
1046 }
1047 else
1048 {
1049 req.trailingOk = true;
1050 return response(resp);
1051 }
1052 }
Ratan Guptab8e99552017-07-27 07:07:48 +05301053 }
vishwa1eaea4f2016-02-26 11:57:40 -06001054
PavanKumarIntel3771f5f2023-11-02 06:26:42 +00001055 if (parameter >= oemCmdStart)
Johnathan Manteyb87034e2019-09-16 10:50:50 -07001056 {
1057 return setLanOem(channel, parameter, req);
1058 }
1059
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001060 req.trailingOk = true;
1061 return response(ccParamNotSupported);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001062}
1063
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001064RspType<> setLan(Context::ptr ctx, uint4_t channelBits, uint4_t reserved1,
1065 uint8_t parameter, message::Payload& req)
1066{
1067 try
1068 {
1069 return setLanInt(ctx, channelBits, reserved1, parameter, req);
1070 }
1071 catch (ipmi::Cc cc)
1072 {
1073 return response(cc);
1074 }
1075 catch (const sdbusplus::exception_t& e)
1076 {
1077 if (std::string_view{InvalidArgument::errName} == e.name())
1078 {
1079 return responseInvalidFieldRequest();
1080 }
1081 throw;
1082 }
1083}
1084
vijayabharathix shettycc769252020-02-27 17:52:20 +00001085RspType<message::Payload> getLan(Context::ptr ctx, uint4_t channelBits,
1086 uint3_t reserved, bool revOnly,
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001087 uint8_t parameter, uint8_t set, uint8_t block)
Ratan Guptab8e99552017-07-27 07:07:48 +05301088{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001089 message::Payload ret;
1090 constexpr uint8_t current_revision = 0x11;
1091 ret.pack(current_revision);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001092
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001093 if (revOnly)
Suryakanth Sekare4054402019-08-08 15:16:52 +05301094 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001095 return responseSuccess(std::move(ret));
Suryakanth Sekare4054402019-08-08 15:16:52 +05301096 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001097
vijayabharathix shettycc769252020-02-27 17:52:20 +00001098 const uint8_t channel = convertCurrentChannelNum(
1099 static_cast<uint8_t>(channelBits), ctx->channel);
1100 if (reserved || !isValidChannel(channel))
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001101 {
George Liu32e8f5d2024-07-17 19:52:25 +08001102 lg2::error("Get Lan - Invalid field in request");
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001103 return responseInvalidFieldRequest();
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001104 }
1105
Jian Zhangcf19d142023-07-31 10:22:53 +08001106 if (!isLanChannel(channel).value_or(false))
1107 {
George Liu32e8f5d2024-07-17 19:52:25 +08001108 lg2::error("Set Lan - Not a LAN channel");
Jian Zhangcf19d142023-07-31 10:22:53 +08001109 return responseInvalidFieldRequest();
1110 }
1111
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001112 static std::vector<uint8_t> cipherList;
1113 static bool listInit = false;
1114 if (!listInit)
1115 {
1116 try
1117 {
1118 cipherList = cipher::getCipherList();
1119 listInit = true;
1120 }
1121 catch (const std::exception& e)
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -05001122 {}
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001123 }
1124
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001125 switch (static_cast<LanParam>(parameter))
Tom Josepha30c8d32018-03-22 02:15:03 +05301126 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001127 case LanParam::SetStatus:
Tom Josepha30c8d32018-03-22 02:15:03 +05301128 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001129 SetStatus status;
1130 try
1131 {
1132 status = setStatus.at(channel);
1133 }
1134 catch (const std::out_of_range&)
1135 {
1136 status = SetStatus::Complete;
1137 }
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001138 ret.pack(types::enum_cast<uint2_t>(status), uint6_t{});
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001139 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301140 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001141 case LanParam::AuthSupport:
Tom Josepha30c8d32018-03-22 02:15:03 +05301142 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001143 std::bitset<6> support;
1144 ret.pack(support, uint2_t{});
1145 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301146 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001147 case LanParam::AuthEnables:
vishwa1eaea4f2016-02-26 11:57:40 -06001148 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001149 std::bitset<6> enables;
1150 ret.pack(enables, uint2_t{}); // Callback
1151 ret.pack(enables, uint2_t{}); // User
1152 ret.pack(enables, uint2_t{}); // Operator
1153 ret.pack(enables, uint2_t{}); // Admin
1154 ret.pack(enables, uint2_t{}); // OEM
1155 return responseSuccess(std::move(ret));
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001156 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001157 case LanParam::IP:
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001158 {
1159 auto ifaddr = channelCall<getIfAddr4>(channel);
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001160 stdplus::In4Addr addr{};
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001161 if (ifaddr)
1162 {
1163 addr = ifaddr->address;
1164 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001165 ret.pack(stdplus::raw::asView<char>(addr));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001166 return responseSuccess(std::move(ret));
1167 }
1168 case LanParam::IPSrc:
1169 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001170 auto src = channelCall<getEthProp<bool>>(channel, "DHCP4")
1171 ? IPSrc::DHCP
1172 : IPSrc::Static;
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001173 ret.pack(types::enum_cast<uint4_t>(src), uint4_t{});
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001174 return responseSuccess(std::move(ret));
1175 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001176 case LanParam::MAC:
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001177 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001178 auto mac = channelCall<getMACProperty>(channel);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001179 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001180 return responseSuccess(std::move(ret));
1181 }
1182 case LanParam::SubnetMask:
1183 {
1184 auto ifaddr = channelCall<getIfAddr4>(channel);
1185 uint8_t prefix = AddrFamily<AF_INET>::defaultPrefix;
1186 if (ifaddr)
Ratan Guptab8e99552017-07-27 07:07:48 +05301187 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001188 prefix = ifaddr->prefix;
1189 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001190 auto netmask = stdplus::pfxToMask<stdplus::In4Addr>(prefix);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001191 ret.pack(stdplus::raw::asView<char>(netmask));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001192 return responseSuccess(std::move(ret));
1193 }
1194 case LanParam::Gateway1:
1195 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001196 auto gateway = channelCall<getGatewayProperty<AF_INET>>(channel);
1197 ret.pack(stdplus::raw::asView<char>(
1198 gateway.value_or(stdplus::In4Addr{})));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001199 return responseSuccess(std::move(ret));
1200 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001201 case LanParam::Gateway1MAC:
1202 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001203 stdplus::EtherAddr mac{};
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001204 auto neighbor = channelCall<getGatewayNeighbor<AF_INET>>(channel);
1205 if (neighbor)
1206 {
1207 mac = neighbor->mac;
1208 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001209 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001210 return responseSuccess(std::move(ret));
1211 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001212 case LanParam::VLANId:
1213 {
1214 uint16_t vlan = channelCall<getVLANProperty>(channel);
1215 if (vlan != 0)
1216 {
1217 vlan |= VLAN_ENABLE_FLAG;
Ratan Guptab8e99552017-07-27 07:07:48 +05301218 }
1219 else
1220 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001221 vlan = lastDisabledVlan[channel];
Ratan Guptab8e99552017-07-27 07:07:48 +05301222 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001223 ret.pack(vlan);
1224 return responseSuccess(std::move(ret));
Adriana Kobylak342df102016-02-10 13:48:16 -06001225 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001226 case LanParam::CiphersuiteSupport:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001227 {
srikanta mondal1d8579c2020-04-15 17:13:25 +00001228 if (getChannelSessionSupport(channel) ==
1229 EChannelSessSupported::none)
1230 {
1231 return responseInvalidFieldRequest();
1232 }
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001233 if (!listInit)
1234 {
1235 return responseUnspecifiedError();
1236 }
1237 ret.pack(static_cast<uint8_t>(cipherList.size() - 1));
1238 return responseSuccess(std::move(ret));
1239 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001240 case LanParam::CiphersuiteEntries:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001241 {
srikanta mondal1d8579c2020-04-15 17:13:25 +00001242 if (getChannelSessionSupport(channel) ==
1243 EChannelSessSupported::none)
1244 {
1245 return responseInvalidFieldRequest();
1246 }
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001247 if (!listInit)
1248 {
1249 return responseUnspecifiedError();
1250 }
1251 ret.pack(cipherList);
1252 return responseSuccess(std::move(ret));
1253 }
William A. Kennington III16064aa2019-04-13 17:44:53 -07001254 case LanParam::IPFamilySupport:
1255 {
1256 std::bitset<8> support;
1257 support[IPFamilySupportFlag::IPv6Only] = 0;
1258 support[IPFamilySupportFlag::DualStack] = 1;
1259 support[IPFamilySupportFlag::IPv6Alerts] = 1;
1260 ret.pack(support);
1261 return responseSuccess(std::move(ret));
1262 }
1263 case LanParam::IPFamilyEnables:
1264 {
1265 ret.pack(static_cast<uint8_t>(IPFamilyEnables::DualStack));
1266 return responseSuccess(std::move(ret));
1267 }
1268 case LanParam::IPv6Status:
1269 {
1270 ret.pack(MAX_IPV6_STATIC_ADDRESSES);
1271 ret.pack(MAX_IPV6_DYNAMIC_ADDRESSES);
1272 std::bitset<8> support;
1273 support[IPv6StatusFlag::DHCP] = 1;
1274 support[IPv6StatusFlag::SLAAC] = 1;
1275 ret.pack(support);
1276 return responseSuccess(std::move(ret));
1277 }
1278 case LanParam::IPv6StaticAddresses:
1279 {
1280 if (set >= MAX_IPV6_STATIC_ADDRESSES)
1281 {
1282 return responseParmOutOfRange();
1283 }
1284 getLanIPv6Address(ret, channel, set, originsV6Static);
1285 return responseSuccess(std::move(ret));
1286 }
1287 case LanParam::IPv6DynamicAddresses:
1288 {
1289 if (set >= MAX_IPV6_DYNAMIC_ADDRESSES)
1290 {
1291 return responseParmOutOfRange();
1292 }
1293 getLanIPv6Address(ret, channel, set, originsV6Dynamic);
1294 return responseSuccess(std::move(ret));
1295 }
1296 case LanParam::IPv6RouterControl:
1297 {
1298 std::bitset<8> control;
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001299 control[IPv6RouterControlFlag::Dynamic] =
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001300 channelCall<getEthProp<bool>>(channel, "IPv6AcceptRA");
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001301 control[IPv6RouterControlFlag::Static] = 1;
William A. Kennington III16064aa2019-04-13 17:44:53 -07001302 ret.pack(control);
1303 return responseSuccess(std::move(ret));
1304 }
1305 case LanParam::IPv6StaticRouter1IP:
1306 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001307 stdplus::In6Addr gateway{};
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001308 if (!channelCall<getEthProp<bool>>(channel, "IPv6AcceptRA"))
William A. Kennington III16064aa2019-04-13 17:44:53 -07001309 {
1310 gateway =
1311 channelCall<getGatewayProperty<AF_INET6>>(channel).value_or(
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001312 stdplus::In6Addr{});
William A. Kennington III16064aa2019-04-13 17:44:53 -07001313 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001314 ret.pack(stdplus::raw::asView<char>(gateway));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001315 return responseSuccess(std::move(ret));
1316 }
1317 case LanParam::IPv6StaticRouter1MAC:
1318 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001319 stdplus::EtherAddr mac{};
William A. Kennington III16064aa2019-04-13 17:44:53 -07001320 auto neighbor = channelCall<getGatewayNeighbor<AF_INET6>>(channel);
1321 if (neighbor)
1322 {
1323 mac = neighbor->mac;
1324 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001325 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001326 return responseSuccess(std::move(ret));
1327 }
1328 case LanParam::IPv6StaticRouter1PrefixLength:
1329 {
Jian Zhang796e8242024-02-01 14:07:34 +08001330 ret.pack(uint8_t{0});
William A. Kennington III16064aa2019-04-13 17:44:53 -07001331 return responseSuccess(std::move(ret));
1332 }
1333 case LanParam::IPv6StaticRouter1PrefixValue:
1334 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001335 ret.pack(stdplus::raw::asView<char>(stdplus::In6Addr{}));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001336 return responseSuccess(std::move(ret));
1337 }
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001338 case LanParam::cipherSuitePrivilegeLevels:
1339 {
1340 std::array<uint4_t, ipmi::maxCSRecords> csPrivilegeLevels;
1341
1342 uint8_t resp =
1343 getCipherConfigObject(csPrivFileName, csPrivDefaultFileName)
1344 .getCSPrivilegeLevels(channel, csPrivilegeLevels);
1345 if (!resp)
1346 {
1347 constexpr uint8_t reserved1 = 0x00;
1348 ret.pack(reserved1, csPrivilegeLevels);
1349 return responseSuccess(std::move(ret));
1350 }
1351 else
1352 {
1353 return response(resp);
1354 }
1355 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001356 }
1357
PavanKumarIntel3771f5f2023-11-02 06:26:42 +00001358 if (parameter >= oemCmdStart)
Johnathan Manteyb87034e2019-09-16 10:50:50 -07001359 {
1360 return getLanOem(channel, parameter, set, block);
1361 }
1362
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001363 return response(ccParamNotSupported);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001364}
1365
Jian Zhang23f44652022-03-17 17:13:10 +08001366constexpr const char* solInterface = "xyz.openbmc_project.Ipmi.SOL";
1367constexpr const char* solPath = "/xyz/openbmc_project/ipmi/sol/";
1368constexpr const uint16_t solDefaultPort = 623;
1369
1370RspType<> setSolConfParams(Context::ptr ctx, uint4_t channelBits,
Willy Tu11d68892022-01-20 10:37:34 -08001371 uint4_t /*reserved*/, uint8_t parameter,
Jian Zhang23f44652022-03-17 17:13:10 +08001372 message::Payload& req)
1373{
1374 const uint8_t channel = convertCurrentChannelNum(
1375 static_cast<uint8_t>(channelBits), ctx->channel);
1376
1377 if (!isValidChannel(channel))
1378 {
George Liu32e8f5d2024-07-17 19:52:25 +08001379 lg2::error("Set Sol Config - Invalid channel in request");
Jian Zhang23f44652022-03-17 17:13:10 +08001380 return responseInvalidFieldRequest();
1381 }
1382
1383 std::string solService{};
1384 std::string solPathWitheEthName = solPath + ipmi::getChannelName(channel);
1385
1386 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1387 {
George Liu32e8f5d2024-07-17 19:52:25 +08001388 lg2::error("Set Sol Config - Invalid solInterface, service: {SERVICE}, "
1389 "object path: {OBJPATH}, interface: {INTERFACE}",
1390 "SERVICE", solService, "OBJPATH", solPathWitheEthName,
1391 "INTERFACE", solInterface);
Jian Zhang23f44652022-03-17 17:13:10 +08001392 return responseInvalidFieldRequest();
1393 }
1394
1395 switch (static_cast<SolConfParam>(parameter))
1396 {
1397 case SolConfParam::Progress:
1398 {
1399 uint8_t progress;
1400 if (req.unpack(progress) != 0 || !req.fullyUnpacked())
1401 {
1402 return responseReqDataLenInvalid();
1403 }
1404
1405 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1406 solInterface, "Progress", progress))
1407 {
1408 return responseUnspecifiedError();
1409 }
1410 break;
1411 }
1412 case SolConfParam::Enable:
1413 {
1414 bool enable;
1415 uint7_t reserved2;
1416
1417 if (req.unpack(enable, reserved2) != 0 || !req.fullyUnpacked())
1418 {
1419 return responseReqDataLenInvalid();
1420 }
1421
1422 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1423 solInterface, "Enable", enable))
1424 {
1425 return responseUnspecifiedError();
1426 }
1427 break;
1428 }
1429 case SolConfParam::Authentication:
1430 {
1431 uint4_t privilegeBits{};
1432 uint2_t reserved2{};
1433 bool forceAuth = false;
1434 bool forceEncrypt = false;
1435
1436 if (req.unpack(privilegeBits, reserved2, forceAuth, forceEncrypt) !=
1437 0 ||
1438 !req.fullyUnpacked())
1439 {
1440 return responseReqDataLenInvalid();
1441 }
1442
1443 uint8_t privilege = static_cast<uint8_t>(privilegeBits);
Jonathan Domana48bf772023-05-26 17:54:57 -07001444 if (privilege < static_cast<uint8_t>(Privilege::User) ||
Jian Zhang23f44652022-03-17 17:13:10 +08001445 privilege > static_cast<uint8_t>(Privilege::Oem))
1446 {
1447 return ipmi::responseInvalidFieldRequest();
1448 }
1449
1450 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1451 solInterface, "Privilege", privilege))
1452 {
1453 return responseUnspecifiedError();
1454 }
1455
1456 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1457 solInterface, "ForceEncryption",
1458 forceEncrypt))
1459 {
1460 return responseUnspecifiedError();
1461 }
1462
1463 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1464 solInterface, "ForceAuthentication",
1465 forceAuth))
1466 {
1467 return responseUnspecifiedError();
1468 }
1469 break;
1470 }
1471 case SolConfParam::Accumulate:
1472 {
1473 uint8_t interval;
1474 uint8_t threshold;
1475 if (req.unpack(interval, threshold) != 0 || !req.fullyUnpacked())
1476 {
1477 return responseReqDataLenInvalid();
1478 }
1479
1480 if (threshold == 0)
1481 {
1482 return responseInvalidFieldRequest();
1483 }
1484
1485 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1486 solInterface, "AccumulateIntervalMS",
1487 interval))
1488 {
1489 return responseUnspecifiedError();
1490 }
1491
1492 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1493 solInterface, "Threshold", threshold))
1494 {
1495 return responseUnspecifiedError();
1496 }
1497 break;
1498 }
1499 case SolConfParam::Retry:
1500 {
1501 uint3_t countBits;
1502 uint5_t reserved2;
1503 uint8_t interval;
1504
1505 if (req.unpack(countBits, reserved2, interval) != 0 ||
1506 !req.fullyUnpacked())
1507 {
1508 return responseReqDataLenInvalid();
1509 }
1510
1511 uint8_t count = static_cast<uint8_t>(countBits);
1512 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1513 solInterface, "RetryCount", count))
1514 {
1515 return responseUnspecifiedError();
1516 }
1517
1518 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1519 solInterface, "RetryIntervalMS",
1520 interval))
1521 {
1522 return responseUnspecifiedError();
1523 }
1524 break;
1525 }
1526 case SolConfParam::Port:
1527 {
1528 return response(ipmiCCWriteReadParameter);
1529 }
1530 case SolConfParam::NonVbitrate:
1531 case SolConfParam::Vbitrate:
1532 case SolConfParam::Channel:
1533 default:
1534 return response(ipmiCCParamNotSupported);
1535 }
1536 return responseSuccess();
1537}
1538
Patrick Williams1318a5e2024-08-16 15:19:54 -04001539RspType<message::Payload> getSolConfParams(
1540 Context::ptr ctx, uint4_t channelBits, uint3_t /*reserved*/, bool revOnly,
1541 uint8_t parameter, uint8_t /*set*/, uint8_t /*block*/)
Jian Zhang23f44652022-03-17 17:13:10 +08001542{
1543 message::Payload ret;
1544 constexpr uint8_t current_revision = 0x11;
1545 ret.pack(current_revision);
1546 if (revOnly)
1547 {
1548 return responseSuccess(std::move(ret));
1549 }
1550
1551 const uint8_t channel = convertCurrentChannelNum(
1552 static_cast<uint8_t>(channelBits), ctx->channel);
1553
1554 if (!isValidChannel(channel))
1555 {
George Liu32e8f5d2024-07-17 19:52:25 +08001556 lg2::error("Get Sol Config - Invalid channel in request");
Jian Zhang23f44652022-03-17 17:13:10 +08001557 return responseInvalidFieldRequest();
1558 }
1559
1560 std::string solService{};
1561 std::string solPathWitheEthName = solPath + ipmi::getChannelName(channel);
1562
1563 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1564 {
George Liu32e8f5d2024-07-17 19:52:25 +08001565 lg2::error("Set Sol Config - Invalid solInterface, service: {SERVICE}, "
1566 "object path: {OBJPATH}, interface: {INTERFACE}",
1567 "SERVICE", solService, "OBJPATH", solPathWitheEthName,
1568 "INTERFACE", solInterface);
Jian Zhang23f44652022-03-17 17:13:10 +08001569 return responseInvalidFieldRequest();
1570 }
1571
1572 switch (static_cast<SolConfParam>(parameter))
1573 {
1574 case SolConfParam::Progress:
1575 {
1576 uint8_t progress;
1577 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1578 solInterface, "Progress", progress))
1579 {
1580 return responseUnspecifiedError();
1581 }
1582 ret.pack(progress);
1583 return responseSuccess(std::move(ret));
1584 }
1585 case SolConfParam::Enable:
1586 {
1587 bool enable{};
1588 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1589 solInterface, "Enable", enable))
1590 {
1591 return responseUnspecifiedError();
1592 }
1593 ret.pack(enable, uint7_t{});
1594 return responseSuccess(std::move(ret));
1595 }
1596 case SolConfParam::Authentication:
1597 {
1598 // 4bits, cast when pack
1599 uint8_t privilege;
1600 bool forceAuth = false;
1601 bool forceEncrypt = false;
1602
1603 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1604 solInterface, "Privilege", privilege))
1605 {
1606 return responseUnspecifiedError();
1607 }
1608
1609 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1610 solInterface, "ForceAuthentication",
1611 forceAuth))
1612 {
1613 return responseUnspecifiedError();
1614 }
1615
1616 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1617 solInterface, "ForceEncryption",
1618 forceEncrypt))
1619 {
1620 return responseUnspecifiedError();
1621 }
1622 ret.pack(uint4_t{privilege}, uint2_t{}, forceAuth, forceEncrypt);
1623 return responseSuccess(std::move(ret));
1624 }
1625 case SolConfParam::Accumulate:
1626 {
1627 uint8_t interval{}, threshold{};
1628
1629 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1630 solInterface, "AccumulateIntervalMS",
1631 interval))
1632 {
1633 return responseUnspecifiedError();
1634 }
1635
1636 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1637 solInterface, "Threshold", threshold))
1638 {
1639 return responseUnspecifiedError();
1640 }
1641 ret.pack(interval, threshold);
1642 return responseSuccess(std::move(ret));
1643 }
1644 case SolConfParam::Retry:
1645 {
1646 // 3bits, cast when cast
1647 uint8_t count{};
1648 uint8_t interval{};
1649
1650 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1651 solInterface, "RetryCount", count))
1652 {
1653 return responseUnspecifiedError();
1654 }
1655
1656 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1657 solInterface, "RetryIntervalMS",
1658 interval))
1659 {
1660 return responseUnspecifiedError();
1661 }
1662 ret.pack(uint3_t{count}, uint5_t{}, interval);
1663 return responseSuccess(std::move(ret));
1664 }
1665 case SolConfParam::Port:
1666 {
1667 auto port = solDefaultPort;
1668 ret.pack(static_cast<uint16_t>(port));
1669 return responseSuccess(std::move(ret));
1670 }
1671 case SolConfParam::Channel:
1672 {
1673 ret.pack(channel);
1674 return responseSuccess(std::move(ret));
1675 }
1676 case SolConfParam::NonVbitrate:
Jonathan Domana48bf772023-05-26 17:54:57 -07001677 {
1678 uint64_t baudRate;
1679 uint8_t encodedBitRate = 0;
1680 if (ipmi::getDbusProperty(
1681 ctx, "xyz.openbmc_project.Console.default",
1682 "/xyz/openbmc_project/console/default",
1683 "xyz.openbmc_project.Console.UART", "Baud", baudRate))
1684 {
1685 return ipmi::responseUnspecifiedError();
1686 }
1687 switch (baudRate)
1688 {
1689 case 9600:
1690 encodedBitRate = 0x06;
1691 break;
1692 case 19200:
1693 encodedBitRate = 0x07;
1694 break;
1695 case 38400:
1696 encodedBitRate = 0x08;
1697 break;
1698 case 57600:
1699 encodedBitRate = 0x09;
1700 break;
1701 case 115200:
1702 encodedBitRate = 0x0a;
1703 break;
1704 default:
1705 break;
1706 }
1707 ret.pack(encodedBitRate);
1708 return responseSuccess(std::move(ret));
1709 }
Jian Zhang23f44652022-03-17 17:13:10 +08001710 case SolConfParam::Vbitrate:
1711 default:
1712 return response(ipmiCCParamNotSupported);
1713 }
1714
1715 return response(ccParamNotSupported);
1716}
1717
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001718} // namespace transport
1719} // namespace ipmi
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301720
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001721void register_netfn_transport_functions() __attribute__((constructor));
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301722
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001723void register_netfn_transport_functions()
1724{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001725 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1726 ipmi::transport::cmdSetLanConfigParameters,
1727 ipmi::Privilege::Admin, ipmi::transport::setLan);
1728 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1729 ipmi::transport::cmdGetLanConfigParameters,
Johnathan Mantey34698d52019-11-19 14:47:30 -08001730 ipmi::Privilege::Operator, ipmi::transport::getLan);
Jian Zhang23f44652022-03-17 17:13:10 +08001731 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1732 ipmi::transport::cmdSetSolConfigParameters,
1733 ipmi::Privilege::Admin,
1734 ipmi::transport::setSolConfParams);
1735 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1736 ipmi::transport::cmdGetSolConfigParameters,
1737 ipmi::Privilege::User,
1738 ipmi::transport::getSolConfParams);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001739}