blob: a9bc7c889723e788ff8c8e38cef5dad7e3e21e3b [file] [log] [blame]
Patrick Venture690a2342020-05-17 11:51:31 -07001#include "transporthandler.hpp"
2
William A. Kennington III726f2bd2023-06-21 01:11:40 -07003#include <stdplus/net/addr/subnet.hpp>
William A. Kennington III7a3831b2023-06-21 01:10:49 -07004#include <stdplus/raw.hpp>
5
6#include <array>
William A. Kennington III726f2bd2023-06-21 01:11:40 -07007#include <fstream>
William A. Kennington III7a3831b2023-06-21 01:10:49 -07008
William A. Kennington IIIc514d872019-04-06 18:19:38 -07009using phosphor::logging::commit;
10using phosphor::logging::elog;
11using phosphor::logging::entry;
12using phosphor::logging::level;
13using phosphor::logging::log;
Willy Tu523e2d12023-09-05 11:36:48 -070014using sdbusplus::error::xyz::openbmc_project::common::InternalFailure;
William A. Kennington III7a3831b2023-06-21 01:10:49 -070015using sdbusplus::error::xyz::openbmc_project::common::InvalidArgument;
Willy Tu523e2d12023-09-05 11:36:48 -070016using sdbusplus::server::xyz::openbmc_project::network::EthernetInterface;
17using sdbusplus::server::xyz::openbmc_project::network::IP;
18using sdbusplus::server::xyz::openbmc_project::network::Neighbor;
William A. Kennington IIIc514d872019-04-06 18:19:38 -070019
Johnathan Manteyaffadb52019-10-07 10:13:53 -070020namespace cipher
21{
22
23std::vector<uint8_t> getCipherList()
24{
25 std::vector<uint8_t> cipherList;
26
27 std::ifstream jsonFile(cipher::configFile);
28 if (!jsonFile.is_open())
29 {
30 log<level::ERR>("Channel Cipher suites file not found");
31 elog<InternalFailure>();
32 }
33
34 auto data = Json::parse(jsonFile, nullptr, false);
35 if (data.is_discarded())
36 {
37 log<level::ERR>("Parsing channel cipher suites JSON failed");
38 elog<InternalFailure>();
39 }
40
41 // Byte 1 is reserved
42 cipherList.push_back(0x00);
43
44 for (const auto& record : data)
45 {
46 cipherList.push_back(record.value(cipher, 0));
47 }
48
49 return cipherList;
50}
51} // namespace cipher
52
53namespace ipmi
54{
55namespace transport
56{
57
William A. Kennington IIIc514d872019-04-06 18:19:38 -070058/** @brief Valid address origins for IPv4 */
59const std::unordered_set<IP::AddressOrigin> originsV4 = {
60 IP::AddressOrigin::Static,
61 IP::AddressOrigin::DHCP,
62};
63
Johnathan Manteyb87034e2019-09-16 10:50:50 -070064static constexpr uint8_t oemCmdStart = 192;
65static constexpr uint8_t oemCmdEnd = 255;
66
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
87 auto req = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF,
88 "GetSubTree");
William A. Kennington IIIc72f3602023-10-19 03:51:37 -070089 req.append(std::string_view(PATH_ROOT), 0,
William A. Kennington IIIc514d872019-04-06 18:19:38 -070090 std::vector<std::string>{INTF_VLAN, INTF_ETHERNET});
91 auto reply = bus.call(req);
92 ObjectTree objs;
93 reply.read(objs);
94
95 ChannelParams params;
96 for (const auto& [path, impls] : objs)
97 {
William A. Kennington IIIc72f3602023-10-19 03:51:37 -070098 if (!ifnameInPath(ifname, path))
William A. Kennington IIIc514d872019-04-06 18:19:38 -070099 {
100 continue;
101 }
102 for (const auto& [service, intfs] : impls)
103 {
104 bool vlan = false;
105 bool ethernet = false;
106 for (const auto& intf : intfs)
107 {
108 if (intf == INTF_VLAN)
109 {
110 vlan = true;
111 }
112 else if (intf == INTF_ETHERNET)
113 {
114 ethernet = true;
115 }
116 }
117 if (params.service.empty() && (vlan || ethernet))
118 {
119 params.service = service;
120 }
121 if (params.ifPath.empty() && !vlan && ethernet)
122 {
123 params.ifPath = path;
124 }
125 if (params.logicalPath.empty() && vlan)
126 {
127 params.logicalPath = path;
128 }
129 }
130 }
131
132 // We must have a path for the underlying interface
133 if (params.ifPath.empty())
134 {
135 return std::nullopt;
136 }
137 // We don't have a VLAN so the logical path is the same
138 if (params.logicalPath.empty())
139 {
140 params.logicalPath = params.ifPath;
141 }
142
143 params.id = channel;
144 params.ifname = std::move(ifname);
Willy Tu11d68892022-01-20 10:37:34 -0800145 return params;
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700146}
147
Patrick Williams5d82f472022-07-22 19:26:53 -0500148ChannelParams getChannelParams(sdbusplus::bus_t& bus, uint8_t channel)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700149{
150 auto params = maybeGetChannelParams(bus, channel);
151 if (!params)
152 {
153 log<level::ERR>("Failed to get channel params",
154 entry("CHANNEL=%" PRIu8, channel));
155 elog<InternalFailure>();
156 }
157 return std::move(*params);
158}
159
160/** @brief Wraps the phosphor logging method to insert some additional metadata
161 *
162 * @param[in] params - The parameters for the channel
163 * ...
164 */
165template <auto level, typename... Args>
166auto logWithChannel(const ChannelParams& params, Args&&... args)
167{
168 return log<level>(std::forward<Args>(args)...,
169 entry("CHANNEL=%d", params.id),
170 entry("IFNAME=%s", params.ifname.c_str()));
171}
172template <auto level, typename... Args>
173auto logWithChannel(const std::optional<ChannelParams>& params, Args&&... args)
174{
175 if (params)
176 {
177 return logWithChannel<level>(*params, std::forward<Args>(args)...);
178 }
179 return log<level>(std::forward<Args>(args)...);
180}
181
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700182/** @brief Get / Set the Property value from phosphor-networkd EthernetInterface
183 */
184template <typename T>
185static T getEthProp(sdbusplus::bus_t& bus, const ChannelParams& params,
186 const std::string& prop)
187{
188 return std::get<T>(getDbusProperty(bus, params.service, params.logicalPath,
189 INTF_ETHERNET, prop));
190}
191template <typename T>
192static void setEthProp(sdbusplus::bus_t& bus, const ChannelParams& params,
193 const std::string& prop, const T& t)
194{
195 return setDbusProperty(bus, params.service, params.logicalPath,
196 INTF_ETHERNET, prop, t);
197}
198
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700199/** @brief Determines the MAC of the ethernet interface
200 *
201 * @param[in] bus - The bus object used for lookups
202 * @param[in] params - The parameters for the channel
203 * @return The configured mac address
204 */
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700205stdplus::EtherAddr getMACProperty(sdbusplus::bus_t& bus,
206 const ChannelParams& params)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700207{
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700208 auto prop = getDbusProperty(bus, params.service, params.ifPath, INTF_MAC,
209 "MACAddress");
210 return stdplus::fromStr<stdplus::EtherAddr>(std::get<std::string>(prop));
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700211}
212
213/** @brief Sets the system value for MAC address on the given interface
214 *
215 * @param[in] bus - The bus object used for lookups
216 * @param[in] params - The parameters for the channel
217 * @param[in] mac - MAC address to apply
218 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500219void setMACProperty(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700220 stdplus::EtherAddr mac)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700221{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700222 setDbusProperty(bus, params.service, params.ifPath, INTF_MAC, "MACAddress",
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700223 stdplus::toStr(mac));
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700224}
225
Patrick Williams5d82f472022-07-22 19:26:53 -0500226void deleteObjectIfExists(sdbusplus::bus_t& bus, const std::string& service,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700227 const std::string& path)
228{
229 if (path.empty())
230 {
231 return;
232 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530233 try
tomjose26e17732016-03-03 08:52:51 -0600234 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700235 auto req = bus.new_method_call(service.c_str(), path.c_str(),
236 ipmi::DELETE_INTERFACE, "Delete");
237 bus.call_noreply(req);
238 }
Patrick Williams5d82f472022-07-22 19:26:53 -0500239 catch (const sdbusplus::exception_t& e)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700240 {
jayaprakash Mutyala84c49dc2020-05-18 23:12:13 +0000241 if (strcmp(e.name(),
242 "xyz.openbmc_project.Common.Error.InternalFailure") != 0 &&
243 strcmp(e.name(), "org.freedesktop.DBus.Error.UnknownObject") != 0)
tomjose26e17732016-03-03 08:52:51 -0600244 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700245 // We want to rethrow real errors
246 throw;
tomjose26e17732016-03-03 08:52:51 -0600247 }
248 }
tomjose26e17732016-03-03 08:52:51 -0600249}
250
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700251/** @brief Sets the address info configured for the interface
252 * If a previous address path exists then it will be removed
253 * before the new address is added.
254 *
255 * @param[in] bus - The bus object used for lookups
256 * @param[in] params - The parameters for the channel
257 * @param[in] address - The address of the new IP
258 * @param[in] prefix - The prefix of the new IP
259 */
260template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500261void createIfAddr(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700262 typename AddrFamily<family>::addr address, uint8_t prefix)
Tom Josepha30c8d32018-03-22 02:15:03 +0530263{
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500264 auto newreq = bus.new_method_call(params.service.c_str(),
265 params.logicalPath.c_str(),
266 INTF_IP_CREATE, "IP");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700267 std::string protocol =
Willy Tu523e2d12023-09-05 11:36:48 -0700268 sdbusplus::common::xyz::openbmc_project::network::convertForMessage(
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700269 AddrFamily<family>::protocol);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700270 stdplus::ToStrHandle<stdplus::ToStr<typename AddrFamily<family>::addr>> tsh;
271 newreq.append(protocol, tsh(address), prefix, "");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700272 bus.call_noreply(newreq);
273}
Tom Josepha30c8d32018-03-22 02:15:03 +0530274
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700275/** @brief Trivial helper for getting the IPv4 address from getIfAddrs()
276 *
277 * @param[in] bus - The bus object used for lookups
278 * @param[in] params - The parameters for the channel
279 * @return The address and prefix if found
280 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500281auto getIfAddr4(sdbusplus::bus_t& bus, const ChannelParams& params)
Tom Josepha30c8d32018-03-22 02:15:03 +0530282{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700283 return getIfAddr<AF_INET>(bus, params, 0, originsV4);
284}
Tom Josepha30c8d32018-03-22 02:15:03 +0530285
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700286/** @brief Reconfigures the IPv4 address info configured for the interface
287 *
288 * @param[in] bus - The bus object used for lookups
289 * @param[in] params - The parameters for the channel
290 * @param[in] address - The new address if specified
291 * @param[in] prefix - The new address prefix if specified
292 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500293void reconfigureIfAddr4(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700294 std::optional<stdplus::In4Addr> address,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700295 std::optional<uint8_t> prefix)
296{
297 auto ifaddr = getIfAddr4(bus, params);
298 if (!ifaddr && !address)
Tom Josepha30c8d32018-03-22 02:15:03 +0530299 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700300 log<level::ERR>("Missing address for IPv4 assignment");
Tom Josepha30c8d32018-03-22 02:15:03 +0530301 elog<InternalFailure>();
302 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700303 uint8_t fallbackPrefix = AddrFamily<AF_INET>::defaultPrefix;
304 if (ifaddr)
Tom Josepha30c8d32018-03-22 02:15:03 +0530305 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700306 fallbackPrefix = ifaddr->prefix;
307 deleteObjectIfExists(bus, params.service, ifaddr->path);
308 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700309 auto addr = address.value_or(ifaddr->address);
310 if (addr != stdplus::In4Addr{})
Johnathan Manteycbfa6e12023-06-01 06:57:25 -0700311 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700312 createIfAddr<AF_INET>(bus, params, addr,
Johnathan Manteycbfa6e12023-06-01 06:57:25 -0700313 prefix.value_or(fallbackPrefix));
314 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700315}
316
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700317template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500318std::optional<IfNeigh<family>> findGatewayNeighbor(sdbusplus::bus_t& bus,
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700319 const ChannelParams& params,
320 ObjectLookupCache& neighbors)
321{
322 auto gateway = getGatewayProperty<family>(bus, params);
323 if (!gateway)
324 {
325 return std::nullopt;
326 }
327
328 return findStaticNeighbor<family>(bus, params, *gateway, neighbors);
329}
330
331template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500332std::optional<IfNeigh<family>> getGatewayNeighbor(sdbusplus::bus_t& bus,
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700333 const ChannelParams& params)
334{
335 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
336 return findGatewayNeighbor<family>(bus, params, neighbors);
337}
338
339template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500340void reconfigureGatewayMAC(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700341 stdplus::EtherAddr mac)
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700342{
343 auto gateway = getGatewayProperty<family>(bus, params);
344 if (!gateway)
345 {
346 log<level::ERR>("Tried to set Gateway MAC without Gateway");
347 elog<InternalFailure>();
348 }
349
350 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500351 auto neighbor = findStaticNeighbor<family>(bus, params, *gateway,
352 neighbors);
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700353 if (neighbor)
354 {
355 deleteObjectIfExists(bus, params.service, neighbor->path);
356 }
357
358 createNeighbor<family>(bus, params, *gateway, mac);
359}
360
William A. Kennington III16064aa2019-04-13 17:44:53 -0700361/** @brief Deconfigures the IPv6 address info configured for the interface
362 *
363 * @param[in] bus - The bus object used for lookups
364 * @param[in] params - The parameters for the channel
365 * @param[in] idx - The address index to operate on
366 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500367void deconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III16064aa2019-04-13 17:44:53 -0700368 uint8_t idx)
369{
370 auto ifaddr = getIfAddr<AF_INET6>(bus, params, idx, originsV6Static);
371 if (ifaddr)
372 {
373 deleteObjectIfExists(bus, params.service, ifaddr->path);
374 }
375}
376
377/** @brief Reconfigures the IPv6 address info configured for the interface
378 *
379 * @param[in] bus - The bus object used for lookups
380 * @param[in] params - The parameters for the channel
381 * @param[in] idx - The address index to operate on
382 * @param[in] address - The new address
383 * @param[in] prefix - The new address prefix
384 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500385void reconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700386 uint8_t idx, stdplus::In6Addr address, uint8_t prefix)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700387{
388 deconfigureIfAddr6(bus, params, idx);
389 createIfAddr<AF_INET6>(bus, params, address, prefix);
390}
391
392/** @brief Converts the AddressOrigin into an IPv6Source
393 *
394 * @param[in] origin - The DBus Address Origin to convert
395 * @return The IPv6Source version of the origin
396 */
397IPv6Source originToSourceType(IP::AddressOrigin origin)
398{
399 switch (origin)
400 {
401 case IP::AddressOrigin::Static:
402 return IPv6Source::Static;
403 case IP::AddressOrigin::DHCP:
404 return IPv6Source::DHCP;
405 case IP::AddressOrigin::SLAAC:
406 return IPv6Source::SLAAC;
407 default:
408 {
Willy Tu523e2d12023-09-05 11:36:48 -0700409 auto originStr = sdbusplus::common::xyz::openbmc_project::network::
William A. Kennington III16064aa2019-04-13 17:44:53 -0700410 convertForMessage(origin);
411 log<level::ERR>(
412 "Invalid IP::AddressOrigin conversion to IPv6Source",
413 entry("ORIGIN=%s", originStr.c_str()));
414 elog<InternalFailure>();
415 }
416 }
417}
418
419/** @brief Packs the IPMI message response with IPv6 address data
420 *
421 * @param[out] ret - The IPMI response payload to be packed
422 * @param[in] channel - The channel id corresponding to an ethernet interface
423 * @param[in] set - The set selector for determining address index
424 * @param[in] origins - Set of valid origins for address filtering
425 */
426void getLanIPv6Address(message::Payload& ret, uint8_t channel, uint8_t set,
427 const std::unordered_set<IP::AddressOrigin>& origins)
428{
429 auto source = IPv6Source::Static;
430 bool enabled = false;
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700431 stdplus::In6Addr addr{};
Johnathan Mantey5aae0922021-10-21 13:05:36 -0700432 uint8_t prefix{};
William A. Kennington III16064aa2019-04-13 17:44:53 -0700433 auto status = IPv6AddressStatus::Disabled;
434
435 auto ifaddr = channelCall<getIfAddr<AF_INET6>>(channel, set, origins);
436 if (ifaddr)
437 {
438 source = originToSourceType(ifaddr->origin);
Johnathan Mantey846af862021-10-21 12:48:54 -0700439 enabled = (origins == originsV6Static);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700440 addr = ifaddr->address;
441 prefix = ifaddr->prefix;
442 status = IPv6AddressStatus::Active;
443 }
444
445 ret.pack(set);
William A. Kennington III7a0e5df2021-05-19 13:31:29 -0700446 ret.pack(types::enum_cast<uint4_t>(source), uint3_t{}, enabled);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700447 ret.pack(stdplus::raw::asView<char>(addr));
William A. Kennington III16064aa2019-04-13 17:44:53 -0700448 ret.pack(prefix);
William A. Kennington III7a0e5df2021-05-19 13:31:29 -0700449 ret.pack(types::enum_cast<uint8_t>(status));
William A. Kennington III16064aa2019-04-13 17:44:53 -0700450}
451
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700452/** @brief Gets the vlan ID configured on the interface
453 *
454 * @param[in] bus - The bus object used for lookups
455 * @param[in] params - The parameters for the channel
456 * @return VLAN id or the standard 0 for no VLAN
457 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500458uint16_t getVLANProperty(sdbusplus::bus_t& bus, const ChannelParams& params)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700459{
460 // VLAN devices will always have a separate logical object
461 if (params.ifPath == params.logicalPath)
462 {
463 return 0;
464 }
465
466 auto vlan = std::get<uint32_t>(getDbusProperty(
467 bus, params.service, params.logicalPath, INTF_VLAN, "Id"));
468 if ((vlan & VLAN_VALUE_MASK) != vlan)
469 {
470 logWithChannel<level::ERR>(params, "networkd returned an invalid vlan",
471 entry("VLAN=%" PRIu32, vlan));
Tom Josepha30c8d32018-03-22 02:15:03 +0530472 elog<InternalFailure>();
473 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700474 return vlan;
Tom Josepha30c8d32018-03-22 02:15:03 +0530475}
476
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700477/** @brief Deletes all of the possible configuration parameters for a channel
478 *
479 * @param[in] bus - The bus object used for lookups
480 * @param[in] params - The parameters for the channel
481 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500482void deconfigureChannel(sdbusplus::bus_t& bus, ChannelParams& params)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500483{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700484 // Delete all objects associated with the interface
485 auto objreq = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF,
486 "GetSubTree");
William A. Kennington IIIc72f3602023-10-19 03:51:37 -0700487 objreq.append(std::string_view(PATH_ROOT), 0,
488 std::vector<std::string>{DELETE_INTERFACE});
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700489 auto objreply = bus.call(objreq);
490 ObjectTree objs;
491 objreply.read(objs);
492 for (const auto& [path, impls] : objs)
493 {
William A. Kennington IIIc72f3602023-10-19 03:51:37 -0700494 if (!ifnameInPath(params.ifname, path))
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700495 {
496 continue;
497 }
498 for (const auto& [service, intfs] : impls)
499 {
500 deleteObjectIfExists(bus, service, path);
501 }
502 // Update params to reflect the deletion of vlan
503 if (path == params.logicalPath)
504 {
505 params.logicalPath = params.ifPath;
506 }
507 }
508
509 // Clear out any settings on the lower physical interface
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700510 setEthProp(bus, params, "DHCP4", false);
511 setEthProp(bus, params, "DHCP6", false);
512 setEthProp(bus, params, "IPv6AcceptRA", false);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500513}
514
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700515/** @brief Creates a new VLAN on the specified interface
516 *
517 * @param[in] bus - The bus object used for lookups
518 * @param[in] params - The parameters for the channel
519 * @param[in] vlan - The id of the new vlan
520 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500521void createVLAN(sdbusplus::bus_t& bus, ChannelParams& params, uint16_t vlan)
Ratan Guptab8e99552017-07-27 07:07:48 +0530522{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700523 if (vlan == 0)
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530524 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700525 return;
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530526 }
527
William A. Kennington IIIc72f3602023-10-19 03:51:37 -0700528 auto req = bus.new_method_call(params.service.c_str(), PATH_ROOT.c_str(),
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700529 INTF_VLAN_CREATE, "VLAN");
530 req.append(params.ifname, static_cast<uint32_t>(vlan));
531 auto reply = bus.call(req);
532 sdbusplus::message::object_path newPath;
533 reply.read(newPath);
534 params.logicalPath = std::move(newPath);
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530535}
536
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700537/** @brief Performs the necessary reconfiguration to change the VLAN
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 new vlan id to use
542 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500543void reconfigureVLAN(sdbusplus::bus_t& bus, ChannelParams& params,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700544 uint16_t vlan)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500545{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700546 // Unfortunatetly we don't have built-in functions to migrate our interface
547 // customizations to new VLAN interfaces, or have some kind of decoupling.
548 // We therefore must retain all of our old information, setup the new VLAN
549 // configuration, then restore the old info.
Nan Li3d0df912016-10-18 19:51:41 +0800550
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700551 // Save info from the old logical interface
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700552 bool dhcp4 = getEthProp<bool>(bus, params, "DHCP4");
553 bool dhcp6 = getEthProp<bool>(bus, params, "DHCP6");
554 bool ra = getEthProp<bool>(bus, params, "IPv6AcceptRA");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700555 ObjectLookupCache ips(bus, params, INTF_IP);
556 auto ifaddr4 = findIfAddr<AF_INET>(bus, params, 0, originsV4, ips);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700557 std::vector<IfAddr<AF_INET6>> ifaddrs6;
558 for (uint8_t i = 0; i < MAX_IPV6_STATIC_ADDRESSES; ++i)
559 {
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500560 auto ifaddr6 = findIfAddr<AF_INET6>(bus, params, i, originsV6Static,
561 ips);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700562 if (!ifaddr6)
563 {
564 break;
565 }
566 ifaddrs6.push_back(std::move(*ifaddr6));
567 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700568 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
569 auto neighbor4 = findGatewayNeighbor<AF_INET>(bus, params, neighbors);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700570 auto neighbor6 = findGatewayNeighbor<AF_INET6>(bus, params, neighbors);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500571
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700572 deconfigureChannel(bus, params);
573 createVLAN(bus, params, vlan);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500574
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700575 // Re-establish the saved settings
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700576 setEthProp(bus, params, "DHCP4", dhcp4);
577 setEthProp(bus, params, "DHCP6", dhcp6);
578 setEthProp(bus, params, "IPv6AcceptRA", ra);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700579 if (ifaddr4)
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800580 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700581 createIfAddr<AF_INET>(bus, params, ifaddr4->address, ifaddr4->prefix);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800582 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700583 for (const auto& ifaddr6 : ifaddrs6)
584 {
585 createIfAddr<AF_INET6>(bus, params, ifaddr6.address, ifaddr6.prefix);
586 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700587 if (neighbor4)
588 {
589 createNeighbor<AF_INET>(bus, params, neighbor4->ip, neighbor4->mac);
590 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700591 if (neighbor6)
592 {
593 createNeighbor<AF_INET6>(bus, params, neighbor6->ip, neighbor6->mac);
594 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700595}
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800596
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700597// We need to store this value so it can be returned to the client
598// It is volatile so safe to store in daemon memory.
599static std::unordered_map<uint8_t, SetStatus> setStatus;
600
601// Until we have good support for fixed versions of IPMI tool
602// we need to return the VLAN id for disabled VLANs. The value is only
603// used for verification that a disable operation succeeded and will only
604// be sent if our system indicates that vlans are disabled.
605static std::unordered_map<uint8_t, uint16_t> lastDisabledVlan;
606
607/** @brief Gets the set status for the channel if it exists
608 * Otherise populates and returns the default value.
609 *
610 * @param[in] channel - The channel id corresponding to an ethernet interface
611 * @return A reference to the SetStatus for the channel
612 */
613SetStatus& getSetStatus(uint8_t channel)
614{
615 auto it = setStatus.find(channel);
616 if (it != setStatus.end())
617 {
618 return it->second;
619 }
620 return setStatus[channel] = SetStatus::Complete;
621}
622
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700623/** @brief Unpacks the trivially copyable type from the message */
624template <typename T>
625static T unpackT(message::Payload& req)
626{
627 std::array<uint8_t, sizeof(T)> bytes;
628 if (req.unpack(bytes) != 0)
629 {
630 throw ccReqDataLenInvalid;
631 }
632 return stdplus::raw::copyFrom<T>(bytes);
633}
634
635/** @brief Ensure the message is fully unpacked */
636static void unpackFinal(message::Payload& req)
637{
638 if (!req.fullyUnpacked())
639 {
640 throw ccReqDataTruncated;
641 }
642}
643
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700644/**
645 * Define placeholder command handlers for the OEM Extension bytes for the Set
646 * LAN Configuration Parameters and Get LAN Configuration Parameters
647 * commands. Using "weak" linking allows the placeholder setLanOem/getLanOem
648 * functions below to be overridden.
649 * To create handlers for your own proprietary command set:
650 * Create/modify a phosphor-ipmi-host Bitbake append file within your Yocto
651 * recipe
652 * Create C++ file(s) that define IPMI handler functions matching the
653 * function names below (i.e. setLanOem). The default name for the
654 * transport IPMI commands is transporthandler_oem.cpp.
655 * Add:
Johnathan Manteyefe26682022-08-11 14:30:45 -0700656 * EXTRA_OEMESON:append = "-Dtransport-oem=enabled"
657 * Create a do_configure:prepend()/do_install:append() method in your
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700658 * bbappend file to copy the file to the build directory.
659 * Add:
660 * PROJECT_SRC_DIR := "${THISDIR}/${PN}"
661 * # Copy the "strong" functions into the working directory, overriding the
662 * # placeholder functions.
Johnathan Manteyefe26682022-08-11 14:30:45 -0700663 * do_configure:prepend(){
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700664 * cp -f ${PROJECT_SRC_DIR}/transporthandler_oem.cpp ${S}
665 * }
666 *
667 * # Clean up after complilation has completed
Johnathan Manteyefe26682022-08-11 14:30:45 -0700668 * do_install:append(){
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700669 * rm -f ${S}/transporthandler_oem.cpp
670 * }
671 *
672 */
673
674/**
675 * Define the placeholder OEM commands as having weak linkage. Create
676 * setLanOem, and getLanOem functions in the transporthandler_oem.cpp
677 * file. The functions defined there must not have the "weak" attribute
678 * applied to them.
679 */
680RspType<> setLanOem(uint8_t channel, uint8_t parameter, message::Payload& req)
681 __attribute__((weak));
682RspType<message::Payload> getLanOem(uint8_t channel, uint8_t parameter,
683 uint8_t set, uint8_t block)
684 __attribute__((weak));
685
Willy Tu11d68892022-01-20 10:37:34 -0800686RspType<> setLanOem(uint8_t, uint8_t, message::Payload& req)
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700687{
688 req.trailingOk = true;
689 return response(ccParamNotSupported);
690}
691
Willy Tu11d68892022-01-20 10:37:34 -0800692RspType<message::Payload> getLanOem(uint8_t, uint8_t, uint8_t, uint8_t)
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700693{
694 return response(ccParamNotSupported);
695}
696
Jian Zhangcf19d142023-07-31 10:22:53 +0800697/**
698 * @brief is a valid LAN channel.
699 *
700 * This function checks whether the input channel is a valid LAN channel or not.
701 *
702 * @param[in] channel: the channel number.
703 * @return nullopt if the channel is invalid, false if the channel is not a LAN
704 * channel, true if the channel is a LAN channel.
705 **/
706std::optional<bool> isLanChannel(uint8_t channel)
707{
708 ChannelInfo chInfo;
709 auto cc = getChannelInfo(channel, chInfo);
710 if (cc != ccSuccess)
711 {
712 return std::nullopt;
713 }
714
715 return chInfo.mediumType ==
716 static_cast<uint8_t>(EChannelMediumType::lan8032);
717}
718
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700719RspType<> setLanInt(Context::ptr ctx, uint4_t channelBits, uint4_t reserved1,
720 uint8_t parameter, message::Payload& req)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700721{
vijayabharathix shettycc769252020-02-27 17:52:20 +0000722 const uint8_t channel = convertCurrentChannelNum(
723 static_cast<uint8_t>(channelBits), ctx->channel);
724 if (reserved1 || !isValidChannel(channel))
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700725 {
vijayabharathix shettycc769252020-02-27 17:52:20 +0000726 log<level::ERR>("Set Lan - Invalid field in request");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700727 req.trailingOk = true;
728 return responseInvalidFieldRequest();
729 }
730
Jian Zhangcf19d142023-07-31 10:22:53 +0800731 if (!isLanChannel(channel).value_or(false))
732 {
733 log<level::ERR>("Set Lan - Not a LAN channel");
734 return responseInvalidFieldRequest();
735 }
736
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700737 switch (static_cast<LanParam>(parameter))
738 {
739 case LanParam::SetStatus:
740 {
741 uint2_t flag;
742 uint6_t rsvd;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700743 if (req.unpack(flag, rsvd) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700744 {
745 return responseReqDataLenInvalid();
746 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700747 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800748 if (rsvd)
749 {
750 return responseInvalidFieldRequest();
751 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700752 auto status = static_cast<SetStatus>(static_cast<uint8_t>(flag));
753 switch (status)
754 {
755 case SetStatus::Complete:
756 {
757 getSetStatus(channel) = status;
758 return responseSuccess();
759 }
760 case SetStatus::InProgress:
761 {
762 auto& storedStatus = getSetStatus(channel);
763 if (storedStatus == SetStatus::InProgress)
764 {
765 return response(ccParamSetLocked);
766 }
767 storedStatus = status;
768 return responseSuccess();
769 }
770 case SetStatus::Commit:
771 if (getSetStatus(channel) != SetStatus::InProgress)
772 {
773 return responseInvalidFieldRequest();
774 }
775 return responseSuccess();
776 }
777 return response(ccParamNotSupported);
778 }
779 case LanParam::AuthSupport:
780 {
781 req.trailingOk = true;
782 return response(ccParamReadOnly);
783 }
784 case LanParam::AuthEnables:
785 {
786 req.trailingOk = true;
Johnathan Mantey76ce9c72019-11-14 14:41:46 -0800787 return response(ccParamReadOnly);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700788 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800789 case LanParam::IP:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600790 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700791 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800792 {
793 return responseCommandNotAvailable();
794 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700795 auto ip = unpackT<stdplus::In4Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700796 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700797 channelCall<reconfigureIfAddr4>(channel, ip, std::nullopt);
798 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +0530799 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700800 case LanParam::IPSrc:
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530801 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700802 uint4_t flag;
803 uint4_t rsvd;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700804 if (req.unpack(flag, rsvd) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700805 {
806 return responseReqDataLenInvalid();
807 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700808 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800809 if (rsvd)
810 {
811 return responseInvalidFieldRequest();
812 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700813 switch (static_cast<IPSrc>(static_cast<uint8_t>(flag)))
814 {
815 case IPSrc::DHCP:
Johnathan Mantey65265362019-11-14 11:24:19 -0800816 // The IPSrc IPMI command is only for IPv4
817 // management. Modifying IPv6 state is done using
818 // a completely different Set LAN Configuration
819 // subcommand.
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700820 channelCall<setEthProp<bool>>(channel, "DHCP4", true);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700821 return responseSuccess();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700822 case IPSrc::Unspecified:
823 case IPSrc::Static:
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700824 channelCall<setEthProp<bool>>(channel, "DHCP4", false);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700825 return responseSuccess();
Rajashekar Gade Reddy8a860ea2019-12-24 11:31:19 +0530826 case IPSrc::BIOS:
827 case IPSrc::BMC:
Rajashekar Gade Reddy8a860ea2019-12-24 11:31:19 +0530828 return responseInvalidFieldRequest();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700829 }
830 return response(ccParamNotSupported);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530831 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800832 case LanParam::MAC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530833 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700834 auto mac = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700835 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700836 channelCall<setMACProperty>(channel, mac);
837 return responseSuccess();
Ratan Gupta533d03b2017-07-30 10:39:22 +0530838 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700839 case LanParam::SubnetMask:
Ratan Guptab8e99552017-07-27 07:07:48 +0530840 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700841 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800842 {
843 return responseCommandNotAvailable();
844 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700845 auto pfx = stdplus::maskToPfx(unpackT<stdplus::In4Addr>(req));
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700846 unpackFinal(req);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700847 channelCall<reconfigureIfAddr4>(channel, std::nullopt, pfx);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700848 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +0530849 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700850 case LanParam::Gateway1:
Ratan Guptab8e99552017-07-27 07:07:48 +0530851 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700852 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800853 {
854 return responseCommandNotAvailable();
855 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700856 auto gateway = unpackT<stdplus::In4Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700857 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700858 channelCall<setGatewayProperty<AF_INET>>(channel, gateway);
859 return responseSuccess();
860 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700861 case LanParam::Gateway1MAC:
862 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700863 auto gatewayMAC = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700864 unpackFinal(req);
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700865 channelCall<reconfigureGatewayMAC<AF_INET>>(channel, gatewayMAC);
866 return responseSuccess();
867 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700868 case LanParam::VLANId:
869 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700870 uint12_t vlanData;
871 uint3_t rsvd;
872 bool vlanEnable;
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530873
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700874 if (req.unpack(vlanData, rsvd, vlanEnable) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700875 {
876 return responseReqDataLenInvalid();
877 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700878 unpackFinal(req);
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530879
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700880 if (rsvd)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700881 {
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530882 return responseInvalidFieldRequest();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700883 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530884
885 uint16_t vlan = static_cast<uint16_t>(vlanData);
886
887 if (!vlanEnable)
888 {
889 lastDisabledVlan[channel] = vlan;
890 vlan = 0;
891 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530892
jayaprakash Mutyala84c49dc2020-05-18 23:12:13 +0000893 channelCall<reconfigureVLAN>(channel, vlan);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700894 return responseSuccess();
895 }
896 case LanParam::CiphersuiteSupport:
897 case LanParam::CiphersuiteEntries:
William A. Kennington III16064aa2019-04-13 17:44:53 -0700898 case LanParam::IPFamilySupport:
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700899 {
900 req.trailingOk = true;
901 return response(ccParamReadOnly);
Ratan Guptab8e99552017-07-27 07:07:48 +0530902 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700903 case LanParam::IPFamilyEnables:
904 {
905 uint8_t enables;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700906 if (req.unpack(enables) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700907 {
908 return responseReqDataLenInvalid();
909 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700910 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700911 switch (static_cast<IPFamilyEnables>(enables))
912 {
913 case IPFamilyEnables::DualStack:
914 return responseSuccess();
915 case IPFamilyEnables::IPv4Only:
916 case IPFamilyEnables::IPv6Only:
917 return response(ccParamNotSupported);
918 }
919 return response(ccParamNotSupported);
920 }
921 case LanParam::IPv6Status:
922 {
923 req.trailingOk = true;
924 return response(ccParamReadOnly);
925 }
926 case LanParam::IPv6StaticAddresses:
927 {
928 uint8_t set;
929 uint7_t rsvd;
930 bool enabled;
William A. Kennington III16064aa2019-04-13 17:44:53 -0700931 uint8_t prefix;
932 uint8_t status;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700933 if (req.unpack(set, rsvd, enabled) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700934 {
935 return responseReqDataLenInvalid();
936 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700937 auto ip = unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700938 if (req.unpack(prefix, status) != 0)
939 {
940 return responseReqDataLenInvalid();
941 }
942 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800943 if (rsvd)
944 {
945 return responseInvalidFieldRequest();
946 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700947 if (enabled)
948 {
Jiaqing Zhao6d4a44e2022-01-24 15:04:00 +0800949 if (prefix < MIN_IPV6_PREFIX_LENGTH ||
950 prefix > MAX_IPV6_PREFIX_LENGTH)
951 {
952 return responseParmOutOfRange();
953 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700954 channelCall<reconfigureIfAddr6>(channel, set, ip, prefix);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700955 }
956 else
957 {
958 channelCall<deconfigureIfAddr6>(channel, set);
959 }
960 return responseSuccess();
961 }
962 case LanParam::IPv6DynamicAddresses:
963 {
964 req.trailingOk = true;
965 return response(ccParamReadOnly);
966 }
967 case LanParam::IPv6RouterControl:
968 {
969 std::bitset<8> control;
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800970 constexpr uint8_t reservedRACCBits = 0xfc;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700971 if (req.unpack(control) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700972 {
973 return responseReqDataLenInvalid();
974 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700975 unpackFinal(req);
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800976 if (std::bitset<8> expected(control &
977 std::bitset<8>(reservedRACCBits));
978 expected.any())
William A. Kennington III16064aa2019-04-13 17:44:53 -0700979 {
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800980 return response(ccParamNotSupported);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700981 }
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800982
983 bool enableRA = control[IPv6RouterControlFlag::Dynamic];
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700984 channelCall<setEthProp<bool>>(channel, "IPv6AcceptRA", enableRA);
985 channelCall<setEthProp<bool>>(channel, "DHCP6", enableRA);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700986 return responseSuccess();
987 }
988 case LanParam::IPv6StaticRouter1IP:
989 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700990 auto gateway = unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700991 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700992 channelCall<setGatewayProperty<AF_INET6>>(channel, gateway);
993 return responseSuccess();
994 }
995 case LanParam::IPv6StaticRouter1MAC:
996 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700997 auto mac = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700998 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700999 channelCall<reconfigureGatewayMAC<AF_INET6>>(channel, mac);
1000 return responseSuccess();
1001 }
1002 case LanParam::IPv6StaticRouter1PrefixLength:
1003 {
1004 uint8_t prefix;
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001005 if (req.unpack(prefix) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -07001006 {
1007 return responseReqDataLenInvalid();
1008 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001009 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001010 if (prefix != 0)
1011 {
1012 return responseInvalidFieldRequest();
1013 }
1014 return responseSuccess();
1015 }
1016 case LanParam::IPv6StaticRouter1PrefixValue:
1017 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001018 unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001019 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001020 // Accept any prefix value since our prefix length has to be 0
1021 return responseSuccess();
1022 }
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001023 case LanParam::cipherSuitePrivilegeLevels:
1024 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001025 uint8_t rsvd;
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001026 std::array<uint4_t, ipmi::maxCSRecords> cipherSuitePrivs;
1027
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001028 if (req.unpack(rsvd, cipherSuitePrivs))
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001029 {
1030 return responseReqDataLenInvalid();
1031 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001032 unpackFinal(req);
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001033
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001034 if (rsvd)
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001035 {
1036 return responseInvalidFieldRequest();
1037 }
1038
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -05001039 uint8_t resp = getCipherConfigObject(csPrivFileName,
1040 csPrivDefaultFileName)
1041 .setCSPrivilegeLevels(channel, cipherSuitePrivs);
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001042 if (!resp)
1043 {
1044 return responseSuccess();
1045 }
1046 else
1047 {
1048 req.trailingOk = true;
1049 return response(resp);
1050 }
1051 }
Ratan Guptab8e99552017-07-27 07:07:48 +05301052 }
vishwa1eaea4f2016-02-26 11:57:40 -06001053
Johnathan Manteyb87034e2019-09-16 10:50:50 -07001054 if ((parameter >= oemCmdStart) && (parameter <= oemCmdEnd))
1055 {
1056 return setLanOem(channel, parameter, req);
1057 }
1058
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001059 req.trailingOk = true;
1060 return response(ccParamNotSupported);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001061}
1062
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001063RspType<> setLan(Context::ptr ctx, uint4_t channelBits, uint4_t reserved1,
1064 uint8_t parameter, message::Payload& req)
1065{
1066 try
1067 {
1068 return setLanInt(ctx, channelBits, reserved1, parameter, req);
1069 }
1070 catch (ipmi::Cc cc)
1071 {
1072 return response(cc);
1073 }
1074 catch (const sdbusplus::exception_t& e)
1075 {
1076 if (std::string_view{InvalidArgument::errName} == e.name())
1077 {
1078 return responseInvalidFieldRequest();
1079 }
1080 throw;
1081 }
1082}
1083
vijayabharathix shettycc769252020-02-27 17:52:20 +00001084RspType<message::Payload> getLan(Context::ptr ctx, uint4_t channelBits,
1085 uint3_t reserved, bool revOnly,
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001086 uint8_t parameter, uint8_t set, uint8_t block)
Ratan Guptab8e99552017-07-27 07:07:48 +05301087{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001088 message::Payload ret;
1089 constexpr uint8_t current_revision = 0x11;
1090 ret.pack(current_revision);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001091
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001092 if (revOnly)
Suryakanth Sekare4054402019-08-08 15:16:52 +05301093 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001094 return responseSuccess(std::move(ret));
Suryakanth Sekare4054402019-08-08 15:16:52 +05301095 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001096
vijayabharathix shettycc769252020-02-27 17:52:20 +00001097 const uint8_t channel = convertCurrentChannelNum(
1098 static_cast<uint8_t>(channelBits), ctx->channel);
1099 if (reserved || !isValidChannel(channel))
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001100 {
vijayabharathix shettycc769252020-02-27 17:52:20 +00001101 log<level::ERR>("Get Lan - Invalid field in request");
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001102 return responseInvalidFieldRequest();
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001103 }
1104
Jian Zhangcf19d142023-07-31 10:22:53 +08001105 if (!isLanChannel(channel).value_or(false))
1106 {
1107 log<level::ERR>("Set Lan - Not a LAN channel");
1108 return responseInvalidFieldRequest();
1109 }
1110
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001111 static std::vector<uint8_t> cipherList;
1112 static bool listInit = false;
1113 if (!listInit)
1114 {
1115 try
1116 {
1117 cipherList = cipher::getCipherList();
1118 listInit = true;
1119 }
1120 catch (const std::exception& e)
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -05001121 {}
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001122 }
1123
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001124 switch (static_cast<LanParam>(parameter))
Tom Josepha30c8d32018-03-22 02:15:03 +05301125 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001126 case LanParam::SetStatus:
Tom Josepha30c8d32018-03-22 02:15:03 +05301127 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001128 SetStatus status;
1129 try
1130 {
1131 status = setStatus.at(channel);
1132 }
1133 catch (const std::out_of_range&)
1134 {
1135 status = SetStatus::Complete;
1136 }
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001137 ret.pack(types::enum_cast<uint2_t>(status), uint6_t{});
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001138 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301139 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001140 case LanParam::AuthSupport:
Tom Josepha30c8d32018-03-22 02:15:03 +05301141 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001142 std::bitset<6> support;
1143 ret.pack(support, uint2_t{});
1144 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301145 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001146 case LanParam::AuthEnables:
vishwa1eaea4f2016-02-26 11:57:40 -06001147 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001148 std::bitset<6> enables;
1149 ret.pack(enables, uint2_t{}); // Callback
1150 ret.pack(enables, uint2_t{}); // User
1151 ret.pack(enables, uint2_t{}); // Operator
1152 ret.pack(enables, uint2_t{}); // Admin
1153 ret.pack(enables, uint2_t{}); // OEM
1154 return responseSuccess(std::move(ret));
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001155 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001156 case LanParam::IP:
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001157 {
1158 auto ifaddr = channelCall<getIfAddr4>(channel);
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001159 stdplus::In4Addr addr{};
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001160 if (ifaddr)
1161 {
1162 addr = ifaddr->address;
1163 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001164 ret.pack(stdplus::raw::asView<char>(addr));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001165 return responseSuccess(std::move(ret));
1166 }
1167 case LanParam::IPSrc:
1168 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001169 auto src = channelCall<getEthProp<bool>>(channel, "DHCP4")
1170 ? IPSrc::DHCP
1171 : IPSrc::Static;
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001172 ret.pack(types::enum_cast<uint4_t>(src), uint4_t{});
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001173 return responseSuccess(std::move(ret));
1174 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001175 case LanParam::MAC:
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001176 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001177 auto mac = channelCall<getMACProperty>(channel);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001178 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001179 return responseSuccess(std::move(ret));
1180 }
1181 case LanParam::SubnetMask:
1182 {
1183 auto ifaddr = channelCall<getIfAddr4>(channel);
1184 uint8_t prefix = AddrFamily<AF_INET>::defaultPrefix;
1185 if (ifaddr)
Ratan Guptab8e99552017-07-27 07:07:48 +05301186 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001187 prefix = ifaddr->prefix;
1188 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001189 auto netmask = stdplus::pfxToMask<stdplus::In4Addr>(prefix);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001190 ret.pack(stdplus::raw::asView<char>(netmask));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001191 return responseSuccess(std::move(ret));
1192 }
1193 case LanParam::Gateway1:
1194 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001195 auto gateway = channelCall<getGatewayProperty<AF_INET>>(channel);
1196 ret.pack(stdplus::raw::asView<char>(
1197 gateway.value_or(stdplus::In4Addr{})));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001198 return responseSuccess(std::move(ret));
1199 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001200 case LanParam::Gateway1MAC:
1201 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001202 stdplus::EtherAddr mac{};
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001203 auto neighbor = channelCall<getGatewayNeighbor<AF_INET>>(channel);
1204 if (neighbor)
1205 {
1206 mac = neighbor->mac;
1207 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001208 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001209 return responseSuccess(std::move(ret));
1210 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001211 case LanParam::VLANId:
1212 {
1213 uint16_t vlan = channelCall<getVLANProperty>(channel);
1214 if (vlan != 0)
1215 {
1216 vlan |= VLAN_ENABLE_FLAG;
Ratan Guptab8e99552017-07-27 07:07:48 +05301217 }
1218 else
1219 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001220 vlan = lastDisabledVlan[channel];
Ratan Guptab8e99552017-07-27 07:07:48 +05301221 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001222 ret.pack(vlan);
1223 return responseSuccess(std::move(ret));
Adriana Kobylak342df102016-02-10 13:48:16 -06001224 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001225 case LanParam::CiphersuiteSupport:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001226 {
srikanta mondal1d8579c2020-04-15 17:13:25 +00001227 if (getChannelSessionSupport(channel) ==
1228 EChannelSessSupported::none)
1229 {
1230 return responseInvalidFieldRequest();
1231 }
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001232 if (!listInit)
1233 {
1234 return responseUnspecifiedError();
1235 }
1236 ret.pack(static_cast<uint8_t>(cipherList.size() - 1));
1237 return responseSuccess(std::move(ret));
1238 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001239 case LanParam::CiphersuiteEntries:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001240 {
srikanta mondal1d8579c2020-04-15 17:13:25 +00001241 if (getChannelSessionSupport(channel) ==
1242 EChannelSessSupported::none)
1243 {
1244 return responseInvalidFieldRequest();
1245 }
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001246 if (!listInit)
1247 {
1248 return responseUnspecifiedError();
1249 }
1250 ret.pack(cipherList);
1251 return responseSuccess(std::move(ret));
1252 }
William A. Kennington III16064aa2019-04-13 17:44:53 -07001253 case LanParam::IPFamilySupport:
1254 {
1255 std::bitset<8> support;
1256 support[IPFamilySupportFlag::IPv6Only] = 0;
1257 support[IPFamilySupportFlag::DualStack] = 1;
1258 support[IPFamilySupportFlag::IPv6Alerts] = 1;
1259 ret.pack(support);
1260 return responseSuccess(std::move(ret));
1261 }
1262 case LanParam::IPFamilyEnables:
1263 {
1264 ret.pack(static_cast<uint8_t>(IPFamilyEnables::DualStack));
1265 return responseSuccess(std::move(ret));
1266 }
1267 case LanParam::IPv6Status:
1268 {
1269 ret.pack(MAX_IPV6_STATIC_ADDRESSES);
1270 ret.pack(MAX_IPV6_DYNAMIC_ADDRESSES);
1271 std::bitset<8> support;
1272 support[IPv6StatusFlag::DHCP] = 1;
1273 support[IPv6StatusFlag::SLAAC] = 1;
1274 ret.pack(support);
1275 return responseSuccess(std::move(ret));
1276 }
1277 case LanParam::IPv6StaticAddresses:
1278 {
1279 if (set >= MAX_IPV6_STATIC_ADDRESSES)
1280 {
1281 return responseParmOutOfRange();
1282 }
1283 getLanIPv6Address(ret, channel, set, originsV6Static);
1284 return responseSuccess(std::move(ret));
1285 }
1286 case LanParam::IPv6DynamicAddresses:
1287 {
1288 if (set >= MAX_IPV6_DYNAMIC_ADDRESSES)
1289 {
1290 return responseParmOutOfRange();
1291 }
1292 getLanIPv6Address(ret, channel, set, originsV6Dynamic);
1293 return responseSuccess(std::move(ret));
1294 }
1295 case LanParam::IPv6RouterControl:
1296 {
1297 std::bitset<8> control;
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001298 control[IPv6RouterControlFlag::Dynamic] =
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001299 channelCall<getEthProp<bool>>(channel, "IPv6AcceptRA");
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001300 control[IPv6RouterControlFlag::Static] = 1;
William A. Kennington III16064aa2019-04-13 17:44:53 -07001301 ret.pack(control);
1302 return responseSuccess(std::move(ret));
1303 }
1304 case LanParam::IPv6StaticRouter1IP:
1305 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001306 stdplus::In6Addr gateway{};
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001307 if (!channelCall<getEthProp<bool>>(channel, "IPv6AcceptRA"))
William A. Kennington III16064aa2019-04-13 17:44:53 -07001308 {
1309 gateway =
1310 channelCall<getGatewayProperty<AF_INET6>>(channel).value_or(
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001311 stdplus::In6Addr{});
William A. Kennington III16064aa2019-04-13 17:44:53 -07001312 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001313 ret.pack(stdplus::raw::asView<char>(gateway));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001314 return responseSuccess(std::move(ret));
1315 }
1316 case LanParam::IPv6StaticRouter1MAC:
1317 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001318 stdplus::EtherAddr mac{};
William A. Kennington III16064aa2019-04-13 17:44:53 -07001319 auto neighbor = channelCall<getGatewayNeighbor<AF_INET6>>(channel);
1320 if (neighbor)
1321 {
1322 mac = neighbor->mac;
1323 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001324 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001325 return responseSuccess(std::move(ret));
1326 }
1327 case LanParam::IPv6StaticRouter1PrefixLength:
1328 {
1329 ret.pack(UINT8_C(0));
1330 return responseSuccess(std::move(ret));
1331 }
1332 case LanParam::IPv6StaticRouter1PrefixValue:
1333 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001334 ret.pack(stdplus::raw::asView<char>(stdplus::In6Addr{}));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001335 return responseSuccess(std::move(ret));
1336 }
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001337 case LanParam::cipherSuitePrivilegeLevels:
1338 {
1339 std::array<uint4_t, ipmi::maxCSRecords> csPrivilegeLevels;
1340
1341 uint8_t resp =
1342 getCipherConfigObject(csPrivFileName, csPrivDefaultFileName)
1343 .getCSPrivilegeLevels(channel, csPrivilegeLevels);
1344 if (!resp)
1345 {
1346 constexpr uint8_t reserved1 = 0x00;
1347 ret.pack(reserved1, csPrivilegeLevels);
1348 return responseSuccess(std::move(ret));
1349 }
1350 else
1351 {
1352 return response(resp);
1353 }
1354 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001355 }
1356
Johnathan Manteyb87034e2019-09-16 10:50:50 -07001357 if ((parameter >= oemCmdStart) && (parameter <= oemCmdEnd))
1358 {
1359 return getLanOem(channel, parameter, set, block);
1360 }
1361
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001362 return response(ccParamNotSupported);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001363}
1364
Jian Zhang23f44652022-03-17 17:13:10 +08001365constexpr const char* solInterface = "xyz.openbmc_project.Ipmi.SOL";
1366constexpr const char* solPath = "/xyz/openbmc_project/ipmi/sol/";
1367constexpr const uint16_t solDefaultPort = 623;
1368
1369RspType<> setSolConfParams(Context::ptr ctx, uint4_t channelBits,
Willy Tu11d68892022-01-20 10:37:34 -08001370 uint4_t /*reserved*/, uint8_t parameter,
Jian Zhang23f44652022-03-17 17:13:10 +08001371 message::Payload& req)
1372{
1373 const uint8_t channel = convertCurrentChannelNum(
1374 static_cast<uint8_t>(channelBits), ctx->channel);
1375
1376 if (!isValidChannel(channel))
1377 {
1378 log<level::ERR>("Set Sol Config - Invalid channel in request");
1379 return responseInvalidFieldRequest();
1380 }
1381
1382 std::string solService{};
1383 std::string solPathWitheEthName = solPath + ipmi::getChannelName(channel);
1384
1385 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1386 {
1387 log<level::ERR>("Set Sol Config - Invalid solInterface",
1388 entry("SERVICE=%s", solService.c_str()),
1389 entry("OBJPATH=%s", solPathWitheEthName.c_str()),
1390 entry("INTERFACE=%s", solInterface));
1391 return responseInvalidFieldRequest();
1392 }
1393
1394 switch (static_cast<SolConfParam>(parameter))
1395 {
1396 case SolConfParam::Progress:
1397 {
1398 uint8_t progress;
1399 if (req.unpack(progress) != 0 || !req.fullyUnpacked())
1400 {
1401 return responseReqDataLenInvalid();
1402 }
1403
1404 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1405 solInterface, "Progress", progress))
1406 {
1407 return responseUnspecifiedError();
1408 }
1409 break;
1410 }
1411 case SolConfParam::Enable:
1412 {
1413 bool enable;
1414 uint7_t reserved2;
1415
1416 if (req.unpack(enable, reserved2) != 0 || !req.fullyUnpacked())
1417 {
1418 return responseReqDataLenInvalid();
1419 }
1420
1421 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1422 solInterface, "Enable", enable))
1423 {
1424 return responseUnspecifiedError();
1425 }
1426 break;
1427 }
1428 case SolConfParam::Authentication:
1429 {
1430 uint4_t privilegeBits{};
1431 uint2_t reserved2{};
1432 bool forceAuth = false;
1433 bool forceEncrypt = false;
1434
1435 if (req.unpack(privilegeBits, reserved2, forceAuth, forceEncrypt) !=
1436 0 ||
1437 !req.fullyUnpacked())
1438 {
1439 return responseReqDataLenInvalid();
1440 }
1441
1442 uint8_t privilege = static_cast<uint8_t>(privilegeBits);
Jonathan Domana48bf772023-05-26 17:54:57 -07001443 if (privilege < static_cast<uint8_t>(Privilege::User) ||
Jian Zhang23f44652022-03-17 17:13:10 +08001444 privilege > static_cast<uint8_t>(Privilege::Oem))
1445 {
1446 return ipmi::responseInvalidFieldRequest();
1447 }
1448
1449 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1450 solInterface, "Privilege", privilege))
1451 {
1452 return responseUnspecifiedError();
1453 }
1454
1455 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1456 solInterface, "ForceEncryption",
1457 forceEncrypt))
1458 {
1459 return responseUnspecifiedError();
1460 }
1461
1462 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1463 solInterface, "ForceAuthentication",
1464 forceAuth))
1465 {
1466 return responseUnspecifiedError();
1467 }
1468 break;
1469 }
1470 case SolConfParam::Accumulate:
1471 {
1472 uint8_t interval;
1473 uint8_t threshold;
1474 if (req.unpack(interval, threshold) != 0 || !req.fullyUnpacked())
1475 {
1476 return responseReqDataLenInvalid();
1477 }
1478
1479 if (threshold == 0)
1480 {
1481 return responseInvalidFieldRequest();
1482 }
1483
1484 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1485 solInterface, "AccumulateIntervalMS",
1486 interval))
1487 {
1488 return responseUnspecifiedError();
1489 }
1490
1491 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1492 solInterface, "Threshold", threshold))
1493 {
1494 return responseUnspecifiedError();
1495 }
1496 break;
1497 }
1498 case SolConfParam::Retry:
1499 {
1500 uint3_t countBits;
1501 uint5_t reserved2;
1502 uint8_t interval;
1503
1504 if (req.unpack(countBits, reserved2, interval) != 0 ||
1505 !req.fullyUnpacked())
1506 {
1507 return responseReqDataLenInvalid();
1508 }
1509
1510 uint8_t count = static_cast<uint8_t>(countBits);
1511 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1512 solInterface, "RetryCount", count))
1513 {
1514 return responseUnspecifiedError();
1515 }
1516
1517 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1518 solInterface, "RetryIntervalMS",
1519 interval))
1520 {
1521 return responseUnspecifiedError();
1522 }
1523 break;
1524 }
1525 case SolConfParam::Port:
1526 {
1527 return response(ipmiCCWriteReadParameter);
1528 }
1529 case SolConfParam::NonVbitrate:
1530 case SolConfParam::Vbitrate:
1531 case SolConfParam::Channel:
1532 default:
1533 return response(ipmiCCParamNotSupported);
1534 }
1535 return responseSuccess();
1536}
1537
1538RspType<message::Payload> getSolConfParams(Context::ptr ctx,
1539 uint4_t channelBits,
Willy Tu11d68892022-01-20 10:37:34 -08001540 uint3_t /*reserved*/, bool revOnly,
1541 uint8_t parameter, uint8_t /*set*/,
1542 uint8_t /*block*/)
Jian Zhang23f44652022-03-17 17:13:10 +08001543{
1544 message::Payload ret;
1545 constexpr uint8_t current_revision = 0x11;
1546 ret.pack(current_revision);
1547 if (revOnly)
1548 {
1549 return responseSuccess(std::move(ret));
1550 }
1551
1552 const uint8_t channel = convertCurrentChannelNum(
1553 static_cast<uint8_t>(channelBits), ctx->channel);
1554
1555 if (!isValidChannel(channel))
1556 {
1557 log<level::ERR>("Get Sol Config - Invalid channel in request");
1558 return responseInvalidFieldRequest();
1559 }
1560
1561 std::string solService{};
1562 std::string solPathWitheEthName = solPath + ipmi::getChannelName(channel);
1563
1564 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1565 {
1566 log<level::ERR>("Set Sol Config - Invalid solInterface",
1567 entry("SERVICE=%s", solService.c_str()),
1568 entry("OBJPATH=%s", solPathWitheEthName.c_str()),
1569 entry("INTERFACE=%s", solInterface));
1570 return responseInvalidFieldRequest();
1571 }
1572
1573 switch (static_cast<SolConfParam>(parameter))
1574 {
1575 case SolConfParam::Progress:
1576 {
1577 uint8_t progress;
1578 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1579 solInterface, "Progress", progress))
1580 {
1581 return responseUnspecifiedError();
1582 }
1583 ret.pack(progress);
1584 return responseSuccess(std::move(ret));
1585 }
1586 case SolConfParam::Enable:
1587 {
1588 bool enable{};
1589 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1590 solInterface, "Enable", enable))
1591 {
1592 return responseUnspecifiedError();
1593 }
1594 ret.pack(enable, uint7_t{});
1595 return responseSuccess(std::move(ret));
1596 }
1597 case SolConfParam::Authentication:
1598 {
1599 // 4bits, cast when pack
1600 uint8_t privilege;
1601 bool forceAuth = false;
1602 bool forceEncrypt = false;
1603
1604 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1605 solInterface, "Privilege", privilege))
1606 {
1607 return responseUnspecifiedError();
1608 }
1609
1610 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1611 solInterface, "ForceAuthentication",
1612 forceAuth))
1613 {
1614 return responseUnspecifiedError();
1615 }
1616
1617 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1618 solInterface, "ForceEncryption",
1619 forceEncrypt))
1620 {
1621 return responseUnspecifiedError();
1622 }
1623 ret.pack(uint4_t{privilege}, uint2_t{}, forceAuth, forceEncrypt);
1624 return responseSuccess(std::move(ret));
1625 }
1626 case SolConfParam::Accumulate:
1627 {
1628 uint8_t interval{}, threshold{};
1629
1630 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1631 solInterface, "AccumulateIntervalMS",
1632 interval))
1633 {
1634 return responseUnspecifiedError();
1635 }
1636
1637 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1638 solInterface, "Threshold", threshold))
1639 {
1640 return responseUnspecifiedError();
1641 }
1642 ret.pack(interval, threshold);
1643 return responseSuccess(std::move(ret));
1644 }
1645 case SolConfParam::Retry:
1646 {
1647 // 3bits, cast when cast
1648 uint8_t count{};
1649 uint8_t interval{};
1650
1651 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1652 solInterface, "RetryCount", count))
1653 {
1654 return responseUnspecifiedError();
1655 }
1656
1657 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1658 solInterface, "RetryIntervalMS",
1659 interval))
1660 {
1661 return responseUnspecifiedError();
1662 }
1663 ret.pack(uint3_t{count}, uint5_t{}, interval);
1664 return responseSuccess(std::move(ret));
1665 }
1666 case SolConfParam::Port:
1667 {
1668 auto port = solDefaultPort;
1669 ret.pack(static_cast<uint16_t>(port));
1670 return responseSuccess(std::move(ret));
1671 }
1672 case SolConfParam::Channel:
1673 {
1674 ret.pack(channel);
1675 return responseSuccess(std::move(ret));
1676 }
1677 case SolConfParam::NonVbitrate:
Jonathan Domana48bf772023-05-26 17:54:57 -07001678 {
1679 uint64_t baudRate;
1680 uint8_t encodedBitRate = 0;
1681 if (ipmi::getDbusProperty(
1682 ctx, "xyz.openbmc_project.Console.default",
1683 "/xyz/openbmc_project/console/default",
1684 "xyz.openbmc_project.Console.UART", "Baud", baudRate))
1685 {
1686 return ipmi::responseUnspecifiedError();
1687 }
1688 switch (baudRate)
1689 {
1690 case 9600:
1691 encodedBitRate = 0x06;
1692 break;
1693 case 19200:
1694 encodedBitRate = 0x07;
1695 break;
1696 case 38400:
1697 encodedBitRate = 0x08;
1698 break;
1699 case 57600:
1700 encodedBitRate = 0x09;
1701 break;
1702 case 115200:
1703 encodedBitRate = 0x0a;
1704 break;
1705 default:
1706 break;
1707 }
1708 ret.pack(encodedBitRate);
1709 return responseSuccess(std::move(ret));
1710 }
Jian Zhang23f44652022-03-17 17:13:10 +08001711 case SolConfParam::Vbitrate:
1712 default:
1713 return response(ipmiCCParamNotSupported);
1714 }
1715
1716 return response(ccParamNotSupported);
1717}
1718
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001719} // namespace transport
1720} // namespace ipmi
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301721
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001722void register_netfn_transport_functions() __attribute__((constructor));
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301723
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001724void register_netfn_transport_functions()
1725{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001726 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1727 ipmi::transport::cmdSetLanConfigParameters,
1728 ipmi::Privilege::Admin, ipmi::transport::setLan);
1729 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1730 ipmi::transport::cmdGetLanConfigParameters,
Johnathan Mantey34698d52019-11-19 14:47:30 -08001731 ipmi::Privilege::Operator, ipmi::transport::getLan);
Jian Zhang23f44652022-03-17 17:13:10 +08001732 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1733 ipmi::transport::cmdSetSolConfigParameters,
1734 ipmi::Privilege::Admin,
1735 ipmi::transport::setSolConfParams);
1736 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1737 ipmi::transport::cmdGetSolConfigParameters,
1738 ipmi::Privilege::User,
1739 ipmi::transport::getSolConfParams);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001740}