blob: 24b84c0c222e204c930226ae0f14d57cb4b8634c [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::commit;
12using phosphor::logging::elog;
13using phosphor::logging::entry;
14using phosphor::logging::level;
15using phosphor::logging::log;
Willy Tu523e2d12023-09-05 11:36:48 -070016using sdbusplus::error::xyz::openbmc_project::common::InternalFailure;
William A. Kennington III7a3831b2023-06-21 01:10:49 -070017using sdbusplus::error::xyz::openbmc_project::common::InvalidArgument;
Willy Tu523e2d12023-09-05 11:36:48 -070018using sdbusplus::server::xyz::openbmc_project::network::EthernetInterface;
19using sdbusplus::server::xyz::openbmc_project::network::IP;
20using sdbusplus::server::xyz::openbmc_project::network::Neighbor;
William A. Kennington IIIc514d872019-04-06 18:19:38 -070021
Johnathan Manteyaffadb52019-10-07 10:13:53 -070022namespace cipher
23{
24
25std::vector<uint8_t> getCipherList()
26{
27 std::vector<uint8_t> cipherList;
28
29 std::ifstream jsonFile(cipher::configFile);
30 if (!jsonFile.is_open())
31 {
George Liu32e8f5d2024-07-17 19:52:25 +080032 lg2::error("Channel Cipher suites file not found");
Johnathan Manteyaffadb52019-10-07 10:13:53 -070033 elog<InternalFailure>();
34 }
35
36 auto data = Json::parse(jsonFile, nullptr, false);
37 if (data.is_discarded())
38 {
George Liu32e8f5d2024-07-17 19:52:25 +080039 lg2::error("Parsing channel cipher suites JSON failed");
Johnathan Manteyaffadb52019-10-07 10:13:53 -070040 elog<InternalFailure>();
41 }
42
43 // Byte 1 is reserved
44 cipherList.push_back(0x00);
45
46 for (const auto& record : data)
47 {
48 cipherList.push_back(record.value(cipher, 0));
49 }
50
51 return cipherList;
52}
53} // namespace cipher
54
55namespace ipmi
56{
57namespace transport
58{
59
William A. Kennington IIIc514d872019-04-06 18:19:38 -070060/** @brief Valid address origins for IPv4 */
61const std::unordered_set<IP::AddressOrigin> originsV4 = {
62 IP::AddressOrigin::Static,
63 IP::AddressOrigin::DHCP,
64};
65
Johnathan Manteyb87034e2019-09-16 10:50:50 -070066static constexpr uint8_t oemCmdStart = 192;
Johnathan Manteyb87034e2019-09-16 10:50:50 -070067
William A. Kennington IIIc72f3602023-10-19 03:51:37 -070068// Checks if the ifname is part of the networkd path
69// This assumes the path came from the network subtree PATH_ROOT
70bool ifnameInPath(std::string_view ifname, std::string_view path)
71{
72 constexpr auto rs = PATH_ROOT.size() + 1; // ROOT + separator
73 const auto is = rs + ifname.size(); // ROOT + sep + ifname
74 return path.size() > rs && path.substr(rs).starts_with(ifname) &&
75 (path.size() == is || path[is] == '/');
76}
77
Patrick Williams5d82f472022-07-22 19:26:53 -050078std::optional<ChannelParams> maybeGetChannelParams(sdbusplus::bus_t& bus,
William A. Kennington IIIc514d872019-04-06 18:19:38 -070079 uint8_t channel)
80{
81 auto ifname = getChannelName(channel);
82 if (ifname.empty())
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080083 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -070084 return std::nullopt;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080085 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080086
William A. Kennington IIIc514d872019-04-06 18:19:38 -070087 // Enumerate all VLAN + ETHERNET interfaces
George Liuc1c7eac2024-02-04 17:24:19 +080088 std::vector<std::string> interfaces = {INTF_VLAN, INTF_ETHERNET};
89 ipmi::ObjectTree objs = ipmi::getSubTree(bus, interfaces,
90 std::string{PATH_ROOT});
William A. Kennington IIIc514d872019-04-06 18:19:38 -070091
92 ChannelParams params;
93 for (const auto& [path, impls] : objs)
94 {
William A. Kennington IIIc72f3602023-10-19 03:51:37 -070095 if (!ifnameInPath(ifname, path))
William A. Kennington IIIc514d872019-04-06 18:19:38 -070096 {
97 continue;
98 }
99 for (const auto& [service, intfs] : impls)
100 {
101 bool vlan = false;
102 bool ethernet = false;
103 for (const auto& intf : intfs)
104 {
105 if (intf == INTF_VLAN)
106 {
107 vlan = true;
108 }
109 else if (intf == INTF_ETHERNET)
110 {
111 ethernet = true;
112 }
113 }
114 if (params.service.empty() && (vlan || ethernet))
115 {
116 params.service = service;
117 }
118 if (params.ifPath.empty() && !vlan && ethernet)
119 {
120 params.ifPath = path;
121 }
122 if (params.logicalPath.empty() && vlan)
123 {
124 params.logicalPath = path;
125 }
126 }
127 }
128
129 // We must have a path for the underlying interface
130 if (params.ifPath.empty())
131 {
132 return std::nullopt;
133 }
134 // We don't have a VLAN so the logical path is the same
135 if (params.logicalPath.empty())
136 {
137 params.logicalPath = params.ifPath;
138 }
139
140 params.id = channel;
141 params.ifname = std::move(ifname);
Willy Tu11d68892022-01-20 10:37:34 -0800142 return params;
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700143}
144
Patrick Williams5d82f472022-07-22 19:26:53 -0500145ChannelParams getChannelParams(sdbusplus::bus_t& bus, uint8_t channel)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700146{
147 auto params = maybeGetChannelParams(bus, channel);
148 if (!params)
149 {
George Liu32e8f5d2024-07-17 19:52:25 +0800150 lg2::error("Failed to get channel params: {CHANNEL}", "CHANNEL",
151 channel);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700152 elog<InternalFailure>();
153 }
154 return std::move(*params);
155}
156
157/** @brief Wraps the phosphor logging method to insert some additional metadata
158 *
159 * @param[in] params - The parameters for the channel
160 * ...
161 */
162template <auto level, typename... Args>
163auto logWithChannel(const ChannelParams& params, Args&&... args)
164{
165 return log<level>(std::forward<Args>(args)...,
166 entry("CHANNEL=%d", params.id),
167 entry("IFNAME=%s", params.ifname.c_str()));
168}
169template <auto level, typename... Args>
170auto logWithChannel(const std::optional<ChannelParams>& params, Args&&... args)
171{
172 if (params)
173 {
174 return logWithChannel<level>(*params, std::forward<Args>(args)...);
175 }
176 return log<level>(std::forward<Args>(args)...);
177}
178
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700179/** @brief Get / Set the Property value from phosphor-networkd EthernetInterface
180 */
181template <typename T>
182static T getEthProp(sdbusplus::bus_t& bus, const ChannelParams& params,
183 const std::string& prop)
184{
185 return std::get<T>(getDbusProperty(bus, params.service, params.logicalPath,
186 INTF_ETHERNET, prop));
187}
188template <typename T>
189static void setEthProp(sdbusplus::bus_t& bus, const ChannelParams& params,
190 const std::string& prop, const T& t)
191{
192 return setDbusProperty(bus, params.service, params.logicalPath,
193 INTF_ETHERNET, prop, t);
194}
195
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700196/** @brief Determines the MAC of the ethernet interface
197 *
198 * @param[in] bus - The bus object used for lookups
199 * @param[in] params - The parameters for the channel
200 * @return The configured mac address
201 */
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700202stdplus::EtherAddr getMACProperty(sdbusplus::bus_t& bus,
203 const ChannelParams& params)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700204{
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700205 auto prop = getDbusProperty(bus, params.service, params.ifPath, INTF_MAC,
206 "MACAddress");
207 return stdplus::fromStr<stdplus::EtherAddr>(std::get<std::string>(prop));
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700208}
209
210/** @brief Sets the system value for MAC address on the given interface
211 *
212 * @param[in] bus - The bus object used for lookups
213 * @param[in] params - The parameters for the channel
214 * @param[in] mac - MAC address to apply
215 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500216void setMACProperty(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700217 stdplus::EtherAddr mac)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700218{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700219 setDbusProperty(bus, params.service, params.ifPath, INTF_MAC, "MACAddress",
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700220 stdplus::toStr(mac));
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700221}
222
Patrick Williams5d82f472022-07-22 19:26:53 -0500223void deleteObjectIfExists(sdbusplus::bus_t& bus, const std::string& service,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700224 const std::string& path)
225{
226 if (path.empty())
227 {
228 return;
229 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530230 try
tomjose26e17732016-03-03 08:52:51 -0600231 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700232 auto req = bus.new_method_call(service.c_str(), path.c_str(),
233 ipmi::DELETE_INTERFACE, "Delete");
234 bus.call_noreply(req);
235 }
Patrick Williams5d82f472022-07-22 19:26:53 -0500236 catch (const sdbusplus::exception_t& e)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700237 {
jayaprakash Mutyala84c49dc2020-05-18 23:12:13 +0000238 if (strcmp(e.name(),
239 "xyz.openbmc_project.Common.Error.InternalFailure") != 0 &&
240 strcmp(e.name(), "org.freedesktop.DBus.Error.UnknownObject") != 0)
tomjose26e17732016-03-03 08:52:51 -0600241 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700242 // We want to rethrow real errors
243 throw;
tomjose26e17732016-03-03 08:52:51 -0600244 }
245 }
tomjose26e17732016-03-03 08:52:51 -0600246}
247
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700248/** @brief Sets the address info configured for the interface
249 * If a previous address path exists then it will be removed
250 * before the new address is added.
251 *
252 * @param[in] bus - The bus object used for lookups
253 * @param[in] params - The parameters for the channel
254 * @param[in] address - The address of the new IP
255 * @param[in] prefix - The prefix of the new IP
256 */
257template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500258void createIfAddr(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700259 typename AddrFamily<family>::addr address, uint8_t prefix)
Tom Josepha30c8d32018-03-22 02:15:03 +0530260{
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500261 auto newreq = bus.new_method_call(params.service.c_str(),
262 params.logicalPath.c_str(),
263 INTF_IP_CREATE, "IP");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700264 std::string protocol =
Willy Tu523e2d12023-09-05 11:36:48 -0700265 sdbusplus::common::xyz::openbmc_project::network::convertForMessage(
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700266 AddrFamily<family>::protocol);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700267 stdplus::ToStrHandle<stdplus::ToStr<typename AddrFamily<family>::addr>> tsh;
268 newreq.append(protocol, tsh(address), prefix, "");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700269 bus.call_noreply(newreq);
270}
Tom Josepha30c8d32018-03-22 02:15:03 +0530271
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700272/** @brief Trivial helper for getting the IPv4 address from getIfAddrs()
273 *
274 * @param[in] bus - The bus object used for lookups
275 * @param[in] params - The parameters for the channel
276 * @return The address and prefix if found
277 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500278auto getIfAddr4(sdbusplus::bus_t& bus, const ChannelParams& params)
Tom Josepha30c8d32018-03-22 02:15:03 +0530279{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700280 return getIfAddr<AF_INET>(bus, params, 0, originsV4);
281}
Tom Josepha30c8d32018-03-22 02:15:03 +0530282
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700283/** @brief Reconfigures the IPv4 address info configured for the interface
284 *
285 * @param[in] bus - The bus object used for lookups
286 * @param[in] params - The parameters for the channel
287 * @param[in] address - The new address if specified
288 * @param[in] prefix - The new address prefix if specified
289 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500290void reconfigureIfAddr4(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700291 std::optional<stdplus::In4Addr> address,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700292 std::optional<uint8_t> prefix)
293{
294 auto ifaddr = getIfAddr4(bus, params);
295 if (!ifaddr && !address)
Tom Josepha30c8d32018-03-22 02:15:03 +0530296 {
George Liu32e8f5d2024-07-17 19:52:25 +0800297 lg2::error("Missing address for IPv4 assignment");
Tom Josepha30c8d32018-03-22 02:15:03 +0530298 elog<InternalFailure>();
299 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700300 uint8_t fallbackPrefix = AddrFamily<AF_INET>::defaultPrefix;
301 if (ifaddr)
Tom Josepha30c8d32018-03-22 02:15:03 +0530302 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700303 fallbackPrefix = ifaddr->prefix;
304 deleteObjectIfExists(bus, params.service, ifaddr->path);
305 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700306 auto addr = address.value_or(ifaddr->address);
307 if (addr != stdplus::In4Addr{})
Johnathan Manteycbfa6e12023-06-01 06:57:25 -0700308 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700309 createIfAddr<AF_INET>(bus, params, addr,
Johnathan Manteycbfa6e12023-06-01 06:57:25 -0700310 prefix.value_or(fallbackPrefix));
311 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700312}
313
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700314template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500315std::optional<IfNeigh<family>> findGatewayNeighbor(sdbusplus::bus_t& bus,
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700316 const ChannelParams& params,
317 ObjectLookupCache& neighbors)
318{
319 auto gateway = getGatewayProperty<family>(bus, params);
320 if (!gateway)
321 {
322 return std::nullopt;
323 }
324
325 return findStaticNeighbor<family>(bus, params, *gateway, neighbors);
326}
327
328template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500329std::optional<IfNeigh<family>> getGatewayNeighbor(sdbusplus::bus_t& bus,
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700330 const ChannelParams& params)
331{
332 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
333 return findGatewayNeighbor<family>(bus, params, neighbors);
334}
335
336template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500337void reconfigureGatewayMAC(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700338 stdplus::EtherAddr mac)
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700339{
340 auto gateway = getGatewayProperty<family>(bus, params);
341 if (!gateway)
342 {
George Liu32e8f5d2024-07-17 19:52:25 +0800343 lg2::error("Tried to set Gateway MAC without Gateway");
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700344 elog<InternalFailure>();
345 }
346
347 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500348 auto neighbor = findStaticNeighbor<family>(bus, params, *gateway,
349 neighbors);
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700350 if (neighbor)
351 {
352 deleteObjectIfExists(bus, params.service, neighbor->path);
353 }
354
355 createNeighbor<family>(bus, params, *gateway, mac);
356}
357
William A. Kennington III16064aa2019-04-13 17:44:53 -0700358/** @brief Deconfigures the IPv6 address info configured for the interface
359 *
360 * @param[in] bus - The bus object used for lookups
361 * @param[in] params - The parameters for the channel
362 * @param[in] idx - The address index to operate on
363 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500364void deconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III16064aa2019-04-13 17:44:53 -0700365 uint8_t idx)
366{
367 auto ifaddr = getIfAddr<AF_INET6>(bus, params, idx, originsV6Static);
368 if (ifaddr)
369 {
370 deleteObjectIfExists(bus, params.service, ifaddr->path);
371 }
372}
373
374/** @brief Reconfigures the IPv6 address info configured for the interface
375 *
376 * @param[in] bus - The bus object used for lookups
377 * @param[in] params - The parameters for the channel
378 * @param[in] idx - The address index to operate on
379 * @param[in] address - The new address
380 * @param[in] prefix - The new address prefix
381 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500382void reconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700383 uint8_t idx, stdplus::In6Addr address, uint8_t prefix)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700384{
385 deconfigureIfAddr6(bus, params, idx);
386 createIfAddr<AF_INET6>(bus, params, address, prefix);
387}
388
389/** @brief Converts the AddressOrigin into an IPv6Source
390 *
391 * @param[in] origin - The DBus Address Origin to convert
392 * @return The IPv6Source version of the origin
393 */
394IPv6Source originToSourceType(IP::AddressOrigin origin)
395{
396 switch (origin)
397 {
398 case IP::AddressOrigin::Static:
399 return IPv6Source::Static;
400 case IP::AddressOrigin::DHCP:
401 return IPv6Source::DHCP;
402 case IP::AddressOrigin::SLAAC:
403 return IPv6Source::SLAAC;
404 default:
405 {
Willy Tu523e2d12023-09-05 11:36:48 -0700406 auto originStr = sdbusplus::common::xyz::openbmc_project::network::
William A. Kennington III16064aa2019-04-13 17:44:53 -0700407 convertForMessage(origin);
George Liu32e8f5d2024-07-17 19:52:25 +0800408 lg2::error("Invalid IP::AddressOrigin conversion to IPv6Source, "
409 "origin: {ORIGIN}",
410 "ORIGIN", originStr);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700411 elog<InternalFailure>();
412 }
413 }
414}
415
416/** @brief Packs the IPMI message response with IPv6 address data
417 *
418 * @param[out] ret - The IPMI response payload to be packed
419 * @param[in] channel - The channel id corresponding to an ethernet interface
420 * @param[in] set - The set selector for determining address index
421 * @param[in] origins - Set of valid origins for address filtering
422 */
423void getLanIPv6Address(message::Payload& ret, uint8_t channel, uint8_t set,
424 const std::unordered_set<IP::AddressOrigin>& origins)
425{
426 auto source = IPv6Source::Static;
427 bool enabled = false;
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700428 stdplus::In6Addr addr{};
Johnathan Mantey5aae0922021-10-21 13:05:36 -0700429 uint8_t prefix{};
William A. Kennington III16064aa2019-04-13 17:44:53 -0700430 auto status = IPv6AddressStatus::Disabled;
431
432 auto ifaddr = channelCall<getIfAddr<AF_INET6>>(channel, set, origins);
433 if (ifaddr)
434 {
435 source = originToSourceType(ifaddr->origin);
Johnathan Mantey846af862021-10-21 12:48:54 -0700436 enabled = (origins == originsV6Static);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700437 addr = ifaddr->address;
438 prefix = ifaddr->prefix;
439 status = IPv6AddressStatus::Active;
440 }
441
442 ret.pack(set);
William A. Kennington III7a0e5df2021-05-19 13:31:29 -0700443 ret.pack(types::enum_cast<uint4_t>(source), uint3_t{}, enabled);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700444 ret.pack(stdplus::raw::asView<char>(addr));
William A. Kennington III16064aa2019-04-13 17:44:53 -0700445 ret.pack(prefix);
William A. Kennington III7a0e5df2021-05-19 13:31:29 -0700446 ret.pack(types::enum_cast<uint8_t>(status));
William A. Kennington III16064aa2019-04-13 17:44:53 -0700447}
448
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700449/** @brief Gets the vlan ID configured on the interface
450 *
451 * @param[in] bus - The bus object used for lookups
452 * @param[in] params - The parameters for the channel
453 * @return VLAN id or the standard 0 for no VLAN
454 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500455uint16_t getVLANProperty(sdbusplus::bus_t& bus, const ChannelParams& params)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700456{
457 // VLAN devices will always have a separate logical object
458 if (params.ifPath == params.logicalPath)
459 {
460 return 0;
461 }
462
463 auto vlan = std::get<uint32_t>(getDbusProperty(
464 bus, params.service, params.logicalPath, INTF_VLAN, "Id"));
465 if ((vlan & VLAN_VALUE_MASK) != vlan)
466 {
467 logWithChannel<level::ERR>(params, "networkd returned an invalid vlan",
468 entry("VLAN=%" PRIu32, vlan));
Tom Josepha30c8d32018-03-22 02:15:03 +0530469 elog<InternalFailure>();
470 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700471 return vlan;
Tom Josepha30c8d32018-03-22 02:15:03 +0530472}
473
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700474/** @brief Deletes all of the possible configuration parameters for a channel
475 *
476 * @param[in] bus - The bus object used for lookups
477 * @param[in] params - The parameters for the channel
478 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500479void deconfigureChannel(sdbusplus::bus_t& bus, ChannelParams& params)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500480{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700481 // Delete all objects associated with the interface
George Liuc1c7eac2024-02-04 17:24:19 +0800482 ObjectTree objs =
483 ipmi::getSubTree(bus, std::vector<std::string>{DELETE_INTERFACE},
484 std::string{PATH_ROOT});
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700485 for (const auto& [path, impls] : objs)
486 {
William A. Kennington IIIc72f3602023-10-19 03:51:37 -0700487 if (!ifnameInPath(params.ifname, path))
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700488 {
489 continue;
490 }
491 for (const auto& [service, intfs] : impls)
492 {
493 deleteObjectIfExists(bus, service, path);
494 }
495 // Update params to reflect the deletion of vlan
496 if (path == params.logicalPath)
497 {
498 params.logicalPath = params.ifPath;
499 }
500 }
501
502 // Clear out any settings on the lower physical interface
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700503 setEthProp(bus, params, "DHCP4", false);
504 setEthProp(bus, params, "DHCP6", false);
505 setEthProp(bus, params, "IPv6AcceptRA", false);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500506}
507
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700508/** @brief Creates a new VLAN on the specified interface
509 *
510 * @param[in] bus - The bus object used for lookups
511 * @param[in] params - The parameters for the channel
512 * @param[in] vlan - The id of the new vlan
513 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500514void createVLAN(sdbusplus::bus_t& bus, ChannelParams& params, uint16_t vlan)
Ratan Guptab8e99552017-07-27 07:07:48 +0530515{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700516 if (vlan == 0)
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530517 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700518 return;
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530519 }
520
William A. Kennington IIIc72f3602023-10-19 03:51:37 -0700521 auto req = bus.new_method_call(params.service.c_str(), PATH_ROOT.c_str(),
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700522 INTF_VLAN_CREATE, "VLAN");
523 req.append(params.ifname, static_cast<uint32_t>(vlan));
524 auto reply = bus.call(req);
525 sdbusplus::message::object_path newPath;
526 reply.read(newPath);
527 params.logicalPath = std::move(newPath);
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530528}
529
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700530/** @brief Performs the necessary reconfiguration to change the VLAN
531 *
532 * @param[in] bus - The bus object used for lookups
533 * @param[in] params - The parameters for the channel
534 * @param[in] vlan - The new vlan id to use
535 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500536void reconfigureVLAN(sdbusplus::bus_t& bus, ChannelParams& params,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700537 uint16_t vlan)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500538{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700539 // Unfortunatetly we don't have built-in functions to migrate our interface
540 // customizations to new VLAN interfaces, or have some kind of decoupling.
541 // We therefore must retain all of our old information, setup the new VLAN
542 // configuration, then restore the old info.
Nan Li3d0df912016-10-18 19:51:41 +0800543
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700544 // Save info from the old logical interface
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700545 bool dhcp4 = getEthProp<bool>(bus, params, "DHCP4");
546 bool dhcp6 = getEthProp<bool>(bus, params, "DHCP6");
547 bool ra = getEthProp<bool>(bus, params, "IPv6AcceptRA");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700548 ObjectLookupCache ips(bus, params, INTF_IP);
549 auto ifaddr4 = findIfAddr<AF_INET>(bus, params, 0, originsV4, ips);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700550 std::vector<IfAddr<AF_INET6>> ifaddrs6;
551 for (uint8_t i = 0; i < MAX_IPV6_STATIC_ADDRESSES; ++i)
552 {
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500553 auto ifaddr6 = findIfAddr<AF_INET6>(bus, params, i, originsV6Static,
554 ips);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700555 if (!ifaddr6)
556 {
557 break;
558 }
559 ifaddrs6.push_back(std::move(*ifaddr6));
560 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700561 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
562 auto neighbor4 = findGatewayNeighbor<AF_INET>(bus, params, neighbors);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700563 auto neighbor6 = findGatewayNeighbor<AF_INET6>(bus, params, neighbors);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500564
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700565 deconfigureChannel(bus, params);
566 createVLAN(bus, params, vlan);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500567
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700568 // Re-establish the saved settings
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700569 setEthProp(bus, params, "DHCP4", dhcp4);
570 setEthProp(bus, params, "DHCP6", dhcp6);
571 setEthProp(bus, params, "IPv6AcceptRA", ra);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700572 if (ifaddr4)
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800573 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700574 createIfAddr<AF_INET>(bus, params, ifaddr4->address, ifaddr4->prefix);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800575 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700576 for (const auto& ifaddr6 : ifaddrs6)
577 {
578 createIfAddr<AF_INET6>(bus, params, ifaddr6.address, ifaddr6.prefix);
579 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700580 if (neighbor4)
581 {
582 createNeighbor<AF_INET>(bus, params, neighbor4->ip, neighbor4->mac);
583 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700584 if (neighbor6)
585 {
586 createNeighbor<AF_INET6>(bus, params, neighbor6->ip, neighbor6->mac);
587 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700588}
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800589
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700590// We need to store this value so it can be returned to the client
591// It is volatile so safe to store in daemon memory.
592static std::unordered_map<uint8_t, SetStatus> setStatus;
593
594// Until we have good support for fixed versions of IPMI tool
595// we need to return the VLAN id for disabled VLANs. The value is only
596// used for verification that a disable operation succeeded and will only
597// be sent if our system indicates that vlans are disabled.
598static std::unordered_map<uint8_t, uint16_t> lastDisabledVlan;
599
600/** @brief Gets the set status for the channel if it exists
601 * Otherise populates and returns the default value.
602 *
603 * @param[in] channel - The channel id corresponding to an ethernet interface
604 * @return A reference to the SetStatus for the channel
605 */
606SetStatus& getSetStatus(uint8_t channel)
607{
608 auto it = setStatus.find(channel);
609 if (it != setStatus.end())
610 {
611 return it->second;
612 }
613 return setStatus[channel] = SetStatus::Complete;
614}
615
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700616/** @brief Unpacks the trivially copyable type from the message */
617template <typename T>
618static T unpackT(message::Payload& req)
619{
620 std::array<uint8_t, sizeof(T)> bytes;
621 if (req.unpack(bytes) != 0)
622 {
623 throw ccReqDataLenInvalid;
624 }
625 return stdplus::raw::copyFrom<T>(bytes);
626}
627
628/** @brief Ensure the message is fully unpacked */
629static void unpackFinal(message::Payload& req)
630{
631 if (!req.fullyUnpacked())
632 {
633 throw ccReqDataTruncated;
634 }
635}
636
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700637/**
638 * Define placeholder command handlers for the OEM Extension bytes for the Set
639 * LAN Configuration Parameters and Get LAN Configuration Parameters
640 * commands. Using "weak" linking allows the placeholder setLanOem/getLanOem
641 * functions below to be overridden.
642 * To create handlers for your own proprietary command set:
643 * Create/modify a phosphor-ipmi-host Bitbake append file within your Yocto
644 * recipe
645 * Create C++ file(s) that define IPMI handler functions matching the
646 * function names below (i.e. setLanOem). The default name for the
647 * transport IPMI commands is transporthandler_oem.cpp.
648 * Add:
Johnathan Manteyefe26682022-08-11 14:30:45 -0700649 * EXTRA_OEMESON:append = "-Dtransport-oem=enabled"
650 * Create a do_configure:prepend()/do_install:append() method in your
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700651 * bbappend file to copy the file to the build directory.
652 * Add:
653 * PROJECT_SRC_DIR := "${THISDIR}/${PN}"
654 * # Copy the "strong" functions into the working directory, overriding the
655 * # placeholder functions.
Johnathan Manteyefe26682022-08-11 14:30:45 -0700656 * do_configure:prepend(){
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700657 * cp -f ${PROJECT_SRC_DIR}/transporthandler_oem.cpp ${S}
658 * }
659 *
660 * # Clean up after complilation has completed
Johnathan Manteyefe26682022-08-11 14:30:45 -0700661 * do_install:append(){
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700662 * rm -f ${S}/transporthandler_oem.cpp
663 * }
664 *
665 */
666
667/**
668 * Define the placeholder OEM commands as having weak linkage. Create
669 * setLanOem, and getLanOem functions in the transporthandler_oem.cpp
670 * file. The functions defined there must not have the "weak" attribute
671 * applied to them.
672 */
673RspType<> setLanOem(uint8_t channel, uint8_t parameter, message::Payload& req)
674 __attribute__((weak));
675RspType<message::Payload> getLanOem(uint8_t channel, uint8_t parameter,
676 uint8_t set, uint8_t block)
677 __attribute__((weak));
678
Willy Tu11d68892022-01-20 10:37:34 -0800679RspType<> setLanOem(uint8_t, uint8_t, message::Payload& req)
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700680{
681 req.trailingOk = true;
682 return response(ccParamNotSupported);
683}
684
Willy Tu11d68892022-01-20 10:37:34 -0800685RspType<message::Payload> getLanOem(uint8_t, uint8_t, uint8_t, uint8_t)
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700686{
687 return response(ccParamNotSupported);
688}
689
Jian Zhangcf19d142023-07-31 10:22:53 +0800690/**
691 * @brief is a valid LAN channel.
692 *
693 * This function checks whether the input channel is a valid LAN channel or not.
694 *
695 * @param[in] channel: the channel number.
696 * @return nullopt if the channel is invalid, false if the channel is not a LAN
697 * channel, true if the channel is a LAN channel.
698 **/
699std::optional<bool> isLanChannel(uint8_t channel)
700{
701 ChannelInfo chInfo;
702 auto cc = getChannelInfo(channel, chInfo);
703 if (cc != ccSuccess)
704 {
705 return std::nullopt;
706 }
707
708 return chInfo.mediumType ==
709 static_cast<uint8_t>(EChannelMediumType::lan8032);
710}
711
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700712RspType<> setLanInt(Context::ptr ctx, uint4_t channelBits, uint4_t reserved1,
713 uint8_t parameter, message::Payload& req)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700714{
vijayabharathix shettycc769252020-02-27 17:52:20 +0000715 const uint8_t channel = convertCurrentChannelNum(
716 static_cast<uint8_t>(channelBits), ctx->channel);
717 if (reserved1 || !isValidChannel(channel))
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700718 {
George Liu32e8f5d2024-07-17 19:52:25 +0800719 lg2::error("Set Lan - Invalid field in request");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700720 req.trailingOk = true;
721 return responseInvalidFieldRequest();
722 }
723
Jian Zhangcf19d142023-07-31 10:22:53 +0800724 if (!isLanChannel(channel).value_or(false))
725 {
George Liu32e8f5d2024-07-17 19:52:25 +0800726 lg2::error("Set Lan - Not a LAN channel");
Jian Zhangcf19d142023-07-31 10:22:53 +0800727 return responseInvalidFieldRequest();
728 }
729
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700730 switch (static_cast<LanParam>(parameter))
731 {
732 case LanParam::SetStatus:
733 {
734 uint2_t flag;
735 uint6_t rsvd;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700736 if (req.unpack(flag, rsvd) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700737 {
738 return responseReqDataLenInvalid();
739 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700740 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800741 if (rsvd)
742 {
743 return responseInvalidFieldRequest();
744 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700745 auto status = static_cast<SetStatus>(static_cast<uint8_t>(flag));
746 switch (status)
747 {
748 case SetStatus::Complete:
749 {
750 getSetStatus(channel) = status;
751 return responseSuccess();
752 }
753 case SetStatus::InProgress:
754 {
755 auto& storedStatus = getSetStatus(channel);
756 if (storedStatus == SetStatus::InProgress)
757 {
758 return response(ccParamSetLocked);
759 }
760 storedStatus = status;
761 return responseSuccess();
762 }
763 case SetStatus::Commit:
764 if (getSetStatus(channel) != SetStatus::InProgress)
765 {
766 return responseInvalidFieldRequest();
767 }
768 return responseSuccess();
769 }
770 return response(ccParamNotSupported);
771 }
772 case LanParam::AuthSupport:
773 {
774 req.trailingOk = true;
775 return response(ccParamReadOnly);
776 }
777 case LanParam::AuthEnables:
778 {
779 req.trailingOk = true;
Johnathan Mantey76ce9c72019-11-14 14:41:46 -0800780 return response(ccParamReadOnly);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700781 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800782 case LanParam::IP:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600783 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700784 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800785 {
786 return responseCommandNotAvailable();
787 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700788 auto ip = unpackT<stdplus::In4Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700789 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700790 channelCall<reconfigureIfAddr4>(channel, ip, std::nullopt);
791 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +0530792 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700793 case LanParam::IPSrc:
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530794 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700795 uint4_t flag;
796 uint4_t rsvd;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700797 if (req.unpack(flag, rsvd) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700798 {
799 return responseReqDataLenInvalid();
800 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700801 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800802 if (rsvd)
803 {
804 return responseInvalidFieldRequest();
805 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700806 switch (static_cast<IPSrc>(static_cast<uint8_t>(flag)))
807 {
808 case IPSrc::DHCP:
Johnathan Mantey65265362019-11-14 11:24:19 -0800809 // The IPSrc IPMI command is only for IPv4
810 // management. Modifying IPv6 state is done using
811 // a completely different Set LAN Configuration
812 // subcommand.
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700813 channelCall<setEthProp<bool>>(channel, "DHCP4", true);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700814 return responseSuccess();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700815 case IPSrc::Unspecified:
816 case IPSrc::Static:
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700817 channelCall<setEthProp<bool>>(channel, "DHCP4", false);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700818 return responseSuccess();
Rajashekar Gade Reddy8a860ea2019-12-24 11:31:19 +0530819 case IPSrc::BIOS:
820 case IPSrc::BMC:
Rajashekar Gade Reddy8a860ea2019-12-24 11:31:19 +0530821 return responseInvalidFieldRequest();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700822 }
823 return response(ccParamNotSupported);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530824 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800825 case LanParam::MAC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530826 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700827 auto mac = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700828 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700829 channelCall<setMACProperty>(channel, mac);
830 return responseSuccess();
Ratan Gupta533d03b2017-07-30 10:39:22 +0530831 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700832 case LanParam::SubnetMask:
Ratan Guptab8e99552017-07-27 07:07:48 +0530833 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700834 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800835 {
836 return responseCommandNotAvailable();
837 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700838 auto pfx = stdplus::maskToPfx(unpackT<stdplus::In4Addr>(req));
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700839 unpackFinal(req);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700840 channelCall<reconfigureIfAddr4>(channel, std::nullopt, pfx);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700841 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +0530842 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700843 case LanParam::Gateway1:
Ratan Guptab8e99552017-07-27 07:07:48 +0530844 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700845 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800846 {
847 return responseCommandNotAvailable();
848 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700849 auto gateway = unpackT<stdplus::In4Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700850 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700851 channelCall<setGatewayProperty<AF_INET>>(channel, gateway);
852 return responseSuccess();
853 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700854 case LanParam::Gateway1MAC:
855 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700856 auto gatewayMAC = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700857 unpackFinal(req);
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700858 channelCall<reconfigureGatewayMAC<AF_INET>>(channel, gatewayMAC);
859 return responseSuccess();
860 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700861 case LanParam::VLANId:
862 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700863 uint12_t vlanData;
864 uint3_t rsvd;
865 bool vlanEnable;
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530866
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700867 if (req.unpack(vlanData, rsvd, vlanEnable) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700868 {
869 return responseReqDataLenInvalid();
870 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700871 unpackFinal(req);
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530872
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700873 if (rsvd)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700874 {
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530875 return responseInvalidFieldRequest();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700876 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530877
878 uint16_t vlan = static_cast<uint16_t>(vlanData);
879
880 if (!vlanEnable)
881 {
882 lastDisabledVlan[channel] = vlan;
883 vlan = 0;
884 }
Jayaprakash Mutyala0d1d7ad2024-06-19 10:19:33 +0000885 else if (vlan == 0 || vlan == VLAN_VALUE_MASK)
886 {
887 return responseInvalidFieldRequest();
888 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530889
jayaprakash Mutyala84c49dc2020-05-18 23:12:13 +0000890 channelCall<reconfigureVLAN>(channel, vlan);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700891 return responseSuccess();
892 }
893 case LanParam::CiphersuiteSupport:
894 case LanParam::CiphersuiteEntries:
William A. Kennington III16064aa2019-04-13 17:44:53 -0700895 case LanParam::IPFamilySupport:
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700896 {
897 req.trailingOk = true;
898 return response(ccParamReadOnly);
Ratan Guptab8e99552017-07-27 07:07:48 +0530899 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700900 case LanParam::IPFamilyEnables:
901 {
902 uint8_t enables;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700903 if (req.unpack(enables) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700904 {
905 return responseReqDataLenInvalid();
906 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700907 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700908 switch (static_cast<IPFamilyEnables>(enables))
909 {
910 case IPFamilyEnables::DualStack:
911 return responseSuccess();
912 case IPFamilyEnables::IPv4Only:
913 case IPFamilyEnables::IPv6Only:
914 return response(ccParamNotSupported);
915 }
916 return response(ccParamNotSupported);
917 }
918 case LanParam::IPv6Status:
919 {
920 req.trailingOk = true;
921 return response(ccParamReadOnly);
922 }
923 case LanParam::IPv6StaticAddresses:
924 {
925 uint8_t set;
926 uint7_t rsvd;
927 bool enabled;
William A. Kennington III16064aa2019-04-13 17:44:53 -0700928 uint8_t prefix;
929 uint8_t status;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700930 if (req.unpack(set, rsvd, enabled) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700931 {
932 return responseReqDataLenInvalid();
933 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700934 auto ip = unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700935 if (req.unpack(prefix, status) != 0)
936 {
937 return responseReqDataLenInvalid();
938 }
939 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800940 if (rsvd)
941 {
942 return responseInvalidFieldRequest();
943 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700944 if (enabled)
945 {
Jiaqing Zhao6d4a44e2022-01-24 15:04:00 +0800946 if (prefix < MIN_IPV6_PREFIX_LENGTH ||
947 prefix > MAX_IPV6_PREFIX_LENGTH)
948 {
949 return responseParmOutOfRange();
950 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700951 channelCall<reconfigureIfAddr6>(channel, set, ip, prefix);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700952 }
953 else
954 {
955 channelCall<deconfigureIfAddr6>(channel, set);
956 }
957 return responseSuccess();
958 }
959 case LanParam::IPv6DynamicAddresses:
960 {
961 req.trailingOk = true;
962 return response(ccParamReadOnly);
963 }
964 case LanParam::IPv6RouterControl:
965 {
966 std::bitset<8> control;
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800967 constexpr uint8_t reservedRACCBits = 0xfc;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700968 if (req.unpack(control) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700969 {
970 return responseReqDataLenInvalid();
971 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700972 unpackFinal(req);
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800973 if (std::bitset<8> expected(control &
974 std::bitset<8>(reservedRACCBits));
975 expected.any())
William A. Kennington III16064aa2019-04-13 17:44:53 -0700976 {
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800977 return response(ccParamNotSupported);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700978 }
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800979
980 bool enableRA = control[IPv6RouterControlFlag::Dynamic];
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700981 channelCall<setEthProp<bool>>(channel, "IPv6AcceptRA", enableRA);
982 channelCall<setEthProp<bool>>(channel, "DHCP6", enableRA);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700983 return responseSuccess();
984 }
985 case LanParam::IPv6StaticRouter1IP:
986 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700987 auto gateway = unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700988 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700989 channelCall<setGatewayProperty<AF_INET6>>(channel, gateway);
990 return responseSuccess();
991 }
992 case LanParam::IPv6StaticRouter1MAC:
993 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700994 auto mac = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700995 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700996 channelCall<reconfigureGatewayMAC<AF_INET6>>(channel, mac);
997 return responseSuccess();
998 }
999 case LanParam::IPv6StaticRouter1PrefixLength:
1000 {
1001 uint8_t prefix;
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001002 if (req.unpack(prefix) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -07001003 {
1004 return responseReqDataLenInvalid();
1005 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001006 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001007 if (prefix != 0)
1008 {
1009 return responseInvalidFieldRequest();
1010 }
1011 return responseSuccess();
1012 }
1013 case LanParam::IPv6StaticRouter1PrefixValue:
1014 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001015 unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001016 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001017 // Accept any prefix value since our prefix length has to be 0
1018 return responseSuccess();
1019 }
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001020 case LanParam::cipherSuitePrivilegeLevels:
1021 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001022 uint8_t rsvd;
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001023 std::array<uint4_t, ipmi::maxCSRecords> cipherSuitePrivs;
1024
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001025 if (req.unpack(rsvd, cipherSuitePrivs))
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001026 {
1027 return responseReqDataLenInvalid();
1028 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001029 unpackFinal(req);
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001030
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001031 if (rsvd)
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001032 {
1033 return responseInvalidFieldRequest();
1034 }
1035
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -05001036 uint8_t resp = getCipherConfigObject(csPrivFileName,
1037 csPrivDefaultFileName)
1038 .setCSPrivilegeLevels(channel, cipherSuitePrivs);
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001039 if (!resp)
1040 {
1041 return responseSuccess();
1042 }
1043 else
1044 {
1045 req.trailingOk = true;
1046 return response(resp);
1047 }
1048 }
Ratan Guptab8e99552017-07-27 07:07:48 +05301049 }
vishwa1eaea4f2016-02-26 11:57:40 -06001050
PavanKumarIntel3771f5f2023-11-02 06:26:42 +00001051 if (parameter >= oemCmdStart)
Johnathan Manteyb87034e2019-09-16 10:50:50 -07001052 {
1053 return setLanOem(channel, parameter, req);
1054 }
1055
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001056 req.trailingOk = true;
1057 return response(ccParamNotSupported);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001058}
1059
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001060RspType<> setLan(Context::ptr ctx, uint4_t channelBits, uint4_t reserved1,
1061 uint8_t parameter, message::Payload& req)
1062{
1063 try
1064 {
1065 return setLanInt(ctx, channelBits, reserved1, parameter, req);
1066 }
1067 catch (ipmi::Cc cc)
1068 {
1069 return response(cc);
1070 }
1071 catch (const sdbusplus::exception_t& e)
1072 {
1073 if (std::string_view{InvalidArgument::errName} == e.name())
1074 {
1075 return responseInvalidFieldRequest();
1076 }
1077 throw;
1078 }
1079}
1080
vijayabharathix shettycc769252020-02-27 17:52:20 +00001081RspType<message::Payload> getLan(Context::ptr ctx, uint4_t channelBits,
1082 uint3_t reserved, bool revOnly,
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001083 uint8_t parameter, uint8_t set, uint8_t block)
Ratan Guptab8e99552017-07-27 07:07:48 +05301084{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001085 message::Payload ret;
1086 constexpr uint8_t current_revision = 0x11;
1087 ret.pack(current_revision);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001088
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001089 if (revOnly)
Suryakanth Sekare4054402019-08-08 15:16:52 +05301090 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001091 return responseSuccess(std::move(ret));
Suryakanth Sekare4054402019-08-08 15:16:52 +05301092 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001093
vijayabharathix shettycc769252020-02-27 17:52:20 +00001094 const uint8_t channel = convertCurrentChannelNum(
1095 static_cast<uint8_t>(channelBits), ctx->channel);
1096 if (reserved || !isValidChannel(channel))
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001097 {
George Liu32e8f5d2024-07-17 19:52:25 +08001098 lg2::error("Get Lan - Invalid field in request");
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001099 return responseInvalidFieldRequest();
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001100 }
1101
Jian Zhangcf19d142023-07-31 10:22:53 +08001102 if (!isLanChannel(channel).value_or(false))
1103 {
George Liu32e8f5d2024-07-17 19:52:25 +08001104 lg2::error("Set Lan - Not a LAN channel");
Jian Zhangcf19d142023-07-31 10:22:53 +08001105 return responseInvalidFieldRequest();
1106 }
1107
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001108 static std::vector<uint8_t> cipherList;
1109 static bool listInit = false;
1110 if (!listInit)
1111 {
1112 try
1113 {
1114 cipherList = cipher::getCipherList();
1115 listInit = true;
1116 }
1117 catch (const std::exception& e)
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -05001118 {}
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001119 }
1120
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001121 switch (static_cast<LanParam>(parameter))
Tom Josepha30c8d32018-03-22 02:15:03 +05301122 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001123 case LanParam::SetStatus:
Tom Josepha30c8d32018-03-22 02:15:03 +05301124 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001125 SetStatus status;
1126 try
1127 {
1128 status = setStatus.at(channel);
1129 }
1130 catch (const std::out_of_range&)
1131 {
1132 status = SetStatus::Complete;
1133 }
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001134 ret.pack(types::enum_cast<uint2_t>(status), uint6_t{});
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001135 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301136 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001137 case LanParam::AuthSupport:
Tom Josepha30c8d32018-03-22 02:15:03 +05301138 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001139 std::bitset<6> support;
1140 ret.pack(support, uint2_t{});
1141 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301142 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001143 case LanParam::AuthEnables:
vishwa1eaea4f2016-02-26 11:57:40 -06001144 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001145 std::bitset<6> enables;
1146 ret.pack(enables, uint2_t{}); // Callback
1147 ret.pack(enables, uint2_t{}); // User
1148 ret.pack(enables, uint2_t{}); // Operator
1149 ret.pack(enables, uint2_t{}); // Admin
1150 ret.pack(enables, uint2_t{}); // OEM
1151 return responseSuccess(std::move(ret));
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001152 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001153 case LanParam::IP:
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001154 {
1155 auto ifaddr = channelCall<getIfAddr4>(channel);
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001156 stdplus::In4Addr addr{};
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001157 if (ifaddr)
1158 {
1159 addr = ifaddr->address;
1160 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001161 ret.pack(stdplus::raw::asView<char>(addr));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001162 return responseSuccess(std::move(ret));
1163 }
1164 case LanParam::IPSrc:
1165 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001166 auto src = channelCall<getEthProp<bool>>(channel, "DHCP4")
1167 ? IPSrc::DHCP
1168 : IPSrc::Static;
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001169 ret.pack(types::enum_cast<uint4_t>(src), uint4_t{});
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001170 return responseSuccess(std::move(ret));
1171 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001172 case LanParam::MAC:
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001173 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001174 auto mac = channelCall<getMACProperty>(channel);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001175 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001176 return responseSuccess(std::move(ret));
1177 }
1178 case LanParam::SubnetMask:
1179 {
1180 auto ifaddr = channelCall<getIfAddr4>(channel);
1181 uint8_t prefix = AddrFamily<AF_INET>::defaultPrefix;
1182 if (ifaddr)
Ratan Guptab8e99552017-07-27 07:07:48 +05301183 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001184 prefix = ifaddr->prefix;
1185 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001186 auto netmask = stdplus::pfxToMask<stdplus::In4Addr>(prefix);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001187 ret.pack(stdplus::raw::asView<char>(netmask));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001188 return responseSuccess(std::move(ret));
1189 }
1190 case LanParam::Gateway1:
1191 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001192 auto gateway = channelCall<getGatewayProperty<AF_INET>>(channel);
1193 ret.pack(stdplus::raw::asView<char>(
1194 gateway.value_or(stdplus::In4Addr{})));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001195 return responseSuccess(std::move(ret));
1196 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001197 case LanParam::Gateway1MAC:
1198 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001199 stdplus::EtherAddr mac{};
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001200 auto neighbor = channelCall<getGatewayNeighbor<AF_INET>>(channel);
1201 if (neighbor)
1202 {
1203 mac = neighbor->mac;
1204 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001205 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001206 return responseSuccess(std::move(ret));
1207 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001208 case LanParam::VLANId:
1209 {
1210 uint16_t vlan = channelCall<getVLANProperty>(channel);
1211 if (vlan != 0)
1212 {
1213 vlan |= VLAN_ENABLE_FLAG;
Ratan Guptab8e99552017-07-27 07:07:48 +05301214 }
1215 else
1216 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001217 vlan = lastDisabledVlan[channel];
Ratan Guptab8e99552017-07-27 07:07:48 +05301218 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001219 ret.pack(vlan);
1220 return responseSuccess(std::move(ret));
Adriana Kobylak342df102016-02-10 13:48:16 -06001221 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001222 case LanParam::CiphersuiteSupport:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001223 {
srikanta mondal1d8579c2020-04-15 17:13:25 +00001224 if (getChannelSessionSupport(channel) ==
1225 EChannelSessSupported::none)
1226 {
1227 return responseInvalidFieldRequest();
1228 }
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001229 if (!listInit)
1230 {
1231 return responseUnspecifiedError();
1232 }
1233 ret.pack(static_cast<uint8_t>(cipherList.size() - 1));
1234 return responseSuccess(std::move(ret));
1235 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001236 case LanParam::CiphersuiteEntries:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001237 {
srikanta mondal1d8579c2020-04-15 17:13:25 +00001238 if (getChannelSessionSupport(channel) ==
1239 EChannelSessSupported::none)
1240 {
1241 return responseInvalidFieldRequest();
1242 }
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001243 if (!listInit)
1244 {
1245 return responseUnspecifiedError();
1246 }
1247 ret.pack(cipherList);
1248 return responseSuccess(std::move(ret));
1249 }
William A. Kennington III16064aa2019-04-13 17:44:53 -07001250 case LanParam::IPFamilySupport:
1251 {
1252 std::bitset<8> support;
1253 support[IPFamilySupportFlag::IPv6Only] = 0;
1254 support[IPFamilySupportFlag::DualStack] = 1;
1255 support[IPFamilySupportFlag::IPv6Alerts] = 1;
1256 ret.pack(support);
1257 return responseSuccess(std::move(ret));
1258 }
1259 case LanParam::IPFamilyEnables:
1260 {
1261 ret.pack(static_cast<uint8_t>(IPFamilyEnables::DualStack));
1262 return responseSuccess(std::move(ret));
1263 }
1264 case LanParam::IPv6Status:
1265 {
1266 ret.pack(MAX_IPV6_STATIC_ADDRESSES);
1267 ret.pack(MAX_IPV6_DYNAMIC_ADDRESSES);
1268 std::bitset<8> support;
1269 support[IPv6StatusFlag::DHCP] = 1;
1270 support[IPv6StatusFlag::SLAAC] = 1;
1271 ret.pack(support);
1272 return responseSuccess(std::move(ret));
1273 }
1274 case LanParam::IPv6StaticAddresses:
1275 {
1276 if (set >= MAX_IPV6_STATIC_ADDRESSES)
1277 {
1278 return responseParmOutOfRange();
1279 }
1280 getLanIPv6Address(ret, channel, set, originsV6Static);
1281 return responseSuccess(std::move(ret));
1282 }
1283 case LanParam::IPv6DynamicAddresses:
1284 {
1285 if (set >= MAX_IPV6_DYNAMIC_ADDRESSES)
1286 {
1287 return responseParmOutOfRange();
1288 }
1289 getLanIPv6Address(ret, channel, set, originsV6Dynamic);
1290 return responseSuccess(std::move(ret));
1291 }
1292 case LanParam::IPv6RouterControl:
1293 {
1294 std::bitset<8> control;
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001295 control[IPv6RouterControlFlag::Dynamic] =
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001296 channelCall<getEthProp<bool>>(channel, "IPv6AcceptRA");
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001297 control[IPv6RouterControlFlag::Static] = 1;
William A. Kennington III16064aa2019-04-13 17:44:53 -07001298 ret.pack(control);
1299 return responseSuccess(std::move(ret));
1300 }
1301 case LanParam::IPv6StaticRouter1IP:
1302 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001303 stdplus::In6Addr gateway{};
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001304 if (!channelCall<getEthProp<bool>>(channel, "IPv6AcceptRA"))
William A. Kennington III16064aa2019-04-13 17:44:53 -07001305 {
1306 gateway =
1307 channelCall<getGatewayProperty<AF_INET6>>(channel).value_or(
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001308 stdplus::In6Addr{});
William A. Kennington III16064aa2019-04-13 17:44:53 -07001309 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001310 ret.pack(stdplus::raw::asView<char>(gateway));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001311 return responseSuccess(std::move(ret));
1312 }
1313 case LanParam::IPv6StaticRouter1MAC:
1314 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001315 stdplus::EtherAddr mac{};
William A. Kennington III16064aa2019-04-13 17:44:53 -07001316 auto neighbor = channelCall<getGatewayNeighbor<AF_INET6>>(channel);
1317 if (neighbor)
1318 {
1319 mac = neighbor->mac;
1320 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001321 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001322 return responseSuccess(std::move(ret));
1323 }
1324 case LanParam::IPv6StaticRouter1PrefixLength:
1325 {
Jian Zhang796e8242024-02-01 14:07:34 +08001326 ret.pack(uint8_t{0});
William A. Kennington III16064aa2019-04-13 17:44:53 -07001327 return responseSuccess(std::move(ret));
1328 }
1329 case LanParam::IPv6StaticRouter1PrefixValue:
1330 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001331 ret.pack(stdplus::raw::asView<char>(stdplus::In6Addr{}));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001332 return responseSuccess(std::move(ret));
1333 }
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001334 case LanParam::cipherSuitePrivilegeLevels:
1335 {
1336 std::array<uint4_t, ipmi::maxCSRecords> csPrivilegeLevels;
1337
1338 uint8_t resp =
1339 getCipherConfigObject(csPrivFileName, csPrivDefaultFileName)
1340 .getCSPrivilegeLevels(channel, csPrivilegeLevels);
1341 if (!resp)
1342 {
1343 constexpr uint8_t reserved1 = 0x00;
1344 ret.pack(reserved1, csPrivilegeLevels);
1345 return responseSuccess(std::move(ret));
1346 }
1347 else
1348 {
1349 return response(resp);
1350 }
1351 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001352 }
1353
PavanKumarIntel3771f5f2023-11-02 06:26:42 +00001354 if (parameter >= oemCmdStart)
Johnathan Manteyb87034e2019-09-16 10:50:50 -07001355 {
1356 return getLanOem(channel, parameter, set, block);
1357 }
1358
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001359 return response(ccParamNotSupported);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001360}
1361
Jian Zhang23f44652022-03-17 17:13:10 +08001362constexpr const char* solInterface = "xyz.openbmc_project.Ipmi.SOL";
1363constexpr const char* solPath = "/xyz/openbmc_project/ipmi/sol/";
1364constexpr const uint16_t solDefaultPort = 623;
1365
1366RspType<> setSolConfParams(Context::ptr ctx, uint4_t channelBits,
Willy Tu11d68892022-01-20 10:37:34 -08001367 uint4_t /*reserved*/, uint8_t parameter,
Jian Zhang23f44652022-03-17 17:13:10 +08001368 message::Payload& req)
1369{
1370 const uint8_t channel = convertCurrentChannelNum(
1371 static_cast<uint8_t>(channelBits), ctx->channel);
1372
1373 if (!isValidChannel(channel))
1374 {
George Liu32e8f5d2024-07-17 19:52:25 +08001375 lg2::error("Set Sol Config - Invalid channel in request");
Jian Zhang23f44652022-03-17 17:13:10 +08001376 return responseInvalidFieldRequest();
1377 }
1378
1379 std::string solService{};
1380 std::string solPathWitheEthName = solPath + ipmi::getChannelName(channel);
1381
1382 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1383 {
George Liu32e8f5d2024-07-17 19:52:25 +08001384 lg2::error("Set Sol Config - Invalid solInterface, service: {SERVICE}, "
1385 "object path: {OBJPATH}, interface: {INTERFACE}",
1386 "SERVICE", solService, "OBJPATH", solPathWitheEthName,
1387 "INTERFACE", solInterface);
Jian Zhang23f44652022-03-17 17:13:10 +08001388 return responseInvalidFieldRequest();
1389 }
1390
1391 switch (static_cast<SolConfParam>(parameter))
1392 {
1393 case SolConfParam::Progress:
1394 {
1395 uint8_t progress;
1396 if (req.unpack(progress) != 0 || !req.fullyUnpacked())
1397 {
1398 return responseReqDataLenInvalid();
1399 }
1400
1401 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1402 solInterface, "Progress", progress))
1403 {
1404 return responseUnspecifiedError();
1405 }
1406 break;
1407 }
1408 case SolConfParam::Enable:
1409 {
1410 bool enable;
1411 uint7_t reserved2;
1412
1413 if (req.unpack(enable, reserved2) != 0 || !req.fullyUnpacked())
1414 {
1415 return responseReqDataLenInvalid();
1416 }
1417
1418 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1419 solInterface, "Enable", enable))
1420 {
1421 return responseUnspecifiedError();
1422 }
1423 break;
1424 }
1425 case SolConfParam::Authentication:
1426 {
1427 uint4_t privilegeBits{};
1428 uint2_t reserved2{};
1429 bool forceAuth = false;
1430 bool forceEncrypt = false;
1431
1432 if (req.unpack(privilegeBits, reserved2, forceAuth, forceEncrypt) !=
1433 0 ||
1434 !req.fullyUnpacked())
1435 {
1436 return responseReqDataLenInvalid();
1437 }
1438
1439 uint8_t privilege = static_cast<uint8_t>(privilegeBits);
Jonathan Domana48bf772023-05-26 17:54:57 -07001440 if (privilege < static_cast<uint8_t>(Privilege::User) ||
Jian Zhang23f44652022-03-17 17:13:10 +08001441 privilege > static_cast<uint8_t>(Privilege::Oem))
1442 {
1443 return ipmi::responseInvalidFieldRequest();
1444 }
1445
1446 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1447 solInterface, "Privilege", privilege))
1448 {
1449 return responseUnspecifiedError();
1450 }
1451
1452 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1453 solInterface, "ForceEncryption",
1454 forceEncrypt))
1455 {
1456 return responseUnspecifiedError();
1457 }
1458
1459 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1460 solInterface, "ForceAuthentication",
1461 forceAuth))
1462 {
1463 return responseUnspecifiedError();
1464 }
1465 break;
1466 }
1467 case SolConfParam::Accumulate:
1468 {
1469 uint8_t interval;
1470 uint8_t threshold;
1471 if (req.unpack(interval, threshold) != 0 || !req.fullyUnpacked())
1472 {
1473 return responseReqDataLenInvalid();
1474 }
1475
1476 if (threshold == 0)
1477 {
1478 return responseInvalidFieldRequest();
1479 }
1480
1481 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1482 solInterface, "AccumulateIntervalMS",
1483 interval))
1484 {
1485 return responseUnspecifiedError();
1486 }
1487
1488 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1489 solInterface, "Threshold", threshold))
1490 {
1491 return responseUnspecifiedError();
1492 }
1493 break;
1494 }
1495 case SolConfParam::Retry:
1496 {
1497 uint3_t countBits;
1498 uint5_t reserved2;
1499 uint8_t interval;
1500
1501 if (req.unpack(countBits, reserved2, interval) != 0 ||
1502 !req.fullyUnpacked())
1503 {
1504 return responseReqDataLenInvalid();
1505 }
1506
1507 uint8_t count = static_cast<uint8_t>(countBits);
1508 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1509 solInterface, "RetryCount", count))
1510 {
1511 return responseUnspecifiedError();
1512 }
1513
1514 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1515 solInterface, "RetryIntervalMS",
1516 interval))
1517 {
1518 return responseUnspecifiedError();
1519 }
1520 break;
1521 }
1522 case SolConfParam::Port:
1523 {
1524 return response(ipmiCCWriteReadParameter);
1525 }
1526 case SolConfParam::NonVbitrate:
1527 case SolConfParam::Vbitrate:
1528 case SolConfParam::Channel:
1529 default:
1530 return response(ipmiCCParamNotSupported);
1531 }
1532 return responseSuccess();
1533}
1534
1535RspType<message::Payload> getSolConfParams(Context::ptr ctx,
1536 uint4_t channelBits,
Willy Tu11d68892022-01-20 10:37:34 -08001537 uint3_t /*reserved*/, bool revOnly,
1538 uint8_t parameter, uint8_t /*set*/,
1539 uint8_t /*block*/)
Jian Zhang23f44652022-03-17 17:13:10 +08001540{
1541 message::Payload ret;
1542 constexpr uint8_t current_revision = 0x11;
1543 ret.pack(current_revision);
1544 if (revOnly)
1545 {
1546 return responseSuccess(std::move(ret));
1547 }
1548
1549 const uint8_t channel = convertCurrentChannelNum(
1550 static_cast<uint8_t>(channelBits), ctx->channel);
1551
1552 if (!isValidChannel(channel))
1553 {
George Liu32e8f5d2024-07-17 19:52:25 +08001554 lg2::error("Get Sol Config - Invalid channel in request");
Jian Zhang23f44652022-03-17 17:13:10 +08001555 return responseInvalidFieldRequest();
1556 }
1557
1558 std::string solService{};
1559 std::string solPathWitheEthName = solPath + ipmi::getChannelName(channel);
1560
1561 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1562 {
George Liu32e8f5d2024-07-17 19:52:25 +08001563 lg2::error("Set Sol Config - Invalid solInterface, service: {SERVICE}, "
1564 "object path: {OBJPATH}, interface: {INTERFACE}",
1565 "SERVICE", solService, "OBJPATH", solPathWitheEthName,
1566 "INTERFACE", solInterface);
Jian Zhang23f44652022-03-17 17:13:10 +08001567 return responseInvalidFieldRequest();
1568 }
1569
1570 switch (static_cast<SolConfParam>(parameter))
1571 {
1572 case SolConfParam::Progress:
1573 {
1574 uint8_t progress;
1575 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1576 solInterface, "Progress", progress))
1577 {
1578 return responseUnspecifiedError();
1579 }
1580 ret.pack(progress);
1581 return responseSuccess(std::move(ret));
1582 }
1583 case SolConfParam::Enable:
1584 {
1585 bool enable{};
1586 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1587 solInterface, "Enable", enable))
1588 {
1589 return responseUnspecifiedError();
1590 }
1591 ret.pack(enable, uint7_t{});
1592 return responseSuccess(std::move(ret));
1593 }
1594 case SolConfParam::Authentication:
1595 {
1596 // 4bits, cast when pack
1597 uint8_t privilege;
1598 bool forceAuth = false;
1599 bool forceEncrypt = false;
1600
1601 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1602 solInterface, "Privilege", privilege))
1603 {
1604 return responseUnspecifiedError();
1605 }
1606
1607 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1608 solInterface, "ForceAuthentication",
1609 forceAuth))
1610 {
1611 return responseUnspecifiedError();
1612 }
1613
1614 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1615 solInterface, "ForceEncryption",
1616 forceEncrypt))
1617 {
1618 return responseUnspecifiedError();
1619 }
1620 ret.pack(uint4_t{privilege}, uint2_t{}, forceAuth, forceEncrypt);
1621 return responseSuccess(std::move(ret));
1622 }
1623 case SolConfParam::Accumulate:
1624 {
1625 uint8_t interval{}, threshold{};
1626
1627 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1628 solInterface, "AccumulateIntervalMS",
1629 interval))
1630 {
1631 return responseUnspecifiedError();
1632 }
1633
1634 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1635 solInterface, "Threshold", threshold))
1636 {
1637 return responseUnspecifiedError();
1638 }
1639 ret.pack(interval, threshold);
1640 return responseSuccess(std::move(ret));
1641 }
1642 case SolConfParam::Retry:
1643 {
1644 // 3bits, cast when cast
1645 uint8_t count{};
1646 uint8_t interval{};
1647
1648 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1649 solInterface, "RetryCount", count))
1650 {
1651 return responseUnspecifiedError();
1652 }
1653
1654 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1655 solInterface, "RetryIntervalMS",
1656 interval))
1657 {
1658 return responseUnspecifiedError();
1659 }
1660 ret.pack(uint3_t{count}, uint5_t{}, interval);
1661 return responseSuccess(std::move(ret));
1662 }
1663 case SolConfParam::Port:
1664 {
1665 auto port = solDefaultPort;
1666 ret.pack(static_cast<uint16_t>(port));
1667 return responseSuccess(std::move(ret));
1668 }
1669 case SolConfParam::Channel:
1670 {
1671 ret.pack(channel);
1672 return responseSuccess(std::move(ret));
1673 }
1674 case SolConfParam::NonVbitrate:
Jonathan Domana48bf772023-05-26 17:54:57 -07001675 {
1676 uint64_t baudRate;
1677 uint8_t encodedBitRate = 0;
1678 if (ipmi::getDbusProperty(
1679 ctx, "xyz.openbmc_project.Console.default",
1680 "/xyz/openbmc_project/console/default",
1681 "xyz.openbmc_project.Console.UART", "Baud", baudRate))
1682 {
1683 return ipmi::responseUnspecifiedError();
1684 }
1685 switch (baudRate)
1686 {
1687 case 9600:
1688 encodedBitRate = 0x06;
1689 break;
1690 case 19200:
1691 encodedBitRate = 0x07;
1692 break;
1693 case 38400:
1694 encodedBitRate = 0x08;
1695 break;
1696 case 57600:
1697 encodedBitRate = 0x09;
1698 break;
1699 case 115200:
1700 encodedBitRate = 0x0a;
1701 break;
1702 default:
1703 break;
1704 }
1705 ret.pack(encodedBitRate);
1706 return responseSuccess(std::move(ret));
1707 }
Jian Zhang23f44652022-03-17 17:13:10 +08001708 case SolConfParam::Vbitrate:
1709 default:
1710 return response(ipmiCCParamNotSupported);
1711 }
1712
1713 return response(ccParamNotSupported);
1714}
1715
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001716} // namespace transport
1717} // namespace ipmi
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301718
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001719void register_netfn_transport_functions() __attribute__((constructor));
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301720
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001721void register_netfn_transport_functions()
1722{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001723 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1724 ipmi::transport::cmdSetLanConfigParameters,
1725 ipmi::Privilege::Admin, ipmi::transport::setLan);
1726 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1727 ipmi::transport::cmdGetLanConfigParameters,
Johnathan Mantey34698d52019-11-19 14:47:30 -08001728 ipmi::Privilege::Operator, ipmi::transport::getLan);
Jian Zhang23f44652022-03-17 17:13:10 +08001729 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1730 ipmi::transport::cmdSetSolConfigParameters,
1731 ipmi::Privilege::Admin,
1732 ipmi::transport::setSolConfParams);
1733 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1734 ipmi::transport::cmdGetSolConfigParameters,
1735 ipmi::Privilege::User,
1736 ipmi::transport::getSolConfParams);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001737}