blob: 1ffe911f1a67a0ccdd168d551d0a10a37d766fef [file] [log] [blame]
Patrick Venture690a2342020-05-17 11:51:31 -07001#include "transporthandler.hpp"
2
William A. Kennington III7a3831b2023-06-21 01:10:49 -07003#include <stdplus/raw.hpp>
4
5#include <array>
6
William A. Kennington IIIc514d872019-04-06 18:19:38 -07007using phosphor::logging::commit;
8using phosphor::logging::elog;
9using phosphor::logging::entry;
10using phosphor::logging::level;
11using phosphor::logging::log;
Willy Tu523e2d12023-09-05 11:36:48 -070012using sdbusplus::error::xyz::openbmc_project::common::InternalFailure;
William A. Kennington III7a3831b2023-06-21 01:10:49 -070013using sdbusplus::error::xyz::openbmc_project::common::InvalidArgument;
Willy Tu523e2d12023-09-05 11:36:48 -070014using sdbusplus::server::xyz::openbmc_project::network::EthernetInterface;
15using sdbusplus::server::xyz::openbmc_project::network::IP;
16using sdbusplus::server::xyz::openbmc_project::network::Neighbor;
William A. Kennington IIIc514d872019-04-06 18:19:38 -070017
Johnathan Manteyaffadb52019-10-07 10:13:53 -070018namespace cipher
19{
20
21std::vector<uint8_t> getCipherList()
22{
23 std::vector<uint8_t> cipherList;
24
25 std::ifstream jsonFile(cipher::configFile);
26 if (!jsonFile.is_open())
27 {
28 log<level::ERR>("Channel Cipher suites file not found");
29 elog<InternalFailure>();
30 }
31
32 auto data = Json::parse(jsonFile, nullptr, false);
33 if (data.is_discarded())
34 {
35 log<level::ERR>("Parsing channel cipher suites JSON failed");
36 elog<InternalFailure>();
37 }
38
39 // Byte 1 is reserved
40 cipherList.push_back(0x00);
41
42 for (const auto& record : data)
43 {
44 cipherList.push_back(record.value(cipher, 0));
45 }
46
47 return cipherList;
48}
49} // namespace cipher
50
51namespace ipmi
52{
53namespace transport
54{
55
William A. Kennington IIIc514d872019-04-06 18:19:38 -070056/** @brief Valid address origins for IPv4 */
57const std::unordered_set<IP::AddressOrigin> originsV4 = {
58 IP::AddressOrigin::Static,
59 IP::AddressOrigin::DHCP,
60};
61
Johnathan Manteyb87034e2019-09-16 10:50:50 -070062static constexpr uint8_t oemCmdStart = 192;
63static constexpr uint8_t oemCmdEnd = 255;
64
Patrick Williams5d82f472022-07-22 19:26:53 -050065std::optional<ChannelParams> maybeGetChannelParams(sdbusplus::bus_t& bus,
William A. Kennington IIIc514d872019-04-06 18:19:38 -070066 uint8_t channel)
67{
68 auto ifname = getChannelName(channel);
69 if (ifname.empty())
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080070 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -070071 return std::nullopt;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080072 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080073
William A. Kennington IIIc514d872019-04-06 18:19:38 -070074 // Enumerate all VLAN + ETHERNET interfaces
75 auto req = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF,
76 "GetSubTree");
77 req.append(PATH_ROOT, 0,
78 std::vector<std::string>{INTF_VLAN, INTF_ETHERNET});
79 auto reply = bus.call(req);
80 ObjectTree objs;
81 reply.read(objs);
82
83 ChannelParams params;
84 for (const auto& [path, impls] : objs)
85 {
86 if (path.find(ifname) == path.npos)
87 {
88 continue;
89 }
90 for (const auto& [service, intfs] : impls)
91 {
92 bool vlan = false;
93 bool ethernet = false;
94 for (const auto& intf : intfs)
95 {
96 if (intf == INTF_VLAN)
97 {
98 vlan = true;
99 }
100 else if (intf == INTF_ETHERNET)
101 {
102 ethernet = true;
103 }
104 }
105 if (params.service.empty() && (vlan || ethernet))
106 {
107 params.service = service;
108 }
109 if (params.ifPath.empty() && !vlan && ethernet)
110 {
111 params.ifPath = path;
112 }
113 if (params.logicalPath.empty() && vlan)
114 {
115 params.logicalPath = path;
116 }
117 }
118 }
119
120 // We must have a path for the underlying interface
121 if (params.ifPath.empty())
122 {
123 return std::nullopt;
124 }
125 // We don't have a VLAN so the logical path is the same
126 if (params.logicalPath.empty())
127 {
128 params.logicalPath = params.ifPath;
129 }
130
131 params.id = channel;
132 params.ifname = std::move(ifname);
Willy Tu11d68892022-01-20 10:37:34 -0800133 return params;
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700134}
135
Patrick Williams5d82f472022-07-22 19:26:53 -0500136ChannelParams getChannelParams(sdbusplus::bus_t& bus, uint8_t channel)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700137{
138 auto params = maybeGetChannelParams(bus, channel);
139 if (!params)
140 {
141 log<level::ERR>("Failed to get channel params",
142 entry("CHANNEL=%" PRIu8, channel));
143 elog<InternalFailure>();
144 }
145 return std::move(*params);
146}
147
148/** @brief Wraps the phosphor logging method to insert some additional metadata
149 *
150 * @param[in] params - The parameters for the channel
151 * ...
152 */
153template <auto level, typename... Args>
154auto logWithChannel(const ChannelParams& params, Args&&... args)
155{
156 return log<level>(std::forward<Args>(args)...,
157 entry("CHANNEL=%d", params.id),
158 entry("IFNAME=%s", params.ifname.c_str()));
159}
160template <auto level, typename... Args>
161auto logWithChannel(const std::optional<ChannelParams>& params, Args&&... args)
162{
163 if (params)
164 {
165 return logWithChannel<level>(*params, std::forward<Args>(args)...);
166 }
167 return log<level>(std::forward<Args>(args)...);
168}
169
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700170ether_addr stringToMAC(const char* mac)
171{
172 const ether_addr* ret = ether_aton(mac);
173 if (ret == nullptr)
174 {
175 log<level::ERR>("Invalid MAC Address", entry("MAC=%s", mac));
176 elog<InternalFailure>();
177 }
178 return *ret;
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 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500204ether_addr getMACProperty(sdbusplus::bus_t& bus, const ChannelParams& params)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700205{
206 auto macStr = std::get<std::string>(getDbusProperty(
207 bus, params.service, params.ifPath, INTF_MAC, "MACAddress"));
208 return stringToMAC(macStr.c_str());
209}
210
211/** @brief Sets the system value for MAC address on the given interface
212 *
213 * @param[in] bus - The bus object used for lookups
214 * @param[in] params - The parameters for the channel
215 * @param[in] mac - MAC address to apply
216 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500217void setMACProperty(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700218 const ether_addr& mac)
219{
220 std::string macStr = ether_ntoa(&mac);
221 setDbusProperty(bus, params.service, params.ifPath, INTF_MAC, "MACAddress",
222 macStr);
223}
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 IIIc514d872019-04-06 18:19:38 -0700261 const typename AddrFamily<family>::addr& address,
262 uint8_t prefix)
Tom Josepha30c8d32018-03-22 02:15:03 +0530263{
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500264 auto newreq = bus.new_method_call(params.service.c_str(),
265 params.logicalPath.c_str(),
266 INTF_IP_CREATE, "IP");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700267 std::string protocol =
Willy Tu523e2d12023-09-05 11:36:48 -0700268 sdbusplus::common::xyz::openbmc_project::network::convertForMessage(
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700269 AddrFamily<family>::protocol);
270 newreq.append(protocol, addrToString<family>(address), prefix, "");
271 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 IIIc514d872019-04-06 18:19:38 -0700293 const std::optional<in_addr>& address,
294 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 }
Johnathan Manteycbfa6e12023-06-01 06:57:25 -0700308
Jian Zhangd05b9dd2023-07-04 14:48:40 +0800309 if (struct in_addr nullIPv4{0};
Jayaprakash Mutyala4e02b432023-07-13 13:50:40 +0000310 (address == std::nullopt && prefix != std::nullopt) ||
311 (address != std::nullopt &&
312 (address.value().s_addr != nullIPv4.s_addr)))
Johnathan Manteycbfa6e12023-06-01 06:57:25 -0700313 {
314 createIfAddr<AF_INET>(bus, params, address.value_or(ifaddr->address),
315 prefix.value_or(fallbackPrefix));
316 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700317}
318
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700319template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500320std::optional<IfNeigh<family>> findGatewayNeighbor(sdbusplus::bus_t& bus,
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700321 const ChannelParams& params,
322 ObjectLookupCache& neighbors)
323{
324 auto gateway = getGatewayProperty<family>(bus, params);
325 if (!gateway)
326 {
327 return std::nullopt;
328 }
329
330 return findStaticNeighbor<family>(bus, params, *gateway, neighbors);
331}
332
333template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500334std::optional<IfNeigh<family>> getGatewayNeighbor(sdbusplus::bus_t& bus,
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700335 const ChannelParams& params)
336{
337 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
338 return findGatewayNeighbor<family>(bus, params, neighbors);
339}
340
341template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500342void reconfigureGatewayMAC(sdbusplus::bus_t& bus, const ChannelParams& params,
343 const ether_addr& mac)
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700344{
345 auto gateway = getGatewayProperty<family>(bus, params);
346 if (!gateway)
347 {
348 log<level::ERR>("Tried to set Gateway MAC without Gateway");
349 elog<InternalFailure>();
350 }
351
352 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500353 auto neighbor = findStaticNeighbor<family>(bus, params, *gateway,
354 neighbors);
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700355 if (neighbor)
356 {
357 deleteObjectIfExists(bus, params.service, neighbor->path);
358 }
359
360 createNeighbor<family>(bus, params, *gateway, mac);
361}
362
William A. Kennington III16064aa2019-04-13 17:44:53 -0700363/** @brief Deconfigures the IPv6 address info configured for the interface
364 *
365 * @param[in] bus - The bus object used for lookups
366 * @param[in] params - The parameters for the channel
367 * @param[in] idx - The address index to operate on
368 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500369void deconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III16064aa2019-04-13 17:44:53 -0700370 uint8_t idx)
371{
372 auto ifaddr = getIfAddr<AF_INET6>(bus, params, idx, originsV6Static);
373 if (ifaddr)
374 {
375 deleteObjectIfExists(bus, params.service, ifaddr->path);
376 }
377}
378
379/** @brief Reconfigures the IPv6 address info configured for the interface
380 *
381 * @param[in] bus - The bus object used for lookups
382 * @param[in] params - The parameters for the channel
383 * @param[in] idx - The address index to operate on
384 * @param[in] address - The new address
385 * @param[in] prefix - The new address prefix
386 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500387void reconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III16064aa2019-04-13 17:44:53 -0700388 uint8_t idx, const in6_addr& address, uint8_t prefix)
389{
390 deconfigureIfAddr6(bus, params, idx);
391 createIfAddr<AF_INET6>(bus, params, address, prefix);
392}
393
394/** @brief Converts the AddressOrigin into an IPv6Source
395 *
396 * @param[in] origin - The DBus Address Origin to convert
397 * @return The IPv6Source version of the origin
398 */
399IPv6Source originToSourceType(IP::AddressOrigin origin)
400{
401 switch (origin)
402 {
403 case IP::AddressOrigin::Static:
404 return IPv6Source::Static;
405 case IP::AddressOrigin::DHCP:
406 return IPv6Source::DHCP;
407 case IP::AddressOrigin::SLAAC:
408 return IPv6Source::SLAAC;
409 default:
410 {
Willy Tu523e2d12023-09-05 11:36:48 -0700411 auto originStr = sdbusplus::common::xyz::openbmc_project::network::
William A. Kennington III16064aa2019-04-13 17:44:53 -0700412 convertForMessage(origin);
413 log<level::ERR>(
414 "Invalid IP::AddressOrigin conversion to IPv6Source",
415 entry("ORIGIN=%s", originStr.c_str()));
416 elog<InternalFailure>();
417 }
418 }
419}
420
421/** @brief Packs the IPMI message response with IPv6 address data
422 *
423 * @param[out] ret - The IPMI response payload to be packed
424 * @param[in] channel - The channel id corresponding to an ethernet interface
425 * @param[in] set - The set selector for determining address index
426 * @param[in] origins - Set of valid origins for address filtering
427 */
428void getLanIPv6Address(message::Payload& ret, uint8_t channel, uint8_t set,
429 const std::unordered_set<IP::AddressOrigin>& origins)
430{
431 auto source = IPv6Source::Static;
432 bool enabled = false;
433 in6_addr addr{};
Johnathan Mantey5aae0922021-10-21 13:05:36 -0700434 uint8_t prefix{};
William A. Kennington III16064aa2019-04-13 17:44:53 -0700435 auto status = IPv6AddressStatus::Disabled;
436
437 auto ifaddr = channelCall<getIfAddr<AF_INET6>>(channel, set, origins);
438 if (ifaddr)
439 {
440 source = originToSourceType(ifaddr->origin);
Johnathan Mantey846af862021-10-21 12:48:54 -0700441 enabled = (origins == originsV6Static);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700442 addr = ifaddr->address;
443 prefix = ifaddr->prefix;
444 status = IPv6AddressStatus::Active;
445 }
446
447 ret.pack(set);
William A. Kennington III7a0e5df2021-05-19 13:31:29 -0700448 ret.pack(types::enum_cast<uint4_t>(source), uint3_t{}, enabled);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700449 ret.pack(std::string_view(reinterpret_cast<char*>(&addr), sizeof(addr)));
450 ret.pack(prefix);
William A. Kennington III7a0e5df2021-05-19 13:31:29 -0700451 ret.pack(types::enum_cast<uint8_t>(status));
William A. Kennington III16064aa2019-04-13 17:44:53 -0700452}
453
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700454/** @brief Gets the vlan ID configured on the interface
455 *
456 * @param[in] bus - The bus object used for lookups
457 * @param[in] params - The parameters for the channel
458 * @return VLAN id or the standard 0 for no VLAN
459 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500460uint16_t getVLANProperty(sdbusplus::bus_t& bus, const ChannelParams& params)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700461{
462 // VLAN devices will always have a separate logical object
463 if (params.ifPath == params.logicalPath)
464 {
465 return 0;
466 }
467
468 auto vlan = std::get<uint32_t>(getDbusProperty(
469 bus, params.service, params.logicalPath, INTF_VLAN, "Id"));
470 if ((vlan & VLAN_VALUE_MASK) != vlan)
471 {
472 logWithChannel<level::ERR>(params, "networkd returned an invalid vlan",
473 entry("VLAN=%" PRIu32, vlan));
Tom Josepha30c8d32018-03-22 02:15:03 +0530474 elog<InternalFailure>();
475 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700476 return vlan;
Tom Josepha30c8d32018-03-22 02:15:03 +0530477}
478
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700479/** @brief Deletes all of the possible configuration parameters for a channel
480 *
481 * @param[in] bus - The bus object used for lookups
482 * @param[in] params - The parameters for the channel
483 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500484void deconfigureChannel(sdbusplus::bus_t& bus, ChannelParams& params)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500485{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700486 // Delete all objects associated with the interface
487 auto objreq = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF,
488 "GetSubTree");
489 objreq.append(PATH_ROOT, 0, std::vector<std::string>{DELETE_INTERFACE});
490 auto objreply = bus.call(objreq);
491 ObjectTree objs;
492 objreply.read(objs);
493 for (const auto& [path, impls] : objs)
494 {
495 if (path.find(params.ifname) == path.npos)
496 {
497 continue;
498 }
499 for (const auto& [service, intfs] : impls)
500 {
501 deleteObjectIfExists(bus, service, path);
502 }
503 // Update params to reflect the deletion of vlan
504 if (path == params.logicalPath)
505 {
506 params.logicalPath = params.ifPath;
507 }
508 }
509
510 // Clear out any settings on the lower physical interface
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700511 setEthProp(bus, params, "DHCP4", false);
512 setEthProp(bus, params, "DHCP6", false);
513 setEthProp(bus, params, "IPv6AcceptRA", false);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500514}
515
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700516/** @brief Creates a new VLAN on the specified interface
517 *
518 * @param[in] bus - The bus object used for lookups
519 * @param[in] params - The parameters for the channel
520 * @param[in] vlan - The id of the new vlan
521 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500522void createVLAN(sdbusplus::bus_t& bus, ChannelParams& params, uint16_t vlan)
Ratan Guptab8e99552017-07-27 07:07:48 +0530523{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700524 if (vlan == 0)
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530525 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700526 return;
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530527 }
528
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700529 auto req = bus.new_method_call(params.service.c_str(), PATH_ROOT,
530 INTF_VLAN_CREATE, "VLAN");
531 req.append(params.ifname, static_cast<uint32_t>(vlan));
532 auto reply = bus.call(req);
533 sdbusplus::message::object_path newPath;
534 reply.read(newPath);
535 params.logicalPath = std::move(newPath);
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530536}
537
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700538/** @brief Performs the necessary reconfiguration to change the VLAN
539 *
540 * @param[in] bus - The bus object used for lookups
541 * @param[in] params - The parameters for the channel
542 * @param[in] vlan - The new vlan id to use
543 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500544void reconfigureVLAN(sdbusplus::bus_t& bus, ChannelParams& params,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700545 uint16_t vlan)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500546{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700547 // Unfortunatetly we don't have built-in functions to migrate our interface
548 // customizations to new VLAN interfaces, or have some kind of decoupling.
549 // We therefore must retain all of our old information, setup the new VLAN
550 // configuration, then restore the old info.
Nan Li3d0df912016-10-18 19:51:41 +0800551
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700552 // Save info from the old logical interface
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700553 bool dhcp4 = getEthProp<bool>(bus, params, "DHCP4");
554 bool dhcp6 = getEthProp<bool>(bus, params, "DHCP6");
555 bool ra = getEthProp<bool>(bus, params, "IPv6AcceptRA");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700556 ObjectLookupCache ips(bus, params, INTF_IP);
557 auto ifaddr4 = findIfAddr<AF_INET>(bus, params, 0, originsV4, ips);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700558 std::vector<IfAddr<AF_INET6>> ifaddrs6;
559 for (uint8_t i = 0; i < MAX_IPV6_STATIC_ADDRESSES; ++i)
560 {
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500561 auto ifaddr6 = findIfAddr<AF_INET6>(bus, params, i, originsV6Static,
562 ips);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700563 if (!ifaddr6)
564 {
565 break;
566 }
567 ifaddrs6.push_back(std::move(*ifaddr6));
568 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700569 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
570 auto neighbor4 = findGatewayNeighbor<AF_INET>(bus, params, neighbors);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700571 auto neighbor6 = findGatewayNeighbor<AF_INET6>(bus, params, neighbors);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500572
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700573 deconfigureChannel(bus, params);
574 createVLAN(bus, params, vlan);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500575
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700576 // Re-establish the saved settings
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700577 setEthProp(bus, params, "DHCP4", dhcp4);
578 setEthProp(bus, params, "DHCP6", dhcp6);
579 setEthProp(bus, params, "IPv6AcceptRA", ra);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700580 if (ifaddr4)
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800581 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700582 createIfAddr<AF_INET>(bus, params, ifaddr4->address, ifaddr4->prefix);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800583 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700584 for (const auto& ifaddr6 : ifaddrs6)
585 {
586 createIfAddr<AF_INET6>(bus, params, ifaddr6.address, ifaddr6.prefix);
587 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700588 if (neighbor4)
589 {
590 createNeighbor<AF_INET>(bus, params, neighbor4->ip, neighbor4->mac);
591 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700592 if (neighbor6)
593 {
594 createNeighbor<AF_INET6>(bus, params, neighbor6->ip, neighbor6->mac);
595 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700596}
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800597
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700598/** @brief Turns a prefix into a netmask
599 *
600 * @param[in] prefix - The prefix length
601 * @return The netmask
602 */
603in_addr prefixToNetmask(uint8_t prefix)
604{
605 if (prefix > 32)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500606 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700607 log<level::ERR>("Invalid prefix", entry("PREFIX=%" PRIu8, prefix));
608 elog<InternalFailure>();
609 }
610 if (prefix == 0)
611 {
612 // Avoids 32-bit lshift by 32 UB
613 return {};
614 }
615 return {htobe32(~UINT32_C(0) << (32 - prefix))};
616}
617
618/** @brief Turns a a netmask into a prefix length
619 *
620 * @param[in] netmask - The netmask in byte form
621 * @return The prefix length
622 */
623uint8_t netmaskToPrefix(in_addr netmask)
624{
625 uint32_t x = be32toh(netmask.s_addr);
626 if ((~x & (~x + 1)) != 0)
627 {
628 char maskStr[INET_ADDRSTRLEN];
629 inet_ntop(AF_INET, &netmask, maskStr, sizeof(maskStr));
630 log<level::ERR>("Invalid netmask", entry("NETMASK=%s", maskStr));
631 elog<InternalFailure>();
632 }
Johnathan Mantey62c05dd2019-11-20 14:07:44 -0800633 return static_cast<bool>(x)
634 ? AddrFamily<AF_INET>::defaultPrefix - __builtin_ctz(x)
635 : 0;
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700636}
637
638// We need to store this value so it can be returned to the client
639// It is volatile so safe to store in daemon memory.
640static std::unordered_map<uint8_t, SetStatus> setStatus;
641
642// Until we have good support for fixed versions of IPMI tool
643// we need to return the VLAN id for disabled VLANs. The value is only
644// used for verification that a disable operation succeeded and will only
645// be sent if our system indicates that vlans are disabled.
646static std::unordered_map<uint8_t, uint16_t> lastDisabledVlan;
647
648/** @brief Gets the set status for the channel if it exists
649 * Otherise populates and returns the default value.
650 *
651 * @param[in] channel - The channel id corresponding to an ethernet interface
652 * @return A reference to the SetStatus for the channel
653 */
654SetStatus& getSetStatus(uint8_t channel)
655{
656 auto it = setStatus.find(channel);
657 if (it != setStatus.end())
658 {
659 return it->second;
660 }
661 return setStatus[channel] = SetStatus::Complete;
662}
663
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700664/** @brief Unpacks the trivially copyable type from the message */
665template <typename T>
666static T unpackT(message::Payload& req)
667{
668 std::array<uint8_t, sizeof(T)> bytes;
669 if (req.unpack(bytes) != 0)
670 {
671 throw ccReqDataLenInvalid;
672 }
673 return stdplus::raw::copyFrom<T>(bytes);
674}
675
676/** @brief Ensure the message is fully unpacked */
677static void unpackFinal(message::Payload& req)
678{
679 if (!req.fullyUnpacked())
680 {
681 throw ccReqDataTruncated;
682 }
683}
684
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700685/**
686 * Define placeholder command handlers for the OEM Extension bytes for the Set
687 * LAN Configuration Parameters and Get LAN Configuration Parameters
688 * commands. Using "weak" linking allows the placeholder setLanOem/getLanOem
689 * functions below to be overridden.
690 * To create handlers for your own proprietary command set:
691 * Create/modify a phosphor-ipmi-host Bitbake append file within your Yocto
692 * recipe
693 * Create C++ file(s) that define IPMI handler functions matching the
694 * function names below (i.e. setLanOem). The default name for the
695 * transport IPMI commands is transporthandler_oem.cpp.
696 * Add:
Johnathan Manteyefe26682022-08-11 14:30:45 -0700697 * EXTRA_OEMESON:append = "-Dtransport-oem=enabled"
698 * Create a do_configure:prepend()/do_install:append() method in your
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700699 * bbappend file to copy the file to the build directory.
700 * Add:
701 * PROJECT_SRC_DIR := "${THISDIR}/${PN}"
702 * # Copy the "strong" functions into the working directory, overriding the
703 * # placeholder functions.
Johnathan Manteyefe26682022-08-11 14:30:45 -0700704 * do_configure:prepend(){
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700705 * cp -f ${PROJECT_SRC_DIR}/transporthandler_oem.cpp ${S}
706 * }
707 *
708 * # Clean up after complilation has completed
Johnathan Manteyefe26682022-08-11 14:30:45 -0700709 * do_install:append(){
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700710 * rm -f ${S}/transporthandler_oem.cpp
711 * }
712 *
713 */
714
715/**
716 * Define the placeholder OEM commands as having weak linkage. Create
717 * setLanOem, and getLanOem functions in the transporthandler_oem.cpp
718 * file. The functions defined there must not have the "weak" attribute
719 * applied to them.
720 */
721RspType<> setLanOem(uint8_t channel, uint8_t parameter, message::Payload& req)
722 __attribute__((weak));
723RspType<message::Payload> getLanOem(uint8_t channel, uint8_t parameter,
724 uint8_t set, uint8_t block)
725 __attribute__((weak));
726
Willy Tu11d68892022-01-20 10:37:34 -0800727RspType<> setLanOem(uint8_t, uint8_t, message::Payload& req)
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700728{
729 req.trailingOk = true;
730 return response(ccParamNotSupported);
731}
732
Willy Tu11d68892022-01-20 10:37:34 -0800733RspType<message::Payload> getLanOem(uint8_t, uint8_t, uint8_t, uint8_t)
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700734{
735 return response(ccParamNotSupported);
736}
Rajashekar Gade Reddy0b993fd2019-12-24 16:37:15 +0530737/**
738 * @brief is MAC address valid.
739 *
740 * This function checks whether the MAC address is valid or not.
741 *
742 * @param[in] mac - MAC address.
743 * @return true if MAC address is valid else retun false.
744 **/
745bool isValidMACAddress(const ether_addr& mac)
746{
747 // check if mac address is empty
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700748 if (stdplus::raw::equal(mac, ether_addr{}))
Rajashekar Gade Reddy0b993fd2019-12-24 16:37:15 +0530749 {
750 return false;
751 }
752 // we accept only unicast MAC addresses and same thing has been checked in
753 // phosphor-network layer. If the least significant bit of the first octet
754 // is set to 1, it is multicast MAC else it is unicast MAC address.
755 if (mac.ether_addr_octet[0] & 1)
756 {
757 return false;
758 }
759 return true;
760}
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700761
Jian Zhangcf19d142023-07-31 10:22:53 +0800762/**
763 * @brief is a valid LAN channel.
764 *
765 * This function checks whether the input channel is a valid LAN channel or not.
766 *
767 * @param[in] channel: the channel number.
768 * @return nullopt if the channel is invalid, false if the channel is not a LAN
769 * channel, true if the channel is a LAN channel.
770 **/
771std::optional<bool> isLanChannel(uint8_t channel)
772{
773 ChannelInfo chInfo;
774 auto cc = getChannelInfo(channel, chInfo);
775 if (cc != ccSuccess)
776 {
777 return std::nullopt;
778 }
779
780 return chInfo.mediumType ==
781 static_cast<uint8_t>(EChannelMediumType::lan8032);
782}
783
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700784RspType<> setLanInt(Context::ptr ctx, uint4_t channelBits, uint4_t reserved1,
785 uint8_t parameter, message::Payload& req)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700786{
vijayabharathix shettycc769252020-02-27 17:52:20 +0000787 const uint8_t channel = convertCurrentChannelNum(
788 static_cast<uint8_t>(channelBits), ctx->channel);
789 if (reserved1 || !isValidChannel(channel))
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700790 {
vijayabharathix shettycc769252020-02-27 17:52:20 +0000791 log<level::ERR>("Set Lan - Invalid field in request");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700792 req.trailingOk = true;
793 return responseInvalidFieldRequest();
794 }
795
Jian Zhangcf19d142023-07-31 10:22:53 +0800796 if (!isLanChannel(channel).value_or(false))
797 {
798 log<level::ERR>("Set Lan - Not a LAN channel");
799 return responseInvalidFieldRequest();
800 }
801
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700802 switch (static_cast<LanParam>(parameter))
803 {
804 case LanParam::SetStatus:
805 {
806 uint2_t flag;
807 uint6_t rsvd;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700808 if (req.unpack(flag, rsvd) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700809 {
810 return responseReqDataLenInvalid();
811 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700812 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800813 if (rsvd)
814 {
815 return responseInvalidFieldRequest();
816 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700817 auto status = static_cast<SetStatus>(static_cast<uint8_t>(flag));
818 switch (status)
819 {
820 case SetStatus::Complete:
821 {
822 getSetStatus(channel) = status;
823 return responseSuccess();
824 }
825 case SetStatus::InProgress:
826 {
827 auto& storedStatus = getSetStatus(channel);
828 if (storedStatus == SetStatus::InProgress)
829 {
830 return response(ccParamSetLocked);
831 }
832 storedStatus = status;
833 return responseSuccess();
834 }
835 case SetStatus::Commit:
836 if (getSetStatus(channel) != SetStatus::InProgress)
837 {
838 return responseInvalidFieldRequest();
839 }
840 return responseSuccess();
841 }
842 return response(ccParamNotSupported);
843 }
844 case LanParam::AuthSupport:
845 {
846 req.trailingOk = true;
847 return response(ccParamReadOnly);
848 }
849 case LanParam::AuthEnables:
850 {
851 req.trailingOk = true;
Johnathan Mantey76ce9c72019-11-14 14:41:46 -0800852 return response(ccParamReadOnly);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700853 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800854 case LanParam::IP:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600855 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700856 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800857 {
858 return responseCommandNotAvailable();
859 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700860 auto ip = unpackT<in_addr>(req);
861 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700862 channelCall<reconfigureIfAddr4>(channel, ip, std::nullopt);
863 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +0530864 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700865 case LanParam::IPSrc:
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530866 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700867 uint4_t flag;
868 uint4_t rsvd;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700869 if (req.unpack(flag, rsvd) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700870 {
871 return responseReqDataLenInvalid();
872 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700873 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -0800874 if (rsvd)
875 {
876 return responseInvalidFieldRequest();
877 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700878 switch (static_cast<IPSrc>(static_cast<uint8_t>(flag)))
879 {
880 case IPSrc::DHCP:
Johnathan Mantey65265362019-11-14 11:24:19 -0800881 // The IPSrc IPMI command is only for IPv4
882 // management. Modifying IPv6 state is done using
883 // a completely different Set LAN Configuration
884 // subcommand.
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700885 channelCall<setEthProp<bool>>(channel, "DHCP4", true);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700886 return responseSuccess();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700887 case IPSrc::Unspecified:
888 case IPSrc::Static:
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700889 channelCall<setEthProp<bool>>(channel, "DHCP4", false);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700890 return responseSuccess();
Rajashekar Gade Reddy8a860ea2019-12-24 11:31:19 +0530891 case IPSrc::BIOS:
892 case IPSrc::BMC:
Rajashekar Gade Reddy8a860ea2019-12-24 11:31:19 +0530893 return responseInvalidFieldRequest();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700894 }
895 return response(ccParamNotSupported);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530896 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800897 case LanParam::MAC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530898 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700899 auto mac = unpackT<ether_addr>(req);
900 unpackFinal(req);
Rajashekar Gade Reddy0b993fd2019-12-24 16:37:15 +0530901 if (!isValidMACAddress(mac))
902 {
903 return responseInvalidFieldRequest();
904 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700905 channelCall<setMACProperty>(channel, mac);
906 return responseSuccess();
Ratan Gupta533d03b2017-07-30 10:39:22 +0530907 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700908 case LanParam::SubnetMask:
Ratan Guptab8e99552017-07-27 07:07:48 +0530909 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700910 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800911 {
912 return responseCommandNotAvailable();
913 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700914 auto netmask = unpackT<in_addr>(req);
915 unpackFinal(req);
Jiaqing Zhao6d4a44e2022-01-24 15:04:00 +0800916 uint8_t prefix = netmaskToPrefix(netmask);
917 if (prefix < MIN_IPV4_PREFIX_LENGTH)
918 {
919 return responseInvalidFieldRequest();
920 }
921 channelCall<reconfigureIfAddr4>(channel, std::nullopt, prefix);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700922 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +0530923 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700924 case LanParam::Gateway1:
Ratan Guptab8e99552017-07-27 07:07:48 +0530925 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700926 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800927 {
928 return responseCommandNotAvailable();
929 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700930 auto gateway = unpackT<in_addr>(req);
931 unpackFinal(req);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700932 channelCall<setGatewayProperty<AF_INET>>(channel, gateway);
933 return responseSuccess();
934 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700935 case LanParam::Gateway1MAC:
936 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700937 auto gatewayMAC = unpackT<ether_addr>(req);
938 unpackFinal(req);
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700939 channelCall<reconfigureGatewayMAC<AF_INET>>(channel, gatewayMAC);
940 return responseSuccess();
941 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700942 case LanParam::VLANId:
943 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700944 uint12_t vlanData;
945 uint3_t rsvd;
946 bool vlanEnable;
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530947
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700948 if (req.unpack(vlanData, rsvd, vlanEnable) != 0)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700949 {
950 return responseReqDataLenInvalid();
951 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700952 unpackFinal(req);
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530953
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700954 if (rsvd)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700955 {
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530956 return responseInvalidFieldRequest();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700957 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530958
959 uint16_t vlan = static_cast<uint16_t>(vlanData);
960
961 if (!vlanEnable)
962 {
963 lastDisabledVlan[channel] = vlan;
964 vlan = 0;
965 }
jayaprakash Mutyala84c49dc2020-05-18 23:12:13 +0000966 else if (vlan == 0 || vlan == VLAN_VALUE_MASK)
967 {
968 return responseInvalidFieldRequest();
969 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530970
jayaprakash Mutyala84c49dc2020-05-18 23:12:13 +0000971 channelCall<reconfigureVLAN>(channel, vlan);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700972 return responseSuccess();
973 }
974 case LanParam::CiphersuiteSupport:
975 case LanParam::CiphersuiteEntries:
William A. Kennington III16064aa2019-04-13 17:44:53 -0700976 case LanParam::IPFamilySupport:
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700977 {
978 req.trailingOk = true;
979 return response(ccParamReadOnly);
Ratan Guptab8e99552017-07-27 07:07:48 +0530980 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700981 case LanParam::IPFamilyEnables:
982 {
983 uint8_t enables;
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700984 if (req.unpack(enables) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -0700985 {
986 return responseReqDataLenInvalid();
987 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -0700988 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700989 switch (static_cast<IPFamilyEnables>(enables))
990 {
991 case IPFamilyEnables::DualStack:
992 return responseSuccess();
993 case IPFamilyEnables::IPv4Only:
994 case IPFamilyEnables::IPv6Only:
995 return response(ccParamNotSupported);
996 }
997 return response(ccParamNotSupported);
998 }
999 case LanParam::IPv6Status:
1000 {
1001 req.trailingOk = true;
1002 return response(ccParamReadOnly);
1003 }
1004 case LanParam::IPv6StaticAddresses:
1005 {
1006 uint8_t set;
1007 uint7_t rsvd;
1008 bool enabled;
William A. Kennington III16064aa2019-04-13 17:44:53 -07001009 uint8_t prefix;
1010 uint8_t status;
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001011 if (req.unpack(set, rsvd, enabled) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -07001012 {
1013 return responseReqDataLenInvalid();
1014 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001015 auto ip = unpackT<in6_addr>(req);
1016 if (req.unpack(prefix, status) != 0)
1017 {
1018 return responseReqDataLenInvalid();
1019 }
1020 unpackFinal(req);
Johnathan Mantey4a156852019-12-11 13:47:43 -08001021 if (rsvd)
1022 {
1023 return responseInvalidFieldRequest();
1024 }
William A. Kennington III16064aa2019-04-13 17:44:53 -07001025 if (enabled)
1026 {
Jiaqing Zhao6d4a44e2022-01-24 15:04:00 +08001027 if (prefix < MIN_IPV6_PREFIX_LENGTH ||
1028 prefix > MAX_IPV6_PREFIX_LENGTH)
1029 {
1030 return responseParmOutOfRange();
1031 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001032 channelCall<reconfigureIfAddr6>(channel, set, ip, prefix);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001033 }
1034 else
1035 {
1036 channelCall<deconfigureIfAddr6>(channel, set);
1037 }
1038 return responseSuccess();
1039 }
1040 case LanParam::IPv6DynamicAddresses:
1041 {
1042 req.trailingOk = true;
1043 return response(ccParamReadOnly);
1044 }
1045 case LanParam::IPv6RouterControl:
1046 {
1047 std::bitset<8> control;
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001048 constexpr uint8_t reservedRACCBits = 0xfc;
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001049 if (req.unpack(control) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -07001050 {
1051 return responseReqDataLenInvalid();
1052 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001053 unpackFinal(req);
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001054 if (std::bitset<8> expected(control &
1055 std::bitset<8>(reservedRACCBits));
1056 expected.any())
William A. Kennington III16064aa2019-04-13 17:44:53 -07001057 {
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001058 return response(ccParamNotSupported);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001059 }
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001060
1061 bool enableRA = control[IPv6RouterControlFlag::Dynamic];
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001062 channelCall<setEthProp<bool>>(channel, "IPv6AcceptRA", enableRA);
1063 channelCall<setEthProp<bool>>(channel, "DHCP6", enableRA);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001064 return responseSuccess();
1065 }
1066 case LanParam::IPv6StaticRouter1IP:
1067 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001068 auto gateway = unpackT<in6_addr>(req);
1069 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001070 channelCall<setGatewayProperty<AF_INET6>>(channel, gateway);
1071 return responseSuccess();
1072 }
1073 case LanParam::IPv6StaticRouter1MAC:
1074 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001075 auto mac = unpackT<ether_addr>(req);
1076 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001077 channelCall<reconfigureGatewayMAC<AF_INET6>>(channel, mac);
1078 return responseSuccess();
1079 }
1080 case LanParam::IPv6StaticRouter1PrefixLength:
1081 {
1082 uint8_t prefix;
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001083 if (req.unpack(prefix) != 0)
William A. Kennington III16064aa2019-04-13 17:44:53 -07001084 {
1085 return responseReqDataLenInvalid();
1086 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001087 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001088 if (prefix != 0)
1089 {
1090 return responseInvalidFieldRequest();
1091 }
1092 return responseSuccess();
1093 }
1094 case LanParam::IPv6StaticRouter1PrefixValue:
1095 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001096 unpackT<in6_addr>(req);
1097 unpackFinal(req);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001098 // Accept any prefix value since our prefix length has to be 0
1099 return responseSuccess();
1100 }
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001101 case LanParam::cipherSuitePrivilegeLevels:
1102 {
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001103 uint8_t rsvd;
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001104 std::array<uint4_t, ipmi::maxCSRecords> cipherSuitePrivs;
1105
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001106 if (req.unpack(rsvd, cipherSuitePrivs))
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001107 {
1108 return responseReqDataLenInvalid();
1109 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001110 unpackFinal(req);
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001111
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001112 if (rsvd)
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001113 {
1114 return responseInvalidFieldRequest();
1115 }
1116
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -05001117 uint8_t resp = getCipherConfigObject(csPrivFileName,
1118 csPrivDefaultFileName)
1119 .setCSPrivilegeLevels(channel, cipherSuitePrivs);
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001120 if (!resp)
1121 {
1122 return responseSuccess();
1123 }
1124 else
1125 {
1126 req.trailingOk = true;
1127 return response(resp);
1128 }
1129 }
Ratan Guptab8e99552017-07-27 07:07:48 +05301130 }
vishwa1eaea4f2016-02-26 11:57:40 -06001131
Johnathan Manteyb87034e2019-09-16 10:50:50 -07001132 if ((parameter >= oemCmdStart) && (parameter <= oemCmdEnd))
1133 {
1134 return setLanOem(channel, parameter, req);
1135 }
1136
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001137 req.trailingOk = true;
1138 return response(ccParamNotSupported);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001139}
1140
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001141RspType<> setLan(Context::ptr ctx, uint4_t channelBits, uint4_t reserved1,
1142 uint8_t parameter, message::Payload& req)
1143{
1144 try
1145 {
1146 return setLanInt(ctx, channelBits, reserved1, parameter, req);
1147 }
1148 catch (ipmi::Cc cc)
1149 {
1150 return response(cc);
1151 }
1152 catch (const sdbusplus::exception_t& e)
1153 {
1154 if (std::string_view{InvalidArgument::errName} == e.name())
1155 {
1156 return responseInvalidFieldRequest();
1157 }
1158 throw;
1159 }
1160}
1161
vijayabharathix shettycc769252020-02-27 17:52:20 +00001162RspType<message::Payload> getLan(Context::ptr ctx, uint4_t channelBits,
1163 uint3_t reserved, bool revOnly,
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001164 uint8_t parameter, uint8_t set, uint8_t block)
Ratan Guptab8e99552017-07-27 07:07:48 +05301165{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001166 message::Payload ret;
1167 constexpr uint8_t current_revision = 0x11;
1168 ret.pack(current_revision);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001169
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001170 if (revOnly)
Suryakanth Sekare4054402019-08-08 15:16:52 +05301171 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001172 return responseSuccess(std::move(ret));
Suryakanth Sekare4054402019-08-08 15:16:52 +05301173 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001174
vijayabharathix shettycc769252020-02-27 17:52:20 +00001175 const uint8_t channel = convertCurrentChannelNum(
1176 static_cast<uint8_t>(channelBits), ctx->channel);
1177 if (reserved || !isValidChannel(channel))
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001178 {
vijayabharathix shettycc769252020-02-27 17:52:20 +00001179 log<level::ERR>("Get Lan - Invalid field in request");
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001180 return responseInvalidFieldRequest();
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001181 }
1182
Jian Zhangcf19d142023-07-31 10:22:53 +08001183 if (!isLanChannel(channel).value_or(false))
1184 {
1185 log<level::ERR>("Set Lan - Not a LAN channel");
1186 return responseInvalidFieldRequest();
1187 }
1188
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001189 static std::vector<uint8_t> cipherList;
1190 static bool listInit = false;
1191 if (!listInit)
1192 {
1193 try
1194 {
1195 cipherList = cipher::getCipherList();
1196 listInit = true;
1197 }
1198 catch (const std::exception& e)
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -05001199 {}
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001200 }
1201
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001202 switch (static_cast<LanParam>(parameter))
Tom Josepha30c8d32018-03-22 02:15:03 +05301203 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001204 case LanParam::SetStatus:
Tom Josepha30c8d32018-03-22 02:15:03 +05301205 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001206 SetStatus status;
1207 try
1208 {
1209 status = setStatus.at(channel);
1210 }
1211 catch (const std::out_of_range&)
1212 {
1213 status = SetStatus::Complete;
1214 }
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001215 ret.pack(types::enum_cast<uint2_t>(status), uint6_t{});
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001216 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301217 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001218 case LanParam::AuthSupport:
Tom Josepha30c8d32018-03-22 02:15:03 +05301219 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001220 std::bitset<6> support;
1221 ret.pack(support, uint2_t{});
1222 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301223 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001224 case LanParam::AuthEnables:
vishwa1eaea4f2016-02-26 11:57:40 -06001225 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001226 std::bitset<6> enables;
1227 ret.pack(enables, uint2_t{}); // Callback
1228 ret.pack(enables, uint2_t{}); // User
1229 ret.pack(enables, uint2_t{}); // Operator
1230 ret.pack(enables, uint2_t{}); // Admin
1231 ret.pack(enables, uint2_t{}); // OEM
1232 return responseSuccess(std::move(ret));
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001233 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001234 case LanParam::IP:
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001235 {
1236 auto ifaddr = channelCall<getIfAddr4>(channel);
1237 in_addr addr{};
1238 if (ifaddr)
1239 {
1240 addr = ifaddr->address;
1241 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001242 ret.pack(stdplus::raw::asView<char>(addr));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001243 return responseSuccess(std::move(ret));
1244 }
1245 case LanParam::IPSrc:
1246 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001247 auto src = channelCall<getEthProp<bool>>(channel, "DHCP4")
1248 ? IPSrc::DHCP
1249 : IPSrc::Static;
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001250 ret.pack(types::enum_cast<uint4_t>(src), uint4_t{});
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001251 return responseSuccess(std::move(ret));
1252 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001253 case LanParam::MAC:
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001254 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001255 ether_addr mac = channelCall<getMACProperty>(channel);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001256 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001257 return responseSuccess(std::move(ret));
1258 }
1259 case LanParam::SubnetMask:
1260 {
1261 auto ifaddr = channelCall<getIfAddr4>(channel);
1262 uint8_t prefix = AddrFamily<AF_INET>::defaultPrefix;
1263 if (ifaddr)
Ratan Guptab8e99552017-07-27 07:07:48 +05301264 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001265 prefix = ifaddr->prefix;
1266 }
1267 in_addr netmask = prefixToNetmask(prefix);
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001268 ret.pack(stdplus::raw::asView<char>(netmask));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001269 return responseSuccess(std::move(ret));
1270 }
1271 case LanParam::Gateway1:
1272 {
1273 auto gateway =
1274 channelCall<getGatewayProperty<AF_INET>>(channel).value_or(
1275 in_addr{});
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001276 ret.pack(stdplus::raw::asView<char>(gateway));
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001277 return responseSuccess(std::move(ret));
1278 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001279 case LanParam::Gateway1MAC:
1280 {
1281 ether_addr mac{};
1282 auto neighbor = channelCall<getGatewayNeighbor<AF_INET>>(channel);
1283 if (neighbor)
1284 {
1285 mac = neighbor->mac;
1286 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001287 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington III4bbc3db2019-04-15 00:02:10 -07001288 return responseSuccess(std::move(ret));
1289 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001290 case LanParam::VLANId:
1291 {
1292 uint16_t vlan = channelCall<getVLANProperty>(channel);
1293 if (vlan != 0)
1294 {
1295 vlan |= VLAN_ENABLE_FLAG;
Ratan Guptab8e99552017-07-27 07:07:48 +05301296 }
1297 else
1298 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001299 vlan = lastDisabledVlan[channel];
Ratan Guptab8e99552017-07-27 07:07:48 +05301300 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001301 ret.pack(vlan);
1302 return responseSuccess(std::move(ret));
Adriana Kobylak342df102016-02-10 13:48:16 -06001303 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001304 case LanParam::CiphersuiteSupport:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001305 {
srikanta mondal1d8579c2020-04-15 17:13:25 +00001306 if (getChannelSessionSupport(channel) ==
1307 EChannelSessSupported::none)
1308 {
1309 return responseInvalidFieldRequest();
1310 }
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001311 if (!listInit)
1312 {
1313 return responseUnspecifiedError();
1314 }
1315 ret.pack(static_cast<uint8_t>(cipherList.size() - 1));
1316 return responseSuccess(std::move(ret));
1317 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001318 case LanParam::CiphersuiteEntries:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001319 {
srikanta mondal1d8579c2020-04-15 17:13:25 +00001320 if (getChannelSessionSupport(channel) ==
1321 EChannelSessSupported::none)
1322 {
1323 return responseInvalidFieldRequest();
1324 }
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001325 if (!listInit)
1326 {
1327 return responseUnspecifiedError();
1328 }
1329 ret.pack(cipherList);
1330 return responseSuccess(std::move(ret));
1331 }
William A. Kennington III16064aa2019-04-13 17:44:53 -07001332 case LanParam::IPFamilySupport:
1333 {
1334 std::bitset<8> support;
1335 support[IPFamilySupportFlag::IPv6Only] = 0;
1336 support[IPFamilySupportFlag::DualStack] = 1;
1337 support[IPFamilySupportFlag::IPv6Alerts] = 1;
1338 ret.pack(support);
1339 return responseSuccess(std::move(ret));
1340 }
1341 case LanParam::IPFamilyEnables:
1342 {
1343 ret.pack(static_cast<uint8_t>(IPFamilyEnables::DualStack));
1344 return responseSuccess(std::move(ret));
1345 }
1346 case LanParam::IPv6Status:
1347 {
1348 ret.pack(MAX_IPV6_STATIC_ADDRESSES);
1349 ret.pack(MAX_IPV6_DYNAMIC_ADDRESSES);
1350 std::bitset<8> support;
1351 support[IPv6StatusFlag::DHCP] = 1;
1352 support[IPv6StatusFlag::SLAAC] = 1;
1353 ret.pack(support);
1354 return responseSuccess(std::move(ret));
1355 }
1356 case LanParam::IPv6StaticAddresses:
1357 {
1358 if (set >= MAX_IPV6_STATIC_ADDRESSES)
1359 {
1360 return responseParmOutOfRange();
1361 }
1362 getLanIPv6Address(ret, channel, set, originsV6Static);
1363 return responseSuccess(std::move(ret));
1364 }
1365 case LanParam::IPv6DynamicAddresses:
1366 {
1367 if (set >= MAX_IPV6_DYNAMIC_ADDRESSES)
1368 {
1369 return responseParmOutOfRange();
1370 }
1371 getLanIPv6Address(ret, channel, set, originsV6Dynamic);
1372 return responseSuccess(std::move(ret));
1373 }
1374 case LanParam::IPv6RouterControl:
1375 {
1376 std::bitset<8> control;
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001377 control[IPv6RouterControlFlag::Dynamic] =
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001378 channelCall<getEthProp<bool>>(channel, "IPv6AcceptRA");
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001379 control[IPv6RouterControlFlag::Static] = 1;
William A. Kennington III16064aa2019-04-13 17:44:53 -07001380 ret.pack(control);
1381 return responseSuccess(std::move(ret));
1382 }
1383 case LanParam::IPv6StaticRouter1IP:
1384 {
1385 in6_addr gateway{};
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001386 if (!channelCall<getEthProp<bool>>(channel, "IPv6AcceptRA"))
William A. Kennington III16064aa2019-04-13 17:44:53 -07001387 {
1388 gateway =
1389 channelCall<getGatewayProperty<AF_INET6>>(channel).value_or(
1390 in6_addr{});
1391 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001392 ret.pack(stdplus::raw::asView<char>(gateway));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001393 return responseSuccess(std::move(ret));
1394 }
1395 case LanParam::IPv6StaticRouter1MAC:
1396 {
1397 ether_addr mac{};
1398 auto neighbor = channelCall<getGatewayNeighbor<AF_INET6>>(channel);
1399 if (neighbor)
1400 {
1401 mac = neighbor->mac;
1402 }
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001403 ret.pack(stdplus::raw::asView<char>(mac));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001404 return responseSuccess(std::move(ret));
1405 }
1406 case LanParam::IPv6StaticRouter1PrefixLength:
1407 {
1408 ret.pack(UINT8_C(0));
1409 return responseSuccess(std::move(ret));
1410 }
1411 case LanParam::IPv6StaticRouter1PrefixValue:
1412 {
1413 in6_addr prefix{};
William A. Kennington III7a3831b2023-06-21 01:10:49 -07001414 ret.pack(stdplus::raw::asView<char>(prefix));
William A. Kennington III16064aa2019-04-13 17:44:53 -07001415 return responseSuccess(std::move(ret));
1416 }
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001417 case LanParam::cipherSuitePrivilegeLevels:
1418 {
1419 std::array<uint4_t, ipmi::maxCSRecords> csPrivilegeLevels;
1420
1421 uint8_t resp =
1422 getCipherConfigObject(csPrivFileName, csPrivDefaultFileName)
1423 .getCSPrivilegeLevels(channel, csPrivilegeLevels);
1424 if (!resp)
1425 {
1426 constexpr uint8_t reserved1 = 0x00;
1427 ret.pack(reserved1, csPrivilegeLevels);
1428 return responseSuccess(std::move(ret));
1429 }
1430 else
1431 {
1432 return response(resp);
1433 }
1434 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001435 }
1436
Johnathan Manteyb87034e2019-09-16 10:50:50 -07001437 if ((parameter >= oemCmdStart) && (parameter <= oemCmdEnd))
1438 {
1439 return getLanOem(channel, parameter, set, block);
1440 }
1441
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001442 return response(ccParamNotSupported);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001443}
1444
Jian Zhang23f44652022-03-17 17:13:10 +08001445constexpr const char* solInterface = "xyz.openbmc_project.Ipmi.SOL";
1446constexpr const char* solPath = "/xyz/openbmc_project/ipmi/sol/";
1447constexpr const uint16_t solDefaultPort = 623;
1448
1449RspType<> setSolConfParams(Context::ptr ctx, uint4_t channelBits,
Willy Tu11d68892022-01-20 10:37:34 -08001450 uint4_t /*reserved*/, uint8_t parameter,
Jian Zhang23f44652022-03-17 17:13:10 +08001451 message::Payload& req)
1452{
1453 const uint8_t channel = convertCurrentChannelNum(
1454 static_cast<uint8_t>(channelBits), ctx->channel);
1455
1456 if (!isValidChannel(channel))
1457 {
1458 log<level::ERR>("Set Sol Config - Invalid channel in request");
1459 return responseInvalidFieldRequest();
1460 }
1461
1462 std::string solService{};
1463 std::string solPathWitheEthName = solPath + ipmi::getChannelName(channel);
1464
1465 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1466 {
1467 log<level::ERR>("Set Sol Config - Invalid solInterface",
1468 entry("SERVICE=%s", solService.c_str()),
1469 entry("OBJPATH=%s", solPathWitheEthName.c_str()),
1470 entry("INTERFACE=%s", solInterface));
1471 return responseInvalidFieldRequest();
1472 }
1473
1474 switch (static_cast<SolConfParam>(parameter))
1475 {
1476 case SolConfParam::Progress:
1477 {
1478 uint8_t progress;
1479 if (req.unpack(progress) != 0 || !req.fullyUnpacked())
1480 {
1481 return responseReqDataLenInvalid();
1482 }
1483
1484 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1485 solInterface, "Progress", progress))
1486 {
1487 return responseUnspecifiedError();
1488 }
1489 break;
1490 }
1491 case SolConfParam::Enable:
1492 {
1493 bool enable;
1494 uint7_t reserved2;
1495
1496 if (req.unpack(enable, reserved2) != 0 || !req.fullyUnpacked())
1497 {
1498 return responseReqDataLenInvalid();
1499 }
1500
1501 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1502 solInterface, "Enable", enable))
1503 {
1504 return responseUnspecifiedError();
1505 }
1506 break;
1507 }
1508 case SolConfParam::Authentication:
1509 {
1510 uint4_t privilegeBits{};
1511 uint2_t reserved2{};
1512 bool forceAuth = false;
1513 bool forceEncrypt = false;
1514
1515 if (req.unpack(privilegeBits, reserved2, forceAuth, forceEncrypt) !=
1516 0 ||
1517 !req.fullyUnpacked())
1518 {
1519 return responseReqDataLenInvalid();
1520 }
1521
1522 uint8_t privilege = static_cast<uint8_t>(privilegeBits);
Jonathan Domana48bf772023-05-26 17:54:57 -07001523 if (privilege < static_cast<uint8_t>(Privilege::User) ||
Jian Zhang23f44652022-03-17 17:13:10 +08001524 privilege > static_cast<uint8_t>(Privilege::Oem))
1525 {
1526 return ipmi::responseInvalidFieldRequest();
1527 }
1528
1529 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1530 solInterface, "Privilege", privilege))
1531 {
1532 return responseUnspecifiedError();
1533 }
1534
1535 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1536 solInterface, "ForceEncryption",
1537 forceEncrypt))
1538 {
1539 return responseUnspecifiedError();
1540 }
1541
1542 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1543 solInterface, "ForceAuthentication",
1544 forceAuth))
1545 {
1546 return responseUnspecifiedError();
1547 }
1548 break;
1549 }
1550 case SolConfParam::Accumulate:
1551 {
1552 uint8_t interval;
1553 uint8_t threshold;
1554 if (req.unpack(interval, threshold) != 0 || !req.fullyUnpacked())
1555 {
1556 return responseReqDataLenInvalid();
1557 }
1558
1559 if (threshold == 0)
1560 {
1561 return responseInvalidFieldRequest();
1562 }
1563
1564 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1565 solInterface, "AccumulateIntervalMS",
1566 interval))
1567 {
1568 return responseUnspecifiedError();
1569 }
1570
1571 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1572 solInterface, "Threshold", threshold))
1573 {
1574 return responseUnspecifiedError();
1575 }
1576 break;
1577 }
1578 case SolConfParam::Retry:
1579 {
1580 uint3_t countBits;
1581 uint5_t reserved2;
1582 uint8_t interval;
1583
1584 if (req.unpack(countBits, reserved2, interval) != 0 ||
1585 !req.fullyUnpacked())
1586 {
1587 return responseReqDataLenInvalid();
1588 }
1589
1590 uint8_t count = static_cast<uint8_t>(countBits);
1591 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1592 solInterface, "RetryCount", count))
1593 {
1594 return responseUnspecifiedError();
1595 }
1596
1597 if (ipmi::setDbusProperty(ctx, solService, solPathWitheEthName,
1598 solInterface, "RetryIntervalMS",
1599 interval))
1600 {
1601 return responseUnspecifiedError();
1602 }
1603 break;
1604 }
1605 case SolConfParam::Port:
1606 {
1607 return response(ipmiCCWriteReadParameter);
1608 }
1609 case SolConfParam::NonVbitrate:
1610 case SolConfParam::Vbitrate:
1611 case SolConfParam::Channel:
1612 default:
1613 return response(ipmiCCParamNotSupported);
1614 }
1615 return responseSuccess();
1616}
1617
1618RspType<message::Payload> getSolConfParams(Context::ptr ctx,
1619 uint4_t channelBits,
Willy Tu11d68892022-01-20 10:37:34 -08001620 uint3_t /*reserved*/, bool revOnly,
1621 uint8_t parameter, uint8_t /*set*/,
1622 uint8_t /*block*/)
Jian Zhang23f44652022-03-17 17:13:10 +08001623{
1624 message::Payload ret;
1625 constexpr uint8_t current_revision = 0x11;
1626 ret.pack(current_revision);
1627 if (revOnly)
1628 {
1629 return responseSuccess(std::move(ret));
1630 }
1631
1632 const uint8_t channel = convertCurrentChannelNum(
1633 static_cast<uint8_t>(channelBits), ctx->channel);
1634
1635 if (!isValidChannel(channel))
1636 {
1637 log<level::ERR>("Get Sol Config - Invalid channel in request");
1638 return responseInvalidFieldRequest();
1639 }
1640
1641 std::string solService{};
1642 std::string solPathWitheEthName = solPath + ipmi::getChannelName(channel);
1643
1644 if (ipmi::getService(ctx, solInterface, solPathWitheEthName, solService))
1645 {
1646 log<level::ERR>("Set Sol Config - Invalid solInterface",
1647 entry("SERVICE=%s", solService.c_str()),
1648 entry("OBJPATH=%s", solPathWitheEthName.c_str()),
1649 entry("INTERFACE=%s", solInterface));
1650 return responseInvalidFieldRequest();
1651 }
1652
1653 switch (static_cast<SolConfParam>(parameter))
1654 {
1655 case SolConfParam::Progress:
1656 {
1657 uint8_t progress;
1658 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1659 solInterface, "Progress", progress))
1660 {
1661 return responseUnspecifiedError();
1662 }
1663 ret.pack(progress);
1664 return responseSuccess(std::move(ret));
1665 }
1666 case SolConfParam::Enable:
1667 {
1668 bool enable{};
1669 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1670 solInterface, "Enable", enable))
1671 {
1672 return responseUnspecifiedError();
1673 }
1674 ret.pack(enable, uint7_t{});
1675 return responseSuccess(std::move(ret));
1676 }
1677 case SolConfParam::Authentication:
1678 {
1679 // 4bits, cast when pack
1680 uint8_t privilege;
1681 bool forceAuth = false;
1682 bool forceEncrypt = false;
1683
1684 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1685 solInterface, "Privilege", privilege))
1686 {
1687 return responseUnspecifiedError();
1688 }
1689
1690 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1691 solInterface, "ForceAuthentication",
1692 forceAuth))
1693 {
1694 return responseUnspecifiedError();
1695 }
1696
1697 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1698 solInterface, "ForceEncryption",
1699 forceEncrypt))
1700 {
1701 return responseUnspecifiedError();
1702 }
1703 ret.pack(uint4_t{privilege}, uint2_t{}, forceAuth, forceEncrypt);
1704 return responseSuccess(std::move(ret));
1705 }
1706 case SolConfParam::Accumulate:
1707 {
1708 uint8_t interval{}, threshold{};
1709
1710 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1711 solInterface, "AccumulateIntervalMS",
1712 interval))
1713 {
1714 return responseUnspecifiedError();
1715 }
1716
1717 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1718 solInterface, "Threshold", threshold))
1719 {
1720 return responseUnspecifiedError();
1721 }
1722 ret.pack(interval, threshold);
1723 return responseSuccess(std::move(ret));
1724 }
1725 case SolConfParam::Retry:
1726 {
1727 // 3bits, cast when cast
1728 uint8_t count{};
1729 uint8_t interval{};
1730
1731 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1732 solInterface, "RetryCount", count))
1733 {
1734 return responseUnspecifiedError();
1735 }
1736
1737 if (ipmi::getDbusProperty(ctx, solService, solPathWitheEthName,
1738 solInterface, "RetryIntervalMS",
1739 interval))
1740 {
1741 return responseUnspecifiedError();
1742 }
1743 ret.pack(uint3_t{count}, uint5_t{}, interval);
1744 return responseSuccess(std::move(ret));
1745 }
1746 case SolConfParam::Port:
1747 {
1748 auto port = solDefaultPort;
1749 ret.pack(static_cast<uint16_t>(port));
1750 return responseSuccess(std::move(ret));
1751 }
1752 case SolConfParam::Channel:
1753 {
1754 ret.pack(channel);
1755 return responseSuccess(std::move(ret));
1756 }
1757 case SolConfParam::NonVbitrate:
Jonathan Domana48bf772023-05-26 17:54:57 -07001758 {
1759 uint64_t baudRate;
1760 uint8_t encodedBitRate = 0;
1761 if (ipmi::getDbusProperty(
1762 ctx, "xyz.openbmc_project.Console.default",
1763 "/xyz/openbmc_project/console/default",
1764 "xyz.openbmc_project.Console.UART", "Baud", baudRate))
1765 {
1766 return ipmi::responseUnspecifiedError();
1767 }
1768 switch (baudRate)
1769 {
1770 case 9600:
1771 encodedBitRate = 0x06;
1772 break;
1773 case 19200:
1774 encodedBitRate = 0x07;
1775 break;
1776 case 38400:
1777 encodedBitRate = 0x08;
1778 break;
1779 case 57600:
1780 encodedBitRate = 0x09;
1781 break;
1782 case 115200:
1783 encodedBitRate = 0x0a;
1784 break;
1785 default:
1786 break;
1787 }
1788 ret.pack(encodedBitRate);
1789 return responseSuccess(std::move(ret));
1790 }
Jian Zhang23f44652022-03-17 17:13:10 +08001791 case SolConfParam::Vbitrate:
1792 default:
1793 return response(ipmiCCParamNotSupported);
1794 }
1795
1796 return response(ccParamNotSupported);
1797}
1798
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001799} // namespace transport
1800} // namespace ipmi
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301801
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001802void register_netfn_transport_functions() __attribute__((constructor));
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301803
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001804void register_netfn_transport_functions()
1805{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001806 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1807 ipmi::transport::cmdSetLanConfigParameters,
1808 ipmi::Privilege::Admin, ipmi::transport::setLan);
1809 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1810 ipmi::transport::cmdGetLanConfigParameters,
Johnathan Mantey34698d52019-11-19 14:47:30 -08001811 ipmi::Privilege::Operator, ipmi::transport::getLan);
Jian Zhang23f44652022-03-17 17:13:10 +08001812 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1813 ipmi::transport::cmdSetSolConfigParameters,
1814 ipmi::Privilege::Admin,
1815 ipmi::transport::setSolConfParams);
1816 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1817 ipmi::transport::cmdGetSolConfigParameters,
1818 ipmi::Privilege::User,
1819 ipmi::transport::getSolConfParams);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001820}