blob: 669728ef1bcfa554ff13cc46c007ee930416eb33 [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>
William A. Kennington III726f2bd2023-06-21 01:11:40 -07004#include <stdplus/net/addr/subnet.hpp>
William A. Kennington III7a3831b2023-06-21 01:10:49 -07005#include <stdplus/raw.hpp>
6
7#include <array>
William A. Kennington III726f2bd2023-06-21 01:11:40 -07008#include <fstream>
William A. Kennington III7a3831b2023-06-21 01:10:49 -07009
William A. Kennington IIIc514d872019-04-06 18:19:38 -070010using phosphor::logging::commit;
11using phosphor::logging::elog;
12using phosphor::logging::entry;
13using phosphor::logging::level;
14using phosphor::logging::log;
Willy Tu523e2d12023-09-05 11:36:48 -070015using sdbusplus::error::xyz::openbmc_project::common::InternalFailure;
William A. Kennington III7a3831b2023-06-21 01:10:49 -070016using sdbusplus::error::xyz::openbmc_project::common::InvalidArgument;
Willy Tu523e2d12023-09-05 11:36:48 -070017using sdbusplus::server::xyz::openbmc_project::network::EthernetInterface;
18using sdbusplus::server::xyz::openbmc_project::network::IP;
19using sdbusplus::server::xyz::openbmc_project::network::Neighbor;
William A. Kennington IIIc514d872019-04-06 18:19:38 -070020
Johnathan Manteyaffadb52019-10-07 10:13:53 -070021namespace cipher
22{
23
24std::vector<uint8_t> getCipherList()
25{
26 std::vector<uint8_t> cipherList;
27
28 std::ifstream jsonFile(cipher::configFile);
29 if (!jsonFile.is_open())
30 {
31 log<level::ERR>("Channel Cipher suites file not found");
32 elog<InternalFailure>();
33 }
34
35 auto data = Json::parse(jsonFile, nullptr, false);
36 if (data.is_discarded())
37 {
38 log<level::ERR>("Parsing channel cipher suites JSON failed");
39 elog<InternalFailure>();
40 }
41
42 // Byte 1 is reserved
43 cipherList.push_back(0x00);
44
45 for (const auto& record : data)
46 {
47 cipherList.push_back(record.value(cipher, 0));
48 }
49
50 return cipherList;
51}
52} // namespace cipher
53
54namespace ipmi
55{
56namespace transport
57{
58
William A. Kennington IIIc514d872019-04-06 18:19:38 -070059/** @brief Valid address origins for IPv4 */
60const std::unordered_set<IP::AddressOrigin> originsV4 = {
61 IP::AddressOrigin::Static,
62 IP::AddressOrigin::DHCP,
63};
64
Johnathan Manteyb87034e2019-09-16 10:50:50 -070065static constexpr uint8_t oemCmdStart = 192;
Johnathan Manteyb87034e2019-09-16 10:50:50 -070066
William A. Kennington IIIc72f3602023-10-19 03:51:37 -070067// Checks if the ifname is part of the networkd path
68// This assumes the path came from the network subtree PATH_ROOT
69bool ifnameInPath(std::string_view ifname, std::string_view path)
70{
71 constexpr auto rs = PATH_ROOT.size() + 1; // ROOT + separator
72 const auto is = rs + ifname.size(); // ROOT + sep + ifname
73 return path.size() > rs && path.substr(rs).starts_with(ifname) &&
74 (path.size() == is || path[is] == '/');
75}
76
Patrick Williams5d82f472022-07-22 19:26:53 -050077std::optional<ChannelParams> maybeGetChannelParams(sdbusplus::bus_t& bus,
William A. Kennington IIIc514d872019-04-06 18:19:38 -070078 uint8_t channel)
79{
80 auto ifname = getChannelName(channel);
81 if (ifname.empty())
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080082 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -070083 return std::nullopt;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080084 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080085
William A. Kennington IIIc514d872019-04-06 18:19:38 -070086 // Enumerate all VLAN + ETHERNET interfaces
George Liuc1c7eac2024-02-04 17:24:19 +080087 std::vector<std::string> interfaces = {INTF_VLAN, INTF_ETHERNET};
88 ipmi::ObjectTree objs = ipmi::getSubTree(bus, interfaces,
89 std::string{PATH_ROOT});
William A. Kennington IIIc514d872019-04-06 18:19:38 -070090
91 ChannelParams params;
92 for (const auto& [path, impls] : objs)
93 {
William A. Kennington IIIc72f3602023-10-19 03:51:37 -070094 if (!ifnameInPath(ifname, path))
William A. Kennington IIIc514d872019-04-06 18:19:38 -070095 {
96 continue;
97 }
98 for (const auto& [service, intfs] : impls)
99 {
100 bool vlan = false;
101 bool ethernet = false;
102 for (const auto& intf : intfs)
103 {
104 if (intf == INTF_VLAN)
105 {
106 vlan = true;
107 }
108 else if (intf == INTF_ETHERNET)
109 {
110 ethernet = true;
111 }
112 }
113 if (params.service.empty() && (vlan || ethernet))
114 {
115 params.service = service;
116 }
117 if (params.ifPath.empty() && !vlan && ethernet)
118 {
119 params.ifPath = path;
120 }
121 if (params.logicalPath.empty() && vlan)
122 {
123 params.logicalPath = path;
124 }
125 }
126 }
127
128 // We must have a path for the underlying interface
129 if (params.ifPath.empty())
130 {
131 return std::nullopt;
132 }
133 // We don't have a VLAN so the logical path is the same
134 if (params.logicalPath.empty())
135 {
136 params.logicalPath = params.ifPath;
137 }
138
139 params.id = channel;
140 params.ifname = std::move(ifname);
Willy Tu11d68892022-01-20 10:37:34 -0800141 return params;
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700142}
143
Patrick Williams5d82f472022-07-22 19:26:53 -0500144ChannelParams getChannelParams(sdbusplus::bus_t& bus, uint8_t channel)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700145{
146 auto params = maybeGetChannelParams(bus, channel);
147 if (!params)
148 {
149 log<level::ERR>("Failed to get channel params",
150 entry("CHANNEL=%" PRIu8, channel));
151 elog<InternalFailure>();
152 }
153 return std::move(*params);
154}
155
156/** @brief Wraps the phosphor logging method to insert some additional metadata
157 *
158 * @param[in] params - The parameters for the channel
159 * ...
160 */
161template <auto level, typename... Args>
162auto logWithChannel(const ChannelParams& params, Args&&... args)
163{
164 return log<level>(std::forward<Args>(args)...,
165 entry("CHANNEL=%d", params.id),
166 entry("IFNAME=%s", params.ifname.c_str()));
167}
168template <auto level, typename... Args>
169auto logWithChannel(const std::optional<ChannelParams>& params, Args&&... args)
170{
171 if (params)
172 {
173 return logWithChannel<level>(*params, std::forward<Args>(args)...);
174 }
175 return log<level>(std::forward<Args>(args)...);
176}
177
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700178/** @brief Get / Set the Property value from phosphor-networkd EthernetInterface
179 */
180template <typename T>
181static T getEthProp(sdbusplus::bus_t& bus, const ChannelParams& params,
182 const std::string& prop)
183{
184 return std::get<T>(getDbusProperty(bus, params.service, params.logicalPath,
185 INTF_ETHERNET, prop));
186}
187template <typename T>
188static void setEthProp(sdbusplus::bus_t& bus, const ChannelParams& params,
189 const std::string& prop, const T& t)
190{
191 return setDbusProperty(bus, params.service, params.logicalPath,
192 INTF_ETHERNET, prop, t);
193}
194
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700195/** @brief Determines the MAC of the ethernet interface
196 *
197 * @param[in] bus - The bus object used for lookups
198 * @param[in] params - The parameters for the channel
199 * @return The configured mac address
200 */
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700201stdplus::EtherAddr getMACProperty(sdbusplus::bus_t& bus,
202 const ChannelParams& params)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700203{
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700204 auto prop = getDbusProperty(bus, params.service, params.ifPath, INTF_MAC,
205 "MACAddress");
206 return stdplus::fromStr<stdplus::EtherAddr>(std::get<std::string>(prop));
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700207}
208
209/** @brief Sets the system value for MAC address on the given interface
210 *
211 * @param[in] bus - The bus object used for lookups
212 * @param[in] params - The parameters for the channel
213 * @param[in] mac - MAC address to apply
214 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500215void setMACProperty(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700216 stdplus::EtherAddr mac)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700217{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700218 setDbusProperty(bus, params.service, params.ifPath, INTF_MAC, "MACAddress",
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700219 stdplus::toStr(mac));
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700220}
221
Patrick Williams5d82f472022-07-22 19:26:53 -0500222void deleteObjectIfExists(sdbusplus::bus_t& bus, const std::string& service,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700223 const std::string& path)
224{
225 if (path.empty())
226 {
227 return;
228 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530229 try
tomjose26e17732016-03-03 08:52:51 -0600230 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700231 auto req = bus.new_method_call(service.c_str(), path.c_str(),
232 ipmi::DELETE_INTERFACE, "Delete");
233 bus.call_noreply(req);
234 }
Patrick Williams5d82f472022-07-22 19:26:53 -0500235 catch (const sdbusplus::exception_t& e)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700236 {
jayaprakash Mutyala84c49dc2020-05-18 23:12:13 +0000237 if (strcmp(e.name(),
238 "xyz.openbmc_project.Common.Error.InternalFailure") != 0 &&
239 strcmp(e.name(), "org.freedesktop.DBus.Error.UnknownObject") != 0)
tomjose26e17732016-03-03 08:52:51 -0600240 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700241 // We want to rethrow real errors
242 throw;
tomjose26e17732016-03-03 08:52:51 -0600243 }
244 }
tomjose26e17732016-03-03 08:52:51 -0600245}
246
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700247/** @brief Sets the address info configured for the interface
248 * If a previous address path exists then it will be removed
249 * before the new address is added.
250 *
251 * @param[in] bus - The bus object used for lookups
252 * @param[in] params - The parameters for the channel
253 * @param[in] address - The address of the new IP
254 * @param[in] prefix - The prefix of the new IP
255 */
256template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500257void createIfAddr(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700258 typename AddrFamily<family>::addr address, uint8_t prefix)
Tom Josepha30c8d32018-03-22 02:15:03 +0530259{
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500260 auto newreq = bus.new_method_call(params.service.c_str(),
261 params.logicalPath.c_str(),
262 INTF_IP_CREATE, "IP");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700263 std::string protocol =
Willy Tu523e2d12023-09-05 11:36:48 -0700264 sdbusplus::common::xyz::openbmc_project::network::convertForMessage(
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700265 AddrFamily<family>::protocol);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700266 stdplus::ToStrHandle<stdplus::ToStr<typename AddrFamily<family>::addr>> tsh;
267 newreq.append(protocol, tsh(address), prefix, "");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700268 bus.call_noreply(newreq);
269}
Tom Josepha30c8d32018-03-22 02:15:03 +0530270
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700271/** @brief Trivial helper for getting the IPv4 address from getIfAddrs()
272 *
273 * @param[in] bus - The bus object used for lookups
274 * @param[in] params - The parameters for the channel
275 * @return The address and prefix if found
276 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500277auto getIfAddr4(sdbusplus::bus_t& bus, const ChannelParams& params)
Tom Josepha30c8d32018-03-22 02:15:03 +0530278{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700279 return getIfAddr<AF_INET>(bus, params, 0, originsV4);
280}
Tom Josepha30c8d32018-03-22 02:15:03 +0530281
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700282/** @brief Reconfigures the IPv4 address info configured for the interface
283 *
284 * @param[in] bus - The bus object used for lookups
285 * @param[in] params - The parameters for the channel
286 * @param[in] address - The new address if specified
287 * @param[in] prefix - The new address prefix if specified
288 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500289void reconfigureIfAddr4(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700290 std::optional<stdplus::In4Addr> address,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700291 std::optional<uint8_t> prefix)
292{
293 auto ifaddr = getIfAddr4(bus, params);
294 if (!ifaddr && !address)
Tom Josepha30c8d32018-03-22 02:15:03 +0530295 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700296 log<level::ERR>("Missing address for IPv4 assignment");
Tom Josepha30c8d32018-03-22 02:15:03 +0530297 elog<InternalFailure>();
298 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700299 uint8_t fallbackPrefix = AddrFamily<AF_INET>::defaultPrefix;
300 if (ifaddr)
Tom Josepha30c8d32018-03-22 02:15:03 +0530301 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700302 fallbackPrefix = ifaddr->prefix;
303 deleteObjectIfExists(bus, params.service, ifaddr->path);
304 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700305 auto addr = address.value_or(ifaddr->address);
306 if (addr != stdplus::In4Addr{})
Johnathan Manteycbfa6e12023-06-01 06:57:25 -0700307 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700308 createIfAddr<AF_INET>(bus, params, addr,
Johnathan Manteycbfa6e12023-06-01 06:57:25 -0700309 prefix.value_or(fallbackPrefix));
310 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700311}
312
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700313template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500314std::optional<IfNeigh<family>> findGatewayNeighbor(sdbusplus::bus_t& bus,
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700315 const ChannelParams& params,
316 ObjectLookupCache& neighbors)
317{
318 auto gateway = getGatewayProperty<family>(bus, params);
319 if (!gateway)
320 {
321 return std::nullopt;
322 }
323
324 return findStaticNeighbor<family>(bus, params, *gateway, neighbors);
325}
326
327template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500328std::optional<IfNeigh<family>> getGatewayNeighbor(sdbusplus::bus_t& bus,
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700329 const ChannelParams& params)
330{
331 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
332 return findGatewayNeighbor<family>(bus, params, neighbors);
333}
334
335template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500336void reconfigureGatewayMAC(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700337 stdplus::EtherAddr mac)
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700338{
339 auto gateway = getGatewayProperty<family>(bus, params);
340 if (!gateway)
341 {
342 log<level::ERR>("Tried to set Gateway MAC without Gateway");
343 elog<InternalFailure>();
344 }
345
346 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500347 auto neighbor = findStaticNeighbor<family>(bus, params, *gateway,
348 neighbors);
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700349 if (neighbor)
350 {
351 deleteObjectIfExists(bus, params.service, neighbor->path);
352 }
353
354 createNeighbor<family>(bus, params, *gateway, mac);
355}
356
William A. Kennington III16064aa2019-04-13 17:44:53 -0700357/** @brief Deconfigures the IPv6 address info configured for the interface
358 *
359 * @param[in] bus - The bus object used for lookups
360 * @param[in] params - The parameters for the channel
361 * @param[in] idx - The address index to operate on
362 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500363void deconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III16064aa2019-04-13 17:44:53 -0700364 uint8_t idx)
365{
366 auto ifaddr = getIfAddr<AF_INET6>(bus, params, idx, originsV6Static);
367 if (ifaddr)
368 {
369 deleteObjectIfExists(bus, params.service, ifaddr->path);
370 }
371}
372
373/** @brief Reconfigures the IPv6 address info configured for the interface
374 *
375 * @param[in] bus - The bus object used for lookups
376 * @param[in] params - The parameters for the channel
377 * @param[in] idx - The address index to operate on
378 * @param[in] address - The new address
379 * @param[in] prefix - The new address prefix
380 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500381void reconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700382 uint8_t idx, stdplus::In6Addr address, uint8_t prefix)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700383{
384 deconfigureIfAddr6(bus, params, idx);
385 createIfAddr<AF_INET6>(bus, params, address, prefix);
386}
387
388/** @brief Converts the AddressOrigin into an IPv6Source
389 *
390 * @param[in] origin - The DBus Address Origin to convert
391 * @return The IPv6Source version of the origin
392 */
393IPv6Source originToSourceType(IP::AddressOrigin origin)
394{
395 switch (origin)
396 {
397 case IP::AddressOrigin::Static:
398 return IPv6Source::Static;
399 case IP::AddressOrigin::DHCP:
400 return IPv6Source::DHCP;
401 case IP::AddressOrigin::SLAAC:
402 return IPv6Source::SLAAC;
403 default:
404 {
Willy Tu523e2d12023-09-05 11:36:48 -0700405 auto originStr = sdbusplus::common::xyz::openbmc_project::network::
William A. Kennington III16064aa2019-04-13 17:44:53 -0700406 convertForMessage(origin);
407 log<level::ERR>(
408 "Invalid IP::AddressOrigin conversion to IPv6Source",
409 entry("ORIGIN=%s", originStr.c_str()));
410 elog<InternalFailure>();
411 }
412 }
413}
414
415/** @brief Packs the IPMI message response with IPv6 address data
416 *
417 * @param[out] ret - The IPMI response payload to be packed
418 * @param[in] channel - The channel id corresponding to an ethernet interface
419 * @param[in] set - The set selector for determining address index
420 * @param[in] origins - Set of valid origins for address filtering
421 */
422void getLanIPv6Address(message::Payload& ret, uint8_t channel, uint8_t set,
423 const std::unordered_set<IP::AddressOrigin>& origins)
424{
425 auto source = IPv6Source::Static;
426 bool enabled = false;
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700427 stdplus::In6Addr addr{};
Johnathan Mantey5aae0922021-10-21 13:05:36 -0700428 uint8_t prefix{};
William A. Kennington III16064aa2019-04-13 17:44:53 -0700429 auto status = IPv6AddressStatus::Disabled;
430
431 auto ifaddr = channelCall<getIfAddr<AF_INET6>>(channel, set, origins);
432 if (ifaddr)
433 {
434 source = originToSourceType(ifaddr->origin);
Johnathan Mantey846af862021-10-21 12:48:54 -0700435 enabled = (origins == originsV6Static);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700436 addr = ifaddr->address;
437 prefix = ifaddr->prefix;
438 status = IPv6AddressStatus::Active;
439 }
440
441 ret.pack(set);
William A. Kennington III7a0e5df2021-05-19 13:31:29 -0700442 ret.pack(types::enum_cast<uint4_t>(source), uint3_t{}, enabled);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700443 ret.pack(stdplus::raw::asView<char>(addr));
William A. Kennington III16064aa2019-04-13 17:44:53 -0700444 ret.pack(prefix);
William A. Kennington III7a0e5df2021-05-19 13:31:29 -0700445 ret.pack(types::enum_cast<uint8_t>(status));
William A. Kennington III16064aa2019-04-13 17:44:53 -0700446}
447
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700448/** @brief Gets the vlan ID configured on the interface
449 *
450 * @param[in] bus - The bus object used for lookups
451 * @param[in] params - The parameters for the channel
452 * @return VLAN id or the standard 0 for no VLAN
453 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500454uint16_t getVLANProperty(sdbusplus::bus_t& bus, const ChannelParams& params)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700455{
456 // VLAN devices will always have a separate logical object
457 if (params.ifPath == params.logicalPath)
458 {
459 return 0;
460 }
461
462 auto vlan = std::get<uint32_t>(getDbusProperty(
463 bus, params.service, params.logicalPath, INTF_VLAN, "Id"));
464 if ((vlan & VLAN_VALUE_MASK) != vlan)
465 {
466 logWithChannel<level::ERR>(params, "networkd returned an invalid vlan",
467 entry("VLAN=%" PRIu32, vlan));
Tom Josepha30c8d32018-03-22 02:15:03 +0530468 elog<InternalFailure>();
469 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700470 return vlan;
Tom Josepha30c8d32018-03-22 02:15:03 +0530471}
472
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700473/** @brief Deletes all of the possible configuration parameters for a channel
474 *
475 * @param[in] bus - The bus object used for lookups
476 * @param[in] params - The parameters for the channel
477 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500478void deconfigureChannel(sdbusplus::bus_t& bus, ChannelParams& params)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500479{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700480 // Delete all objects associated with the interface
George Liuc1c7eac2024-02-04 17:24:19 +0800481 ObjectTree objs =
482 ipmi::getSubTree(bus, std::vector<std::string>{DELETE_INTERFACE},
483 std::string{PATH_ROOT});
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700484 for (const auto& [path, impls] : objs)
485 {
William A. Kennington IIIc72f3602023-10-19 03:51:37 -0700486 if (!ifnameInPath(params.ifname, path))
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700487 {
488 continue;
489 }
490 for (const auto& [service, intfs] : impls)
491 {
492 deleteObjectIfExists(bus, service, path);
493 }
494 // Update params to reflect the deletion of vlan
495 if (path == params.logicalPath)
496 {
497 params.logicalPath = params.ifPath;
498 }
499 }
500
501 // Clear out any settings on the lower physical interface
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700502 setEthProp(bus, params, "DHCP4", false);
503 setEthProp(bus, params, "DHCP6", false);
504 setEthProp(bus, params, "IPv6AcceptRA", false);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500505}
506
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700507/** @brief Creates a new VLAN on the specified interface
508 *
509 * @param[in] bus - The bus object used for lookups
510 * @param[in] params - The parameters for the channel
511 * @param[in] vlan - The id of the new vlan
512 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500513void createVLAN(sdbusplus::bus_t& bus, ChannelParams& params, uint16_t vlan)
Ratan Guptab8e99552017-07-27 07:07:48 +0530514{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700515 if (vlan == 0)
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530516 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700517 return;
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530518 }
519
William A. Kennington IIIc72f3602023-10-19 03:51:37 -0700520 auto req = bus.new_method_call(params.service.c_str(), PATH_ROOT.c_str(),
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700521 INTF_VLAN_CREATE, "VLAN");
522 req.append(params.ifname, static_cast<uint32_t>(vlan));
523 auto reply = bus.call(req);
524 sdbusplus::message::object_path newPath;
525 reply.read(newPath);
526 params.logicalPath = std::move(newPath);
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530527}
528
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700529/** @brief Performs the necessary reconfiguration to change the VLAN
530 *
531 * @param[in] bus - The bus object used for lookups
532 * @param[in] params - The parameters for the channel
533 * @param[in] vlan - The new vlan id to use
534 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500535void reconfigureVLAN(sdbusplus::bus_t& bus, ChannelParams& params,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700536 uint16_t vlan)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500537{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700538 // Unfortunatetly we don't have built-in functions to migrate our interface
539 // customizations to new VLAN interfaces, or have some kind of decoupling.
540 // We therefore must retain all of our old information, setup the new VLAN
541 // configuration, then restore the old info.
Nan Li3d0df912016-10-18 19:51:41 +0800542
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700543 // Save info from the old logical interface
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700544 bool dhcp4 = getEthProp<bool>(bus, params, "DHCP4");
545 bool dhcp6 = getEthProp<bool>(bus, params, "DHCP6");
546 bool ra = getEthProp<bool>(bus, params, "IPv6AcceptRA");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700547 ObjectLookupCache ips(bus, params, INTF_IP);
548 auto ifaddr4 = findIfAddr<AF_INET>(bus, params, 0, originsV4, ips);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700549 std::vector<IfAddr<AF_INET6>> ifaddrs6;
550 for (uint8_t i = 0; i < MAX_IPV6_STATIC_ADDRESSES; ++i)
551 {
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500552 auto ifaddr6 = findIfAddr<AF_INET6>(bus, params, i, originsV6Static,
553 ips);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700554 if (!ifaddr6)
555 {
556 break;
557 }
558 ifaddrs6.push_back(std::move(*ifaddr6));
559 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700560 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
561 auto neighbor4 = findGatewayNeighbor<AF_INET>(bus, params, neighbors);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700562 auto neighbor6 = findGatewayNeighbor<AF_INET6>(bus, params, neighbors);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500563
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700564 deconfigureChannel(bus, params);
565 createVLAN(bus, params, vlan);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500566
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700567 // Re-establish the saved settings
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700568 setEthProp(bus, params, "DHCP4", dhcp4);
569 setEthProp(bus, params, "DHCP6", dhcp6);
570 setEthProp(bus, params, "IPv6AcceptRA", ra);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700571 if (ifaddr4)
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800572 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700573 createIfAddr<AF_INET>(bus, params, ifaddr4->address, ifaddr4->prefix);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800574 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700575 for (const auto& ifaddr6 : ifaddrs6)
576 {
577 createIfAddr<AF_INET6>(bus, params, ifaddr6.address, ifaddr6.prefix);
578 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700579 if (neighbor4)
580 {
581 createNeighbor<AF_INET>(bus, params, neighbor4->ip, neighbor4->mac);
582 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700583 if (neighbor6)
584 {
585 createNeighbor<AF_INET6>(bus, params, neighbor6->ip, neighbor6->mac);
586 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700587}
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800588
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700589// We need to store this value so it can be returned to the client
590// It is volatile so safe to store in daemon memory.
591static std::unordered_map<uint8_t, SetStatus> setStatus;
592
593// Until we have good support for fixed versions of IPMI tool
594// we need to return the VLAN id for disabled VLANs. The value is only
595// used for verification that a disable operation succeeded and will only
596// be sent if our system indicates that vlans are disabled.
597static std::unordered_map<uint8_t, uint16_t> lastDisabledVlan;
598
599/** @brief Gets the set status for the channel if it exists
600 * Otherise populates and returns the default value.
601 *
602 * @param[in] channel - The channel id corresponding to an ethernet interface
603 * @return A reference to the SetStatus for the channel
604 */
605SetStatus& getSetStatus(uint8_t channel)
606{
607 auto it = setStatus.find(channel);
608 if (it != setStatus.end())
609 {
610 return it->second;
611 }
612 return setStatus[channel] = SetStatus::Complete;
613}
614
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700615/** @brief Unpacks the trivially copyable type from the message */
616template <typename T>
617static T unpackT(message::Payload& req)
618{
619 std::array<uint8_t, sizeof(T)> bytes;
620 if (req.unpack(bytes) != 0)
621 {
622 throw ccReqDataLenInvalid;
623 }
624 return stdplus::raw::copyFrom<T>(bytes);
625}
626
627/** @brief Ensure the message is fully unpacked */
628static void unpackFinal(message::Payload& req)
629{
630 if (!req.fullyUnpacked())
631 {
632 throw ccReqDataTruncated;
633 }
634}
635
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700636/**
637 * Define placeholder command handlers for the OEM Extension bytes for the Set
638 * LAN Configuration Parameters and Get LAN Configuration Parameters
639 * commands. Using "weak" linking allows the placeholder setLanOem/getLanOem
640 * functions below to be overridden.
641 * To create handlers for your own proprietary command set:
642 * Create/modify a phosphor-ipmi-host Bitbake append file within your Yocto
643 * recipe
644 * Create C++ file(s) that define IPMI handler functions matching the
645 * function names below (i.e. setLanOem). The default name for the
646 * transport IPMI commands is transporthandler_oem.cpp.
647 * Add:
Johnathan Manteyefe26682022-08-11 14:30:45 -0700648 * EXTRA_OEMESON:append = "-Dtransport-oem=enabled"
649 * Create a do_configure:prepend()/do_install:append() method in your
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700650 * bbappend file to copy the file to the build directory.
651 * Add:
652 * PROJECT_SRC_DIR := "${THISDIR}/${PN}"
653 * # Copy the "strong" functions into the working directory, overriding the
654 * # placeholder functions.
Johnathan Manteyefe26682022-08-11 14:30:45 -0700655 * do_configure:prepend(){
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700656 * cp -f ${PROJECT_SRC_DIR}/transporthandler_oem.cpp ${S}
657 * }
658 *
659 * # Clean up after complilation has completed
Johnathan Manteyefe26682022-08-11 14:30:45 -0700660 * do_install:append(){
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700661 * rm -f ${S}/transporthandler_oem.cpp
662 * }
663 *
664 */
665
666/**
667 * Define the placeholder OEM commands as having weak linkage. Create
668 * setLanOem, and getLanOem functions in the transporthandler_oem.cpp
669 * file. The functions defined there must not have the "weak" attribute
670 * applied to them.
671 */
672RspType<> setLanOem(uint8_t channel, uint8_t parameter, message::Payload& req)
673 __attribute__((weak));
674RspType<message::Payload> getLanOem(uint8_t channel, uint8_t parameter,
675 uint8_t set, uint8_t block)
676 __attribute__((weak));
677
Willy Tu11d68892022-01-20 10:37:34 -0800678RspType<> setLanOem(uint8_t, uint8_t, message::Payload& req)
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700679{
680 req.trailingOk = true;
681 return response(ccParamNotSupported);
682}
683
Willy Tu11d68892022-01-20 10:37:34 -0800684RspType<message::Payload> getLanOem(uint8_t, uint8_t, uint8_t, uint8_t)
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700685{
686 return response(ccParamNotSupported);
687}
688
Jian Zhangcf19d142023-07-31 10:22:53 +0800689/**
690 * @brief is a valid LAN channel.
691 *
692 * This function checks whether the input channel is a valid LAN channel or not.
693 *
694 * @param[in] channel: the channel number.
695 * @return nullopt if the channel is invalid, false if the channel is not a LAN
696 * channel, true if the channel is a LAN channel.
697 **/
698std::optional<bool> isLanChannel(uint8_t channel)
699{
700 ChannelInfo chInfo;
701 auto cc = getChannelInfo(channel, chInfo);
702 if (cc != ccSuccess)
703 {
704 return std::nullopt;
705 }
706
707 return chInfo.mediumType ==
708 static_cast<uint8_t>(EChannelMediumType::lan8032);
709}
710
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700711RspType<> setLanInt(Context::ptr ctx, uint4_t channelBits, uint4_t reserved1,
712 uint8_t parameter, message::Payload& req)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700713{
vijayabharathix shettycc769252020-02-27 17:52:20 +0000714 const uint8_t channel = convertCurrentChannelNum(
715 static_cast<uint8_t>(channelBits), ctx->channel);
716 if (reserved1 || !isValidChannel(channel))
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700717 {
vijayabharathix shettycc769252020-02-27 17:52:20 +0000718 log<level::ERR>("Set Lan - Invalid field in request");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700719 req.trailingOk = true;
720 return responseInvalidFieldRequest();
721 }
722
Jian Zhangcf19d142023-07-31 10:22:53 +0800723 if (!isLanChannel(channel).value_or(false))
724 {
725 log<level::ERR>("Set Lan - Not a LAN channel");
726 return responseInvalidFieldRequest();
727 }
728
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700729 switch (static_cast<LanParam>(parameter))
730 {
731 case LanParam::SetStatus:
732 {
733 uint2_t flag;
734 uint6_t rsvd;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700735 if (req.unpack(flag, rsvd) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700736 {
737 return responseReqDataLenInvalid();
738 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700739 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800740 if (rsvd)
741 {
742 return responseInvalidFieldRequest();
743 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700744 auto status = static_cast<SetStatus>(static_cast<uint8_t>(flag));
745 switch (status)
746 {
747 case SetStatus::Complete:
748 {
749 getSetStatus(channel) = status;
750 return responseSuccess();
751 }
752 case SetStatus::InProgress:
753 {
754 auto& storedStatus = getSetStatus(channel);
755 if (storedStatus == SetStatus::InProgress)
756 {
757 return response(ccParamSetLocked);
758 }
759 storedStatus = status;
760 return responseSuccess();
761 }
762 case SetStatus::Commit:
763 if (getSetStatus(channel) != SetStatus::InProgress)
764 {
765 return responseInvalidFieldRequest();
766 }
767 return responseSuccess();
768 }
769 return response(ccParamNotSupported);
770 }
771 case LanParam::AuthSupport:
772 {
773 req.trailingOk = true;
774 return response(ccParamReadOnly);
775 }
776 case LanParam::AuthEnables:
777 {
778 req.trailingOk = true;
Johnathan Mantey76ce9c72019-11-14 14:41:46 -0800779 return response(ccParamReadOnly);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700780 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800781 case LanParam::IP:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600782 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700783 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800784 {
785 return responseCommandNotAvailable();
786 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700787 auto ip = unpackT<stdplus::In4Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700788 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700789 channelCall<reconfigureIfAddr4>(channel, ip, std::nullopt);
790 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +0530791 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700792 case LanParam::IPSrc:
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530793 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700794 uint4_t flag;
795 uint4_t rsvd;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700796 if (req.unpack(flag, rsvd) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700797 {
798 return responseReqDataLenInvalid();
799 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700800 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800801 if (rsvd)
802 {
803 return responseInvalidFieldRequest();
804 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700805 switch (static_cast<IPSrc>(static_cast<uint8_t>(flag)))
806 {
807 case IPSrc::DHCP:
Johnathan Mantey65265362019-11-14 11:24:19 -0800808 // The IPSrc IPMI command is only for IPv4
809 // management. Modifying IPv6 state is done using
810 // a completely different Set LAN Configuration
811 // subcommand.
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700812 channelCall<setEthProp<bool>>(channel, "DHCP4", true);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700813 return responseSuccess();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700814 case IPSrc::Unspecified:
815 case IPSrc::Static:
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700816 channelCall<setEthProp<bool>>(channel, "DHCP4", false);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700817 return responseSuccess();
Rajashekar Gade Reddy8a860ea2019-12-24 11:31:19 +0530818 case IPSrc::BIOS:
819 case IPSrc::BMC:
Rajashekar Gade Reddy8a860ea2019-12-24 11:31:19 +0530820 return responseInvalidFieldRequest();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700821 }
822 return response(ccParamNotSupported);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530823 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800824 case LanParam::MAC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530825 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700826 auto mac = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700827 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700828 channelCall<setMACProperty>(channel, mac);
829 return responseSuccess();
Ratan Gupta533d03b2017-07-30 10:39:22 +0530830 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700831 case LanParam::SubnetMask:
Ratan Guptab8e99552017-07-27 07:07:48 +0530832 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700833 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800834 {
835 return responseCommandNotAvailable();
836 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700837 auto pfx = stdplus::maskToPfx(unpackT<stdplus::In4Addr>(req));
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700838 unpackFinal(req);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700839 channelCall<reconfigureIfAddr4>(channel, std::nullopt, pfx);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700840 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +0530841 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700842 case LanParam::Gateway1:
Ratan Guptab8e99552017-07-27 07:07:48 +0530843 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700844 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800845 {
846 return responseCommandNotAvailable();
847 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700848 auto gateway = unpackT<stdplus::In4Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700849 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700850 channelCall<setGatewayProperty<AF_INET>>(channel, gateway);
851 return responseSuccess();
852 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700853 case LanParam::Gateway1MAC:
854 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700855 auto gatewayMAC = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700856 unpackFinal(req);
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700857 channelCall<reconfigureGatewayMAC<AF_INET>>(channel, gatewayMAC);
858 return responseSuccess();
859 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700860 case LanParam::VLANId:
861 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700862 uint12_t vlanData;
863 uint3_t rsvd;
864 bool vlanEnable;
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530865
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700866 if (req.unpack(vlanData, rsvd, vlanEnable) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700867 {
868 return responseReqDataLenInvalid();
869 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700870 unpackFinal(req);
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530871
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700872 if (rsvd)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700873 {
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530874 return responseInvalidFieldRequest();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700875 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530876
877 uint16_t vlan = static_cast<uint16_t>(vlanData);
878
879 if (!vlanEnable)
880 {
881 lastDisabledVlan[channel] = vlan;
882 vlan = 0;
883 }
Jayaprakash Mutyala0d1d7ad2024-06-19 10:19:33 +0000884 else if (vlan == 0 || vlan == VLAN_VALUE_MASK)
885 {
886 return responseInvalidFieldRequest();
887 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530888
jayaprakash Mutyala84c49dc2020-05-18 23:12:13 +0000889 channelCall<reconfigureVLAN>(channel, vlan);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700890 return responseSuccess();
891 }
892 case LanParam::CiphersuiteSupport:
893 case LanParam::CiphersuiteEntries:
William A. Kennington III16064aa2019-04-13 17:44:53 -0700894 case LanParam::IPFamilySupport:
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700895 {
896 req.trailingOk = true;
897 return response(ccParamReadOnly);
Ratan Guptab8e99552017-07-27 07:07:48 +0530898 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700899 case LanParam::IPFamilyEnables:
900 {
901 uint8_t enables;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700902 if (req.unpack(enables) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700903 {
904 return responseReqDataLenInvalid();
905 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700906 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700907 switch (static_cast<IPFamilyEnables>(enables))
908 {
909 case IPFamilyEnables::DualStack:
910 return responseSuccess();
911 case IPFamilyEnables::IPv4Only:
912 case IPFamilyEnables::IPv6Only:
913 return response(ccParamNotSupported);
914 }
915 return response(ccParamNotSupported);
916 }
917 case LanParam::IPv6Status:
918 {
919 req.trailingOk = true;
920 return response(ccParamReadOnly);
921 }
922 case LanParam::IPv6StaticAddresses:
923 {
924 uint8_t set;
925 uint7_t rsvd;
926 bool enabled;
William A. Kennington III16064aa2019-04-13 17:44:53 -0700927 uint8_t prefix;
928 uint8_t status;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700929 if (req.unpack(set, rsvd, enabled) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700930 {
931 return responseReqDataLenInvalid();
932 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700933 auto ip = unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700934 if (req.unpack(prefix, status) != 0)
935 {
936 return responseReqDataLenInvalid();
937 }
938 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800939 if (rsvd)
940 {
941 return responseInvalidFieldRequest();
942 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700943 if (enabled)
944 {
Jiaqing Zhao6d4a44e2022-01-24 15:04:00 +0800945 if (prefix < MIN_IPV6_PREFIX_LENGTH ||
946 prefix > MAX_IPV6_PREFIX_LENGTH)
947 {
948 return responseParmOutOfRange();
949 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700950 channelCall<reconfigureIfAddr6>(channel, set, ip, prefix);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700951 }
952 else
953 {
954 channelCall<deconfigureIfAddr6>(channel, set);
955 }
956 return responseSuccess();
957 }
958 case LanParam::IPv6DynamicAddresses:
959 {
960 req.trailingOk = true;
961 return response(ccParamReadOnly);
962 }
963 case LanParam::IPv6RouterControl:
964 {
965 std::bitset<8> control;
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800966 constexpr uint8_t reservedRACCBits = 0xfc;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700967 if (req.unpack(control) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700968 {
969 return responseReqDataLenInvalid();
970 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700971 unpackFinal(req);
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800972 if (std::bitset<8> expected(control &
973 std::bitset<8>(reservedRACCBits));
974 expected.any())
William A. Kennington III16064aa2019-04-13 17:44:53 -0700975 {
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800976 return response(ccParamNotSupported);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700977 }
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800978
979 bool enableRA = control[IPv6RouterControlFlag::Dynamic];
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700980 channelCall<setEthProp<bool>>(channel, "IPv6AcceptRA", enableRA);
981 channelCall<setEthProp<bool>>(channel, "DHCP6", enableRA);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700982 return responseSuccess();
983 }
984 case LanParam::IPv6StaticRouter1IP:
985 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700986 auto gateway = unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700987 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700988 channelCall<setGatewayProperty<AF_INET6>>(channel, gateway);
989 return responseSuccess();
990 }
991 case LanParam::IPv6StaticRouter1MAC:
992 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700993 auto mac = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700994 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700995 channelCall<reconfigureGatewayMAC<AF_INET6>>(channel, mac);
996 return responseSuccess();
997 }
998 case LanParam::IPv6StaticRouter1PrefixLength:
999 {
1000 uint8_t prefix;
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001001 if (req.unpack(prefix) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -07001002 {
1003 return responseReqDataLenInvalid();
1004 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001005 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001006 if (prefix != 0)
1007 {
1008 return responseInvalidFieldRequest();
1009 }
1010 return responseSuccess();
1011 }
1012 case LanParam::IPv6StaticRouter1PrefixValue:
1013 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001014 unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001015 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001016 // Accept any prefix value since our prefix length has to be 0
1017 return responseSuccess();
1018 }
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001019 case LanParam::cipherSuitePrivilegeLevels:
1020 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001021 uint8_t rsvd;
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001022 std::array<uint4_t, ipmi::maxCSRecords> cipherSuitePrivs;
1023
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001024 if (req.unpack(rsvd, cipherSuitePrivs))
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001025 {
1026 return responseReqDataLenInvalid();
1027 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001028 unpackFinal(req);
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001029
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001030 if (rsvd)
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001031 {
1032 return responseInvalidFieldRequest();
1033 }
1034
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -05001035 uint8_t resp = getCipherConfigObject(csPrivFileName,
1036 csPrivDefaultFileName)
1037 .setCSPrivilegeLevels(channel, cipherSuitePrivs);
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001038 if (!resp)
1039 {
1040 return responseSuccess();
1041 }
1042 else
1043 {
1044 req.trailingOk = true;
1045 return response(resp);
1046 }
1047 }
Ratan Guptab8e99552017-07-27 07:07:48 +05301048 }
vishwa1eaea4f2016-02-26 11:57:40 -06001049
PavanKumarIntel3771f5f2023-11-02 06:26:42 +00001050 if (parameter >= oemCmdStart)
Johnathan Manteyb87034e2019-09-16 10:50:50 -07001051 {
1052 return setLanOem(channel, parameter, req);
1053 }
1054
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001055 req.trailingOk = true;
1056 return response(ccParamNotSupported);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001057}
1058
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001059RspType<> setLan(Context::ptr ctx, uint4_t channelBits, uint4_t reserved1,
1060 uint8_t parameter, message::Payload& req)
1061{
1062 try
1063 {
1064 return setLanInt(ctx, channelBits, reserved1, parameter, req);
1065 }
1066 catch (ipmi::Cc cc)
1067 {
1068 return response(cc);
1069 }
1070 catch (const sdbusplus::exception_t& e)
1071 {
1072 if (std::string_view{InvalidArgument::errName} == e.name())
1073 {
1074 return responseInvalidFieldRequest();
1075 }
1076 throw;
1077 }
1078}
1079
vijayabharathix shettycc769252020-02-27 17:52:20 +00001080RspType<message::Payload> getLan(Context::ptr ctx, uint4_t channelBits,
1081 uint3_t reserved, bool revOnly,
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001082 uint8_t parameter, uint8_t set, uint8_t block)
Ratan Guptab8e99552017-07-27 07:07:48 +05301083{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001084 message::Payload ret;
1085 constexpr uint8_t current_revision = 0x11;
1086 ret.pack(current_revision);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001087
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001088 if (revOnly)
Suryakanth Sekare4054402019-08-08 15:16:52 +05301089 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001090 return responseSuccess(std::move(ret));
Suryakanth Sekare4054402019-08-08 15:16:52 +05301091 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001092
vijayabharathix shettycc769252020-02-27 17:52:20 +00001093 const uint8_t channel = convertCurrentChannelNum(
1094 static_cast<uint8_t>(channelBits), ctx->channel);
1095 if (reserved || !isValidChannel(channel))
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001096 {
vijayabharathix shettycc769252020-02-27 17:52:20 +00001097 log<level::ERR>("Get Lan - Invalid field in request");
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001098 return responseInvalidFieldRequest();
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001099 }
1100
Jian Zhangcf19d142023-07-31 10:22:53 +08001101 if (!isLanChannel(channel).value_or(false))
1102 {
1103 log<level::ERR>("Set Lan - Not a LAN channel");
1104 return responseInvalidFieldRequest();
1105 }
1106
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001107 static std::vector<uint8_t> cipherList;
1108 static bool listInit = false;
1109 if (!listInit)
1110 {
1111 try
1112 {
1113 cipherList = cipher::getCipherList();
1114 listInit = true;
1115 }
1116 catch (const std::exception& e)
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -05001117 {}
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001118 }
1119
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001120 switch (static_cast<LanParam>(parameter))
Tom Josepha30c8d32018-03-22 02:15:03 +05301121 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001122 case LanParam::SetStatus:
Tom Josepha30c8d32018-03-22 02:15:03 +05301123 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001124 SetStatus status;
1125 try
1126 {
1127 status = setStatus.at(channel);
1128 }
1129 catch (const std::out_of_range&)
1130 {
1131 status = SetStatus::Complete;
1132 }
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001133 ret.pack(types::enum_cast<uint2_t>(status), uint6_t{});
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001134 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301135 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001136 case LanParam::AuthSupport:
Tom Josepha30c8d32018-03-22 02:15:03 +05301137 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001138 std::bitset<6> support;
1139 ret.pack(support, uint2_t{});
1140 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301141 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001142 case LanParam::AuthEnables:
vishwa1eaea4f2016-02-26 11:57:40 -06001143 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001144 std::bitset<6> enables;
1145 ret.pack(enables, uint2_t{}); // Callback
1146 ret.pack(enables, uint2_t{}); // User
1147 ret.pack(enables, uint2_t{}); // Operator
1148 ret.pack(enables, uint2_t{}); // Admin
1149 ret.pack(enables, uint2_t{}); // OEM
1150 return responseSuccess(std::move(ret));
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001151 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001152 case LanParam::IP:
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001153 {
1154 auto ifaddr = channelCall<getIfAddr4>(channel);
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001155 stdplus::In4Addr addr{};
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001156 if (ifaddr)
1157 {
1158 addr = ifaddr->address;
1159 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001160 ret.pack(stdplus::raw::asView<char>(addr));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001161 return responseSuccess(std::move(ret));
1162 }
1163 case LanParam::IPSrc:
1164 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001165 auto src = channelCall<getEthProp<bool>>(channel, "DHCP4")
1166 ? IPSrc::DHCP
1167 : IPSrc::Static;
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001168 ret.pack(types::enum_cast<uint4_t>(src), uint4_t{});
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001169 return responseSuccess(std::move(ret));
1170 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001171 case LanParam::MAC:
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001172 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001173 auto mac = channelCall<getMACProperty>(channel);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001174 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001175 return responseSuccess(std::move(ret));
1176 }
1177 case LanParam::SubnetMask:
1178 {
1179 auto ifaddr = channelCall<getIfAddr4>(channel);
1180 uint8_t prefix = AddrFamily<AF_INET>::defaultPrefix;
1181 if (ifaddr)
Ratan Guptab8e99552017-07-27 07:07:48 +05301182 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001183 prefix = ifaddr->prefix;
1184 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001185 auto netmask = stdplus::pfxToMask<stdplus::In4Addr>(prefix);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001186 ret.pack(stdplus::raw::asView<char>(netmask));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001187 return responseSuccess(std::move(ret));
1188 }
1189 case LanParam::Gateway1:
1190 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001191 auto gateway = channelCall<getGatewayProperty<AF_INET>>(channel);
1192 ret.pack(stdplus::raw::asView<char>(
1193 gateway.value_or(stdplus::In4Addr{})));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001194 return responseSuccess(std::move(ret));
1195 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001196 case LanParam::Gateway1MAC:
1197 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001198 stdplus::EtherAddr mac{};
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001199 auto neighbor = channelCall<getGatewayNeighbor<AF_INET>>(channel);
1200 if (neighbor)
1201 {
1202 mac = neighbor->mac;
1203 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001204 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001205 return responseSuccess(std::move(ret));
1206 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001207 case LanParam::VLANId:
1208 {
1209 uint16_t vlan = channelCall<getVLANProperty>(channel);
1210 if (vlan != 0)
1211 {
1212 vlan |= VLAN_ENABLE_FLAG;
Ratan Guptab8e99552017-07-27 07:07:48 +05301213 }
1214 else
1215 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001216 vlan = lastDisabledVlan[channel];
Ratan Guptab8e99552017-07-27 07:07:48 +05301217 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001218 ret.pack(vlan);
1219 return responseSuccess(std::move(ret));
Adriana Kobylak342df102016-02-10 13:48:16 -06001220 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001221 case LanParam::CiphersuiteSupport:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001222 {
srikanta mondal1d8579c2020-04-15 17:13:25 +00001223 if (getChannelSessionSupport(channel) ==
1224 EChannelSessSupported::none)
1225 {
1226 return responseInvalidFieldRequest();
1227 }
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001228 if (!listInit)
1229 {
1230 return responseUnspecifiedError();
1231 }
1232 ret.pack(static_cast<uint8_t>(cipherList.size() - 1));
1233 return responseSuccess(std::move(ret));
1234 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001235 case LanParam::CiphersuiteEntries:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001236 {
srikanta mondal1d8579c2020-04-15 17:13:25 +00001237 if (getChannelSessionSupport(channel) ==
1238 EChannelSessSupported::none)
1239 {
1240 return responseInvalidFieldRequest();
1241 }
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001242 if (!listInit)
1243 {
1244 return responseUnspecifiedError();
1245 }
1246 ret.pack(cipherList);
1247 return responseSuccess(std::move(ret));
1248 }
William A. Kennington III16064aa2019-04-13 17:44:53 -07001249 case LanParam::IPFamilySupport:
1250 {
1251 std::bitset<8> support;
1252 support[IPFamilySupportFlag::IPv6Only] = 0;
1253 support[IPFamilySupportFlag::DualStack] = 1;
1254 support[IPFamilySupportFlag::IPv6Alerts] = 1;
1255 ret.pack(support);
1256 return responseSuccess(std::move(ret));
1257 }
1258 case LanParam::IPFamilyEnables:
1259 {
1260 ret.pack(static_cast<uint8_t>(IPFamilyEnables::DualStack));
1261 return responseSuccess(std::move(ret));
1262 }
1263 case LanParam::IPv6Status:
1264 {
1265 ret.pack(MAX_IPV6_STATIC_ADDRESSES);
1266 ret.pack(MAX_IPV6_DYNAMIC_ADDRESSES);
1267 std::bitset<8> support;
1268 support[IPv6StatusFlag::DHCP] = 1;
1269 support[IPv6StatusFlag::SLAAC] = 1;
1270 ret.pack(support);
1271 return responseSuccess(std::move(ret));
1272 }
1273 case LanParam::IPv6StaticAddresses:
1274 {
1275 if (set >= MAX_IPV6_STATIC_ADDRESSES)
1276 {
1277 return responseParmOutOfRange();
1278 }
1279 getLanIPv6Address(ret, channel, set, originsV6Static);
1280 return responseSuccess(std::move(ret));
1281 }
1282 case LanParam::IPv6DynamicAddresses:
1283 {
1284 if (set >= MAX_IPV6_DYNAMIC_ADDRESSES)
1285 {
1286 return responseParmOutOfRange();
1287 }
1288 getLanIPv6Address(ret, channel, set, originsV6Dynamic);
1289 return responseSuccess(std::move(ret));
1290 }
1291 case LanParam::IPv6RouterControl:
1292 {
1293 std::bitset<8> control;
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001294 control[IPv6RouterControlFlag::Dynamic] =
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001295 channelCall<getEthProp<bool>>(channel, "IPv6AcceptRA");
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001296 control[IPv6RouterControlFlag::Static] = 1;
William A. Kennington III16064aa2019-04-13 17:44:53 -07001297 ret.pack(control);
1298 return responseSuccess(std::move(ret));
1299 }
1300 case LanParam::IPv6StaticRouter1IP:
1301 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001302 stdplus::In6Addr gateway{};
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001303 if (!channelCall<getEthProp<bool>>(channel, "IPv6AcceptRA"))
William A. Kennington III16064aa2019-04-13 17:44:53 -07001304 {
1305 gateway =
1306 channelCall<getGatewayProperty<AF_INET6>>(channel).value_or(
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001307 stdplus::In6Addr{});
William A. Kennington III16064aa2019-04-13 17:44:53 -07001308 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001309 ret.pack(stdplus::raw::asView<char>(gateway));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001310 return responseSuccess(std::move(ret));
1311 }
1312 case LanParam::IPv6StaticRouter1MAC:
1313 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001314 stdplus::EtherAddr mac{};
William A. Kennington III16064aa2019-04-13 17:44:53 -07001315 auto neighbor = channelCall<getGatewayNeighbor<AF_INET6>>(channel);
1316 if (neighbor)
1317 {
1318 mac = neighbor->mac;
1319 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001320 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001321 return responseSuccess(std::move(ret));
1322 }
1323 case LanParam::IPv6StaticRouter1PrefixLength:
1324 {
Jian Zhang796e8242024-02-01 14:07:34 +08001325 ret.pack(uint8_t{0});
William A. Kennington III16064aa2019-04-13 17:44:53 -07001326 return responseSuccess(std::move(ret));
1327 }
1328 case LanParam::IPv6StaticRouter1PrefixValue:
1329 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001330 ret.pack(stdplus::raw::asView<char>(stdplus::In6Addr{}));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001331 return responseSuccess(std::move(ret));
1332 }
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001333 case LanParam::cipherSuitePrivilegeLevels:
1334 {
1335 std::array<uint4_t, ipmi::maxCSRecords> csPrivilegeLevels;
1336
1337 uint8_t resp =
1338 getCipherConfigObject(csPrivFileName, csPrivDefaultFileName)
1339 .getCSPrivilegeLevels(channel, csPrivilegeLevels);
1340 if (!resp)
1341 {
1342 constexpr uint8_t reserved1 = 0x00;
1343 ret.pack(reserved1, csPrivilegeLevels);
1344 return responseSuccess(std::move(ret));
1345 }
1346 else
1347 {
1348 return response(resp);
1349 }
1350 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001351 }
1352
PavanKumarIntel3771f5f2023-11-02 06:26:42 +00001353 if (parameter >= oemCmdStart)
Johnathan Manteyb87034e2019-09-16 10:50:50 -07001354 {
1355 return getLanOem(channel, parameter, set, block);
1356 }
1357
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001358 return response(ccParamNotSupported);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001359}
1360
Jian Zhang23f44652022-03-17 17:13:10 +08001361constexpr const char* solInterface = "xyz.openbmc_project.Ipmi.SOL";
1362constexpr const char* solPath = "/xyz/openbmc_project/ipmi/sol/";
1363constexpr const uint16_t solDefaultPort = 623;
1364
1365RspType<> setSolConfParams(Context::ptr ctx, uint4_t channelBits,
Willy Tu11d68892022-01-20 10:37:34 -08001366 uint4_t /*reserved*/, uint8_t parameter,
Jian Zhang23f44652022-03-17 17:13:10 +08001367 message::Payload& req)
1368{
1369 const uint8_t channel = convertCurrentChannelNum(
1370 static_cast<uint8_t>(channelBits), ctx->channel);
1371
1372 if (!isValidChannel(channel))
1373 {
1374 log<level::ERR>("Set Sol Config - Invalid channel in request");
1375 return responseInvalidFieldRequest();
1376 }
1377
1378 std::string solService{};
1379 std::string solPathWitheEthName = solPath + ipmi::getChannelName(channel);
1380
1381 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1382 {
1383 log<level::ERR>("Set Sol Config - Invalid solInterface",
1384 entry("SERVICE=%s", solService.c_str()),
1385 entry("OBJPATH=%s", solPathWitheEthName.c_str()),
1386 entry("INTERFACE=%s", solInterface));
1387 return responseInvalidFieldRequest();
1388 }
1389
1390 switch (static_cast<SolConfParam>(parameter))
1391 {
1392 case SolConfParam::Progress:
1393 {
1394 uint8_t progress;
1395 if (req.unpack(progress) != 0 || !req.fullyUnpacked())
1396 {
1397 return responseReqDataLenInvalid();
1398 }
1399
1400 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1401 solInterface, "Progress", progress))
1402 {
1403 return responseUnspecifiedError();
1404 }
1405 break;
1406 }
1407 case SolConfParam::Enable:
1408 {
1409 bool enable;
1410 uint7_t reserved2;
1411
1412 if (req.unpack(enable, reserved2) != 0 || !req.fullyUnpacked())
1413 {
1414 return responseReqDataLenInvalid();
1415 }
1416
1417 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1418 solInterface, "Enable", enable))
1419 {
1420 return responseUnspecifiedError();
1421 }
1422 break;
1423 }
1424 case SolConfParam::Authentication:
1425 {
1426 uint4_t privilegeBits{};
1427 uint2_t reserved2{};
1428 bool forceAuth = false;
1429 bool forceEncrypt = false;
1430
1431 if (req.unpack(privilegeBits, reserved2, forceAuth, forceEncrypt) !=
1432 0 ||
1433 !req.fullyUnpacked())
1434 {
1435 return responseReqDataLenInvalid();
1436 }
1437
1438 uint8_t privilege = static_cast<uint8_t>(privilegeBits);
Jonathan Domana48bf772023-05-26 17:54:57 -07001439 if (privilege < static_cast<uint8_t>(Privilege::User) ||
Jian Zhang23f44652022-03-17 17:13:10 +08001440 privilege > static_cast<uint8_t>(Privilege::Oem))
1441 {
1442 return ipmi::responseInvalidFieldRequest();
1443 }
1444
1445 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1446 solInterface, "Privilege", privilege))
1447 {
1448 return responseUnspecifiedError();
1449 }
1450
1451 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1452 solInterface, "ForceEncryption",
1453 forceEncrypt))
1454 {
1455 return responseUnspecifiedError();
1456 }
1457
1458 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1459 solInterface, "ForceAuthentication",
1460 forceAuth))
1461 {
1462 return responseUnspecifiedError();
1463 }
1464 break;
1465 }
1466 case SolConfParam::Accumulate:
1467 {
1468 uint8_t interval;
1469 uint8_t threshold;
1470 if (req.unpack(interval, threshold) != 0 || !req.fullyUnpacked())
1471 {
1472 return responseReqDataLenInvalid();
1473 }
1474
1475 if (threshold == 0)
1476 {
1477 return responseInvalidFieldRequest();
1478 }
1479
1480 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1481 solInterface, "AccumulateIntervalMS",
1482 interval))
1483 {
1484 return responseUnspecifiedError();
1485 }
1486
1487 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1488 solInterface, "Threshold", threshold))
1489 {
1490 return responseUnspecifiedError();
1491 }
1492 break;
1493 }
1494 case SolConfParam::Retry:
1495 {
1496 uint3_t countBits;
1497 uint5_t reserved2;
1498 uint8_t interval;
1499
1500 if (req.unpack(countBits, reserved2, interval) != 0 ||
1501 !req.fullyUnpacked())
1502 {
1503 return responseReqDataLenInvalid();
1504 }
1505
1506 uint8_t count = static_cast<uint8_t>(countBits);
1507 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1508 solInterface, "RetryCount", count))
1509 {
1510 return responseUnspecifiedError();
1511 }
1512
1513 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1514 solInterface, "RetryIntervalMS",
1515 interval))
1516 {
1517 return responseUnspecifiedError();
1518 }
1519 break;
1520 }
1521 case SolConfParam::Port:
1522 {
1523 return response(ipmiCCWriteReadParameter);
1524 }
1525 case SolConfParam::NonVbitrate:
1526 case SolConfParam::Vbitrate:
1527 case SolConfParam::Channel:
1528 default:
1529 return response(ipmiCCParamNotSupported);
1530 }
1531 return responseSuccess();
1532}
1533
1534RspType<message::Payload> getSolConfParams(Context::ptr ctx,
1535 uint4_t channelBits,
Willy Tu11d68892022-01-20 10:37:34 -08001536 uint3_t /*reserved*/, bool revOnly,
1537 uint8_t parameter, uint8_t /*set*/,
1538 uint8_t /*block*/)
Jian Zhang23f44652022-03-17 17:13:10 +08001539{
1540 message::Payload ret;
1541 constexpr uint8_t current_revision = 0x11;
1542 ret.pack(current_revision);
1543 if (revOnly)
1544 {
1545 return responseSuccess(std::move(ret));
1546 }
1547
1548 const uint8_t channel = convertCurrentChannelNum(
1549 static_cast<uint8_t>(channelBits), ctx->channel);
1550
1551 if (!isValidChannel(channel))
1552 {
1553 log<level::ERR>("Get Sol Config - Invalid channel in request");
1554 return responseInvalidFieldRequest();
1555 }
1556
1557 std::string solService{};
1558 std::string solPathWitheEthName = solPath + ipmi::getChannelName(channel);
1559
1560 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1561 {
1562 log<level::ERR>("Set Sol Config - Invalid solInterface",
1563 entry("SERVICE=%s", solService.c_str()),
1564 entry("OBJPATH=%s", solPathWitheEthName.c_str()),
1565 entry("INTERFACE=%s", solInterface));
1566 return responseInvalidFieldRequest();
1567 }
1568
1569 switch (static_cast<SolConfParam>(parameter))
1570 {
1571 case SolConfParam::Progress:
1572 {
1573 uint8_t progress;
1574 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1575 solInterface, "Progress", progress))
1576 {
1577 return responseUnspecifiedError();
1578 }
1579 ret.pack(progress);
1580 return responseSuccess(std::move(ret));
1581 }
1582 case SolConfParam::Enable:
1583 {
1584 bool enable{};
1585 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1586 solInterface, "Enable", enable))
1587 {
1588 return responseUnspecifiedError();
1589 }
1590 ret.pack(enable, uint7_t{});
1591 return responseSuccess(std::move(ret));
1592 }
1593 case SolConfParam::Authentication:
1594 {
1595 // 4bits, cast when pack
1596 uint8_t privilege;
1597 bool forceAuth = false;
1598 bool forceEncrypt = false;
1599
1600 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1601 solInterface, "Privilege", privilege))
1602 {
1603 return responseUnspecifiedError();
1604 }
1605
1606 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1607 solInterface, "ForceAuthentication",
1608 forceAuth))
1609 {
1610 return responseUnspecifiedError();
1611 }
1612
1613 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1614 solInterface, "ForceEncryption",
1615 forceEncrypt))
1616 {
1617 return responseUnspecifiedError();
1618 }
1619 ret.pack(uint4_t{privilege}, uint2_t{}, forceAuth, forceEncrypt);
1620 return responseSuccess(std::move(ret));
1621 }
1622 case SolConfParam::Accumulate:
1623 {
1624 uint8_t interval{}, threshold{};
1625
1626 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1627 solInterface, "AccumulateIntervalMS",
1628 interval))
1629 {
1630 return responseUnspecifiedError();
1631 }
1632
1633 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1634 solInterface, "Threshold", threshold))
1635 {
1636 return responseUnspecifiedError();
1637 }
1638 ret.pack(interval, threshold);
1639 return responseSuccess(std::move(ret));
1640 }
1641 case SolConfParam::Retry:
1642 {
1643 // 3bits, cast when cast
1644 uint8_t count{};
1645 uint8_t interval{};
1646
1647 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1648 solInterface, "RetryCount", count))
1649 {
1650 return responseUnspecifiedError();
1651 }
1652
1653 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1654 solInterface, "RetryIntervalMS",
1655 interval))
1656 {
1657 return responseUnspecifiedError();
1658 }
1659 ret.pack(uint3_t{count}, uint5_t{}, interval);
1660 return responseSuccess(std::move(ret));
1661 }
1662 case SolConfParam::Port:
1663 {
1664 auto port = solDefaultPort;
1665 ret.pack(static_cast<uint16_t>(port));
1666 return responseSuccess(std::move(ret));
1667 }
1668 case SolConfParam::Channel:
1669 {
1670 ret.pack(channel);
1671 return responseSuccess(std::move(ret));
1672 }
1673 case SolConfParam::NonVbitrate:
Jonathan Domana48bf772023-05-26 17:54:57 -07001674 {
1675 uint64_t baudRate;
1676 uint8_t encodedBitRate = 0;
1677 if (ipmi::getDbusProperty(
1678 ctx, "xyz.openbmc_project.Console.default",
1679 "/xyz/openbmc_project/console/default",
1680 "xyz.openbmc_project.Console.UART", "Baud", baudRate))
1681 {
1682 return ipmi::responseUnspecifiedError();
1683 }
1684 switch (baudRate)
1685 {
1686 case 9600:
1687 encodedBitRate = 0x06;
1688 break;
1689 case 19200:
1690 encodedBitRate = 0x07;
1691 break;
1692 case 38400:
1693 encodedBitRate = 0x08;
1694 break;
1695 case 57600:
1696 encodedBitRate = 0x09;
1697 break;
1698 case 115200:
1699 encodedBitRate = 0x0a;
1700 break;
1701 default:
1702 break;
1703 }
1704 ret.pack(encodedBitRate);
1705 return responseSuccess(std::move(ret));
1706 }
Jian Zhang23f44652022-03-17 17:13:10 +08001707 case SolConfParam::Vbitrate:
1708 default:
1709 return response(ipmiCCParamNotSupported);
1710 }
1711
1712 return response(ccParamNotSupported);
1713}
1714
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001715} // namespace transport
1716} // namespace ipmi
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301717
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001718void register_netfn_transport_functions() __attribute__((constructor));
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301719
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001720void register_netfn_transport_functions()
1721{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001722 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1723 ipmi::transport::cmdSetLanConfigParameters,
1724 ipmi::Privilege::Admin, ipmi::transport::setLan);
1725 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1726 ipmi::transport::cmdGetLanConfigParameters,
Johnathan Mantey34698d52019-11-19 14:47:30 -08001727 ipmi::Privilege::Operator, ipmi::transport::getLan);
Jian Zhang23f44652022-03-17 17:13:10 +08001728 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1729 ipmi::transport::cmdSetSolConfigParameters,
1730 ipmi::Privilege::Admin,
1731 ipmi::transport::setSolConfParams);
1732 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1733 ipmi::transport::cmdGetSolConfigParameters,
1734 ipmi::Privilege::User,
1735 ipmi::transport::getSolConfParams);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001736}