blob: 59d5f15aefbf09658108d482659c3f6358d14395 [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;
Johnathan Manteyb87034e2019-09-16 10:50:50 -070065
William A. Kennington IIIc72f3602023-10-19 03:51:37 -070066// Checks if the ifname is part of the networkd path
67// This assumes the path came from the network subtree PATH_ROOT
68bool ifnameInPath(std::string_view ifname, std::string_view path)
69{
70 constexpr auto rs = PATH_ROOT.size() + 1; // ROOT + separator
71 const auto is = rs + ifname.size(); // ROOT + sep + ifname
72 return path.size() > rs && path.substr(rs).starts_with(ifname) &&
73 (path.size() == is || path[is] == '/');
74}
75
Patrick Williams5d82f472022-07-22 19:26:53 -050076std::optional<ChannelParams> maybeGetChannelParams(sdbusplus::bus_t& bus,
William A. Kennington IIIc514d872019-04-06 18:19:38 -070077 uint8_t channel)
78{
79 auto ifname = getChannelName(channel);
80 if (ifname.empty())
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080081 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -070082 return std::nullopt;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080083 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080084
William A. Kennington IIIc514d872019-04-06 18:19:38 -070085 // Enumerate all VLAN + ETHERNET interfaces
86 auto req = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF,
87 "GetSubTree");
William A. Kennington IIIc72f3602023-10-19 03:51:37 -070088 req.append(std::string_view(PATH_ROOT), 0,
William A. Kennington IIIc514d872019-04-06 18:19:38 -070089 std::vector<std::string>{INTF_VLAN, INTF_ETHERNET});
90 auto reply = bus.call(req);
91 ObjectTree objs;
92 reply.read(objs);
93
94 ChannelParams params;
95 for (const auto& [path, impls] : objs)
96 {
William A. Kennington IIIc72f3602023-10-19 03:51:37 -070097 if (!ifnameInPath(ifname, path))
William A. Kennington IIIc514d872019-04-06 18:19:38 -070098 {
99 continue;
100 }
101 for (const auto& [service, intfs] : impls)
102 {
103 bool vlan = false;
104 bool ethernet = false;
105 for (const auto& intf : intfs)
106 {
107 if (intf == INTF_VLAN)
108 {
109 vlan = true;
110 }
111 else if (intf == INTF_ETHERNET)
112 {
113 ethernet = true;
114 }
115 }
116 if (params.service.empty() && (vlan || ethernet))
117 {
118 params.service = service;
119 }
120 if (params.ifPath.empty() && !vlan && ethernet)
121 {
122 params.ifPath = path;
123 }
124 if (params.logicalPath.empty() && vlan)
125 {
126 params.logicalPath = path;
127 }
128 }
129 }
130
131 // We must have a path for the underlying interface
132 if (params.ifPath.empty())
133 {
134 return std::nullopt;
135 }
136 // We don't have a VLAN so the logical path is the same
137 if (params.logicalPath.empty())
138 {
139 params.logicalPath = params.ifPath;
140 }
141
142 params.id = channel;
143 params.ifname = std::move(ifname);
Willy Tu11d68892022-01-20 10:37:34 -0800144 return params;
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700145}
146
Patrick Williams5d82f472022-07-22 19:26:53 -0500147ChannelParams getChannelParams(sdbusplus::bus_t& bus, uint8_t channel)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700148{
149 auto params = maybeGetChannelParams(bus, channel);
150 if (!params)
151 {
152 log<level::ERR>("Failed to get channel params",
153 entry("CHANNEL=%" PRIu8, channel));
154 elog<InternalFailure>();
155 }
156 return std::move(*params);
157}
158
159/** @brief Wraps the phosphor logging method to insert some additional metadata
160 *
161 * @param[in] params - The parameters for the channel
162 * ...
163 */
164template <auto level, typename... Args>
165auto logWithChannel(const ChannelParams& params, Args&&... args)
166{
167 return log<level>(std::forward<Args>(args)...,
168 entry("CHANNEL=%d", params.id),
169 entry("IFNAME=%s", params.ifname.c_str()));
170}
171template <auto level, typename... Args>
172auto logWithChannel(const std::optional<ChannelParams>& params, Args&&... args)
173{
174 if (params)
175 {
176 return logWithChannel<level>(*params, std::forward<Args>(args)...);
177 }
178 return log<level>(std::forward<Args>(args)...);
179}
180
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700181/** @brief Get / Set the Property value from phosphor-networkd EthernetInterface
182 */
183template <typename T>
184static T getEthProp(sdbusplus::bus_t& bus, const ChannelParams& params,
185 const std::string& prop)
186{
187 return std::get<T>(getDbusProperty(bus, params.service, params.logicalPath,
188 INTF_ETHERNET, prop));
189}
190template <typename T>
191static void setEthProp(sdbusplus::bus_t& bus, const ChannelParams& params,
192 const std::string& prop, const T& t)
193{
194 return setDbusProperty(bus, params.service, params.logicalPath,
195 INTF_ETHERNET, prop, t);
196}
197
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700198/** @brief Determines the MAC of the ethernet interface
199 *
200 * @param[in] bus - The bus object used for lookups
201 * @param[in] params - The parameters for the channel
202 * @return The configured mac address
203 */
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700204stdplus::EtherAddr getMACProperty(sdbusplus::bus_t& bus,
205 const ChannelParams& params)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700206{
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700207 auto prop = getDbusProperty(bus, params.service, params.ifPath, INTF_MAC,
208 "MACAddress");
209 return stdplus::fromStr<stdplus::EtherAddr>(std::get<std::string>(prop));
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700210}
211
212/** @brief Sets the system value for MAC address on the given interface
213 *
214 * @param[in] bus - The bus object used for lookups
215 * @param[in] params - The parameters for the channel
216 * @param[in] mac - MAC address to apply
217 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500218void setMACProperty(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700219 stdplus::EtherAddr mac)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700220{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700221 setDbusProperty(bus, params.service, params.ifPath, INTF_MAC, "MACAddress",
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700222 stdplus::toStr(mac));
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700223}
224
Patrick Williams5d82f472022-07-22 19:26:53 -0500225void deleteObjectIfExists(sdbusplus::bus_t& bus, const std::string& service,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700226 const std::string& path)
227{
228 if (path.empty())
229 {
230 return;
231 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530232 try
tomjose26e17732016-03-03 08:52:51 -0600233 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700234 auto req = bus.new_method_call(service.c_str(), path.c_str(),
235 ipmi::DELETE_INTERFACE, "Delete");
236 bus.call_noreply(req);
237 }
Patrick Williams5d82f472022-07-22 19:26:53 -0500238 catch (const sdbusplus::exception_t& e)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700239 {
jayaprakash Mutyala84c49dc2020-05-18 23:12:13 +0000240 if (strcmp(e.name(),
241 "xyz.openbmc_project.Common.Error.InternalFailure") != 0 &&
242 strcmp(e.name(), "org.freedesktop.DBus.Error.UnknownObject") != 0)
tomjose26e17732016-03-03 08:52:51 -0600243 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700244 // We want to rethrow real errors
245 throw;
tomjose26e17732016-03-03 08:52:51 -0600246 }
247 }
tomjose26e17732016-03-03 08:52:51 -0600248}
249
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700250/** @brief Sets the address info configured for the interface
251 * If a previous address path exists then it will be removed
252 * before the new address is added.
253 *
254 * @param[in] bus - The bus object used for lookups
255 * @param[in] params - The parameters for the channel
256 * @param[in] address - The address of the new IP
257 * @param[in] prefix - The prefix of the new IP
258 */
259template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500260void createIfAddr(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700261 typename AddrFamily<family>::addr address, uint8_t prefix)
Tom Josepha30c8d32018-03-22 02:15:03 +0530262{
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500263 auto newreq = bus.new_method_call(params.service.c_str(),
264 params.logicalPath.c_str(),
265 INTF_IP_CREATE, "IP");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700266 std::string protocol =
Willy Tu523e2d12023-09-05 11:36:48 -0700267 sdbusplus::common::xyz::openbmc_project::network::convertForMessage(
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700268 AddrFamily<family>::protocol);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700269 stdplus::ToStrHandle<stdplus::ToStr<typename AddrFamily<family>::addr>> tsh;
270 newreq.append(protocol, tsh(address), prefix, "");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700271 bus.call_noreply(newreq);
272}
Tom Josepha30c8d32018-03-22 02:15:03 +0530273
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700274/** @brief Trivial helper for getting the IPv4 address from getIfAddrs()
275 *
276 * @param[in] bus - The bus object used for lookups
277 * @param[in] params - The parameters for the channel
278 * @return The address and prefix if found
279 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500280auto getIfAddr4(sdbusplus::bus_t& bus, const ChannelParams& params)
Tom Josepha30c8d32018-03-22 02:15:03 +0530281{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700282 return getIfAddr<AF_INET>(bus, params, 0, originsV4);
283}
Tom Josepha30c8d32018-03-22 02:15:03 +0530284
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700285/** @brief Reconfigures the IPv4 address info configured for the interface
286 *
287 * @param[in] bus - The bus object used for lookups
288 * @param[in] params - The parameters for the channel
289 * @param[in] address - The new address if specified
290 * @param[in] prefix - The new address prefix if specified
291 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500292void reconfigureIfAddr4(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700293 std::optional<stdplus::In4Addr> address,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700294 std::optional<uint8_t> prefix)
295{
296 auto ifaddr = getIfAddr4(bus, params);
297 if (!ifaddr && !address)
Tom Josepha30c8d32018-03-22 02:15:03 +0530298 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700299 log<level::ERR>("Missing address for IPv4 assignment");
Tom Josepha30c8d32018-03-22 02:15:03 +0530300 elog<InternalFailure>();
301 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700302 uint8_t fallbackPrefix = AddrFamily<AF_INET>::defaultPrefix;
303 if (ifaddr)
Tom Josepha30c8d32018-03-22 02:15:03 +0530304 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700305 fallbackPrefix = ifaddr->prefix;
306 deleteObjectIfExists(bus, params.service, ifaddr->path);
307 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700308 auto addr = address.value_or(ifaddr->address);
309 if (addr != stdplus::In4Addr{})
Johnathan Manteycbfa6e12023-06-01 06:57:25 -0700310 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700311 createIfAddr<AF_INET>(bus, params, addr,
Johnathan Manteycbfa6e12023-06-01 06:57:25 -0700312 prefix.value_or(fallbackPrefix));
313 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700314}
315
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700316template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500317std::optional<IfNeigh<family>> findGatewayNeighbor(sdbusplus::bus_t& bus,
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700318 const ChannelParams& params,
319 ObjectLookupCache& neighbors)
320{
321 auto gateway = getGatewayProperty<family>(bus, params);
322 if (!gateway)
323 {
324 return std::nullopt;
325 }
326
327 return findStaticNeighbor<family>(bus, params, *gateway, neighbors);
328}
329
330template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500331std::optional<IfNeigh<family>> getGatewayNeighbor(sdbusplus::bus_t& bus,
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700332 const ChannelParams& params)
333{
334 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
335 return findGatewayNeighbor<family>(bus, params, neighbors);
336}
337
338template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500339void reconfigureGatewayMAC(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700340 stdplus::EtherAddr mac)
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700341{
342 auto gateway = getGatewayProperty<family>(bus, params);
343 if (!gateway)
344 {
345 log<level::ERR>("Tried to set Gateway MAC without Gateway");
346 elog<InternalFailure>();
347 }
348
349 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500350 auto neighbor = findStaticNeighbor<family>(bus, params, *gateway,
351 neighbors);
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700352 if (neighbor)
353 {
354 deleteObjectIfExists(bus, params.service, neighbor->path);
355 }
356
357 createNeighbor<family>(bus, params, *gateway, mac);
358}
359
William A. Kennington III16064aa2019-04-13 17:44:53 -0700360/** @brief Deconfigures the IPv6 address info configured for the interface
361 *
362 * @param[in] bus - The bus object used for lookups
363 * @param[in] params - The parameters for the channel
364 * @param[in] idx - The address index to operate on
365 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500366void deconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III16064aa2019-04-13 17:44:53 -0700367 uint8_t idx)
368{
369 auto ifaddr = getIfAddr<AF_INET6>(bus, params, idx, originsV6Static);
370 if (ifaddr)
371 {
372 deleteObjectIfExists(bus, params.service, ifaddr->path);
373 }
374}
375
376/** @brief Reconfigures the IPv6 address info configured for the interface
377 *
378 * @param[in] bus - The bus object used for lookups
379 * @param[in] params - The parameters for the channel
380 * @param[in] idx - The address index to operate on
381 * @param[in] address - The new address
382 * @param[in] prefix - The new address prefix
383 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500384void reconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700385 uint8_t idx, stdplus::In6Addr address, uint8_t prefix)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700386{
387 deconfigureIfAddr6(bus, params, idx);
388 createIfAddr<AF_INET6>(bus, params, address, prefix);
389}
390
391/** @brief Converts the AddressOrigin into an IPv6Source
392 *
393 * @param[in] origin - The DBus Address Origin to convert
394 * @return The IPv6Source version of the origin
395 */
396IPv6Source originToSourceType(IP::AddressOrigin origin)
397{
398 switch (origin)
399 {
400 case IP::AddressOrigin::Static:
401 return IPv6Source::Static;
402 case IP::AddressOrigin::DHCP:
403 return IPv6Source::DHCP;
404 case IP::AddressOrigin::SLAAC:
405 return IPv6Source::SLAAC;
406 default:
407 {
Willy Tu523e2d12023-09-05 11:36:48 -0700408 auto originStr = sdbusplus::common::xyz::openbmc_project::network::
William A. Kennington III16064aa2019-04-13 17:44:53 -0700409 convertForMessage(origin);
410 log<level::ERR>(
411 "Invalid IP::AddressOrigin conversion to IPv6Source",
412 entry("ORIGIN=%s", originStr.c_str()));
413 elog<InternalFailure>();
414 }
415 }
416}
417
418/** @brief Packs the IPMI message response with IPv6 address data
419 *
420 * @param[out] ret - The IPMI response payload to be packed
421 * @param[in] channel - The channel id corresponding to an ethernet interface
422 * @param[in] set - The set selector for determining address index
423 * @param[in] origins - Set of valid origins for address filtering
424 */
425void getLanIPv6Address(message::Payload& ret, uint8_t channel, uint8_t set,
426 const std::unordered_set<IP::AddressOrigin>& origins)
427{
428 auto source = IPv6Source::Static;
429 bool enabled = false;
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700430 stdplus::In6Addr addr{};
Johnathan Mantey5aae0922021-10-21 13:05:36 -0700431 uint8_t prefix{};
William A. Kennington III16064aa2019-04-13 17:44:53 -0700432 auto status = IPv6AddressStatus::Disabled;
433
434 auto ifaddr = channelCall<getIfAddr<AF_INET6>>(channel, set, origins);
435 if (ifaddr)
436 {
437 source = originToSourceType(ifaddr->origin);
Johnathan Mantey846af862021-10-21 12:48:54 -0700438 enabled = (origins == originsV6Static);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700439 addr = ifaddr->address;
440 prefix = ifaddr->prefix;
441 status = IPv6AddressStatus::Active;
442 }
443
444 ret.pack(set);
William A. Kennington III7a0e5df2021-05-19 13:31:29 -0700445 ret.pack(types::enum_cast<uint4_t>(source), uint3_t{}, enabled);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700446 ret.pack(stdplus::raw::asView<char>(addr));
William A. Kennington III16064aa2019-04-13 17:44:53 -0700447 ret.pack(prefix);
William A. Kennington III7a0e5df2021-05-19 13:31:29 -0700448 ret.pack(types::enum_cast<uint8_t>(status));
William A. Kennington III16064aa2019-04-13 17:44:53 -0700449}
450
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700451/** @brief Gets the vlan ID configured on the interface
452 *
453 * @param[in] bus - The bus object used for lookups
454 * @param[in] params - The parameters for the channel
455 * @return VLAN id or the standard 0 for no VLAN
456 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500457uint16_t getVLANProperty(sdbusplus::bus_t& bus, const ChannelParams& params)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700458{
459 // VLAN devices will always have a separate logical object
460 if (params.ifPath == params.logicalPath)
461 {
462 return 0;
463 }
464
465 auto vlan = std::get<uint32_t>(getDbusProperty(
466 bus, params.service, params.logicalPath, INTF_VLAN, "Id"));
467 if ((vlan & VLAN_VALUE_MASK) != vlan)
468 {
469 logWithChannel<level::ERR>(params, "networkd returned an invalid vlan",
470 entry("VLAN=%" PRIu32, vlan));
Tom Josepha30c8d32018-03-22 02:15:03 +0530471 elog<InternalFailure>();
472 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700473 return vlan;
Tom Josepha30c8d32018-03-22 02:15:03 +0530474}
475
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700476/** @brief Deletes all of the possible configuration parameters for a channel
477 *
478 * @param[in] bus - The bus object used for lookups
479 * @param[in] params - The parameters for the channel
480 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500481void deconfigureChannel(sdbusplus::bus_t& bus, ChannelParams& params)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500482{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700483 // Delete all objects associated with the interface
484 auto objreq = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF,
485 "GetSubTree");
William A. Kennington IIIc72f3602023-10-19 03:51:37 -0700486 objreq.append(std::string_view(PATH_ROOT), 0,
487 std::vector<std::string>{DELETE_INTERFACE});
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700488 auto objreply = bus.call(objreq);
489 ObjectTree objs;
490 objreply.read(objs);
491 for (const auto& [path, impls] : objs)
492 {
William A. Kennington IIIc72f3602023-10-19 03:51:37 -0700493 if (!ifnameInPath(params.ifname, path))
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700494 {
495 continue;
496 }
497 for (const auto& [service, intfs] : impls)
498 {
499 deleteObjectIfExists(bus, service, path);
500 }
501 // Update params to reflect the deletion of vlan
502 if (path == params.logicalPath)
503 {
504 params.logicalPath = params.ifPath;
505 }
506 }
507
508 // Clear out any settings on the lower physical interface
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700509 setEthProp(bus, params, "DHCP4", false);
510 setEthProp(bus, params, "DHCP6", false);
511 setEthProp(bus, params, "IPv6AcceptRA", false);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500512}
513
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700514/** @brief Creates a new VLAN on the specified interface
515 *
516 * @param[in] bus - The bus object used for lookups
517 * @param[in] params - The parameters for the channel
518 * @param[in] vlan - The id of the new vlan
519 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500520void createVLAN(sdbusplus::bus_t& bus, ChannelParams& params, uint16_t vlan)
Ratan Guptab8e99552017-07-27 07:07:48 +0530521{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700522 if (vlan == 0)
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530523 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700524 return;
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530525 }
526
William A. Kennington IIIc72f3602023-10-19 03:51:37 -0700527 auto req = bus.new_method_call(params.service.c_str(), PATH_ROOT.c_str(),
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700528 INTF_VLAN_CREATE, "VLAN");
529 req.append(params.ifname, static_cast<uint32_t>(vlan));
530 auto reply = bus.call(req);
531 sdbusplus::message::object_path newPath;
532 reply.read(newPath);
533 params.logicalPath = std::move(newPath);
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530534}
535
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700536/** @brief Performs the necessary reconfiguration to change the VLAN
537 *
538 * @param[in] bus - The bus object used for lookups
539 * @param[in] params - The parameters for the channel
540 * @param[in] vlan - The new vlan id to use
541 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500542void reconfigureVLAN(sdbusplus::bus_t& bus, ChannelParams& params,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700543 uint16_t vlan)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500544{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700545 // Unfortunatetly we don't have built-in functions to migrate our interface
546 // customizations to new VLAN interfaces, or have some kind of decoupling.
547 // We therefore must retain all of our old information, setup the new VLAN
548 // configuration, then restore the old info.
Nan Li3d0df912016-10-18 19:51:41 +0800549
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700550 // Save info from the old logical interface
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700551 bool dhcp4 = getEthProp<bool>(bus, params, "DHCP4");
552 bool dhcp6 = getEthProp<bool>(bus, params, "DHCP6");
553 bool ra = getEthProp<bool>(bus, params, "IPv6AcceptRA");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700554 ObjectLookupCache ips(bus, params, INTF_IP);
555 auto ifaddr4 = findIfAddr<AF_INET>(bus, params, 0, originsV4, ips);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700556 std::vector<IfAddr<AF_INET6>> ifaddrs6;
557 for (uint8_t i = 0; i < MAX_IPV6_STATIC_ADDRESSES; ++i)
558 {
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500559 auto ifaddr6 = findIfAddr<AF_INET6>(bus, params, i, originsV6Static,
560 ips);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700561 if (!ifaddr6)
562 {
563 break;
564 }
565 ifaddrs6.push_back(std::move(*ifaddr6));
566 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700567 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
568 auto neighbor4 = findGatewayNeighbor<AF_INET>(bus, params, neighbors);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700569 auto neighbor6 = findGatewayNeighbor<AF_INET6>(bus, params, neighbors);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500570
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700571 deconfigureChannel(bus, params);
572 createVLAN(bus, params, vlan);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500573
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700574 // Re-establish the saved settings
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700575 setEthProp(bus, params, "DHCP4", dhcp4);
576 setEthProp(bus, params, "DHCP6", dhcp6);
577 setEthProp(bus, params, "IPv6AcceptRA", ra);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700578 if (ifaddr4)
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800579 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700580 createIfAddr<AF_INET>(bus, params, ifaddr4->address, ifaddr4->prefix);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800581 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700582 for (const auto& ifaddr6 : ifaddrs6)
583 {
584 createIfAddr<AF_INET6>(bus, params, ifaddr6.address, ifaddr6.prefix);
585 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700586 if (neighbor4)
587 {
588 createNeighbor<AF_INET>(bus, params, neighbor4->ip, neighbor4->mac);
589 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700590 if (neighbor6)
591 {
592 createNeighbor<AF_INET6>(bus, params, neighbor6->ip, neighbor6->mac);
593 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700594}
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800595
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700596// We need to store this value so it can be returned to the client
597// It is volatile so safe to store in daemon memory.
598static std::unordered_map<uint8_t, SetStatus> setStatus;
599
600// Until we have good support for fixed versions of IPMI tool
601// we need to return the VLAN id for disabled VLANs. The value is only
602// used for verification that a disable operation succeeded and will only
603// be sent if our system indicates that vlans are disabled.
604static std::unordered_map<uint8_t, uint16_t> lastDisabledVlan;
605
606/** @brief Gets the set status for the channel if it exists
607 * Otherise populates and returns the default value.
608 *
609 * @param[in] channel - The channel id corresponding to an ethernet interface
610 * @return A reference to the SetStatus for the channel
611 */
612SetStatus& getSetStatus(uint8_t channel)
613{
614 auto it = setStatus.find(channel);
615 if (it != setStatus.end())
616 {
617 return it->second;
618 }
619 return setStatus[channel] = SetStatus::Complete;
620}
621
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700622/** @brief Unpacks the trivially copyable type from the message */
623template <typename T>
624static T unpackT(message::Payload& req)
625{
626 std::array<uint8_t, sizeof(T)> bytes;
627 if (req.unpack(bytes) != 0)
628 {
629 throw ccReqDataLenInvalid;
630 }
631 return stdplus::raw::copyFrom<T>(bytes);
632}
633
634/** @brief Ensure the message is fully unpacked */
635static void unpackFinal(message::Payload& req)
636{
637 if (!req.fullyUnpacked())
638 {
639 throw ccReqDataTruncated;
640 }
641}
642
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700643/**
644 * Define placeholder command handlers for the OEM Extension bytes for the Set
645 * LAN Configuration Parameters and Get LAN Configuration Parameters
646 * commands. Using "weak" linking allows the placeholder setLanOem/getLanOem
647 * functions below to be overridden.
648 * To create handlers for your own proprietary command set:
649 * Create/modify a phosphor-ipmi-host Bitbake append file within your Yocto
650 * recipe
651 * Create C++ file(s) that define IPMI handler functions matching the
652 * function names below (i.e. setLanOem). The default name for the
653 * transport IPMI commands is transporthandler_oem.cpp.
654 * Add:
Johnathan Manteyefe26682022-08-11 14:30:45 -0700655 * EXTRA_OEMESON:append = "-Dtransport-oem=enabled"
656 * Create a do_configure:prepend()/do_install:append() method in your
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700657 * bbappend file to copy the file to the build directory.
658 * Add:
659 * PROJECT_SRC_DIR := "${THISDIR}/${PN}"
660 * # Copy the "strong" functions into the working directory, overriding the
661 * # placeholder functions.
Johnathan Manteyefe26682022-08-11 14:30:45 -0700662 * do_configure:prepend(){
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700663 * cp -f ${PROJECT_SRC_DIR}/transporthandler_oem.cpp ${S}
664 * }
665 *
666 * # Clean up after complilation has completed
Johnathan Manteyefe26682022-08-11 14:30:45 -0700667 * do_install:append(){
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700668 * rm -f ${S}/transporthandler_oem.cpp
669 * }
670 *
671 */
672
673/**
674 * Define the placeholder OEM commands as having weak linkage. Create
675 * setLanOem, and getLanOem functions in the transporthandler_oem.cpp
676 * file. The functions defined there must not have the "weak" attribute
677 * applied to them.
678 */
679RspType<> setLanOem(uint8_t channel, uint8_t parameter, message::Payload& req)
680 __attribute__((weak));
681RspType<message::Payload> getLanOem(uint8_t channel, uint8_t parameter,
682 uint8_t set, uint8_t block)
683 __attribute__((weak));
684
Willy Tu11d68892022-01-20 10:37:34 -0800685RspType<> setLanOem(uint8_t, uint8_t, message::Payload& req)
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700686{
687 req.trailingOk = true;
688 return response(ccParamNotSupported);
689}
690
Willy Tu11d68892022-01-20 10:37:34 -0800691RspType<message::Payload> getLanOem(uint8_t, uint8_t, uint8_t, uint8_t)
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700692{
693 return response(ccParamNotSupported);
694}
695
Jian Zhangcf19d142023-07-31 10:22:53 +0800696/**
697 * @brief is a valid LAN channel.
698 *
699 * This function checks whether the input channel is a valid LAN channel or not.
700 *
701 * @param[in] channel: the channel number.
702 * @return nullopt if the channel is invalid, false if the channel is not a LAN
703 * channel, true if the channel is a LAN channel.
704 **/
705std::optional<bool> isLanChannel(uint8_t channel)
706{
707 ChannelInfo chInfo;
708 auto cc = getChannelInfo(channel, chInfo);
709 if (cc != ccSuccess)
710 {
711 return std::nullopt;
712 }
713
714 return chInfo.mediumType ==
715 static_cast<uint8_t>(EChannelMediumType::lan8032);
716}
717
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700718RspType<> setLanInt(Context::ptr ctx, uint4_t channelBits, uint4_t reserved1,
719 uint8_t parameter, message::Payload& req)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700720{
vijayabharathix shettycc769252020-02-27 17:52:20 +0000721 const uint8_t channel = convertCurrentChannelNum(
722 static_cast<uint8_t>(channelBits), ctx->channel);
723 if (reserved1 || !isValidChannel(channel))
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700724 {
vijayabharathix shettycc769252020-02-27 17:52:20 +0000725 log<level::ERR>("Set Lan - Invalid field in request");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700726 req.trailingOk = true;
727 return responseInvalidFieldRequest();
728 }
729
Jian Zhangcf19d142023-07-31 10:22:53 +0800730 if (!isLanChannel(channel).value_or(false))
731 {
732 log<level::ERR>("Set Lan - Not a LAN channel");
733 return responseInvalidFieldRequest();
734 }
735
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700736 switch (static_cast<LanParam>(parameter))
737 {
738 case LanParam::SetStatus:
739 {
740 uint2_t flag;
741 uint6_t rsvd;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700742 if (req.unpack(flag, rsvd) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700743 {
744 return responseReqDataLenInvalid();
745 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700746 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800747 if (rsvd)
748 {
749 return responseInvalidFieldRequest();
750 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700751 auto status = static_cast<SetStatus>(static_cast<uint8_t>(flag));
752 switch (status)
753 {
754 case SetStatus::Complete:
755 {
756 getSetStatus(channel) = status;
757 return responseSuccess();
758 }
759 case SetStatus::InProgress:
760 {
761 auto& storedStatus = getSetStatus(channel);
762 if (storedStatus == SetStatus::InProgress)
763 {
764 return response(ccParamSetLocked);
765 }
766 storedStatus = status;
767 return responseSuccess();
768 }
769 case SetStatus::Commit:
770 if (getSetStatus(channel) != SetStatus::InProgress)
771 {
772 return responseInvalidFieldRequest();
773 }
774 return responseSuccess();
775 }
776 return response(ccParamNotSupported);
777 }
778 case LanParam::AuthSupport:
779 {
780 req.trailingOk = true;
781 return response(ccParamReadOnly);
782 }
783 case LanParam::AuthEnables:
784 {
785 req.trailingOk = true;
Johnathan Mantey76ce9c72019-11-14 14:41:46 -0800786 return response(ccParamReadOnly);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700787 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800788 case LanParam::IP:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600789 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700790 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800791 {
792 return responseCommandNotAvailable();
793 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700794 auto ip = unpackT<stdplus::In4Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700795 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700796 channelCall<reconfigureIfAddr4>(channel, ip, std::nullopt);
797 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +0530798 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700799 case LanParam::IPSrc:
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530800 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700801 uint4_t flag;
802 uint4_t rsvd;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700803 if (req.unpack(flag, rsvd) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700804 {
805 return responseReqDataLenInvalid();
806 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700807 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800808 if (rsvd)
809 {
810 return responseInvalidFieldRequest();
811 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700812 switch (static_cast<IPSrc>(static_cast<uint8_t>(flag)))
813 {
814 case IPSrc::DHCP:
Johnathan Mantey65265362019-11-14 11:24:19 -0800815 // The IPSrc IPMI command is only for IPv4
816 // management. Modifying IPv6 state is done using
817 // a completely different Set LAN Configuration
818 // subcommand.
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700819 channelCall<setEthProp<bool>>(channel, "DHCP4", true);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700820 return responseSuccess();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700821 case IPSrc::Unspecified:
822 case IPSrc::Static:
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700823 channelCall<setEthProp<bool>>(channel, "DHCP4", false);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700824 return responseSuccess();
Rajashekar Gade Reddy8a860ea2019-12-24 11:31:19 +0530825 case IPSrc::BIOS:
826 case IPSrc::BMC:
Rajashekar Gade Reddy8a860ea2019-12-24 11:31:19 +0530827 return responseInvalidFieldRequest();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700828 }
829 return response(ccParamNotSupported);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530830 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800831 case LanParam::MAC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530832 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700833 auto mac = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700834 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700835 channelCall<setMACProperty>(channel, mac);
836 return responseSuccess();
Ratan Gupta533d03b2017-07-30 10:39:22 +0530837 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700838 case LanParam::SubnetMask:
Ratan Guptab8e99552017-07-27 07:07:48 +0530839 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700840 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800841 {
842 return responseCommandNotAvailable();
843 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700844 auto pfx = stdplus::maskToPfx(unpackT<stdplus::In4Addr>(req));
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700845 unpackFinal(req);
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700846 channelCall<reconfigureIfAddr4>(channel, std::nullopt, pfx);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700847 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +0530848 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700849 case LanParam::Gateway1:
Ratan Guptab8e99552017-07-27 07:07:48 +0530850 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700851 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800852 {
853 return responseCommandNotAvailable();
854 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700855 auto gateway = unpackT<stdplus::In4Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700856 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700857 channelCall<setGatewayProperty<AF_INET>>(channel, gateway);
858 return responseSuccess();
859 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700860 case LanParam::Gateway1MAC:
861 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700862 auto gatewayMAC = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700863 unpackFinal(req);
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700864 channelCall<reconfigureGatewayMAC<AF_INET>>(channel, gatewayMAC);
865 return responseSuccess();
866 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700867 case LanParam::VLANId:
868 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700869 uint12_t vlanData;
870 uint3_t rsvd;
871 bool vlanEnable;
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530872
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700873 if (req.unpack(vlanData, rsvd, vlanEnable) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700874 {
875 return responseReqDataLenInvalid();
876 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700877 unpackFinal(req);
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530878
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700879 if (rsvd)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700880 {
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530881 return responseInvalidFieldRequest();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700882 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530883
884 uint16_t vlan = static_cast<uint16_t>(vlanData);
885
886 if (!vlanEnable)
887 {
888 lastDisabledVlan[channel] = vlan;
889 vlan = 0;
890 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530891
jayaprakash Mutyala84c49dc2020-05-18 23:12:13 +0000892 channelCall<reconfigureVLAN>(channel, vlan);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700893 return responseSuccess();
894 }
895 case LanParam::CiphersuiteSupport:
896 case LanParam::CiphersuiteEntries:
William A. Kennington III16064aa2019-04-13 17:44:53 -0700897 case LanParam::IPFamilySupport:
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700898 {
899 req.trailingOk = true;
900 return response(ccParamReadOnly);
Ratan Guptab8e99552017-07-27 07:07:48 +0530901 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700902 case LanParam::IPFamilyEnables:
903 {
904 uint8_t enables;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700905 if (req.unpack(enables) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700906 {
907 return responseReqDataLenInvalid();
908 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700909 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700910 switch (static_cast<IPFamilyEnables>(enables))
911 {
912 case IPFamilyEnables::DualStack:
913 return responseSuccess();
914 case IPFamilyEnables::IPv4Only:
915 case IPFamilyEnables::IPv6Only:
916 return response(ccParamNotSupported);
917 }
918 return response(ccParamNotSupported);
919 }
920 case LanParam::IPv6Status:
921 {
922 req.trailingOk = true;
923 return response(ccParamReadOnly);
924 }
925 case LanParam::IPv6StaticAddresses:
926 {
927 uint8_t set;
928 uint7_t rsvd;
929 bool enabled;
William A. Kennington III16064aa2019-04-13 17:44:53 -0700930 uint8_t prefix;
931 uint8_t status;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700932 if (req.unpack(set, rsvd, enabled) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700933 {
934 return responseReqDataLenInvalid();
935 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700936 auto ip = unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700937 if (req.unpack(prefix, status) != 0)
938 {
939 return responseReqDataLenInvalid();
940 }
941 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800942 if (rsvd)
943 {
944 return responseInvalidFieldRequest();
945 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700946 if (enabled)
947 {
Jiaqing Zhao6d4a44e2022-01-24 15:04:00 +0800948 if (prefix < MIN_IPV6_PREFIX_LENGTH ||
949 prefix > MAX_IPV6_PREFIX_LENGTH)
950 {
951 return responseParmOutOfRange();
952 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700953 channelCall<reconfigureIfAddr6>(channel, set, ip, prefix);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700954 }
955 else
956 {
957 channelCall<deconfigureIfAddr6>(channel, set);
958 }
959 return responseSuccess();
960 }
961 case LanParam::IPv6DynamicAddresses:
962 {
963 req.trailingOk = true;
964 return response(ccParamReadOnly);
965 }
966 case LanParam::IPv6RouterControl:
967 {
968 std::bitset<8> control;
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800969 constexpr uint8_t reservedRACCBits = 0xfc;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700970 if (req.unpack(control) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700971 {
972 return responseReqDataLenInvalid();
973 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700974 unpackFinal(req);
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800975 if (std::bitset<8> expected(control &
976 std::bitset<8>(reservedRACCBits));
977 expected.any())
William A. Kennington III16064aa2019-04-13 17:44:53 -0700978 {
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800979 return response(ccParamNotSupported);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700980 }
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800981
982 bool enableRA = control[IPv6RouterControlFlag::Dynamic];
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700983 channelCall<setEthProp<bool>>(channel, "IPv6AcceptRA", enableRA);
984 channelCall<setEthProp<bool>>(channel, "DHCP6", enableRA);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700985 return responseSuccess();
986 }
987 case LanParam::IPv6StaticRouter1IP:
988 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700989 auto gateway = unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700990 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700991 channelCall<setGatewayProperty<AF_INET6>>(channel, gateway);
992 return responseSuccess();
993 }
994 case LanParam::IPv6StaticRouter1MAC:
995 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700996 auto mac = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700997 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700998 channelCall<reconfigureGatewayMAC<AF_INET6>>(channel, mac);
999 return responseSuccess();
1000 }
1001 case LanParam::IPv6StaticRouter1PrefixLength:
1002 {
1003 uint8_t prefix;
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001004 if (req.unpack(prefix) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -07001005 {
1006 return responseReqDataLenInvalid();
1007 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001008 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001009 if (prefix != 0)
1010 {
1011 return responseInvalidFieldRequest();
1012 }
1013 return responseSuccess();
1014 }
1015 case LanParam::IPv6StaticRouter1PrefixValue:
1016 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001017 unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001018 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001019 // Accept any prefix value since our prefix length has to be 0
1020 return responseSuccess();
1021 }
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001022 case LanParam::cipherSuitePrivilegeLevels:
1023 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001024 uint8_t rsvd;
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001025 std::array<uint4_t, ipmi::maxCSRecords> cipherSuitePrivs;
1026
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001027 if (req.unpack(rsvd, cipherSuitePrivs))
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001028 {
1029 return responseReqDataLenInvalid();
1030 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001031 unpackFinal(req);
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001032
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001033 if (rsvd)
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001034 {
1035 return responseInvalidFieldRequest();
1036 }
1037
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -05001038 uint8_t resp = getCipherConfigObject(csPrivFileName,
1039 csPrivDefaultFileName)
1040 .setCSPrivilegeLevels(channel, cipherSuitePrivs);
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001041 if (!resp)
1042 {
1043 return responseSuccess();
1044 }
1045 else
1046 {
1047 req.trailingOk = true;
1048 return response(resp);
1049 }
1050 }
Ratan Guptab8e99552017-07-27 07:07:48 +05301051 }
vishwa1eaea4f2016-02-26 11:57:40 -06001052
PavanKumarIntel3771f5f2023-11-02 06:26:42 +00001053 if (parameter >= oemCmdStart)
Johnathan Manteyb87034e2019-09-16 10:50:50 -07001054 {
1055 return setLanOem(channel, parameter, req);
1056 }
1057
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001058 req.trailingOk = true;
1059 return response(ccParamNotSupported);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001060}
1061
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001062RspType<> setLan(Context::ptr ctx, uint4_t channelBits, uint4_t reserved1,
1063 uint8_t parameter, message::Payload& req)
1064{
1065 try
1066 {
1067 return setLanInt(ctx, channelBits, reserved1, parameter, req);
1068 }
1069 catch (ipmi::Cc cc)
1070 {
1071 return response(cc);
1072 }
1073 catch (const sdbusplus::exception_t& e)
1074 {
1075 if (std::string_view{InvalidArgument::errName} == e.name())
1076 {
1077 return responseInvalidFieldRequest();
1078 }
1079 throw;
1080 }
1081}
1082
vijayabharathix shettycc769252020-02-27 17:52:20 +00001083RspType<message::Payload> getLan(Context::ptr ctx, uint4_t channelBits,
1084 uint3_t reserved, bool revOnly,
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001085 uint8_t parameter, uint8_t set, uint8_t block)
Ratan Guptab8e99552017-07-27 07:07:48 +05301086{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001087 message::Payload ret;
1088 constexpr uint8_t current_revision = 0x11;
1089 ret.pack(current_revision);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001090
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001091 if (revOnly)
Suryakanth Sekare4054402019-08-08 15:16:52 +05301092 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001093 return responseSuccess(std::move(ret));
Suryakanth Sekare4054402019-08-08 15:16:52 +05301094 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001095
vijayabharathix shettycc769252020-02-27 17:52:20 +00001096 const uint8_t channel = convertCurrentChannelNum(
1097 static_cast<uint8_t>(channelBits), ctx->channel);
1098 if (reserved || !isValidChannel(channel))
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001099 {
vijayabharathix shettycc769252020-02-27 17:52:20 +00001100 log<level::ERR>("Get Lan - Invalid field in request");
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001101 return responseInvalidFieldRequest();
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001102 }
1103
Jian Zhangcf19d142023-07-31 10:22:53 +08001104 if (!isLanChannel(channel).value_or(false))
1105 {
1106 log<level::ERR>("Set Lan - Not a LAN channel");
1107 return responseInvalidFieldRequest();
1108 }
1109
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001110 static std::vector<uint8_t> cipherList;
1111 static bool listInit = false;
1112 if (!listInit)
1113 {
1114 try
1115 {
1116 cipherList = cipher::getCipherList();
1117 listInit = true;
1118 }
1119 catch (const std::exception& e)
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -05001120 {}
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001121 }
1122
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001123 switch (static_cast<LanParam>(parameter))
Tom Josepha30c8d32018-03-22 02:15:03 +05301124 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001125 case LanParam::SetStatus:
Tom Josepha30c8d32018-03-22 02:15:03 +05301126 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001127 SetStatus status;
1128 try
1129 {
1130 status = setStatus.at(channel);
1131 }
1132 catch (const std::out_of_range&)
1133 {
1134 status = SetStatus::Complete;
1135 }
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001136 ret.pack(types::enum_cast<uint2_t>(status), uint6_t{});
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001137 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301138 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001139 case LanParam::AuthSupport:
Tom Josepha30c8d32018-03-22 02:15:03 +05301140 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001141 std::bitset<6> support;
1142 ret.pack(support, uint2_t{});
1143 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301144 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001145 case LanParam::AuthEnables:
vishwa1eaea4f2016-02-26 11:57:40 -06001146 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001147 std::bitset<6> enables;
1148 ret.pack(enables, uint2_t{}); // Callback
1149 ret.pack(enables, uint2_t{}); // User
1150 ret.pack(enables, uint2_t{}); // Operator
1151 ret.pack(enables, uint2_t{}); // Admin
1152 ret.pack(enables, uint2_t{}); // OEM
1153 return responseSuccess(std::move(ret));
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001154 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001155 case LanParam::IP:
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001156 {
1157 auto ifaddr = channelCall<getIfAddr4>(channel);
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001158 stdplus::In4Addr addr{};
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001159 if (ifaddr)
1160 {
1161 addr = ifaddr->address;
1162 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001163 ret.pack(stdplus::raw::asView<char>(addr));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001164 return responseSuccess(std::move(ret));
1165 }
1166 case LanParam::IPSrc:
1167 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001168 auto src = channelCall<getEthProp<bool>>(channel, "DHCP4")
1169 ? IPSrc::DHCP
1170 : IPSrc::Static;
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001171 ret.pack(types::enum_cast<uint4_t>(src), uint4_t{});
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001172 return responseSuccess(std::move(ret));
1173 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001174 case LanParam::MAC:
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001175 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001176 auto mac = channelCall<getMACProperty>(channel);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001177 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001178 return responseSuccess(std::move(ret));
1179 }
1180 case LanParam::SubnetMask:
1181 {
1182 auto ifaddr = channelCall<getIfAddr4>(channel);
1183 uint8_t prefix = AddrFamily<AF_INET>::defaultPrefix;
1184 if (ifaddr)
Ratan Guptab8e99552017-07-27 07:07:48 +05301185 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001186 prefix = ifaddr->prefix;
1187 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001188 auto netmask = stdplus::pfxToMask<stdplus::In4Addr>(prefix);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001189 ret.pack(stdplus::raw::asView<char>(netmask));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001190 return responseSuccess(std::move(ret));
1191 }
1192 case LanParam::Gateway1:
1193 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001194 auto gateway = channelCall<getGatewayProperty<AF_INET>>(channel);
1195 ret.pack(stdplus::raw::asView<char>(
1196 gateway.value_or(stdplus::In4Addr{})));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001197 return responseSuccess(std::move(ret));
1198 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001199 case LanParam::Gateway1MAC:
1200 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001201 stdplus::EtherAddr mac{};
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001202 auto neighbor = channelCall<getGatewayNeighbor<AF_INET>>(channel);
1203 if (neighbor)
1204 {
1205 mac = neighbor->mac;
1206 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001207 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001208 return responseSuccess(std::move(ret));
1209 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001210 case LanParam::VLANId:
1211 {
1212 uint16_t vlan = channelCall<getVLANProperty>(channel);
1213 if (vlan != 0)
1214 {
1215 vlan |= VLAN_ENABLE_FLAG;
Ratan Guptab8e99552017-07-27 07:07:48 +05301216 }
1217 else
1218 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001219 vlan = lastDisabledVlan[channel];
Ratan Guptab8e99552017-07-27 07:07:48 +05301220 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001221 ret.pack(vlan);
1222 return responseSuccess(std::move(ret));
Adriana Kobylak342df102016-02-10 13:48:16 -06001223 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001224 case LanParam::CiphersuiteSupport:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001225 {
srikanta mondal1d8579c2020-04-15 17:13:25 +00001226 if (getChannelSessionSupport(channel) ==
1227 EChannelSessSupported::none)
1228 {
1229 return responseInvalidFieldRequest();
1230 }
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001231 if (!listInit)
1232 {
1233 return responseUnspecifiedError();
1234 }
1235 ret.pack(static_cast<uint8_t>(cipherList.size() - 1));
1236 return responseSuccess(std::move(ret));
1237 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001238 case LanParam::CiphersuiteEntries:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001239 {
srikanta mondal1d8579c2020-04-15 17:13:25 +00001240 if (getChannelSessionSupport(channel) ==
1241 EChannelSessSupported::none)
1242 {
1243 return responseInvalidFieldRequest();
1244 }
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001245 if (!listInit)
1246 {
1247 return responseUnspecifiedError();
1248 }
1249 ret.pack(cipherList);
1250 return responseSuccess(std::move(ret));
1251 }
William A. Kennington III16064aa2019-04-13 17:44:53 -07001252 case LanParam::IPFamilySupport:
1253 {
1254 std::bitset<8> support;
1255 support[IPFamilySupportFlag::IPv6Only] = 0;
1256 support[IPFamilySupportFlag::DualStack] = 1;
1257 support[IPFamilySupportFlag::IPv6Alerts] = 1;
1258 ret.pack(support);
1259 return responseSuccess(std::move(ret));
1260 }
1261 case LanParam::IPFamilyEnables:
1262 {
1263 ret.pack(static_cast<uint8_t>(IPFamilyEnables::DualStack));
1264 return responseSuccess(std::move(ret));
1265 }
1266 case LanParam::IPv6Status:
1267 {
1268 ret.pack(MAX_IPV6_STATIC_ADDRESSES);
1269 ret.pack(MAX_IPV6_DYNAMIC_ADDRESSES);
1270 std::bitset<8> support;
1271 support[IPv6StatusFlag::DHCP] = 1;
1272 support[IPv6StatusFlag::SLAAC] = 1;
1273 ret.pack(support);
1274 return responseSuccess(std::move(ret));
1275 }
1276 case LanParam::IPv6StaticAddresses:
1277 {
1278 if (set >= MAX_IPV6_STATIC_ADDRESSES)
1279 {
1280 return responseParmOutOfRange();
1281 }
1282 getLanIPv6Address(ret, channel, set, originsV6Static);
1283 return responseSuccess(std::move(ret));
1284 }
1285 case LanParam::IPv6DynamicAddresses:
1286 {
1287 if (set >= MAX_IPV6_DYNAMIC_ADDRESSES)
1288 {
1289 return responseParmOutOfRange();
1290 }
1291 getLanIPv6Address(ret, channel, set, originsV6Dynamic);
1292 return responseSuccess(std::move(ret));
1293 }
1294 case LanParam::IPv6RouterControl:
1295 {
1296 std::bitset<8> control;
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001297 control[IPv6RouterControlFlag::Dynamic] =
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001298 channelCall<getEthProp<bool>>(channel, "IPv6AcceptRA");
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001299 control[IPv6RouterControlFlag::Static] = 1;
William A. Kennington III16064aa2019-04-13 17:44:53 -07001300 ret.pack(control);
1301 return responseSuccess(std::move(ret));
1302 }
1303 case LanParam::IPv6StaticRouter1IP:
1304 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001305 stdplus::In6Addr gateway{};
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001306 if (!channelCall<getEthProp<bool>>(channel, "IPv6AcceptRA"))
William A. Kennington III16064aa2019-04-13 17:44:53 -07001307 {
1308 gateway =
1309 channelCall<getGatewayProperty<AF_INET6>>(channel).value_or(
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001310 stdplus::In6Addr{});
William A. Kennington III16064aa2019-04-13 17:44:53 -07001311 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001312 ret.pack(stdplus::raw::asView<char>(gateway));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001313 return responseSuccess(std::move(ret));
1314 }
1315 case LanParam::IPv6StaticRouter1MAC:
1316 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001317 stdplus::EtherAddr mac{};
William A. Kennington III16064aa2019-04-13 17:44:53 -07001318 auto neighbor = channelCall<getGatewayNeighbor<AF_INET6>>(channel);
1319 if (neighbor)
1320 {
1321 mac = neighbor->mac;
1322 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001323 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001324 return responseSuccess(std::move(ret));
1325 }
1326 case LanParam::IPv6StaticRouter1PrefixLength:
1327 {
1328 ret.pack(UINT8_C(0));
1329 return responseSuccess(std::move(ret));
1330 }
1331 case LanParam::IPv6StaticRouter1PrefixValue:
1332 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001333 ret.pack(stdplus::raw::asView<char>(stdplus::In6Addr{}));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001334 return responseSuccess(std::move(ret));
1335 }
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001336 case LanParam::cipherSuitePrivilegeLevels:
1337 {
1338 std::array<uint4_t, ipmi::maxCSRecords> csPrivilegeLevels;
1339
1340 uint8_t resp =
1341 getCipherConfigObject(csPrivFileName, csPrivDefaultFileName)
1342 .getCSPrivilegeLevels(channel, csPrivilegeLevels);
1343 if (!resp)
1344 {
1345 constexpr uint8_t reserved1 = 0x00;
1346 ret.pack(reserved1, csPrivilegeLevels);
1347 return responseSuccess(std::move(ret));
1348 }
1349 else
1350 {
1351 return response(resp);
1352 }
1353 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001354 }
1355
PavanKumarIntel3771f5f2023-11-02 06:26:42 +00001356 if (parameter >= oemCmdStart)
Johnathan Manteyb87034e2019-09-16 10:50:50 -07001357 {
1358 return getLanOem(channel, parameter, set, block);
1359 }
1360
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001361 return response(ccParamNotSupported);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001362}
1363
Jian Zhang23f44652022-03-17 17:13:10 +08001364constexpr const char* solInterface = "xyz.openbmc_project.Ipmi.SOL";
1365constexpr const char* solPath = "/xyz/openbmc_project/ipmi/sol/";
1366constexpr const uint16_t solDefaultPort = 623;
1367
1368RspType<> setSolConfParams(Context::ptr ctx, uint4_t channelBits,
Willy Tu11d68892022-01-20 10:37:34 -08001369 uint4_t /*reserved*/, uint8_t parameter,
Jian Zhang23f44652022-03-17 17:13:10 +08001370 message::Payload& req)
1371{
1372 const uint8_t channel = convertCurrentChannelNum(
1373 static_cast<uint8_t>(channelBits), ctx->channel);
1374
1375 if (!isValidChannel(channel))
1376 {
1377 log<level::ERR>("Set Sol Config - Invalid channel in request");
1378 return responseInvalidFieldRequest();
1379 }
1380
1381 std::string solService{};
1382 std::string solPathWitheEthName = solPath + ipmi::getChannelName(channel);
1383
1384 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1385 {
1386 log<level::ERR>("Set Sol Config - Invalid solInterface",
1387 entry("SERVICE=%s", solService.c_str()),
1388 entry("OBJPATH=%s", solPathWitheEthName.c_str()),
1389 entry("INTERFACE=%s", solInterface));
1390 return responseInvalidFieldRequest();
1391 }
1392
1393 switch (static_cast<SolConfParam>(parameter))
1394 {
1395 case SolConfParam::Progress:
1396 {
1397 uint8_t progress;
1398 if (req.unpack(progress) != 0 || !req.fullyUnpacked())
1399 {
1400 return responseReqDataLenInvalid();
1401 }
1402
1403 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1404 solInterface, "Progress", progress))
1405 {
1406 return responseUnspecifiedError();
1407 }
1408 break;
1409 }
1410 case SolConfParam::Enable:
1411 {
1412 bool enable;
1413 uint7_t reserved2;
1414
1415 if (req.unpack(enable, reserved2) != 0 || !req.fullyUnpacked())
1416 {
1417 return responseReqDataLenInvalid();
1418 }
1419
1420 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1421 solInterface, "Enable", enable))
1422 {
1423 return responseUnspecifiedError();
1424 }
1425 break;
1426 }
1427 case SolConfParam::Authentication:
1428 {
1429 uint4_t privilegeBits{};
1430 uint2_t reserved2{};
1431 bool forceAuth = false;
1432 bool forceEncrypt = false;
1433
1434 if (req.unpack(privilegeBits, reserved2, forceAuth, forceEncrypt) !=
1435 0 ||
1436 !req.fullyUnpacked())
1437 {
1438 return responseReqDataLenInvalid();
1439 }
1440
1441 uint8_t privilege = static_cast<uint8_t>(privilegeBits);
Jonathan Domana48bf772023-05-26 17:54:57 -07001442 if (privilege < static_cast<uint8_t>(Privilege::User) ||
Jian Zhang23f44652022-03-17 17:13:10 +08001443 privilege > static_cast<uint8_t>(Privilege::Oem))
1444 {
1445 return ipmi::responseInvalidFieldRequest();
1446 }
1447
1448 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1449 solInterface, "Privilege", privilege))
1450 {
1451 return responseUnspecifiedError();
1452 }
1453
1454 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1455 solInterface, "ForceEncryption",
1456 forceEncrypt))
1457 {
1458 return responseUnspecifiedError();
1459 }
1460
1461 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1462 solInterface, "ForceAuthentication",
1463 forceAuth))
1464 {
1465 return responseUnspecifiedError();
1466 }
1467 break;
1468 }
1469 case SolConfParam::Accumulate:
1470 {
1471 uint8_t interval;
1472 uint8_t threshold;
1473 if (req.unpack(interval, threshold) != 0 || !req.fullyUnpacked())
1474 {
1475 return responseReqDataLenInvalid();
1476 }
1477
1478 if (threshold == 0)
1479 {
1480 return responseInvalidFieldRequest();
1481 }
1482
1483 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1484 solInterface, "AccumulateIntervalMS",
1485 interval))
1486 {
1487 return responseUnspecifiedError();
1488 }
1489
1490 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1491 solInterface, "Threshold", threshold))
1492 {
1493 return responseUnspecifiedError();
1494 }
1495 break;
1496 }
1497 case SolConfParam::Retry:
1498 {
1499 uint3_t countBits;
1500 uint5_t reserved2;
1501 uint8_t interval;
1502
1503 if (req.unpack(countBits, reserved2, interval) != 0 ||
1504 !req.fullyUnpacked())
1505 {
1506 return responseReqDataLenInvalid();
1507 }
1508
1509 uint8_t count = static_cast<uint8_t>(countBits);
1510 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1511 solInterface, "RetryCount", count))
1512 {
1513 return responseUnspecifiedError();
1514 }
1515
1516 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1517 solInterface, "RetryIntervalMS",
1518 interval))
1519 {
1520 return responseUnspecifiedError();
1521 }
1522 break;
1523 }
1524 case SolConfParam::Port:
1525 {
1526 return response(ipmiCCWriteReadParameter);
1527 }
1528 case SolConfParam::NonVbitrate:
1529 case SolConfParam::Vbitrate:
1530 case SolConfParam::Channel:
1531 default:
1532 return response(ipmiCCParamNotSupported);
1533 }
1534 return responseSuccess();
1535}
1536
1537RspType<message::Payload> getSolConfParams(Context::ptr ctx,
1538 uint4_t channelBits,
Willy Tu11d68892022-01-20 10:37:34 -08001539 uint3_t /*reserved*/, bool revOnly,
1540 uint8_t parameter, uint8_t /*set*/,
1541 uint8_t /*block*/)
Jian Zhang23f44652022-03-17 17:13:10 +08001542{
1543 message::Payload ret;
1544 constexpr uint8_t current_revision = 0x11;
1545 ret.pack(current_revision);
1546 if (revOnly)
1547 {
1548 return responseSuccess(std::move(ret));
1549 }
1550
1551 const uint8_t channel = convertCurrentChannelNum(
1552 static_cast<uint8_t>(channelBits), ctx->channel);
1553
1554 if (!isValidChannel(channel))
1555 {
1556 log<level::ERR>("Get Sol Config - Invalid channel in request");
1557 return responseInvalidFieldRequest();
1558 }
1559
1560 std::string solService{};
1561 std::string solPathWitheEthName = solPath + ipmi::getChannelName(channel);
1562
1563 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1564 {
1565 log<level::ERR>("Set Sol Config - Invalid solInterface",
1566 entry("SERVICE=%s", solService.c_str()),
1567 entry("OBJPATH=%s", solPathWitheEthName.c_str()),
1568 entry("INTERFACE=%s", solInterface));
1569 return responseInvalidFieldRequest();
1570 }
1571
1572 switch (static_cast<SolConfParam>(parameter))
1573 {
1574 case SolConfParam::Progress:
1575 {
1576 uint8_t progress;
1577 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1578 solInterface, "Progress", progress))
1579 {
1580 return responseUnspecifiedError();
1581 }
1582 ret.pack(progress);
1583 return responseSuccess(std::move(ret));
1584 }
1585 case SolConfParam::Enable:
1586 {
1587 bool enable{};
1588 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1589 solInterface, "Enable", enable))
1590 {
1591 return responseUnspecifiedError();
1592 }
1593 ret.pack(enable, uint7_t{});
1594 return responseSuccess(std::move(ret));
1595 }
1596 case SolConfParam::Authentication:
1597 {
1598 // 4bits, cast when pack
1599 uint8_t privilege;
1600 bool forceAuth = false;
1601 bool forceEncrypt = false;
1602
1603 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1604 solInterface, "Privilege", privilege))
1605 {
1606 return responseUnspecifiedError();
1607 }
1608
1609 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1610 solInterface, "ForceAuthentication",
1611 forceAuth))
1612 {
1613 return responseUnspecifiedError();
1614 }
1615
1616 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1617 solInterface, "ForceEncryption",
1618 forceEncrypt))
1619 {
1620 return responseUnspecifiedError();
1621 }
1622 ret.pack(uint4_t{privilege}, uint2_t{}, forceAuth, forceEncrypt);
1623 return responseSuccess(std::move(ret));
1624 }
1625 case SolConfParam::Accumulate:
1626 {
1627 uint8_t interval{}, threshold{};
1628
1629 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1630 solInterface, "AccumulateIntervalMS",
1631 interval))
1632 {
1633 return responseUnspecifiedError();
1634 }
1635
1636 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1637 solInterface, "Threshold", threshold))
1638 {
1639 return responseUnspecifiedError();
1640 }
1641 ret.pack(interval, threshold);
1642 return responseSuccess(std::move(ret));
1643 }
1644 case SolConfParam::Retry:
1645 {
1646 // 3bits, cast when cast
1647 uint8_t count{};
1648 uint8_t interval{};
1649
1650 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1651 solInterface, "RetryCount", count))
1652 {
1653 return responseUnspecifiedError();
1654 }
1655
1656 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1657 solInterface, "RetryIntervalMS",
1658 interval))
1659 {
1660 return responseUnspecifiedError();
1661 }
1662 ret.pack(uint3_t{count}, uint5_t{}, interval);
1663 return responseSuccess(std::move(ret));
1664 }
1665 case SolConfParam::Port:
1666 {
1667 auto port = solDefaultPort;
1668 ret.pack(static_cast<uint16_t>(port));
1669 return responseSuccess(std::move(ret));
1670 }
1671 case SolConfParam::Channel:
1672 {
1673 ret.pack(channel);
1674 return responseSuccess(std::move(ret));
1675 }
1676 case SolConfParam::NonVbitrate:
Jonathan Domana48bf772023-05-26 17:54:57 -07001677 {
1678 uint64_t baudRate;
1679 uint8_t encodedBitRate = 0;
1680 if (ipmi::getDbusProperty(
1681 ctx, "xyz.openbmc_project.Console.default",
1682 "/xyz/openbmc_project/console/default",
1683 "xyz.openbmc_project.Console.UART", "Baud", baudRate))
1684 {
1685 return ipmi::responseUnspecifiedError();
1686 }
1687 switch (baudRate)
1688 {
1689 case 9600:
1690 encodedBitRate = 0x06;
1691 break;
1692 case 19200:
1693 encodedBitRate = 0x07;
1694 break;
1695 case 38400:
1696 encodedBitRate = 0x08;
1697 break;
1698 case 57600:
1699 encodedBitRate = 0x09;
1700 break;
1701 case 115200:
1702 encodedBitRate = 0x0a;
1703 break;
1704 default:
1705 break;
1706 }
1707 ret.pack(encodedBitRate);
1708 return responseSuccess(std::move(ret));
1709 }
Jian Zhang23f44652022-03-17 17:13:10 +08001710 case SolConfParam::Vbitrate:
1711 default:
1712 return response(ipmiCCParamNotSupported);
1713 }
1714
1715 return response(ccParamNotSupported);
1716}
1717
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001718} // namespace transport
1719} // namespace ipmi
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301720
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001721void register_netfn_transport_functions() __attribute__((constructor));
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301722
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001723void register_netfn_transport_functions()
1724{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001725 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1726 ipmi::transport::cmdSetLanConfigParameters,
1727 ipmi::Privilege::Admin, ipmi::transport::setLan);
1728 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1729 ipmi::transport::cmdGetLanConfigParameters,
Johnathan Mantey34698d52019-11-19 14:47:30 -08001730 ipmi::Privilege::Operator, ipmi::transport::getLan);
Jian Zhang23f44652022-03-17 17:13:10 +08001731 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1732 ipmi::transport::cmdSetSolConfigParameters,
1733 ipmi::Privilege::Admin,
1734 ipmi::transport::setSolConfParams);
1735 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1736 ipmi::transport::cmdGetSolConfigParameters,
1737 ipmi::Privilege::User,
1738 ipmi::transport::getSolConfParams);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001739}