blob: c7cca213f2e3afcc02c15fd6436806f9a5132375 [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 Williams1318a5e2024-08-16 15:19:54 -040078std::optional<ChannelParams>
79 maybeGetChannelParams(sdbusplus::bus_t& bus, uint8_t channel)
William A. Kennington IIIc514d872019-04-06 18:19:38 -070080{
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};
Patrick Williams1318a5e2024-08-16 15:19:54 -040089 ipmi::ObjectTree objs =
90 ipmi::getSubTree(bus, interfaces, 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 Williams1318a5e2024-08-16 15:19:54 -0400261 auto newreq =
262 bus.new_method_call(params.service.c_str(), 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{
Chanh Nguyen8bd9a9b2024-11-08 09:08:56 +0000280 std::optional<IfAddr<AF_INET>> ifaddr4 = std::nullopt;
281 IP::AddressOrigin src;
282
283 try
284 {
285 src = std::get<bool>(
286 getDbusProperty(bus, params.service, params.logicalPath,
287 INTF_ETHERNET, "DHCP4"))
288 ? IP::AddressOrigin::DHCP
289 : IP::AddressOrigin::Static;
290 }
291 catch (const sdbusplus::exception_t& e)
292 {
293 lg2::error("Failed to get IPv4 source");
294 return ifaddr4;
295 }
296
297 for (uint8_t i = 0; i < MAX_IPV4_ADDRESSES; ++i)
298 {
299 ifaddr4 = getIfAddr<AF_INET>(bus, params, i, originsV4);
300 if (src == ifaddr4->origin)
301 {
302 break;
303 }
304 else
305 {
306 ifaddr4 = std::nullopt;
307 }
308 }
309 return ifaddr4;
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700310}
Tom Josepha30c8d32018-03-22 02:15:03 +0530311
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700312/** @brief Reconfigures the IPv4 address info configured for the interface
313 *
314 * @param[in] bus - The bus object used for lookups
315 * @param[in] params - The parameters for the channel
316 * @param[in] address - The new address if specified
317 * @param[in] prefix - The new address prefix if specified
318 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500319void reconfigureIfAddr4(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700320 std::optional<stdplus::In4Addr> address,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700321 std::optional<uint8_t> prefix)
322{
323 auto ifaddr = getIfAddr4(bus, params);
324 if (!ifaddr && !address)
Tom Josepha30c8d32018-03-22 02:15:03 +0530325 {
George Liu32e8f5d2024-07-17 19:52:25 +0800326 lg2::error("Missing address for IPv4 assignment");
Tom Josepha30c8d32018-03-22 02:15:03 +0530327 elog<InternalFailure>();
328 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700329 uint8_t fallbackPrefix = AddrFamily<AF_INET>::defaultPrefix;
330 if (ifaddr)
Tom Josepha30c8d32018-03-22 02:15:03 +0530331 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700332 fallbackPrefix = ifaddr->prefix;
333 deleteObjectIfExists(bus, params.service, ifaddr->path);
334 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700335 auto addr = address.value_or(ifaddr->address);
336 if (addr != stdplus::In4Addr{})
Johnathan Manteycbfa6e12023-06-01 06:57:25 -0700337 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700338 createIfAddr<AF_INET>(bus, params, addr,
Johnathan Manteycbfa6e12023-06-01 06:57:25 -0700339 prefix.value_or(fallbackPrefix));
340 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700341}
342
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700343template <int family>
Patrick Williams1318a5e2024-08-16 15:19:54 -0400344std::optional<IfNeigh<family>>
345 findGatewayNeighbor(sdbusplus::bus_t& bus, const ChannelParams& params,
346 ObjectLookupCache& neighbors)
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700347{
348 auto gateway = getGatewayProperty<family>(bus, params);
349 if (!gateway)
350 {
351 return std::nullopt;
352 }
353
354 return findStaticNeighbor<family>(bus, params, *gateway, neighbors);
355}
356
357template <int family>
Patrick Williams1318a5e2024-08-16 15:19:54 -0400358std::optional<IfNeigh<family>>
359 getGatewayNeighbor(sdbusplus::bus_t& bus, const ChannelParams& params)
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700360{
361 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
362 return findGatewayNeighbor<family>(bus, params, neighbors);
363}
364
365template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500366void reconfigureGatewayMAC(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700367 stdplus::EtherAddr mac)
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700368{
369 auto gateway = getGatewayProperty<family>(bus, params);
370 if (!gateway)
371 {
George Liu32e8f5d2024-07-17 19:52:25 +0800372 lg2::error("Tried to set Gateway MAC without Gateway");
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700373 elog<InternalFailure>();
374 }
375
376 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
Patrick Williams1318a5e2024-08-16 15:19:54 -0400377 auto neighbor =
378 findStaticNeighbor<family>(bus, params, *gateway, neighbors);
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700379 if (neighbor)
380 {
381 deleteObjectIfExists(bus, params.service, neighbor->path);
382 }
383
384 createNeighbor<family>(bus, params, *gateway, mac);
385}
386
William A. Kennington III16064aa2019-04-13 17:44:53 -0700387/** @brief Deconfigures the IPv6 address info configured for the interface
388 *
389 * @param[in] bus - The bus object used for lookups
390 * @param[in] params - The parameters for the channel
391 * @param[in] idx - The address index to operate on
392 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500393void deconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III16064aa2019-04-13 17:44:53 -0700394 uint8_t idx)
395{
396 auto ifaddr = getIfAddr<AF_INET6>(bus, params, idx, originsV6Static);
397 if (ifaddr)
398 {
399 deleteObjectIfExists(bus, params.service, ifaddr->path);
400 }
401}
402
403/** @brief Reconfigures the IPv6 address info configured for the interface
404 *
405 * @param[in] bus - The bus object used for lookups
406 * @param[in] params - The parameters for the channel
407 * @param[in] idx - The address index to operate on
408 * @param[in] address - The new address
409 * @param[in] prefix - The new address prefix
410 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500411void reconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700412 uint8_t idx, stdplus::In6Addr address, uint8_t prefix)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700413{
414 deconfigureIfAddr6(bus, params, idx);
415 createIfAddr<AF_INET6>(bus, params, address, prefix);
416}
417
418/** @brief Converts the AddressOrigin into an IPv6Source
419 *
420 * @param[in] origin - The DBus Address Origin to convert
421 * @return The IPv6Source version of the origin
422 */
423IPv6Source originToSourceType(IP::AddressOrigin origin)
424{
425 switch (origin)
426 {
427 case IP::AddressOrigin::Static:
428 return IPv6Source::Static;
429 case IP::AddressOrigin::DHCP:
430 return IPv6Source::DHCP;
431 case IP::AddressOrigin::SLAAC:
432 return IPv6Source::SLAAC;
433 default:
434 {
Willy Tu523e2d12023-09-05 11:36:48 -0700435 auto originStr = sdbusplus::common::xyz::openbmc_project::network::
William A. Kennington III16064aa2019-04-13 17:44:53 -0700436 convertForMessage(origin);
George Liu32e8f5d2024-07-17 19:52:25 +0800437 lg2::error("Invalid IP::AddressOrigin conversion to IPv6Source, "
438 "origin: {ORIGIN}",
439 "ORIGIN", originStr);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700440 elog<InternalFailure>();
441 }
442 }
443}
444
445/** @brief Packs the IPMI message response with IPv6 address data
446 *
447 * @param[out] ret - The IPMI response payload to be packed
448 * @param[in] channel - The channel id corresponding to an ethernet interface
449 * @param[in] set - The set selector for determining address index
450 * @param[in] origins - Set of valid origins for address filtering
451 */
452void getLanIPv6Address(message::Payload& ret, uint8_t channel, uint8_t set,
453 const std::unordered_set<IP::AddressOrigin>& origins)
454{
455 auto source = IPv6Source::Static;
456 bool enabled = false;
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700457 stdplus::In6Addr addr{};
Johnathan Mantey5aae0922021-10-21 13:05:36 -0700458 uint8_t prefix{};
William A. Kennington III16064aa2019-04-13 17:44:53 -0700459 auto status = IPv6AddressStatus::Disabled;
460
461 auto ifaddr = channelCall<getIfAddr<AF_INET6>>(channel, set, origins);
462 if (ifaddr)
463 {
464 source = originToSourceType(ifaddr->origin);
Johnathan Mantey846af862021-10-21 12:48:54 -0700465 enabled = (origins == originsV6Static);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700466 addr = ifaddr->address;
467 prefix = ifaddr->prefix;
468 status = IPv6AddressStatus::Active;
469 }
470
471 ret.pack(set);
William A. Kennington III7a0e5df2021-05-19 13:31:29 -0700472 ret.pack(types::enum_cast<uint4_t>(source), uint3_t{}, enabled);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700473 ret.pack(stdplus::raw::asView<char>(addr));
William A. Kennington III16064aa2019-04-13 17:44:53 -0700474 ret.pack(prefix);
William A. Kennington III7a0e5df2021-05-19 13:31:29 -0700475 ret.pack(types::enum_cast<uint8_t>(status));
William A. Kennington III16064aa2019-04-13 17:44:53 -0700476}
477
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700478/** @brief Gets the vlan ID configured on the interface
479 *
480 * @param[in] bus - The bus object used for lookups
481 * @param[in] params - The parameters for the channel
482 * @return VLAN id or the standard 0 for no VLAN
483 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500484uint16_t getVLANProperty(sdbusplus::bus_t& bus, const ChannelParams& params)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700485{
486 // VLAN devices will always have a separate logical object
487 if (params.ifPath == params.logicalPath)
488 {
489 return 0;
490 }
491
492 auto vlan = std::get<uint32_t>(getDbusProperty(
493 bus, params.service, params.logicalPath, INTF_VLAN, "Id"));
494 if ((vlan & VLAN_VALUE_MASK) != vlan)
495 {
496 logWithChannel<level::ERR>(params, "networkd returned an invalid vlan",
497 entry("VLAN=%" PRIu32, vlan));
Tom Josepha30c8d32018-03-22 02:15:03 +0530498 elog<InternalFailure>();
499 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700500 return vlan;
Tom Josepha30c8d32018-03-22 02:15:03 +0530501}
502
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700503/** @brief Deletes all of the possible configuration parameters for a channel
504 *
505 * @param[in] bus - The bus object used for lookups
506 * @param[in] params - The parameters for the channel
507 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500508void deconfigureChannel(sdbusplus::bus_t& bus, ChannelParams& params)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500509{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700510 // Delete all objects associated with the interface
George Liuc1c7eac2024-02-04 17:24:19 +0800511 ObjectTree objs =
512 ipmi::getSubTree(bus, std::vector<std::string>{DELETE_INTERFACE},
513 std::string{PATH_ROOT});
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700514 for (const auto& [path, impls] : objs)
515 {
William A. Kennington IIIc72f3602023-10-19 03:51:37 -0700516 if (!ifnameInPath(params.ifname, path))
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700517 {
518 continue;
519 }
520 for (const auto& [service, intfs] : impls)
521 {
522 deleteObjectIfExists(bus, service, path);
523 }
524 // Update params to reflect the deletion of vlan
525 if (path == params.logicalPath)
526 {
527 params.logicalPath = params.ifPath;
528 }
529 }
530
531 // Clear out any settings on the lower physical interface
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700532 setEthProp(bus, params, "DHCP4", false);
533 setEthProp(bus, params, "DHCP6", false);
534 setEthProp(bus, params, "IPv6AcceptRA", false);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500535}
536
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700537/** @brief Creates a new VLAN on the specified interface
538 *
539 * @param[in] bus - The bus object used for lookups
540 * @param[in] params - The parameters for the channel
541 * @param[in] vlan - The id of the new vlan
542 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500543void createVLAN(sdbusplus::bus_t& bus, ChannelParams& params, uint16_t vlan)
Ratan Guptab8e99552017-07-27 07:07:48 +0530544{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700545 if (vlan == 0)
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530546 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700547 return;
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530548 }
549
William A. Kennington IIIc72f3602023-10-19 03:51:37 -0700550 auto req = bus.new_method_call(params.service.c_str(), PATH_ROOT.c_str(),
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700551 INTF_VLAN_CREATE, "VLAN");
552 req.append(params.ifname, static_cast<uint32_t>(vlan));
553 auto reply = bus.call(req);
554 sdbusplus::message::object_path newPath;
555 reply.read(newPath);
556 params.logicalPath = std::move(newPath);
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530557}
558
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700559/** @brief Performs the necessary reconfiguration to change the VLAN
560 *
561 * @param[in] bus - The bus object used for lookups
562 * @param[in] params - The parameters for the channel
563 * @param[in] vlan - The new vlan id to use
564 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500565void reconfigureVLAN(sdbusplus::bus_t& bus, ChannelParams& params,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700566 uint16_t vlan)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500567{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700568 // Unfortunatetly we don't have built-in functions to migrate our interface
569 // customizations to new VLAN interfaces, or have some kind of decoupling.
570 // We therefore must retain all of our old information, setup the new VLAN
571 // configuration, then restore the old info.
Nan Li3d0df912016-10-18 19:51:41 +0800572
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700573 // Save info from the old logical interface
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700574 bool dhcp4 = getEthProp<bool>(bus, params, "DHCP4");
575 bool dhcp6 = getEthProp<bool>(bus, params, "DHCP6");
576 bool ra = getEthProp<bool>(bus, params, "IPv6AcceptRA");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700577 ObjectLookupCache ips(bus, params, INTF_IP);
578 auto ifaddr4 = findIfAddr<AF_INET>(bus, params, 0, originsV4, ips);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700579 std::vector<IfAddr<AF_INET6>> ifaddrs6;
580 for (uint8_t i = 0; i < MAX_IPV6_STATIC_ADDRESSES; ++i)
581 {
Patrick Williams1318a5e2024-08-16 15:19:54 -0400582 auto ifaddr6 =
583 findIfAddr<AF_INET6>(bus, params, i, originsV6Static, ips);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700584 if (!ifaddr6)
585 {
586 break;
587 }
588 ifaddrs6.push_back(std::move(*ifaddr6));
589 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700590 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
591 auto neighbor4 = findGatewayNeighbor<AF_INET>(bus, params, neighbors);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700592 auto neighbor6 = findGatewayNeighbor<AF_INET6>(bus, params, neighbors);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500593
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700594 deconfigureChannel(bus, params);
595 createVLAN(bus, params, vlan);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500596
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700597 // Re-establish the saved settings
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700598 setEthProp(bus, params, "DHCP4", dhcp4);
599 setEthProp(bus, params, "DHCP6", dhcp6);
600 setEthProp(bus, params, "IPv6AcceptRA", ra);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700601 if (ifaddr4)
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800602 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700603 createIfAddr<AF_INET>(bus, params, ifaddr4->address, ifaddr4->prefix);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800604 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700605 for (const auto& ifaddr6 : ifaddrs6)
606 {
607 createIfAddr<AF_INET6>(bus, params, ifaddr6.address, ifaddr6.prefix);
608 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700609 if (neighbor4)
610 {
611 createNeighbor<AF_INET>(bus, params, neighbor4->ip, neighbor4->mac);
612 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700613 if (neighbor6)
614 {
615 createNeighbor<AF_INET6>(bus, params, neighbor6->ip, neighbor6->mac);
616 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700617}
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800618
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700619// We need to store this value so it can be returned to the client
620// It is volatile so safe to store in daemon memory.
621static std::unordered_map<uint8_t, SetStatus> setStatus;
622
623// Until we have good support for fixed versions of IPMI tool
624// we need to return the VLAN id for disabled VLANs. The value is only
625// used for verification that a disable operation succeeded and will only
626// be sent if our system indicates that vlans are disabled.
627static std::unordered_map<uint8_t, uint16_t> lastDisabledVlan;
628
629/** @brief Gets the set status for the channel if it exists
630 * Otherise populates and returns the default value.
631 *
632 * @param[in] channel - The channel id corresponding to an ethernet interface
633 * @return A reference to the SetStatus for the channel
634 */
635SetStatus& getSetStatus(uint8_t channel)
636{
637 auto it = setStatus.find(channel);
638 if (it != setStatus.end())
639 {
640 return it->second;
641 }
642 return setStatus[channel] = SetStatus::Complete;
643}
644
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700645/** @brief Unpacks the trivially copyable type from the message */
646template <typename T>
647static T unpackT(message::Payload& req)
648{
649 std::array<uint8_t, sizeof(T)> bytes;
650 if (req.unpack(bytes) != 0)
651 {
652 throw ccReqDataLenInvalid;
653 }
654 return stdplus::raw::copyFrom<T>(bytes);
655}
656
657/** @brief Ensure the message is fully unpacked */
658static void unpackFinal(message::Payload& req)
659{
660 if (!req.fullyUnpacked())
661 {
662 throw ccReqDataTruncated;
663 }
664}
665
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700666/**
667 * Define placeholder command handlers for the OEM Extension bytes for the Set
668 * LAN Configuration Parameters and Get LAN Configuration Parameters
669 * commands. Using "weak" linking allows the placeholder setLanOem/getLanOem
670 * functions below to be overridden.
671 * To create handlers for your own proprietary command set:
672 * Create/modify a phosphor-ipmi-host Bitbake append file within your Yocto
673 * recipe
674 * Create C++ file(s) that define IPMI handler functions matching the
675 * function names below (i.e. setLanOem). The default name for the
676 * transport IPMI commands is transporthandler_oem.cpp.
677 * Add:
Johnathan Manteyefe26682022-08-11 14:30:45 -0700678 * EXTRA_OEMESON:append = "-Dtransport-oem=enabled"
679 * Create a do_configure:prepend()/do_install:append() method in your
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700680 * bbappend file to copy the file to the build directory.
681 * Add:
682 * PROJECT_SRC_DIR := "${THISDIR}/${PN}"
683 * # Copy the "strong" functions into the working directory, overriding the
684 * # placeholder functions.
Johnathan Manteyefe26682022-08-11 14:30:45 -0700685 * do_configure:prepend(){
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700686 * cp -f ${PROJECT_SRC_DIR}/transporthandler_oem.cpp ${S}
687 * }
688 *
689 * # Clean up after complilation has completed
Johnathan Manteyefe26682022-08-11 14:30:45 -0700690 * do_install:append(){
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700691 * rm -f ${S}/transporthandler_oem.cpp
692 * }
693 *
694 */
695
696/**
697 * Define the placeholder OEM commands as having weak linkage. Create
698 * setLanOem, and getLanOem functions in the transporthandler_oem.cpp
699 * file. The functions defined there must not have the "weak" attribute
700 * applied to them.
701 */
702RspType<> setLanOem(uint8_t channel, uint8_t parameter, message::Payload& req)
703 __attribute__((weak));
Patrick Williams1318a5e2024-08-16 15:19:54 -0400704RspType<message::Payload>
705 getLanOem(uint8_t channel, uint8_t parameter, uint8_t set, uint8_t block)
706 __attribute__((weak));
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700707
Willy Tu11d68892022-01-20 10:37:34 -0800708RspType<> setLanOem(uint8_t, uint8_t, message::Payload& req)
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700709{
710 req.trailingOk = true;
711 return response(ccParamNotSupported);
712}
713
Willy Tu11d68892022-01-20 10:37:34 -0800714RspType<message::Payload> getLanOem(uint8_t, uint8_t, uint8_t, uint8_t)
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700715{
716 return response(ccParamNotSupported);
717}
718
Jian Zhangcf19d142023-07-31 10:22:53 +0800719/**
720 * @brief is a valid LAN channel.
721 *
722 * This function checks whether the input channel is a valid LAN channel or not.
723 *
724 * @param[in] channel: the channel number.
725 * @return nullopt if the channel is invalid, false if the channel is not a LAN
726 * channel, true if the channel is a LAN channel.
727 **/
728std::optional<bool> isLanChannel(uint8_t channel)
729{
730 ChannelInfo chInfo;
731 auto cc = getChannelInfo(channel, chInfo);
732 if (cc != ccSuccess)
733 {
734 return std::nullopt;
735 }
736
737 return chInfo.mediumType ==
738 static_cast<uint8_t>(EChannelMediumType::lan8032);
739}
740
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700741RspType<> setLanInt(Context::ptr ctx, uint4_t channelBits, uint4_t reserved1,
742 uint8_t parameter, message::Payload& req)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700743{
vijayabharathix shettycc769252020-02-27 17:52:20 +0000744 const uint8_t channel = convertCurrentChannelNum(
745 static_cast<uint8_t>(channelBits), ctx->channel);
746 if (reserved1 || !isValidChannel(channel))
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700747 {
George Liu32e8f5d2024-07-17 19:52:25 +0800748 lg2::error("Set Lan - Invalid field in request");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700749 req.trailingOk = true;
750 return responseInvalidFieldRequest();
751 }
752
Jian Zhangcf19d142023-07-31 10:22:53 +0800753 if (!isLanChannel(channel).value_or(false))
754 {
George Liu32e8f5d2024-07-17 19:52:25 +0800755 lg2::error("Set Lan - Not a LAN channel");
Jian Zhangcf19d142023-07-31 10:22:53 +0800756 return responseInvalidFieldRequest();
757 }
758
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700759 switch (static_cast<LanParam>(parameter))
760 {
761 case LanParam::SetStatus:
762 {
763 uint2_t flag;
764 uint6_t rsvd;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700765 if (req.unpack(flag, rsvd) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700766 {
767 return responseReqDataLenInvalid();
768 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700769 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800770 if (rsvd)
771 {
772 return responseInvalidFieldRequest();
773 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700774 auto status = static_cast<SetStatus>(static_cast<uint8_t>(flag));
775 switch (status)
776 {
777 case SetStatus::Complete:
778 {
779 getSetStatus(channel) = status;
780 return responseSuccess();
781 }
782 case SetStatus::InProgress:
783 {
784 auto& storedStatus = getSetStatus(channel);
785 if (storedStatus == SetStatus::InProgress)
786 {
787 return response(ccParamSetLocked);
788 }
789 storedStatus = status;
790 return responseSuccess();
791 }
792 case SetStatus::Commit:
793 if (getSetStatus(channel) != SetStatus::InProgress)
794 {
795 return responseInvalidFieldRequest();
796 }
797 return responseSuccess();
798 }
799 return response(ccParamNotSupported);
800 }
801 case LanParam::AuthSupport:
802 {
803 req.trailingOk = true;
804 return response(ccParamReadOnly);
805 }
806 case LanParam::AuthEnables:
807 {
808 req.trailingOk = true;
Johnathan Mantey76ce9c72019-11-14 14:41:46 -0800809 return response(ccParamReadOnly);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700810 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800811 case LanParam::IP:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600812 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700813 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800814 {
815 return responseCommandNotAvailable();
816 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700817 auto ip = unpackT<stdplus::In4Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700818 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700819 channelCall<reconfigureIfAddr4>(channel, ip, std::nullopt);
820 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +0530821 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700822 case LanParam::IPSrc:
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530823 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700824 uint4_t flag;
825 uint4_t rsvd;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700826 if (req.unpack(flag, rsvd) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700827 {
828 return responseReqDataLenInvalid();
829 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700830 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800831 if (rsvd)
832 {
833 return responseInvalidFieldRequest();
834 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700835 switch (static_cast<IPSrc>(static_cast<uint8_t>(flag)))
836 {
837 case IPSrc::DHCP:
Johnathan Mantey65265362019-11-14 11:24:19 -0800838 // The IPSrc IPMI command is only for IPv4
839 // management. Modifying IPv6 state is done using
840 // a completely different Set LAN Configuration
841 // subcommand.
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700842 channelCall<setEthProp<bool>>(channel, "DHCP4", true);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700843 return responseSuccess();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700844 case IPSrc::Unspecified:
845 case IPSrc::Static:
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700846 channelCall<setEthProp<bool>>(channel, "DHCP4", false);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700847 return responseSuccess();
Rajashekar Gade Reddy8a860ea2019-12-24 11:31:19 +0530848 case IPSrc::BIOS:
849 case IPSrc::BMC:
Rajashekar Gade Reddy8a860ea2019-12-24 11:31:19 +0530850 return responseInvalidFieldRequest();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700851 }
852 return response(ccParamNotSupported);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530853 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800854 case LanParam::MAC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530855 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700856 auto mac = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700857 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700858 channelCall<setMACProperty>(channel, mac);
859 return responseSuccess();
Ratan Gupta533d03b2017-07-30 10:39:22 +0530860 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700861 case LanParam::SubnetMask:
Ratan Guptab8e99552017-07-27 07:07:48 +0530862 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700863 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800864 {
865 return responseCommandNotAvailable();
866 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700867 auto pfx = stdplus::maskToPfx(unpackT<stdplus::In4Addr>(req));
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700868 unpackFinal(req);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700869 channelCall<reconfigureIfAddr4>(channel, std::nullopt, pfx);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700870 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +0530871 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700872 case LanParam::Gateway1:
Ratan Guptab8e99552017-07-27 07:07:48 +0530873 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700874 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800875 {
876 return responseCommandNotAvailable();
877 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700878 auto gateway = unpackT<stdplus::In4Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700879 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700880 channelCall<setGatewayProperty<AF_INET>>(channel, gateway);
881 return responseSuccess();
882 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700883 case LanParam::Gateway1MAC:
884 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700885 auto gatewayMAC = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700886 unpackFinal(req);
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700887 channelCall<reconfigureGatewayMAC<AF_INET>>(channel, gatewayMAC);
888 return responseSuccess();
889 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700890 case LanParam::VLANId:
891 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700892 uint12_t vlanData;
893 uint3_t rsvd;
894 bool vlanEnable;
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530895
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700896 if (req.unpack(vlanData, rsvd, vlanEnable) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700897 {
898 return responseReqDataLenInvalid();
899 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700900 unpackFinal(req);
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530901
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700902 if (rsvd)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700903 {
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530904 return responseInvalidFieldRequest();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700905 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530906
907 uint16_t vlan = static_cast<uint16_t>(vlanData);
908
909 if (!vlanEnable)
910 {
911 lastDisabledVlan[channel] = vlan;
912 vlan = 0;
913 }
Jayaprakash Mutyala0d1d7ad2024-06-19 10:19:33 +0000914 else if (vlan == 0 || vlan == VLAN_VALUE_MASK)
915 {
916 return responseInvalidFieldRequest();
917 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530918
jayaprakash Mutyala84c49dc2020-05-18 23:12:13 +0000919 channelCall<reconfigureVLAN>(channel, vlan);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700920 return responseSuccess();
921 }
922 case LanParam::CiphersuiteSupport:
923 case LanParam::CiphersuiteEntries:
William A. Kennington III16064aa2019-04-13 17:44:53 -0700924 case LanParam::IPFamilySupport:
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700925 {
926 req.trailingOk = true;
927 return response(ccParamReadOnly);
Ratan Guptab8e99552017-07-27 07:07:48 +0530928 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700929 case LanParam::IPFamilyEnables:
930 {
931 uint8_t enables;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700932 if (req.unpack(enables) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700933 {
934 return responseReqDataLenInvalid();
935 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700936 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700937 switch (static_cast<IPFamilyEnables>(enables))
938 {
939 case IPFamilyEnables::DualStack:
940 return responseSuccess();
941 case IPFamilyEnables::IPv4Only:
942 case IPFamilyEnables::IPv6Only:
943 return response(ccParamNotSupported);
944 }
945 return response(ccParamNotSupported);
946 }
947 case LanParam::IPv6Status:
948 {
949 req.trailingOk = true;
950 return response(ccParamReadOnly);
951 }
952 case LanParam::IPv6StaticAddresses:
953 {
954 uint8_t set;
955 uint7_t rsvd;
956 bool enabled;
William A. Kennington III16064aa2019-04-13 17:44:53 -0700957 uint8_t prefix;
958 uint8_t status;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700959 if (req.unpack(set, rsvd, enabled) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700960 {
961 return responseReqDataLenInvalid();
962 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700963 auto ip = unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700964 if (req.unpack(prefix, status) != 0)
965 {
966 return responseReqDataLenInvalid();
967 }
968 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800969 if (rsvd)
970 {
971 return responseInvalidFieldRequest();
972 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700973 if (enabled)
974 {
Jiaqing Zhao6d4a44e2022-01-24 15:04:00 +0800975 if (prefix < MIN_IPV6_PREFIX_LENGTH ||
976 prefix > MAX_IPV6_PREFIX_LENGTH)
977 {
978 return responseParmOutOfRange();
979 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700980 channelCall<reconfigureIfAddr6>(channel, set, ip, prefix);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700981 }
982 else
983 {
984 channelCall<deconfigureIfAddr6>(channel, set);
985 }
986 return responseSuccess();
987 }
988 case LanParam::IPv6DynamicAddresses:
989 {
990 req.trailingOk = true;
991 return response(ccParamReadOnly);
992 }
993 case LanParam::IPv6RouterControl:
994 {
995 std::bitset<8> control;
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800996 constexpr uint8_t reservedRACCBits = 0xfc;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700997 if (req.unpack(control) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700998 {
999 return responseReqDataLenInvalid();
1000 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001001 unpackFinal(req);
Patrick Williams1318a5e2024-08-16 15:19:54 -04001002 if (std::bitset<8> expected(
1003 control & std::bitset<8>(reservedRACCBits));
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001004 expected.any())
William A. Kennington III16064aa2019-04-13 17:44:53 -07001005 {
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001006 return response(ccParamNotSupported);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001007 }
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001008
1009 bool enableRA = control[IPv6RouterControlFlag::Dynamic];
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001010 channelCall<setEthProp<bool>>(channel, "IPv6AcceptRA", enableRA);
1011 channelCall<setEthProp<bool>>(channel, "DHCP6", enableRA);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001012 return responseSuccess();
1013 }
1014 case LanParam::IPv6StaticRouter1IP:
1015 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001016 auto gateway = unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001017 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001018 channelCall<setGatewayProperty<AF_INET6>>(channel, gateway);
1019 return responseSuccess();
1020 }
1021 case LanParam::IPv6StaticRouter1MAC:
1022 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001023 auto mac = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001024 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001025 channelCall<reconfigureGatewayMAC<AF_INET6>>(channel, mac);
1026 return responseSuccess();
1027 }
1028 case LanParam::IPv6StaticRouter1PrefixLength:
1029 {
1030 uint8_t prefix;
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001031 if (req.unpack(prefix) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -07001032 {
1033 return responseReqDataLenInvalid();
1034 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001035 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001036 if (prefix != 0)
1037 {
1038 return responseInvalidFieldRequest();
1039 }
1040 return responseSuccess();
1041 }
1042 case LanParam::IPv6StaticRouter1PrefixValue:
1043 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001044 unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001045 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001046 // Accept any prefix value since our prefix length has to be 0
1047 return responseSuccess();
1048 }
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001049 case LanParam::cipherSuitePrivilegeLevels:
1050 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001051 uint8_t rsvd;
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001052 std::array<uint4_t, ipmi::maxCSRecords> cipherSuitePrivs;
1053
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001054 if (req.unpack(rsvd, cipherSuitePrivs))
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001055 {
1056 return responseReqDataLenInvalid();
1057 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001058 unpackFinal(req);
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001059
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001060 if (rsvd)
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001061 {
1062 return responseInvalidFieldRequest();
1063 }
1064
Patrick Williams1318a5e2024-08-16 15:19:54 -04001065 uint8_t resp =
1066 getCipherConfigObject(csPrivFileName, csPrivDefaultFileName)
1067 .setCSPrivilegeLevels(channel, cipherSuitePrivs);
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001068 if (!resp)
1069 {
1070 return responseSuccess();
1071 }
1072 else
1073 {
1074 req.trailingOk = true;
1075 return response(resp);
1076 }
1077 }
Ratan Guptab8e99552017-07-27 07:07:48 +05301078 }
vishwa1eaea4f2016-02-26 11:57:40 -06001079
PavanKumarIntel3771f5f2023-11-02 06:26:42 +00001080 if (parameter >= oemCmdStart)
Johnathan Manteyb87034e2019-09-16 10:50:50 -07001081 {
1082 return setLanOem(channel, parameter, req);
1083 }
1084
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001085 req.trailingOk = true;
1086 return response(ccParamNotSupported);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001087}
1088
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001089RspType<> setLan(Context::ptr ctx, uint4_t channelBits, uint4_t reserved1,
1090 uint8_t parameter, message::Payload& req)
1091{
1092 try
1093 {
1094 return setLanInt(ctx, channelBits, reserved1, parameter, req);
1095 }
1096 catch (ipmi::Cc cc)
1097 {
1098 return response(cc);
1099 }
1100 catch (const sdbusplus::exception_t& e)
1101 {
1102 if (std::string_view{InvalidArgument::errName} == e.name())
1103 {
1104 return responseInvalidFieldRequest();
1105 }
1106 throw;
1107 }
1108}
1109
vijayabharathix shettycc769252020-02-27 17:52:20 +00001110RspType<message::Payload> getLan(Context::ptr ctx, uint4_t channelBits,
1111 uint3_t reserved, bool revOnly,
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001112 uint8_t parameter, uint8_t set, uint8_t block)
Ratan Guptab8e99552017-07-27 07:07:48 +05301113{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001114 message::Payload ret;
1115 constexpr uint8_t current_revision = 0x11;
1116 ret.pack(current_revision);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001117
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001118 if (revOnly)
Suryakanth Sekare4054402019-08-08 15:16:52 +05301119 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001120 return responseSuccess(std::move(ret));
Suryakanth Sekare4054402019-08-08 15:16:52 +05301121 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001122
vijayabharathix shettycc769252020-02-27 17:52:20 +00001123 const uint8_t channel = convertCurrentChannelNum(
1124 static_cast<uint8_t>(channelBits), ctx->channel);
1125 if (reserved || !isValidChannel(channel))
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001126 {
George Liu32e8f5d2024-07-17 19:52:25 +08001127 lg2::error("Get Lan - Invalid field in request");
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001128 return responseInvalidFieldRequest();
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001129 }
1130
Jian Zhangcf19d142023-07-31 10:22:53 +08001131 if (!isLanChannel(channel).value_or(false))
1132 {
George Liu32e8f5d2024-07-17 19:52:25 +08001133 lg2::error("Set Lan - Not a LAN channel");
Jian Zhangcf19d142023-07-31 10:22:53 +08001134 return responseInvalidFieldRequest();
1135 }
1136
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001137 static std::vector<uint8_t> cipherList;
1138 static bool listInit = false;
1139 if (!listInit)
1140 {
1141 try
1142 {
1143 cipherList = cipher::getCipherList();
1144 listInit = true;
1145 }
1146 catch (const std::exception& e)
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -05001147 {}
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001148 }
1149
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001150 switch (static_cast<LanParam>(parameter))
Tom Josepha30c8d32018-03-22 02:15:03 +05301151 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001152 case LanParam::SetStatus:
Tom Josepha30c8d32018-03-22 02:15:03 +05301153 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001154 SetStatus status;
1155 try
1156 {
1157 status = setStatus.at(channel);
1158 }
1159 catch (const std::out_of_range&)
1160 {
1161 status = SetStatus::Complete;
1162 }
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001163 ret.pack(types::enum_cast<uint2_t>(status), uint6_t{});
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001164 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301165 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001166 case LanParam::AuthSupport:
Tom Josepha30c8d32018-03-22 02:15:03 +05301167 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001168 std::bitset<6> support;
1169 ret.pack(support, uint2_t{});
1170 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301171 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001172 case LanParam::AuthEnables:
vishwa1eaea4f2016-02-26 11:57:40 -06001173 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001174 std::bitset<6> enables;
1175 ret.pack(enables, uint2_t{}); // Callback
1176 ret.pack(enables, uint2_t{}); // User
1177 ret.pack(enables, uint2_t{}); // Operator
1178 ret.pack(enables, uint2_t{}); // Admin
1179 ret.pack(enables, uint2_t{}); // OEM
1180 return responseSuccess(std::move(ret));
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001181 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001182 case LanParam::IP:
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001183 {
1184 auto ifaddr = channelCall<getIfAddr4>(channel);
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001185 stdplus::In4Addr addr{};
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001186 if (ifaddr)
1187 {
1188 addr = ifaddr->address;
1189 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001190 ret.pack(stdplus::raw::asView<char>(addr));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001191 return responseSuccess(std::move(ret));
1192 }
1193 case LanParam::IPSrc:
1194 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001195 auto src = channelCall<getEthProp<bool>>(channel, "DHCP4")
1196 ? IPSrc::DHCP
1197 : IPSrc::Static;
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001198 ret.pack(types::enum_cast<uint4_t>(src), uint4_t{});
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001199 return responseSuccess(std::move(ret));
1200 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001201 case LanParam::MAC:
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001202 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001203 auto mac = channelCall<getMACProperty>(channel);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001204 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001205 return responseSuccess(std::move(ret));
1206 }
1207 case LanParam::SubnetMask:
1208 {
1209 auto ifaddr = channelCall<getIfAddr4>(channel);
1210 uint8_t prefix = AddrFamily<AF_INET>::defaultPrefix;
1211 if (ifaddr)
Ratan Guptab8e99552017-07-27 07:07:48 +05301212 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001213 prefix = ifaddr->prefix;
1214 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001215 auto netmask = stdplus::pfxToMask<stdplus::In4Addr>(prefix);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001216 ret.pack(stdplus::raw::asView<char>(netmask));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001217 return responseSuccess(std::move(ret));
1218 }
1219 case LanParam::Gateway1:
1220 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001221 auto gateway = channelCall<getGatewayProperty<AF_INET>>(channel);
1222 ret.pack(stdplus::raw::asView<char>(
1223 gateway.value_or(stdplus::In4Addr{})));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001224 return responseSuccess(std::move(ret));
1225 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001226 case LanParam::Gateway1MAC:
1227 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001228 stdplus::EtherAddr mac{};
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001229 auto neighbor = channelCall<getGatewayNeighbor<AF_INET>>(channel);
1230 if (neighbor)
1231 {
1232 mac = neighbor->mac;
1233 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001234 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001235 return responseSuccess(std::move(ret));
1236 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001237 case LanParam::VLANId:
1238 {
1239 uint16_t vlan = channelCall<getVLANProperty>(channel);
1240 if (vlan != 0)
1241 {
1242 vlan |= VLAN_ENABLE_FLAG;
Ratan Guptab8e99552017-07-27 07:07:48 +05301243 }
1244 else
1245 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001246 vlan = lastDisabledVlan[channel];
Ratan Guptab8e99552017-07-27 07:07:48 +05301247 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001248 ret.pack(vlan);
1249 return responseSuccess(std::move(ret));
Adriana Kobylak342df102016-02-10 13:48:16 -06001250 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001251 case LanParam::CiphersuiteSupport:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001252 {
srikanta mondal1d8579c2020-04-15 17:13:25 +00001253 if (getChannelSessionSupport(channel) ==
1254 EChannelSessSupported::none)
1255 {
1256 return responseInvalidFieldRequest();
1257 }
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001258 if (!listInit)
1259 {
1260 return responseUnspecifiedError();
1261 }
1262 ret.pack(static_cast<uint8_t>(cipherList.size() - 1));
1263 return responseSuccess(std::move(ret));
1264 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001265 case LanParam::CiphersuiteEntries:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001266 {
srikanta mondal1d8579c2020-04-15 17:13:25 +00001267 if (getChannelSessionSupport(channel) ==
1268 EChannelSessSupported::none)
1269 {
1270 return responseInvalidFieldRequest();
1271 }
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001272 if (!listInit)
1273 {
1274 return responseUnspecifiedError();
1275 }
1276 ret.pack(cipherList);
1277 return responseSuccess(std::move(ret));
1278 }
William A. Kennington III16064aa2019-04-13 17:44:53 -07001279 case LanParam::IPFamilySupport:
1280 {
1281 std::bitset<8> support;
1282 support[IPFamilySupportFlag::IPv6Only] = 0;
1283 support[IPFamilySupportFlag::DualStack] = 1;
1284 support[IPFamilySupportFlag::IPv6Alerts] = 1;
1285 ret.pack(support);
1286 return responseSuccess(std::move(ret));
1287 }
1288 case LanParam::IPFamilyEnables:
1289 {
1290 ret.pack(static_cast<uint8_t>(IPFamilyEnables::DualStack));
1291 return responseSuccess(std::move(ret));
1292 }
1293 case LanParam::IPv6Status:
1294 {
1295 ret.pack(MAX_IPV6_STATIC_ADDRESSES);
1296 ret.pack(MAX_IPV6_DYNAMIC_ADDRESSES);
1297 std::bitset<8> support;
1298 support[IPv6StatusFlag::DHCP] = 1;
1299 support[IPv6StatusFlag::SLAAC] = 1;
1300 ret.pack(support);
1301 return responseSuccess(std::move(ret));
1302 }
1303 case LanParam::IPv6StaticAddresses:
1304 {
1305 if (set >= MAX_IPV6_STATIC_ADDRESSES)
1306 {
1307 return responseParmOutOfRange();
1308 }
1309 getLanIPv6Address(ret, channel, set, originsV6Static);
1310 return responseSuccess(std::move(ret));
1311 }
1312 case LanParam::IPv6DynamicAddresses:
1313 {
1314 if (set >= MAX_IPV6_DYNAMIC_ADDRESSES)
1315 {
1316 return responseParmOutOfRange();
1317 }
1318 getLanIPv6Address(ret, channel, set, originsV6Dynamic);
1319 return responseSuccess(std::move(ret));
1320 }
1321 case LanParam::IPv6RouterControl:
1322 {
1323 std::bitset<8> control;
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001324 control[IPv6RouterControlFlag::Dynamic] =
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001325 channelCall<getEthProp<bool>>(channel, "IPv6AcceptRA");
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001326 control[IPv6RouterControlFlag::Static] = 1;
William A. Kennington III16064aa2019-04-13 17:44:53 -07001327 ret.pack(control);
1328 return responseSuccess(std::move(ret));
1329 }
1330 case LanParam::IPv6StaticRouter1IP:
1331 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001332 stdplus::In6Addr gateway{};
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001333 if (!channelCall<getEthProp<bool>>(channel, "IPv6AcceptRA"))
William A. Kennington III16064aa2019-04-13 17:44:53 -07001334 {
1335 gateway =
1336 channelCall<getGatewayProperty<AF_INET6>>(channel).value_or(
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001337 stdplus::In6Addr{});
William A. Kennington III16064aa2019-04-13 17:44:53 -07001338 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001339 ret.pack(stdplus::raw::asView<char>(gateway));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001340 return responseSuccess(std::move(ret));
1341 }
1342 case LanParam::IPv6StaticRouter1MAC:
1343 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001344 stdplus::EtherAddr mac{};
William A. Kennington III16064aa2019-04-13 17:44:53 -07001345 auto neighbor = channelCall<getGatewayNeighbor<AF_INET6>>(channel);
1346 if (neighbor)
1347 {
1348 mac = neighbor->mac;
1349 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001350 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001351 return responseSuccess(std::move(ret));
1352 }
1353 case LanParam::IPv6StaticRouter1PrefixLength:
1354 {
Jian Zhang796e8242024-02-01 14:07:34 +08001355 ret.pack(uint8_t{0});
William A. Kennington III16064aa2019-04-13 17:44:53 -07001356 return responseSuccess(std::move(ret));
1357 }
1358 case LanParam::IPv6StaticRouter1PrefixValue:
1359 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001360 ret.pack(stdplus::raw::asView<char>(stdplus::In6Addr{}));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001361 return responseSuccess(std::move(ret));
1362 }
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001363 case LanParam::cipherSuitePrivilegeLevels:
1364 {
1365 std::array<uint4_t, ipmi::maxCSRecords> csPrivilegeLevels;
1366
1367 uint8_t resp =
1368 getCipherConfigObject(csPrivFileName, csPrivDefaultFileName)
1369 .getCSPrivilegeLevels(channel, csPrivilegeLevels);
1370 if (!resp)
1371 {
1372 constexpr uint8_t reserved1 = 0x00;
1373 ret.pack(reserved1, csPrivilegeLevels);
1374 return responseSuccess(std::move(ret));
1375 }
1376 else
1377 {
1378 return response(resp);
1379 }
1380 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001381 }
1382
PavanKumarIntel3771f5f2023-11-02 06:26:42 +00001383 if (parameter >= oemCmdStart)
Johnathan Manteyb87034e2019-09-16 10:50:50 -07001384 {
1385 return getLanOem(channel, parameter, set, block);
1386 }
1387
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001388 return response(ccParamNotSupported);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001389}
1390
Jian Zhang23f44652022-03-17 17:13:10 +08001391constexpr const char* solInterface = "xyz.openbmc_project.Ipmi.SOL";
1392constexpr const char* solPath = "/xyz/openbmc_project/ipmi/sol/";
1393constexpr const uint16_t solDefaultPort = 623;
1394
1395RspType<> setSolConfParams(Context::ptr ctx, uint4_t channelBits,
Willy Tu11d68892022-01-20 10:37:34 -08001396 uint4_t /*reserved*/, uint8_t parameter,
Jian Zhang23f44652022-03-17 17:13:10 +08001397 message::Payload& req)
1398{
1399 const uint8_t channel = convertCurrentChannelNum(
1400 static_cast<uint8_t>(channelBits), ctx->channel);
1401
1402 if (!isValidChannel(channel))
1403 {
George Liu32e8f5d2024-07-17 19:52:25 +08001404 lg2::error("Set Sol Config - Invalid channel in request");
Jian Zhang23f44652022-03-17 17:13:10 +08001405 return responseInvalidFieldRequest();
1406 }
1407
1408 std::string solService{};
1409 std::string solPathWitheEthName = solPath + ipmi::getChannelName(channel);
1410
1411 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1412 {
George Liu32e8f5d2024-07-17 19:52:25 +08001413 lg2::error("Set Sol Config - Invalid solInterface, service: {SERVICE}, "
1414 "object path: {OBJPATH}, interface: {INTERFACE}",
1415 "SERVICE", solService, "OBJPATH", solPathWitheEthName,
1416 "INTERFACE", solInterface);
Jian Zhang23f44652022-03-17 17:13:10 +08001417 return responseInvalidFieldRequest();
1418 }
1419
1420 switch (static_cast<SolConfParam>(parameter))
1421 {
1422 case SolConfParam::Progress:
1423 {
1424 uint8_t progress;
1425 if (req.unpack(progress) != 0 || !req.fullyUnpacked())
1426 {
1427 return responseReqDataLenInvalid();
1428 }
1429
1430 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1431 solInterface, "Progress", progress))
1432 {
1433 return responseUnspecifiedError();
1434 }
1435 break;
1436 }
1437 case SolConfParam::Enable:
1438 {
1439 bool enable;
1440 uint7_t reserved2;
1441
1442 if (req.unpack(enable, reserved2) != 0 || !req.fullyUnpacked())
1443 {
1444 return responseReqDataLenInvalid();
1445 }
1446
1447 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1448 solInterface, "Enable", enable))
1449 {
1450 return responseUnspecifiedError();
1451 }
1452 break;
1453 }
1454 case SolConfParam::Authentication:
1455 {
1456 uint4_t privilegeBits{};
1457 uint2_t reserved2{};
1458 bool forceAuth = false;
1459 bool forceEncrypt = false;
1460
1461 if (req.unpack(privilegeBits, reserved2, forceAuth, forceEncrypt) !=
1462 0 ||
1463 !req.fullyUnpacked())
1464 {
1465 return responseReqDataLenInvalid();
1466 }
1467
1468 uint8_t privilege = static_cast<uint8_t>(privilegeBits);
Jonathan Domana48bf772023-05-26 17:54:57 -07001469 if (privilege < static_cast<uint8_t>(Privilege::User) ||
Jian Zhang23f44652022-03-17 17:13:10 +08001470 privilege > static_cast<uint8_t>(Privilege::Oem))
1471 {
1472 return ipmi::responseInvalidFieldRequest();
1473 }
1474
1475 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1476 solInterface, "Privilege", privilege))
1477 {
1478 return responseUnspecifiedError();
1479 }
1480
1481 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1482 solInterface, "ForceEncryption",
1483 forceEncrypt))
1484 {
1485 return responseUnspecifiedError();
1486 }
1487
1488 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1489 solInterface, "ForceAuthentication",
1490 forceAuth))
1491 {
1492 return responseUnspecifiedError();
1493 }
1494 break;
1495 }
1496 case SolConfParam::Accumulate:
1497 {
1498 uint8_t interval;
1499 uint8_t threshold;
1500 if (req.unpack(interval, threshold) != 0 || !req.fullyUnpacked())
1501 {
1502 return responseReqDataLenInvalid();
1503 }
1504
1505 if (threshold == 0)
1506 {
1507 return responseInvalidFieldRequest();
1508 }
1509
1510 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1511 solInterface, "AccumulateIntervalMS",
1512 interval))
1513 {
1514 return responseUnspecifiedError();
1515 }
1516
1517 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1518 solInterface, "Threshold", threshold))
1519 {
1520 return responseUnspecifiedError();
1521 }
1522 break;
1523 }
1524 case SolConfParam::Retry:
1525 {
1526 uint3_t countBits;
1527 uint5_t reserved2;
1528 uint8_t interval;
1529
1530 if (req.unpack(countBits, reserved2, interval) != 0 ||
1531 !req.fullyUnpacked())
1532 {
1533 return responseReqDataLenInvalid();
1534 }
1535
1536 uint8_t count = static_cast<uint8_t>(countBits);
1537 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1538 solInterface, "RetryCount", count))
1539 {
1540 return responseUnspecifiedError();
1541 }
1542
1543 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1544 solInterface, "RetryIntervalMS",
1545 interval))
1546 {
1547 return responseUnspecifiedError();
1548 }
1549 break;
1550 }
1551 case SolConfParam::Port:
1552 {
1553 return response(ipmiCCWriteReadParameter);
1554 }
1555 case SolConfParam::NonVbitrate:
1556 case SolConfParam::Vbitrate:
1557 case SolConfParam::Channel:
1558 default:
1559 return response(ipmiCCParamNotSupported);
1560 }
1561 return responseSuccess();
1562}
1563
Patrick Williams1318a5e2024-08-16 15:19:54 -04001564RspType<message::Payload> getSolConfParams(
1565 Context::ptr ctx, uint4_t channelBits, uint3_t /*reserved*/, bool revOnly,
1566 uint8_t parameter, uint8_t /*set*/, uint8_t /*block*/)
Jian Zhang23f44652022-03-17 17:13:10 +08001567{
1568 message::Payload ret;
1569 constexpr uint8_t current_revision = 0x11;
1570 ret.pack(current_revision);
1571 if (revOnly)
1572 {
1573 return responseSuccess(std::move(ret));
1574 }
1575
1576 const uint8_t channel = convertCurrentChannelNum(
1577 static_cast<uint8_t>(channelBits), ctx->channel);
1578
1579 if (!isValidChannel(channel))
1580 {
George Liu32e8f5d2024-07-17 19:52:25 +08001581 lg2::error("Get Sol Config - Invalid channel in request");
Jian Zhang23f44652022-03-17 17:13:10 +08001582 return responseInvalidFieldRequest();
1583 }
1584
1585 std::string solService{};
1586 std::string solPathWitheEthName = solPath + ipmi::getChannelName(channel);
1587
1588 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1589 {
George Liu32e8f5d2024-07-17 19:52:25 +08001590 lg2::error("Set Sol Config - Invalid solInterface, service: {SERVICE}, "
1591 "object path: {OBJPATH}, interface: {INTERFACE}",
1592 "SERVICE", solService, "OBJPATH", solPathWitheEthName,
1593 "INTERFACE", solInterface);
Jian Zhang23f44652022-03-17 17:13:10 +08001594 return responseInvalidFieldRequest();
1595 }
1596
1597 switch (static_cast<SolConfParam>(parameter))
1598 {
1599 case SolConfParam::Progress:
1600 {
1601 uint8_t progress;
1602 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1603 solInterface, "Progress", progress))
1604 {
1605 return responseUnspecifiedError();
1606 }
1607 ret.pack(progress);
1608 return responseSuccess(std::move(ret));
1609 }
1610 case SolConfParam::Enable:
1611 {
1612 bool enable{};
1613 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1614 solInterface, "Enable", enable))
1615 {
1616 return responseUnspecifiedError();
1617 }
1618 ret.pack(enable, uint7_t{});
1619 return responseSuccess(std::move(ret));
1620 }
1621 case SolConfParam::Authentication:
1622 {
1623 // 4bits, cast when pack
1624 uint8_t privilege;
1625 bool forceAuth = false;
1626 bool forceEncrypt = false;
1627
1628 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1629 solInterface, "Privilege", privilege))
1630 {
1631 return responseUnspecifiedError();
1632 }
1633
1634 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1635 solInterface, "ForceAuthentication",
1636 forceAuth))
1637 {
1638 return responseUnspecifiedError();
1639 }
1640
1641 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1642 solInterface, "ForceEncryption",
1643 forceEncrypt))
1644 {
1645 return responseUnspecifiedError();
1646 }
1647 ret.pack(uint4_t{privilege}, uint2_t{}, forceAuth, forceEncrypt);
1648 return responseSuccess(std::move(ret));
1649 }
1650 case SolConfParam::Accumulate:
1651 {
1652 uint8_t interval{}, threshold{};
1653
1654 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1655 solInterface, "AccumulateIntervalMS",
1656 interval))
1657 {
1658 return responseUnspecifiedError();
1659 }
1660
1661 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1662 solInterface, "Threshold", threshold))
1663 {
1664 return responseUnspecifiedError();
1665 }
1666 ret.pack(interval, threshold);
1667 return responseSuccess(std::move(ret));
1668 }
1669 case SolConfParam::Retry:
1670 {
1671 // 3bits, cast when cast
1672 uint8_t count{};
1673 uint8_t interval{};
1674
1675 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1676 solInterface, "RetryCount", count))
1677 {
1678 return responseUnspecifiedError();
1679 }
1680
1681 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1682 solInterface, "RetryIntervalMS",
1683 interval))
1684 {
1685 return responseUnspecifiedError();
1686 }
1687 ret.pack(uint3_t{count}, uint5_t{}, interval);
1688 return responseSuccess(std::move(ret));
1689 }
1690 case SolConfParam::Port:
1691 {
1692 auto port = solDefaultPort;
1693 ret.pack(static_cast<uint16_t>(port));
1694 return responseSuccess(std::move(ret));
1695 }
1696 case SolConfParam::Channel:
1697 {
1698 ret.pack(channel);
1699 return responseSuccess(std::move(ret));
1700 }
1701 case SolConfParam::NonVbitrate:
Jonathan Domana48bf772023-05-26 17:54:57 -07001702 {
1703 uint64_t baudRate;
1704 uint8_t encodedBitRate = 0;
1705 if (ipmi::getDbusProperty(
1706 ctx, "xyz.openbmc_project.Console.default",
1707 "/xyz/openbmc_project/console/default",
1708 "xyz.openbmc_project.Console.UART", "Baud", baudRate))
1709 {
1710 return ipmi::responseUnspecifiedError();
1711 }
1712 switch (baudRate)
1713 {
1714 case 9600:
1715 encodedBitRate = 0x06;
1716 break;
1717 case 19200:
1718 encodedBitRate = 0x07;
1719 break;
1720 case 38400:
1721 encodedBitRate = 0x08;
1722 break;
1723 case 57600:
1724 encodedBitRate = 0x09;
1725 break;
1726 case 115200:
1727 encodedBitRate = 0x0a;
1728 break;
1729 default:
1730 break;
1731 }
1732 ret.pack(encodedBitRate);
1733 return responseSuccess(std::move(ret));
1734 }
Jian Zhang23f44652022-03-17 17:13:10 +08001735 case SolConfParam::Vbitrate:
1736 default:
1737 return response(ipmiCCParamNotSupported);
1738 }
1739
1740 return response(ccParamNotSupported);
1741}
1742
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001743} // namespace transport
1744} // namespace ipmi
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301745
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001746void register_netfn_transport_functions() __attribute__((constructor));
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301747
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001748void register_netfn_transport_functions()
1749{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001750 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1751 ipmi::transport::cmdSetLanConfigParameters,
1752 ipmi::Privilege::Admin, ipmi::transport::setLan);
1753 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1754 ipmi::transport::cmdGetLanConfigParameters,
Johnathan Mantey34698d52019-11-19 14:47:30 -08001755 ipmi::Privilege::Operator, ipmi::transport::getLan);
Jian Zhang23f44652022-03-17 17:13:10 +08001756 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1757 ipmi::transport::cmdSetSolConfigParameters,
1758 ipmi::Privilege::Admin,
1759 ipmi::transport::setSolConfParams);
1760 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1761 ipmi::transport::cmdGetSolConfigParameters,
1762 ipmi::Privilege::User,
1763 ipmi::transport::getSolConfParams);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001764}