blob: 0c6e4aca74963c8a3ba5bfbe43ce0479ae4bc3b8 [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 }
Jayaprakash Mutyala0d1d7ad2024-06-19 10:19:33 +0000891 else if (vlan == 0 || vlan == VLAN_VALUE_MASK)
892 {
893 return responseInvalidFieldRequest();
894 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530895
jayaprakash Mutyala84c49dc2020-05-18 23:12:13 +0000896 channelCall<reconfigureVLAN>(channel, vlan);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700897 return responseSuccess();
898 }
899 case LanParam::CiphersuiteSupport:
900 case LanParam::CiphersuiteEntries:
William A. Kennington III16064aa2019-04-13 17:44:53 -0700901 case LanParam::IPFamilySupport:
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700902 {
903 req.trailingOk = true;
904 return response(ccParamReadOnly);
Ratan Guptab8e99552017-07-27 07:07:48 +0530905 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700906 case LanParam::IPFamilyEnables:
907 {
908 uint8_t enables;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700909 if (req.unpack(enables) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700910 {
911 return responseReqDataLenInvalid();
912 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700913 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700914 switch (static_cast<IPFamilyEnables>(enables))
915 {
916 case IPFamilyEnables::DualStack:
917 return responseSuccess();
918 case IPFamilyEnables::IPv4Only:
919 case IPFamilyEnables::IPv6Only:
920 return response(ccParamNotSupported);
921 }
922 return response(ccParamNotSupported);
923 }
924 case LanParam::IPv6Status:
925 {
926 req.trailingOk = true;
927 return response(ccParamReadOnly);
928 }
929 case LanParam::IPv6StaticAddresses:
930 {
931 uint8_t set;
932 uint7_t rsvd;
933 bool enabled;
William A. Kennington III16064aa2019-04-13 17:44:53 -0700934 uint8_t prefix;
935 uint8_t status;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700936 if (req.unpack(set, rsvd, enabled) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700937 {
938 return responseReqDataLenInvalid();
939 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700940 auto ip = unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700941 if (req.unpack(prefix, status) != 0)
942 {
943 return responseReqDataLenInvalid();
944 }
945 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800946 if (rsvd)
947 {
948 return responseInvalidFieldRequest();
949 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700950 if (enabled)
951 {
Jiaqing Zhao6d4a44e2022-01-24 15:04:00 +0800952 if (prefix < MIN_IPV6_PREFIX_LENGTH ||
953 prefix > MAX_IPV6_PREFIX_LENGTH)
954 {
955 return responseParmOutOfRange();
956 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700957 channelCall<reconfigureIfAddr6>(channel, set, ip, prefix);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700958 }
959 else
960 {
961 channelCall<deconfigureIfAddr6>(channel, set);
962 }
963 return responseSuccess();
964 }
965 case LanParam::IPv6DynamicAddresses:
966 {
967 req.trailingOk = true;
968 return response(ccParamReadOnly);
969 }
970 case LanParam::IPv6RouterControl:
971 {
972 std::bitset<8> control;
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800973 constexpr uint8_t reservedRACCBits = 0xfc;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700974 if (req.unpack(control) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700975 {
976 return responseReqDataLenInvalid();
977 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700978 unpackFinal(req);
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800979 if (std::bitset<8> expected(control &
980 std::bitset<8>(reservedRACCBits));
981 expected.any())
William A. Kennington III16064aa2019-04-13 17:44:53 -0700982 {
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800983 return response(ccParamNotSupported);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700984 }
Johnathan Mantey3b7a4072021-01-26 14:24:53 -0800985
986 bool enableRA = control[IPv6RouterControlFlag::Dynamic];
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700987 channelCall<setEthProp<bool>>(channel, "IPv6AcceptRA", enableRA);
988 channelCall<setEthProp<bool>>(channel, "DHCP6", enableRA);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700989 return responseSuccess();
990 }
991 case LanParam::IPv6StaticRouter1IP:
992 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -0700993 auto gateway = unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700994 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700995 channelCall<setGatewayProperty<AF_INET6>>(channel, gateway);
996 return responseSuccess();
997 }
998 case LanParam::IPv6StaticRouter1MAC:
999 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001000 auto mac = unpackT<stdplus::EtherAddr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001001 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001002 channelCall<reconfigureGatewayMAC<AF_INET6>>(channel, mac);
1003 return responseSuccess();
1004 }
1005 case LanParam::IPv6StaticRouter1PrefixLength:
1006 {
1007 uint8_t prefix;
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001008 if (req.unpack(prefix) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -07001009 {
1010 return responseReqDataLenInvalid();
1011 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001012 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001013 if (prefix != 0)
1014 {
1015 return responseInvalidFieldRequest();
1016 }
1017 return responseSuccess();
1018 }
1019 case LanParam::IPv6StaticRouter1PrefixValue:
1020 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001021 unpackT<stdplus::In6Addr>(req);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001022 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001023 // Accept any prefix value since our prefix length has to be 0
1024 return responseSuccess();
1025 }
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001026 case LanParam::cipherSuitePrivilegeLevels:
1027 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001028 uint8_t rsvd;
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001029 std::array<uint4_t, ipmi::maxCSRecords> cipherSuitePrivs;
1030
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001031 if (req.unpack(rsvd, cipherSuitePrivs))
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001032 {
1033 return responseReqDataLenInvalid();
1034 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001035 unpackFinal(req);
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001036
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001037 if (rsvd)
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001038 {
1039 return responseInvalidFieldRequest();
1040 }
1041
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -05001042 uint8_t resp = getCipherConfigObject(csPrivFileName,
1043 csPrivDefaultFileName)
1044 .setCSPrivilegeLevels(channel, cipherSuitePrivs);
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001045 if (!resp)
1046 {
1047 return responseSuccess();
1048 }
1049 else
1050 {
1051 req.trailingOk = true;
1052 return response(resp);
1053 }
1054 }
Ratan Guptab8e99552017-07-27 07:07:48 +05301055 }
vishwa1eaea4f2016-02-26 11:57:40 -06001056
PavanKumarIntel3771f5f2023-11-02 06:26:42 +00001057 if (parameter >= oemCmdStart)
Johnathan Manteyb87034e2019-09-16 10:50:50 -07001058 {
1059 return setLanOem(channel, parameter, req);
1060 }
1061
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001062 req.trailingOk = true;
1063 return response(ccParamNotSupported);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001064}
1065
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001066RspType<> setLan(Context::ptr ctx, uint4_t channelBits, uint4_t reserved1,
1067 uint8_t parameter, message::Payload& req)
1068{
1069 try
1070 {
1071 return setLanInt(ctx, channelBits, reserved1, parameter, req);
1072 }
1073 catch (ipmi::Cc cc)
1074 {
1075 return response(cc);
1076 }
1077 catch (const sdbusplus::exception_t& e)
1078 {
1079 if (std::string_view{InvalidArgument::errName} == e.name())
1080 {
1081 return responseInvalidFieldRequest();
1082 }
1083 throw;
1084 }
1085}
1086
vijayabharathix shettycc769252020-02-27 17:52:20 +00001087RspType<message::Payload> getLan(Context::ptr ctx, uint4_t channelBits,
1088 uint3_t reserved, bool revOnly,
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001089 uint8_t parameter, uint8_t set, uint8_t block)
Ratan Guptab8e99552017-07-27 07:07:48 +05301090{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001091 message::Payload ret;
1092 constexpr uint8_t current_revision = 0x11;
1093 ret.pack(current_revision);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001094
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001095 if (revOnly)
Suryakanth Sekare4054402019-08-08 15:16:52 +05301096 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001097 return responseSuccess(std::move(ret));
Suryakanth Sekare4054402019-08-08 15:16:52 +05301098 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001099
vijayabharathix shettycc769252020-02-27 17:52:20 +00001100 const uint8_t channel = convertCurrentChannelNum(
1101 static_cast<uint8_t>(channelBits), ctx->channel);
1102 if (reserved || !isValidChannel(channel))
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001103 {
vijayabharathix shettycc769252020-02-27 17:52:20 +00001104 log<level::ERR>("Get Lan - Invalid field in request");
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001105 return responseInvalidFieldRequest();
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001106 }
1107
Jian Zhangcf19d142023-07-31 10:22:53 +08001108 if (!isLanChannel(channel).value_or(false))
1109 {
1110 log<level::ERR>("Set Lan - Not a LAN channel");
1111 return responseInvalidFieldRequest();
1112 }
1113
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001114 static std::vector<uint8_t> cipherList;
1115 static bool listInit = false;
1116 if (!listInit)
1117 {
1118 try
1119 {
1120 cipherList = cipher::getCipherList();
1121 listInit = true;
1122 }
1123 catch (const std::exception& e)
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -05001124 {}
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001125 }
1126
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001127 switch (static_cast<LanParam>(parameter))
Tom Josepha30c8d32018-03-22 02:15:03 +05301128 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001129 case LanParam::SetStatus:
Tom Josepha30c8d32018-03-22 02:15:03 +05301130 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001131 SetStatus status;
1132 try
1133 {
1134 status = setStatus.at(channel);
1135 }
1136 catch (const std::out_of_range&)
1137 {
1138 status = SetStatus::Complete;
1139 }
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001140 ret.pack(types::enum_cast<uint2_t>(status), uint6_t{});
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001141 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301142 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001143 case LanParam::AuthSupport:
Tom Josepha30c8d32018-03-22 02:15:03 +05301144 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001145 std::bitset<6> support;
1146 ret.pack(support, uint2_t{});
1147 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301148 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001149 case LanParam::AuthEnables:
vishwa1eaea4f2016-02-26 11:57:40 -06001150 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001151 std::bitset<6> enables;
1152 ret.pack(enables, uint2_t{}); // Callback
1153 ret.pack(enables, uint2_t{}); // User
1154 ret.pack(enables, uint2_t{}); // Operator
1155 ret.pack(enables, uint2_t{}); // Admin
1156 ret.pack(enables, uint2_t{}); // OEM
1157 return responseSuccess(std::move(ret));
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001158 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001159 case LanParam::IP:
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001160 {
1161 auto ifaddr = channelCall<getIfAddr4>(channel);
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001162 stdplus::In4Addr addr{};
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001163 if (ifaddr)
1164 {
1165 addr = ifaddr->address;
1166 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001167 ret.pack(stdplus::raw::asView<char>(addr));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001168 return responseSuccess(std::move(ret));
1169 }
1170 case LanParam::IPSrc:
1171 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001172 auto src = channelCall<getEthProp<bool>>(channel, "DHCP4")
1173 ? IPSrc::DHCP
1174 : IPSrc::Static;
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001175 ret.pack(types::enum_cast<uint4_t>(src), uint4_t{});
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001176 return responseSuccess(std::move(ret));
1177 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001178 case LanParam::MAC:
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001179 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001180 auto mac = channelCall<getMACProperty>(channel);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001181 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001182 return responseSuccess(std::move(ret));
1183 }
1184 case LanParam::SubnetMask:
1185 {
1186 auto ifaddr = channelCall<getIfAddr4>(channel);
1187 uint8_t prefix = AddrFamily<AF_INET>::defaultPrefix;
1188 if (ifaddr)
Ratan Guptab8e99552017-07-27 07:07:48 +05301189 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001190 prefix = ifaddr->prefix;
1191 }
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001192 auto netmask = stdplus::pfxToMask<stdplus::In4Addr>(prefix);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001193 ret.pack(stdplus::raw::asView<char>(netmask));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001194 return responseSuccess(std::move(ret));
1195 }
1196 case LanParam::Gateway1:
1197 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001198 auto gateway = channelCall<getGatewayProperty<AF_INET>>(channel);
1199 ret.pack(stdplus::raw::asView<char>(
1200 gateway.value_or(stdplus::In4Addr{})));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001201 return responseSuccess(std::move(ret));
1202 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001203 case LanParam::Gateway1MAC:
1204 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001205 stdplus::EtherAddr mac{};
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001206 auto neighbor = channelCall<getGatewayNeighbor<AF_INET>>(channel);
1207 if (neighbor)
1208 {
1209 mac = neighbor->mac;
1210 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001211 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001212 return responseSuccess(std::move(ret));
1213 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001214 case LanParam::VLANId:
1215 {
1216 uint16_t vlan = channelCall<getVLANProperty>(channel);
1217 if (vlan != 0)
1218 {
1219 vlan |= VLAN_ENABLE_FLAG;
Ratan Guptab8e99552017-07-27 07:07:48 +05301220 }
1221 else
1222 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001223 vlan = lastDisabledVlan[channel];
Ratan Guptab8e99552017-07-27 07:07:48 +05301224 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001225 ret.pack(vlan);
1226 return responseSuccess(std::move(ret));
Adriana Kobylak342df102016-02-10 13:48:16 -06001227 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001228 case LanParam::CiphersuiteSupport:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001229 {
srikanta mondal1d8579c2020-04-15 17:13:25 +00001230 if (getChannelSessionSupport(channel) ==
1231 EChannelSessSupported::none)
1232 {
1233 return responseInvalidFieldRequest();
1234 }
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001235 if (!listInit)
1236 {
1237 return responseUnspecifiedError();
1238 }
1239 ret.pack(static_cast<uint8_t>(cipherList.size() - 1));
1240 return responseSuccess(std::move(ret));
1241 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001242 case LanParam::CiphersuiteEntries:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001243 {
srikanta mondal1d8579c2020-04-15 17:13:25 +00001244 if (getChannelSessionSupport(channel) ==
1245 EChannelSessSupported::none)
1246 {
1247 return responseInvalidFieldRequest();
1248 }
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001249 if (!listInit)
1250 {
1251 return responseUnspecifiedError();
1252 }
1253 ret.pack(cipherList);
1254 return responseSuccess(std::move(ret));
1255 }
William A. Kennington III16064aa2019-04-13 17:44:53 -07001256 case LanParam::IPFamilySupport:
1257 {
1258 std::bitset<8> support;
1259 support[IPFamilySupportFlag::IPv6Only] = 0;
1260 support[IPFamilySupportFlag::DualStack] = 1;
1261 support[IPFamilySupportFlag::IPv6Alerts] = 1;
1262 ret.pack(support);
1263 return responseSuccess(std::move(ret));
1264 }
1265 case LanParam::IPFamilyEnables:
1266 {
1267 ret.pack(static_cast<uint8_t>(IPFamilyEnables::DualStack));
1268 return responseSuccess(std::move(ret));
1269 }
1270 case LanParam::IPv6Status:
1271 {
1272 ret.pack(MAX_IPV6_STATIC_ADDRESSES);
1273 ret.pack(MAX_IPV6_DYNAMIC_ADDRESSES);
1274 std::bitset<8> support;
1275 support[IPv6StatusFlag::DHCP] = 1;
1276 support[IPv6StatusFlag::SLAAC] = 1;
1277 ret.pack(support);
1278 return responseSuccess(std::move(ret));
1279 }
1280 case LanParam::IPv6StaticAddresses:
1281 {
1282 if (set >= MAX_IPV6_STATIC_ADDRESSES)
1283 {
1284 return responseParmOutOfRange();
1285 }
1286 getLanIPv6Address(ret, channel, set, originsV6Static);
1287 return responseSuccess(std::move(ret));
1288 }
1289 case LanParam::IPv6DynamicAddresses:
1290 {
1291 if (set >= MAX_IPV6_DYNAMIC_ADDRESSES)
1292 {
1293 return responseParmOutOfRange();
1294 }
1295 getLanIPv6Address(ret, channel, set, originsV6Dynamic);
1296 return responseSuccess(std::move(ret));
1297 }
1298 case LanParam::IPv6RouterControl:
1299 {
1300 std::bitset<8> control;
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001301 control[IPv6RouterControlFlag::Dynamic] =
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001302 channelCall<getEthProp<bool>>(channel, "IPv6AcceptRA");
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001303 control[IPv6RouterControlFlag::Static] = 1;
William A. Kennington III16064aa2019-04-13 17:44:53 -07001304 ret.pack(control);
1305 return responseSuccess(std::move(ret));
1306 }
1307 case LanParam::IPv6StaticRouter1IP:
1308 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001309 stdplus::In6Addr gateway{};
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001310 if (!channelCall<getEthProp<bool>>(channel, "IPv6AcceptRA"))
William A. Kennington III16064aa2019-04-13 17:44:53 -07001311 {
1312 gateway =
1313 channelCall<getGatewayProperty<AF_INET6>>(channel).value_or(
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001314 stdplus::In6Addr{});
William A. Kennington III16064aa2019-04-13 17:44:53 -07001315 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001316 ret.pack(stdplus::raw::asView<char>(gateway));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001317 return responseSuccess(std::move(ret));
1318 }
1319 case LanParam::IPv6StaticRouter1MAC:
1320 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001321 stdplus::EtherAddr mac{};
William A. Kennington III16064aa2019-04-13 17:44:53 -07001322 auto neighbor = channelCall<getGatewayNeighbor<AF_INET6>>(channel);
1323 if (neighbor)
1324 {
1325 mac = neighbor->mac;
1326 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001327 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001328 return responseSuccess(std::move(ret));
1329 }
1330 case LanParam::IPv6StaticRouter1PrefixLength:
1331 {
Jian Zhang796e8242024-02-01 14:07:34 +08001332 ret.pack(uint8_t{0});
William A. Kennington III16064aa2019-04-13 17:44:53 -07001333 return responseSuccess(std::move(ret));
1334 }
1335 case LanParam::IPv6StaticRouter1PrefixValue:
1336 {
William A. Kennington III726f2bd2023-06-21 01:11:40 -07001337 ret.pack(stdplus::raw::asView<char>(stdplus::In6Addr{}));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001338 return responseSuccess(std::move(ret));
1339 }
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001340 case LanParam::cipherSuitePrivilegeLevels:
1341 {
1342 std::array<uint4_t, ipmi::maxCSRecords> csPrivilegeLevels;
1343
1344 uint8_t resp =
1345 getCipherConfigObject(csPrivFileName, csPrivDefaultFileName)
1346 .getCSPrivilegeLevels(channel, csPrivilegeLevels);
1347 if (!resp)
1348 {
1349 constexpr uint8_t reserved1 = 0x00;
1350 ret.pack(reserved1, csPrivilegeLevels);
1351 return responseSuccess(std::move(ret));
1352 }
1353 else
1354 {
1355 return response(resp);
1356 }
1357 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001358 }
1359
PavanKumarIntel3771f5f2023-11-02 06:26:42 +00001360 if (parameter >= oemCmdStart)
Johnathan Manteyb87034e2019-09-16 10:50:50 -07001361 {
1362 return getLanOem(channel, parameter, set, block);
1363 }
1364
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001365 return response(ccParamNotSupported);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001366}
1367
Jian Zhang23f44652022-03-17 17:13:10 +08001368constexpr const char* solInterface = "xyz.openbmc_project.Ipmi.SOL";
1369constexpr const char* solPath = "/xyz/openbmc_project/ipmi/sol/";
1370constexpr const uint16_t solDefaultPort = 623;
1371
1372RspType<> setSolConfParams(Context::ptr ctx, uint4_t channelBits,
Willy Tu11d68892022-01-20 10:37:34 -08001373 uint4_t /*reserved*/, uint8_t parameter,
Jian Zhang23f44652022-03-17 17:13:10 +08001374 message::Payload& req)
1375{
1376 const uint8_t channel = convertCurrentChannelNum(
1377 static_cast<uint8_t>(channelBits), ctx->channel);
1378
1379 if (!isValidChannel(channel))
1380 {
1381 log<level::ERR>("Set Sol Config - Invalid channel in request");
1382 return responseInvalidFieldRequest();
1383 }
1384
1385 std::string solService{};
1386 std::string solPathWitheEthName = solPath + ipmi::getChannelName(channel);
1387
1388 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1389 {
1390 log<level::ERR>("Set Sol Config - Invalid solInterface",
1391 entry("SERVICE=%s", solService.c_str()),
1392 entry("OBJPATH=%s", solPathWitheEthName.c_str()),
1393 entry("INTERFACE=%s", solInterface));
1394 return responseInvalidFieldRequest();
1395 }
1396
1397 switch (static_cast<SolConfParam>(parameter))
1398 {
1399 case SolConfParam::Progress:
1400 {
1401 uint8_t progress;
1402 if (req.unpack(progress) != 0 || !req.fullyUnpacked())
1403 {
1404 return responseReqDataLenInvalid();
1405 }
1406
1407 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1408 solInterface, "Progress", progress))
1409 {
1410 return responseUnspecifiedError();
1411 }
1412 break;
1413 }
1414 case SolConfParam::Enable:
1415 {
1416 bool enable;
1417 uint7_t reserved2;
1418
1419 if (req.unpack(enable, reserved2) != 0 || !req.fullyUnpacked())
1420 {
1421 return responseReqDataLenInvalid();
1422 }
1423
1424 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1425 solInterface, "Enable", enable))
1426 {
1427 return responseUnspecifiedError();
1428 }
1429 break;
1430 }
1431 case SolConfParam::Authentication:
1432 {
1433 uint4_t privilegeBits{};
1434 uint2_t reserved2{};
1435 bool forceAuth = false;
1436 bool forceEncrypt = false;
1437
1438 if (req.unpack(privilegeBits, reserved2, forceAuth, forceEncrypt) !=
1439 0 ||
1440 !req.fullyUnpacked())
1441 {
1442 return responseReqDataLenInvalid();
1443 }
1444
1445 uint8_t privilege = static_cast<uint8_t>(privilegeBits);
Jonathan Domana48bf772023-05-26 17:54:57 -07001446 if (privilege < static_cast<uint8_t>(Privilege::User) ||
Jian Zhang23f44652022-03-17 17:13:10 +08001447 privilege > static_cast<uint8_t>(Privilege::Oem))
1448 {
1449 return ipmi::responseInvalidFieldRequest();
1450 }
1451
1452 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1453 solInterface, "Privilege", privilege))
1454 {
1455 return responseUnspecifiedError();
1456 }
1457
1458 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1459 solInterface, "ForceEncryption",
1460 forceEncrypt))
1461 {
1462 return responseUnspecifiedError();
1463 }
1464
1465 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1466 solInterface, "ForceAuthentication",
1467 forceAuth))
1468 {
1469 return responseUnspecifiedError();
1470 }
1471 break;
1472 }
1473 case SolConfParam::Accumulate:
1474 {
1475 uint8_t interval;
1476 uint8_t threshold;
1477 if (req.unpack(interval, threshold) != 0 || !req.fullyUnpacked())
1478 {
1479 return responseReqDataLenInvalid();
1480 }
1481
1482 if (threshold == 0)
1483 {
1484 return responseInvalidFieldRequest();
1485 }
1486
1487 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1488 solInterface, "AccumulateIntervalMS",
1489 interval))
1490 {
1491 return responseUnspecifiedError();
1492 }
1493
1494 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1495 solInterface, "Threshold", threshold))
1496 {
1497 return responseUnspecifiedError();
1498 }
1499 break;
1500 }
1501 case SolConfParam::Retry:
1502 {
1503 uint3_t countBits;
1504 uint5_t reserved2;
1505 uint8_t interval;
1506
1507 if (req.unpack(countBits, reserved2, interval) != 0 ||
1508 !req.fullyUnpacked())
1509 {
1510 return responseReqDataLenInvalid();
1511 }
1512
1513 uint8_t count = static_cast<uint8_t>(countBits);
1514 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1515 solInterface, "RetryCount", count))
1516 {
1517 return responseUnspecifiedError();
1518 }
1519
1520 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1521 solInterface, "RetryIntervalMS",
1522 interval))
1523 {
1524 return responseUnspecifiedError();
1525 }
1526 break;
1527 }
1528 case SolConfParam::Port:
1529 {
1530 return response(ipmiCCWriteReadParameter);
1531 }
1532 case SolConfParam::NonVbitrate:
1533 case SolConfParam::Vbitrate:
1534 case SolConfParam::Channel:
1535 default:
1536 return response(ipmiCCParamNotSupported);
1537 }
1538 return responseSuccess();
1539}
1540
1541RspType<message::Payload> getSolConfParams(Context::ptr ctx,
1542 uint4_t channelBits,
Willy Tu11d68892022-01-20 10:37:34 -08001543 uint3_t /*reserved*/, bool revOnly,
1544 uint8_t parameter, uint8_t /*set*/,
1545 uint8_t /*block*/)
Jian Zhang23f44652022-03-17 17:13:10 +08001546{
1547 message::Payload ret;
1548 constexpr uint8_t current_revision = 0x11;
1549 ret.pack(current_revision);
1550 if (revOnly)
1551 {
1552 return responseSuccess(std::move(ret));
1553 }
1554
1555 const uint8_t channel = convertCurrentChannelNum(
1556 static_cast<uint8_t>(channelBits), ctx->channel);
1557
1558 if (!isValidChannel(channel))
1559 {
1560 log<level::ERR>("Get Sol Config - Invalid channel in request");
1561 return responseInvalidFieldRequest();
1562 }
1563
1564 std::string solService{};
1565 std::string solPathWitheEthName = solPath + ipmi::getChannelName(channel);
1566
1567 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1568 {
1569 log<level::ERR>("Set Sol Config - Invalid solInterface",
1570 entry("SERVICE=%s", solService.c_str()),
1571 entry("OBJPATH=%s", solPathWitheEthName.c_str()),
1572 entry("INTERFACE=%s", solInterface));
1573 return responseInvalidFieldRequest();
1574 }
1575
1576 switch (static_cast<SolConfParam>(parameter))
1577 {
1578 case SolConfParam::Progress:
1579 {
1580 uint8_t progress;
1581 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1582 solInterface, "Progress", progress))
1583 {
1584 return responseUnspecifiedError();
1585 }
1586 ret.pack(progress);
1587 return responseSuccess(std::move(ret));
1588 }
1589 case SolConfParam::Enable:
1590 {
1591 bool enable{};
1592 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1593 solInterface, "Enable", enable))
1594 {
1595 return responseUnspecifiedError();
1596 }
1597 ret.pack(enable, uint7_t{});
1598 return responseSuccess(std::move(ret));
1599 }
1600 case SolConfParam::Authentication:
1601 {
1602 // 4bits, cast when pack
1603 uint8_t privilege;
1604 bool forceAuth = false;
1605 bool forceEncrypt = false;
1606
1607 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1608 solInterface, "Privilege", privilege))
1609 {
1610 return responseUnspecifiedError();
1611 }
1612
1613 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1614 solInterface, "ForceAuthentication",
1615 forceAuth))
1616 {
1617 return responseUnspecifiedError();
1618 }
1619
1620 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1621 solInterface, "ForceEncryption",
1622 forceEncrypt))
1623 {
1624 return responseUnspecifiedError();
1625 }
1626 ret.pack(uint4_t{privilege}, uint2_t{}, forceAuth, forceEncrypt);
1627 return responseSuccess(std::move(ret));
1628 }
1629 case SolConfParam::Accumulate:
1630 {
1631 uint8_t interval{}, threshold{};
1632
1633 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1634 solInterface, "AccumulateIntervalMS",
1635 interval))
1636 {
1637 return responseUnspecifiedError();
1638 }
1639
1640 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1641 solInterface, "Threshold", threshold))
1642 {
1643 return responseUnspecifiedError();
1644 }
1645 ret.pack(interval, threshold);
1646 return responseSuccess(std::move(ret));
1647 }
1648 case SolConfParam::Retry:
1649 {
1650 // 3bits, cast when cast
1651 uint8_t count{};
1652 uint8_t interval{};
1653
1654 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1655 solInterface, "RetryCount", count))
1656 {
1657 return responseUnspecifiedError();
1658 }
1659
1660 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1661 solInterface, "RetryIntervalMS",
1662 interval))
1663 {
1664 return responseUnspecifiedError();
1665 }
1666 ret.pack(uint3_t{count}, uint5_t{}, interval);
1667 return responseSuccess(std::move(ret));
1668 }
1669 case SolConfParam::Port:
1670 {
1671 auto port = solDefaultPort;
1672 ret.pack(static_cast<uint16_t>(port));
1673 return responseSuccess(std::move(ret));
1674 }
1675 case SolConfParam::Channel:
1676 {
1677 ret.pack(channel);
1678 return responseSuccess(std::move(ret));
1679 }
1680 case SolConfParam::NonVbitrate:
Jonathan Domana48bf772023-05-26 17:54:57 -07001681 {
1682 uint64_t baudRate;
1683 uint8_t encodedBitRate = 0;
1684 if (ipmi::getDbusProperty(
1685 ctx, "xyz.openbmc_project.Console.default",
1686 "/xyz/openbmc_project/console/default",
1687 "xyz.openbmc_project.Console.UART", "Baud", baudRate))
1688 {
1689 return ipmi::responseUnspecifiedError();
1690 }
1691 switch (baudRate)
1692 {
1693 case 9600:
1694 encodedBitRate = 0x06;
1695 break;
1696 case 19200:
1697 encodedBitRate = 0x07;
1698 break;
1699 case 38400:
1700 encodedBitRate = 0x08;
1701 break;
1702 case 57600:
1703 encodedBitRate = 0x09;
1704 break;
1705 case 115200:
1706 encodedBitRate = 0x0a;
1707 break;
1708 default:
1709 break;
1710 }
1711 ret.pack(encodedBitRate);
1712 return responseSuccess(std::move(ret));
1713 }
Jian Zhang23f44652022-03-17 17:13:10 +08001714 case SolConfParam::Vbitrate:
1715 default:
1716 return response(ipmiCCParamNotSupported);
1717 }
1718
1719 return response(ccParamNotSupported);
1720}
1721
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001722} // namespace transport
1723} // namespace ipmi
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301724
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001725void register_netfn_transport_functions() __attribute__((constructor));
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301726
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001727void register_netfn_transport_functions()
1728{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001729 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1730 ipmi::transport::cmdSetLanConfigParameters,
1731 ipmi::Privilege::Admin, ipmi::transport::setLan);
1732 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1733 ipmi::transport::cmdGetLanConfigParameters,
Johnathan Mantey34698d52019-11-19 14:47:30 -08001734 ipmi::Privilege::Operator, ipmi::transport::getLan);
Jian Zhang23f44652022-03-17 17:13:10 +08001735 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1736 ipmi::transport::cmdSetSolConfigParameters,
1737 ipmi::Privilege::Admin,
1738 ipmi::transport::setSolConfParams);
1739 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1740 ipmi::transport::cmdGetSolConfigParameters,
1741 ipmi::Privilege::User,
1742 ipmi::transport::getSolConfParams);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001743}