blob: 67084cb0eb30f4216416562f4b065628f834d3e5 [file] [log] [blame]
Patrick Venture690a2342020-05-17 11:51:31 -07001#include "transporthandler.hpp"
2
William A. Kennington IIIc514d872019-04-06 18:19:38 -07003using phosphor::logging::commit;
4using phosphor::logging::elog;
5using phosphor::logging::entry;
6using phosphor::logging::level;
7using phosphor::logging::log;
Willy Tu523e2d12023-09-05 11:36:48 -07008using sdbusplus::error::xyz::openbmc_project::common::InternalFailure;
9using sdbusplus::server::xyz::openbmc_project::network::EthernetInterface;
10using sdbusplus::server::xyz::openbmc_project::network::IP;
11using sdbusplus::server::xyz::openbmc_project::network::Neighbor;
William A. Kennington IIIc514d872019-04-06 18:19:38 -070012
Johnathan Manteyaffadb52019-10-07 10:13:53 -070013namespace cipher
14{
15
16std::vector<uint8_t> getCipherList()
17{
18 std::vector<uint8_t> cipherList;
19
20 std::ifstream jsonFile(cipher::configFile);
21 if (!jsonFile.is_open())
22 {
23 log<level::ERR>("Channel Cipher suites file not found");
24 elog<InternalFailure>();
25 }
26
27 auto data = Json::parse(jsonFile, nullptr, false);
28 if (data.is_discarded())
29 {
30 log<level::ERR>("Parsing channel cipher suites JSON failed");
31 elog<InternalFailure>();
32 }
33
34 // Byte 1 is reserved
35 cipherList.push_back(0x00);
36
37 for (const auto& record : data)
38 {
39 cipherList.push_back(record.value(cipher, 0));
40 }
41
42 return cipherList;
43}
44} // namespace cipher
45
46namespace ipmi
47{
48namespace transport
49{
50
William A. Kennington IIIc514d872019-04-06 18:19:38 -070051/** @brief Valid address origins for IPv4 */
52const std::unordered_set<IP::AddressOrigin> originsV4 = {
53 IP::AddressOrigin::Static,
54 IP::AddressOrigin::DHCP,
55};
56
Johnathan Manteyb87034e2019-09-16 10:50:50 -070057static constexpr uint8_t oemCmdStart = 192;
58static constexpr uint8_t oemCmdEnd = 255;
59
Patrick Williams5d82f472022-07-22 19:26:53 -050060std::optional<ChannelParams> maybeGetChannelParams(sdbusplus::bus_t& bus,
William A. Kennington IIIc514d872019-04-06 18:19:38 -070061 uint8_t channel)
62{
63 auto ifname = getChannelName(channel);
64 if (ifname.empty())
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080065 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -070066 return std::nullopt;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080067 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080068
William A. Kennington IIIc514d872019-04-06 18:19:38 -070069 // Enumerate all VLAN + ETHERNET interfaces
70 auto req = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF,
71 "GetSubTree");
72 req.append(PATH_ROOT, 0,
73 std::vector<std::string>{INTF_VLAN, INTF_ETHERNET});
74 auto reply = bus.call(req);
75 ObjectTree objs;
76 reply.read(objs);
77
78 ChannelParams params;
79 for (const auto& [path, impls] : objs)
80 {
81 if (path.find(ifname) == path.npos)
82 {
83 continue;
84 }
85 for (const auto& [service, intfs] : impls)
86 {
87 bool vlan = false;
88 bool ethernet = false;
89 for (const auto& intf : intfs)
90 {
91 if (intf == INTF_VLAN)
92 {
93 vlan = true;
94 }
95 else if (intf == INTF_ETHERNET)
96 {
97 ethernet = true;
98 }
99 }
100 if (params.service.empty() && (vlan || ethernet))
101 {
102 params.service = service;
103 }
104 if (params.ifPath.empty() && !vlan && ethernet)
105 {
106 params.ifPath = path;
107 }
108 if (params.logicalPath.empty() && vlan)
109 {
110 params.logicalPath = path;
111 }
112 }
113 }
114
115 // We must have a path for the underlying interface
116 if (params.ifPath.empty())
117 {
118 return std::nullopt;
119 }
120 // We don't have a VLAN so the logical path is the same
121 if (params.logicalPath.empty())
122 {
123 params.logicalPath = params.ifPath;
124 }
125
126 params.id = channel;
127 params.ifname = std::move(ifname);
Willy Tu11d68892022-01-20 10:37:34 -0800128 return params;
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700129}
130
Patrick Williams5d82f472022-07-22 19:26:53 -0500131ChannelParams getChannelParams(sdbusplus::bus_t& bus, uint8_t channel)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700132{
133 auto params = maybeGetChannelParams(bus, channel);
134 if (!params)
135 {
136 log<level::ERR>("Failed to get channel params",
137 entry("CHANNEL=%" PRIu8, channel));
138 elog<InternalFailure>();
139 }
140 return std::move(*params);
141}
142
143/** @brief Wraps the phosphor logging method to insert some additional metadata
144 *
145 * @param[in] params - The parameters for the channel
146 * ...
147 */
148template <auto level, typename... Args>
149auto logWithChannel(const ChannelParams& params, Args&&... args)
150{
151 return log<level>(std::forward<Args>(args)...,
152 entry("CHANNEL=%d", params.id),
153 entry("IFNAME=%s", params.ifname.c_str()));
154}
155template <auto level, typename... Args>
156auto logWithChannel(const std::optional<ChannelParams>& params, Args&&... args)
157{
158 if (params)
159 {
160 return logWithChannel<level>(*params, std::forward<Args>(args)...);
161 }
162 return log<level>(std::forward<Args>(args)...);
163}
164
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700165ether_addr stringToMAC(const char* mac)
166{
167 const ether_addr* ret = ether_aton(mac);
168 if (ret == nullptr)
169 {
170 log<level::ERR>("Invalid MAC Address", entry("MAC=%s", mac));
171 elog<InternalFailure>();
172 }
173 return *ret;
174}
175
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700176/** @brief Get / Set the Property value from phosphor-networkd EthernetInterface
177 */
178template <typename T>
179static T getEthProp(sdbusplus::bus_t& bus, const ChannelParams& params,
180 const std::string& prop)
181{
182 return std::get<T>(getDbusProperty(bus, params.service, params.logicalPath,
183 INTF_ETHERNET, prop));
184}
185template <typename T>
186static void setEthProp(sdbusplus::bus_t& bus, const ChannelParams& params,
187 const std::string& prop, const T& t)
188{
189 return setDbusProperty(bus, params.service, params.logicalPath,
190 INTF_ETHERNET, prop, t);
191}
192
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700193/** @brief Determines the MAC of the ethernet interface
194 *
195 * @param[in] bus - The bus object used for lookups
196 * @param[in] params - The parameters for the channel
197 * @return The configured mac address
198 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500199ether_addr getMACProperty(sdbusplus::bus_t& bus, const ChannelParams& params)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700200{
201 auto macStr = std::get<std::string>(getDbusProperty(
202 bus, params.service, params.ifPath, INTF_MAC, "MACAddress"));
203 return stringToMAC(macStr.c_str());
204}
205
206/** @brief Sets the system value for MAC address on the given interface
207 *
208 * @param[in] bus - The bus object used for lookups
209 * @param[in] params - The parameters for the channel
210 * @param[in] mac - MAC address to apply
211 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500212void setMACProperty(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700213 const ether_addr& mac)
214{
215 std::string macStr = ether_ntoa(&mac);
216 setDbusProperty(bus, params.service, params.ifPath, INTF_MAC, "MACAddress",
217 macStr);
218}
219
Patrick Williams5d82f472022-07-22 19:26:53 -0500220void deleteObjectIfExists(sdbusplus::bus_t& bus, const std::string& service,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700221 const std::string& path)
222{
223 if (path.empty())
224 {
225 return;
226 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530227 try
tomjose26e17732016-03-03 08:52:51 -0600228 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700229 auto req = bus.new_method_call(service.c_str(), path.c_str(),
230 ipmi::DELETE_INTERFACE, "Delete");
231 bus.call_noreply(req);
232 }
Patrick Williams5d82f472022-07-22 19:26:53 -0500233 catch (const sdbusplus::exception_t& e)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700234 {
jayaprakash Mutyala84c49dc2020-05-18 23:12:13 +0000235 if (strcmp(e.name(),
236 "xyz.openbmc_project.Common.Error.InternalFailure") != 0 &&
237 strcmp(e.name(), "org.freedesktop.DBus.Error.UnknownObject") != 0)
tomjose26e17732016-03-03 08:52:51 -0600238 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700239 // We want to rethrow real errors
240 throw;
tomjose26e17732016-03-03 08:52:51 -0600241 }
242 }
tomjose26e17732016-03-03 08:52:51 -0600243}
244
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700245/** @brief Sets the address info configured for the interface
246 * If a previous address path exists then it will be removed
247 * before the new address is added.
248 *
249 * @param[in] bus - The bus object used for lookups
250 * @param[in] params - The parameters for the channel
251 * @param[in] address - The address of the new IP
252 * @param[in] prefix - The prefix of the new IP
253 */
254template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500255void createIfAddr(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700256 const typename AddrFamily<family>::addr& address,
257 uint8_t prefix)
Tom Josepha30c8d32018-03-22 02:15:03 +0530258{
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500259 auto newreq = bus.new_method_call(params.service.c_str(),
260 params.logicalPath.c_str(),
261 INTF_IP_CREATE, "IP");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700262 std::string protocol =
Willy Tu523e2d12023-09-05 11:36:48 -0700263 sdbusplus::common::xyz::openbmc_project::network::convertForMessage(
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700264 AddrFamily<family>::protocol);
265 newreq.append(protocol, addrToString<family>(address), prefix, "");
266 bus.call_noreply(newreq);
267}
Tom Josepha30c8d32018-03-22 02:15:03 +0530268
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700269/** @brief Trivial helper for getting the IPv4 address from getIfAddrs()
270 *
271 * @param[in] bus - The bus object used for lookups
272 * @param[in] params - The parameters for the channel
273 * @return The address and prefix if found
274 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500275auto getIfAddr4(sdbusplus::bus_t& bus, const ChannelParams& params)
Tom Josepha30c8d32018-03-22 02:15:03 +0530276{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700277 return getIfAddr<AF_INET>(bus, params, 0, originsV4);
278}
Tom Josepha30c8d32018-03-22 02:15:03 +0530279
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700280/** @brief Reconfigures the IPv4 address info configured for the interface
281 *
282 * @param[in] bus - The bus object used for lookups
283 * @param[in] params - The parameters for the channel
284 * @param[in] address - The new address if specified
285 * @param[in] prefix - The new address prefix if specified
286 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500287void reconfigureIfAddr4(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700288 const std::optional<in_addr>& address,
289 std::optional<uint8_t> prefix)
290{
291 auto ifaddr = getIfAddr4(bus, params);
292 if (!ifaddr && !address)
Tom Josepha30c8d32018-03-22 02:15:03 +0530293 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700294 log<level::ERR>("Missing address for IPv4 assignment");
Tom Josepha30c8d32018-03-22 02:15:03 +0530295 elog<InternalFailure>();
296 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700297 uint8_t fallbackPrefix = AddrFamily<AF_INET>::defaultPrefix;
298 if (ifaddr)
Tom Josepha30c8d32018-03-22 02:15:03 +0530299 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700300 fallbackPrefix = ifaddr->prefix;
301 deleteObjectIfExists(bus, params.service, ifaddr->path);
302 }
Johnathan Manteycbfa6e12023-06-01 06:57:25 -0700303
Jian Zhangd05b9dd2023-07-04 14:48:40 +0800304 if (struct in_addr nullIPv4{0};
Jayaprakash Mutyala4e02b432023-07-13 13:50:40 +0000305 (address == std::nullopt && prefix != std::nullopt) ||
306 (address != std::nullopt &&
307 (address.value().s_addr != nullIPv4.s_addr)))
Johnathan Manteycbfa6e12023-06-01 06:57:25 -0700308 {
309 createIfAddr<AF_INET>(bus, params, address.value_or(ifaddr->address),
310 prefix.value_or(fallbackPrefix));
311 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700312}
313
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700314template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500315std::optional<IfNeigh<family>> findGatewayNeighbor(sdbusplus::bus_t& bus,
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700316 const ChannelParams& params,
317 ObjectLookupCache& neighbors)
318{
319 auto gateway = getGatewayProperty<family>(bus, params);
320 if (!gateway)
321 {
322 return std::nullopt;
323 }
324
325 return findStaticNeighbor<family>(bus, params, *gateway, neighbors);
326}
327
328template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500329std::optional<IfNeigh<family>> getGatewayNeighbor(sdbusplus::bus_t& bus,
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700330 const ChannelParams& params)
331{
332 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
333 return findGatewayNeighbor<family>(bus, params, neighbors);
334}
335
336template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500337void reconfigureGatewayMAC(sdbusplus::bus_t& bus, const ChannelParams& params,
338 const ether_addr& mac)
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700339{
340 auto gateway = getGatewayProperty<family>(bus, params);
341 if (!gateway)
342 {
343 log<level::ERR>("Tried to set Gateway MAC without Gateway");
344 elog<InternalFailure>();
345 }
346
347 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500348 auto neighbor = findStaticNeighbor<family>(bus, params, *gateway,
349 neighbors);
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700350 if (neighbor)
351 {
352 deleteObjectIfExists(bus, params.service, neighbor->path);
353 }
354
355 createNeighbor<family>(bus, params, *gateway, mac);
356}
357
William A. Kennington III16064aa2019-04-13 17:44:53 -0700358/** @brief Deconfigures the IPv6 address info configured for the interface
359 *
360 * @param[in] bus - The bus object used for lookups
361 * @param[in] params - The parameters for the channel
362 * @param[in] idx - The address index to operate on
363 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500364void deconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III16064aa2019-04-13 17:44:53 -0700365 uint8_t idx)
366{
367 auto ifaddr = getIfAddr<AF_INET6>(bus, params, idx, originsV6Static);
368 if (ifaddr)
369 {
370 deleteObjectIfExists(bus, params.service, ifaddr->path);
371 }
372}
373
374/** @brief Reconfigures the IPv6 address info configured for the interface
375 *
376 * @param[in] bus - The bus object used for lookups
377 * @param[in] params - The parameters for the channel
378 * @param[in] idx - The address index to operate on
379 * @param[in] address - The new address
380 * @param[in] prefix - The new address prefix
381 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500382void reconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
William A. Kennington III16064aa2019-04-13 17:44:53 -0700383 uint8_t idx, const in6_addr& address, uint8_t prefix)
384{
385 deconfigureIfAddr6(bus, params, idx);
386 createIfAddr<AF_INET6>(bus, params, address, prefix);
387}
388
389/** @brief Converts the AddressOrigin into an IPv6Source
390 *
391 * @param[in] origin - The DBus Address Origin to convert
392 * @return The IPv6Source version of the origin
393 */
394IPv6Source originToSourceType(IP::AddressOrigin origin)
395{
396 switch (origin)
397 {
398 case IP::AddressOrigin::Static:
399 return IPv6Source::Static;
400 case IP::AddressOrigin::DHCP:
401 return IPv6Source::DHCP;
402 case IP::AddressOrigin::SLAAC:
403 return IPv6Source::SLAAC;
404 default:
405 {
Willy Tu523e2d12023-09-05 11:36:48 -0700406 auto originStr = sdbusplus::common::xyz::openbmc_project::network::
William A. Kennington III16064aa2019-04-13 17:44:53 -0700407 convertForMessage(origin);
408 log<level::ERR>(
409 "Invalid IP::AddressOrigin conversion to IPv6Source",
410 entry("ORIGIN=%s", originStr.c_str()));
411 elog<InternalFailure>();
412 }
413 }
414}
415
416/** @brief Packs the IPMI message response with IPv6 address data
417 *
418 * @param[out] ret - The IPMI response payload to be packed
419 * @param[in] channel - The channel id corresponding to an ethernet interface
420 * @param[in] set - The set selector for determining address index
421 * @param[in] origins - Set of valid origins for address filtering
422 */
423void getLanIPv6Address(message::Payload& ret, uint8_t channel, uint8_t set,
424 const std::unordered_set<IP::AddressOrigin>& origins)
425{
426 auto source = IPv6Source::Static;
427 bool enabled = false;
428 in6_addr addr{};
Johnathan Mantey5aae0922021-10-21 13:05:36 -0700429 uint8_t prefix{};
William A. Kennington III16064aa2019-04-13 17:44:53 -0700430 auto status = IPv6AddressStatus::Disabled;
431
432 auto ifaddr = channelCall<getIfAddr<AF_INET6>>(channel, set, origins);
433 if (ifaddr)
434 {
435 source = originToSourceType(ifaddr->origin);
Johnathan Mantey846af862021-10-21 12:48:54 -0700436 enabled = (origins == originsV6Static);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700437 addr = ifaddr->address;
438 prefix = ifaddr->prefix;
439 status = IPv6AddressStatus::Active;
440 }
441
442 ret.pack(set);
William A. Kennington III7a0e5df2021-05-19 13:31:29 -0700443 ret.pack(types::enum_cast<uint4_t>(source), uint3_t{}, enabled);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700444 ret.pack(std::string_view(reinterpret_cast<char*>(&addr), sizeof(addr)));
445 ret.pack(prefix);
William A. Kennington III7a0e5df2021-05-19 13:31:29 -0700446 ret.pack(types::enum_cast<uint8_t>(status));
William A. Kennington III16064aa2019-04-13 17:44:53 -0700447}
448
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700449/** @brief Gets the vlan ID configured on the interface
450 *
451 * @param[in] bus - The bus object used for lookups
452 * @param[in] params - The parameters for the channel
453 * @return VLAN id or the standard 0 for no VLAN
454 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500455uint16_t getVLANProperty(sdbusplus::bus_t& bus, const ChannelParams& params)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700456{
457 // VLAN devices will always have a separate logical object
458 if (params.ifPath == params.logicalPath)
459 {
460 return 0;
461 }
462
463 auto vlan = std::get<uint32_t>(getDbusProperty(
464 bus, params.service, params.logicalPath, INTF_VLAN, "Id"));
465 if ((vlan & VLAN_VALUE_MASK) != vlan)
466 {
467 logWithChannel<level::ERR>(params, "networkd returned an invalid vlan",
468 entry("VLAN=%" PRIu32, vlan));
Tom Josepha30c8d32018-03-22 02:15:03 +0530469 elog<InternalFailure>();
470 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700471 return vlan;
Tom Josepha30c8d32018-03-22 02:15:03 +0530472}
473
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700474/** @brief Deletes all of the possible configuration parameters for a channel
475 *
476 * @param[in] bus - The bus object used for lookups
477 * @param[in] params - The parameters for the channel
478 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500479void deconfigureChannel(sdbusplus::bus_t& bus, ChannelParams& params)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500480{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700481 // Delete all objects associated with the interface
482 auto objreq = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF,
483 "GetSubTree");
484 objreq.append(PATH_ROOT, 0, std::vector<std::string>{DELETE_INTERFACE});
485 auto objreply = bus.call(objreq);
486 ObjectTree objs;
487 objreply.read(objs);
488 for (const auto& [path, impls] : objs)
489 {
490 if (path.find(params.ifname) == path.npos)
491 {
492 continue;
493 }
494 for (const auto& [service, intfs] : impls)
495 {
496 deleteObjectIfExists(bus, service, path);
497 }
498 // Update params to reflect the deletion of vlan
499 if (path == params.logicalPath)
500 {
501 params.logicalPath = params.ifPath;
502 }
503 }
504
505 // Clear out any settings on the lower physical interface
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700506 setEthProp(bus, params, "DHCP4", false);
507 setEthProp(bus, params, "DHCP6", false);
508 setEthProp(bus, params, "IPv6AcceptRA", false);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500509}
510
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700511/** @brief Creates a new VLAN on the specified interface
512 *
513 * @param[in] bus - The bus object used for lookups
514 * @param[in] params - The parameters for the channel
515 * @param[in] vlan - The id of the new vlan
516 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500517void createVLAN(sdbusplus::bus_t& bus, ChannelParams& params, uint16_t vlan)
Ratan Guptab8e99552017-07-27 07:07:48 +0530518{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700519 if (vlan == 0)
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530520 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700521 return;
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530522 }
523
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700524 auto req = bus.new_method_call(params.service.c_str(), PATH_ROOT,
525 INTF_VLAN_CREATE, "VLAN");
526 req.append(params.ifname, static_cast<uint32_t>(vlan));
527 auto reply = bus.call(req);
528 sdbusplus::message::object_path newPath;
529 reply.read(newPath);
530 params.logicalPath = std::move(newPath);
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530531}
532
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700533/** @brief Performs the necessary reconfiguration to change the VLAN
534 *
535 * @param[in] bus - The bus object used for lookups
536 * @param[in] params - The parameters for the channel
537 * @param[in] vlan - The new vlan id to use
538 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500539void reconfigureVLAN(sdbusplus::bus_t& bus, ChannelParams& params,
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700540 uint16_t vlan)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500541{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700542 // Unfortunatetly we don't have built-in functions to migrate our interface
543 // customizations to new VLAN interfaces, or have some kind of decoupling.
544 // We therefore must retain all of our old information, setup the new VLAN
545 // configuration, then restore the old info.
Nan Li3d0df912016-10-18 19:51:41 +0800546
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700547 // Save info from the old logical interface
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700548 bool dhcp4 = getEthProp<bool>(bus, params, "DHCP4");
549 bool dhcp6 = getEthProp<bool>(bus, params, "DHCP6");
550 bool ra = getEthProp<bool>(bus, params, "IPv6AcceptRA");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700551 ObjectLookupCache ips(bus, params, INTF_IP);
552 auto ifaddr4 = findIfAddr<AF_INET>(bus, params, 0, originsV4, ips);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700553 std::vector<IfAddr<AF_INET6>> ifaddrs6;
554 for (uint8_t i = 0; i < MAX_IPV6_STATIC_ADDRESSES; ++i)
555 {
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500556 auto ifaddr6 = findIfAddr<AF_INET6>(bus, params, i, originsV6Static,
557 ips);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700558 if (!ifaddr6)
559 {
560 break;
561 }
562 ifaddrs6.push_back(std::move(*ifaddr6));
563 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700564 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
565 auto neighbor4 = findGatewayNeighbor<AF_INET>(bus, params, neighbors);
William A. Kennington III16064aa2019-04-13 17:44:53 -0700566 auto neighbor6 = findGatewayNeighbor<AF_INET6>(bus, params, neighbors);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500567
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700568 deconfigureChannel(bus, params);
569 createVLAN(bus, params, vlan);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500570
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700571 // Re-establish the saved settings
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700572 setEthProp(bus, params, "DHCP4", dhcp4);
573 setEthProp(bus, params, "DHCP6", dhcp6);
574 setEthProp(bus, params, "IPv6AcceptRA", ra);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700575 if (ifaddr4)
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800576 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700577 createIfAddr<AF_INET>(bus, params, ifaddr4->address, ifaddr4->prefix);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800578 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700579 for (const auto& ifaddr6 : ifaddrs6)
580 {
581 createIfAddr<AF_INET6>(bus, params, ifaddr6.address, ifaddr6.prefix);
582 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700583 if (neighbor4)
584 {
585 createNeighbor<AF_INET>(bus, params, neighbor4->ip, neighbor4->mac);
586 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700587 if (neighbor6)
588 {
589 createNeighbor<AF_INET6>(bus, params, neighbor6->ip, neighbor6->mac);
590 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700591}
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800592
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700593/** @brief Turns a prefix into a netmask
594 *
595 * @param[in] prefix - The prefix length
596 * @return The netmask
597 */
598in_addr prefixToNetmask(uint8_t prefix)
599{
600 if (prefix > 32)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500601 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700602 log<level::ERR>("Invalid prefix", entry("PREFIX=%" PRIu8, prefix));
603 elog<InternalFailure>();
604 }
605 if (prefix == 0)
606 {
607 // Avoids 32-bit lshift by 32 UB
608 return {};
609 }
610 return {htobe32(~UINT32_C(0) << (32 - prefix))};
611}
612
613/** @brief Turns a a netmask into a prefix length
614 *
615 * @param[in] netmask - The netmask in byte form
616 * @return The prefix length
617 */
618uint8_t netmaskToPrefix(in_addr netmask)
619{
620 uint32_t x = be32toh(netmask.s_addr);
621 if ((~x & (~x + 1)) != 0)
622 {
623 char maskStr[INET_ADDRSTRLEN];
624 inet_ntop(AF_INET, &netmask, maskStr, sizeof(maskStr));
625 log<level::ERR>("Invalid netmask", entry("NETMASK=%s", maskStr));
626 elog<InternalFailure>();
627 }
Johnathan Mantey62c05dd2019-11-20 14:07:44 -0800628 return static_cast<bool>(x)
629 ? AddrFamily<AF_INET>::defaultPrefix - __builtin_ctz(x)
630 : 0;
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700631}
632
633// We need to store this value so it can be returned to the client
634// It is volatile so safe to store in daemon memory.
635static std::unordered_map<uint8_t, SetStatus> setStatus;
636
637// Until we have good support for fixed versions of IPMI tool
638// we need to return the VLAN id for disabled VLANs. The value is only
639// used for verification that a disable operation succeeded and will only
640// be sent if our system indicates that vlans are disabled.
641static std::unordered_map<uint8_t, uint16_t> lastDisabledVlan;
642
643/** @brief Gets the set status for the channel if it exists
644 * Otherise populates and returns the default value.
645 *
646 * @param[in] channel - The channel id corresponding to an ethernet interface
647 * @return A reference to the SetStatus for the channel
648 */
649SetStatus& getSetStatus(uint8_t channel)
650{
651 auto it = setStatus.find(channel);
652 if (it != setStatus.end())
653 {
654 return it->second;
655 }
656 return setStatus[channel] = SetStatus::Complete;
657}
658
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700659/**
660 * Define placeholder command handlers for the OEM Extension bytes for the Set
661 * LAN Configuration Parameters and Get LAN Configuration Parameters
662 * commands. Using "weak" linking allows the placeholder setLanOem/getLanOem
663 * functions below to be overridden.
664 * To create handlers for your own proprietary command set:
665 * Create/modify a phosphor-ipmi-host Bitbake append file within your Yocto
666 * recipe
667 * Create C++ file(s) that define IPMI handler functions matching the
668 * function names below (i.e. setLanOem). The default name for the
669 * transport IPMI commands is transporthandler_oem.cpp.
670 * Add:
Johnathan Manteyefe26682022-08-11 14:30:45 -0700671 * EXTRA_OEMESON:append = "-Dtransport-oem=enabled"
672 * Create a do_configure:prepend()/do_install:append() method in your
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700673 * bbappend file to copy the file to the build directory.
674 * Add:
675 * PROJECT_SRC_DIR := "${THISDIR}/${PN}"
676 * # Copy the "strong" functions into the working directory, overriding the
677 * # placeholder functions.
Johnathan Manteyefe26682022-08-11 14:30:45 -0700678 * do_configure:prepend(){
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700679 * cp -f ${PROJECT_SRC_DIR}/transporthandler_oem.cpp ${S}
680 * }
681 *
682 * # Clean up after complilation has completed
Johnathan Manteyefe26682022-08-11 14:30:45 -0700683 * do_install:append(){
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700684 * rm -f ${S}/transporthandler_oem.cpp
685 * }
686 *
687 */
688
689/**
690 * Define the placeholder OEM commands as having weak linkage. Create
691 * setLanOem, and getLanOem functions in the transporthandler_oem.cpp
692 * file. The functions defined there must not have the "weak" attribute
693 * applied to them.
694 */
695RspType<> setLanOem(uint8_t channel, uint8_t parameter, message::Payload& req)
696 __attribute__((weak));
697RspType<message::Payload> getLanOem(uint8_t channel, uint8_t parameter,
698 uint8_t set, uint8_t block)
699 __attribute__((weak));
700
Willy Tu11d68892022-01-20 10:37:34 -0800701RspType<> setLanOem(uint8_t, uint8_t, message::Payload& req)
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700702{
703 req.trailingOk = true;
704 return response(ccParamNotSupported);
705}
706
Willy Tu11d68892022-01-20 10:37:34 -0800707RspType<message::Payload> getLanOem(uint8_t, uint8_t, uint8_t, uint8_t)
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700708{
709 return response(ccParamNotSupported);
710}
Rajashekar Gade Reddy0b993fd2019-12-24 16:37:15 +0530711/**
712 * @brief is MAC address valid.
713 *
714 * This function checks whether the MAC address is valid or not.
715 *
716 * @param[in] mac - MAC address.
717 * @return true if MAC address is valid else retun false.
718 **/
719bool isValidMACAddress(const ether_addr& mac)
720{
721 // check if mac address is empty
722 if (equal(mac, ether_addr{}))
723 {
724 return false;
725 }
726 // we accept only unicast MAC addresses and same thing has been checked in
727 // phosphor-network layer. If the least significant bit of the first octet
728 // is set to 1, it is multicast MAC else it is unicast MAC address.
729 if (mac.ether_addr_octet[0] & 1)
730 {
731 return false;
732 }
733 return true;
734}
Johnathan Manteyb87034e2019-09-16 10:50:50 -0700735
Jian Zhangcf19d142023-07-31 10:22:53 +0800736/**
737 * @brief is a valid LAN channel.
738 *
739 * This function checks whether the input channel is a valid LAN channel or not.
740 *
741 * @param[in] channel: the channel number.
742 * @return nullopt if the channel is invalid, false if the channel is not a LAN
743 * channel, true if the channel is a LAN channel.
744 **/
745std::optional<bool> isLanChannel(uint8_t channel)
746{
747 ChannelInfo chInfo;
748 auto cc = getChannelInfo(channel, chInfo);
749 if (cc != ccSuccess)
750 {
751 return std::nullopt;
752 }
753
754 return chInfo.mediumType ==
755 static_cast<uint8_t>(EChannelMediumType::lan8032);
756}
757
vijayabharathix shettycc769252020-02-27 17:52:20 +0000758RspType<> setLan(Context::ptr ctx, uint4_t channelBits, uint4_t reserved1,
759 uint8_t parameter, message::Payload& req)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700760{
vijayabharathix shettycc769252020-02-27 17:52:20 +0000761 const uint8_t channel = convertCurrentChannelNum(
762 static_cast<uint8_t>(channelBits), ctx->channel);
763 if (reserved1 || !isValidChannel(channel))
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700764 {
vijayabharathix shettycc769252020-02-27 17:52:20 +0000765 log<level::ERR>("Set Lan - Invalid field in request");
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700766 req.trailingOk = true;
767 return responseInvalidFieldRequest();
768 }
769
Jian Zhangcf19d142023-07-31 10:22:53 +0800770 if (!isLanChannel(channel).value_or(false))
771 {
772 log<level::ERR>("Set Lan - Not a LAN channel");
773 return responseInvalidFieldRequest();
774 }
775
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700776 switch (static_cast<LanParam>(parameter))
777 {
778 case LanParam::SetStatus:
779 {
780 uint2_t flag;
781 uint6_t rsvd;
782 if (req.unpack(flag, rsvd) != 0 || !req.fullyUnpacked())
783 {
784 return responseReqDataLenInvalid();
785 }
Johnathan Mantey4a156852019-12-11 13:47:43 -0800786 if (rsvd)
787 {
788 return responseInvalidFieldRequest();
789 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700790 auto status = static_cast<SetStatus>(static_cast<uint8_t>(flag));
791 switch (status)
792 {
793 case SetStatus::Complete:
794 {
795 getSetStatus(channel) = status;
796 return responseSuccess();
797 }
798 case SetStatus::InProgress:
799 {
800 auto& storedStatus = getSetStatus(channel);
801 if (storedStatus == SetStatus::InProgress)
802 {
803 return response(ccParamSetLocked);
804 }
805 storedStatus = status;
806 return responseSuccess();
807 }
808 case SetStatus::Commit:
809 if (getSetStatus(channel) != SetStatus::InProgress)
810 {
811 return responseInvalidFieldRequest();
812 }
813 return responseSuccess();
814 }
815 return response(ccParamNotSupported);
816 }
817 case LanParam::AuthSupport:
818 {
819 req.trailingOk = true;
820 return response(ccParamReadOnly);
821 }
822 case LanParam::AuthEnables:
823 {
824 req.trailingOk = true;
Johnathan Mantey76ce9c72019-11-14 14:41:46 -0800825 return response(ccParamReadOnly);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700826 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800827 case LanParam::IP:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600828 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700829 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800830 {
831 return responseCommandNotAvailable();
832 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700833 in_addr ip;
834 std::array<uint8_t, sizeof(ip)> bytes;
835 if (req.unpack(bytes) != 0 || !req.fullyUnpacked())
836 {
837 return responseReqDataLenInvalid();
838 }
839 copyInto(ip, bytes);
840 channelCall<reconfigureIfAddr4>(channel, ip, std::nullopt);
841 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +0530842 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700843 case LanParam::IPSrc:
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530844 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700845 uint4_t flag;
846 uint4_t rsvd;
847 if (req.unpack(flag, rsvd) != 0 || !req.fullyUnpacked())
848 {
849 return responseReqDataLenInvalid();
850 }
Johnathan Mantey4a156852019-12-11 13:47:43 -0800851 if (rsvd)
852 {
853 return responseInvalidFieldRequest();
854 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700855 switch (static_cast<IPSrc>(static_cast<uint8_t>(flag)))
856 {
857 case IPSrc::DHCP:
Johnathan Mantey65265362019-11-14 11:24:19 -0800858 // The IPSrc IPMI command is only for IPv4
859 // management. Modifying IPv6 state is done using
860 // a completely different Set LAN Configuration
861 // subcommand.
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700862 channelCall<setEthProp<bool>>(channel, "DHCP4", true);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700863 return responseSuccess();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700864 case IPSrc::Unspecified:
865 case IPSrc::Static:
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700866 channelCall<setEthProp<bool>>(channel, "DHCP4", false);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700867 return responseSuccess();
Rajashekar Gade Reddy8a860ea2019-12-24 11:31:19 +0530868 case IPSrc::BIOS:
869 case IPSrc::BMC:
Rajashekar Gade Reddy8a860ea2019-12-24 11:31:19 +0530870 return responseInvalidFieldRequest();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700871 }
872 return response(ccParamNotSupported);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530873 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800874 case LanParam::MAC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530875 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700876 ether_addr mac;
877 std::array<uint8_t, sizeof(mac)> bytes;
878 if (req.unpack(bytes) != 0 || !req.fullyUnpacked())
Suryakanth Sekar0a327e12019-08-08 14:30:19 +0530879 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700880 return responseReqDataLenInvalid();
Suryakanth Sekar0a327e12019-08-08 14:30:19 +0530881 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700882 copyInto(mac, bytes);
Rajashekar Gade Reddy0b993fd2019-12-24 16:37:15 +0530883
884 if (!isValidMACAddress(mac))
885 {
886 return responseInvalidFieldRequest();
887 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700888 channelCall<setMACProperty>(channel, mac);
889 return responseSuccess();
Ratan Gupta533d03b2017-07-30 10:39:22 +0530890 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700891 case LanParam::SubnetMask:
Ratan Guptab8e99552017-07-27 07:07:48 +0530892 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700893 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800894 {
895 return responseCommandNotAvailable();
896 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700897 in_addr netmask;
898 std::array<uint8_t, sizeof(netmask)> bytes;
899 if (req.unpack(bytes) != 0 || !req.fullyUnpacked())
Ratan Guptab8e99552017-07-27 07:07:48 +0530900 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700901 return responseReqDataLenInvalid();
Ratan Guptab8e99552017-07-27 07:07:48 +0530902 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700903 copyInto(netmask, bytes);
Jiaqing Zhao6d4a44e2022-01-24 15:04:00 +0800904 uint8_t prefix = netmaskToPrefix(netmask);
905 if (prefix < MIN_IPV4_PREFIX_LENGTH)
906 {
907 return responseInvalidFieldRequest();
908 }
909 channelCall<reconfigureIfAddr4>(channel, std::nullopt, prefix);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700910 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +0530911 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700912 case LanParam::Gateway1:
Ratan Guptab8e99552017-07-27 07:07:48 +0530913 {
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -0700914 if (channelCall<getEthProp<bool>>(channel, "DHCP4"))
Johnathan Mantey930104a2019-12-17 09:18:34 -0800915 {
916 return responseCommandNotAvailable();
917 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700918 in_addr gateway;
919 std::array<uint8_t, sizeof(gateway)> bytes;
920 if (req.unpack(bytes) != 0 || !req.fullyUnpacked())
921 {
922 return responseReqDataLenInvalid();
923 }
924 copyInto(gateway, bytes);
925 channelCall<setGatewayProperty<AF_INET>>(channel, gateway);
926 return responseSuccess();
927 }
William A. Kennington III4bbc3db2019-04-15 00:02:10 -0700928 case LanParam::Gateway1MAC:
929 {
930 ether_addr gatewayMAC;
931 std::array<uint8_t, sizeof(gatewayMAC)> bytes;
932 if (req.unpack(bytes) != 0 || !req.fullyUnpacked())
933 {
934 return responseReqDataLenInvalid();
935 }
936 copyInto(gatewayMAC, bytes);
937 channelCall<reconfigureGatewayMAC<AF_INET>>(channel, gatewayMAC);
938 return responseSuccess();
939 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700940 case LanParam::VLANId:
941 {
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530942 uint12_t vlanData = 0;
943 uint3_t reserved = 0;
944 bool vlanEnable = 0;
945
946 if (req.unpack(vlanData) || req.unpack(reserved) ||
947 req.unpack(vlanEnable) || !req.fullyUnpacked())
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700948 {
949 return responseReqDataLenInvalid();
950 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530951
952 if (reserved)
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700953 {
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530954 return responseInvalidFieldRequest();
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700955 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530956
957 uint16_t vlan = static_cast<uint16_t>(vlanData);
958
959 if (!vlanEnable)
960 {
961 lastDisabledVlan[channel] = vlan;
962 vlan = 0;
963 }
jayaprakash Mutyala84c49dc2020-05-18 23:12:13 +0000964 else if (vlan == 0 || vlan == VLAN_VALUE_MASK)
965 {
966 return responseInvalidFieldRequest();
967 }
Suryakanth Sekar8e8c8e22019-08-30 11:54:20 +0530968
jayaprakash Mutyala84c49dc2020-05-18 23:12:13 +0000969 channelCall<reconfigureVLAN>(channel, vlan);
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700970 return responseSuccess();
971 }
972 case LanParam::CiphersuiteSupport:
973 case LanParam::CiphersuiteEntries:
William A. Kennington III16064aa2019-04-13 17:44:53 -0700974 case LanParam::IPFamilySupport:
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700975 {
976 req.trailingOk = true;
977 return response(ccParamReadOnly);
Ratan Guptab8e99552017-07-27 07:07:48 +0530978 }
William A. Kennington III16064aa2019-04-13 17:44:53 -0700979 case LanParam::IPFamilyEnables:
980 {
981 uint8_t enables;
982 if (req.unpack(enables) != 0 || !req.fullyUnpacked())
983 {
984 return responseReqDataLenInvalid();
985 }
986 switch (static_cast<IPFamilyEnables>(enables))
987 {
988 case IPFamilyEnables::DualStack:
989 return responseSuccess();
990 case IPFamilyEnables::IPv4Only:
991 case IPFamilyEnables::IPv6Only:
992 return response(ccParamNotSupported);
993 }
994 return response(ccParamNotSupported);
995 }
996 case LanParam::IPv6Status:
997 {
998 req.trailingOk = true;
999 return response(ccParamReadOnly);
1000 }
1001 case LanParam::IPv6StaticAddresses:
1002 {
1003 uint8_t set;
1004 uint7_t rsvd;
1005 bool enabled;
1006 in6_addr ip;
1007 std::array<uint8_t, sizeof(ip)> ipbytes;
1008 uint8_t prefix;
1009 uint8_t status;
1010 if (req.unpack(set, rsvd, enabled, ipbytes, prefix, status) != 0 ||
1011 !req.fullyUnpacked())
1012 {
1013 return responseReqDataLenInvalid();
1014 }
Johnathan Mantey4a156852019-12-11 13:47:43 -08001015 if (rsvd)
1016 {
1017 return responseInvalidFieldRequest();
1018 }
William A. Kennington III16064aa2019-04-13 17:44:53 -07001019 copyInto(ip, ipbytes);
1020 if (enabled)
1021 {
Jiaqing Zhao6d4a44e2022-01-24 15:04:00 +08001022 if (prefix < MIN_IPV6_PREFIX_LENGTH ||
1023 prefix > MAX_IPV6_PREFIX_LENGTH)
1024 {
1025 return responseParmOutOfRange();
1026 }
Johnathan Manteya291f492021-10-15 13:45:27 -07001027 try
1028 {
1029 channelCall<reconfigureIfAddr6>(channel, set, ip, prefix);
1030 }
Patrick Williams5d82f472022-07-22 19:26:53 -05001031 catch (const sdbusplus::exception_t& e)
Johnathan Manteya291f492021-10-15 13:45:27 -07001032 {
1033 if (std::string_view err{
1034 "xyz.openbmc_project.Common.Error.InvalidArgument"};
1035 err == e.name())
1036 {
1037 return responseInvalidFieldRequest();
1038 }
1039 else
1040 {
1041 throw;
1042 }
1043 }
William A. Kennington III16064aa2019-04-13 17:44:53 -07001044 }
1045 else
1046 {
1047 channelCall<deconfigureIfAddr6>(channel, set);
1048 }
1049 return responseSuccess();
1050 }
1051 case LanParam::IPv6DynamicAddresses:
1052 {
1053 req.trailingOk = true;
1054 return response(ccParamReadOnly);
1055 }
1056 case LanParam::IPv6RouterControl:
1057 {
1058 std::bitset<8> control;
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001059 constexpr uint8_t reservedRACCBits = 0xfc;
William A. Kennington III16064aa2019-04-13 17:44:53 -07001060 if (req.unpack(control) != 0 || !req.fullyUnpacked())
1061 {
1062 return responseReqDataLenInvalid();
1063 }
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001064 if (std::bitset<8> expected(control &
1065 std::bitset<8>(reservedRACCBits));
1066 expected.any())
William A. Kennington III16064aa2019-04-13 17:44:53 -07001067 {
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001068 return response(ccParamNotSupported);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001069 }
Johnathan Mantey3b7a4072021-01-26 14:24:53 -08001070
1071 bool enableRA = control[IPv6RouterControlFlag::Dynamic];
William A. Kennington IIIa8a2e5f2023-06-21 17:50:01 -07001072 channelCall<setEthProp<bool>>(channel, "IPv6AcceptRA", enableRA);
1073 channelCall<setEthProp<bool>>(channel, "DHCP6", enableRA);
William A. Kennington III16064aa2019-04-13 17:44:53 -07001074 return responseSuccess();
1075 }
1076 case LanParam::IPv6StaticRouter1IP:
1077 {
1078 in6_addr gateway;
1079 std::array<uint8_t, sizeof(gateway)> bytes;
1080 if (req.unpack(bytes) != 0 || !req.fullyUnpacked())
1081 {
1082 return responseReqDataLenInvalid();
1083 }
1084 copyInto(gateway, bytes);
1085 channelCall<setGatewayProperty<AF_INET6>>(channel, gateway);
1086 return responseSuccess();
1087 }
1088 case LanParam::IPv6StaticRouter1MAC:
1089 {
1090 ether_addr mac;
1091 std::array<uint8_t, sizeof(mac)> bytes;
1092 if (req.unpack(bytes) != 0 || !req.fullyUnpacked())
1093 {
1094 return responseReqDataLenInvalid();
1095 }
1096 copyInto(mac, bytes);
1097 channelCall<reconfigureGatewayMAC<AF_INET6>>(channel, mac);
1098 return responseSuccess();
1099 }
1100 case LanParam::IPv6StaticRouter1PrefixLength:
1101 {
1102 uint8_t prefix;
1103 if (req.unpack(prefix) != 0 || !req.fullyUnpacked())
1104 {
1105 return responseReqDataLenInvalid();
1106 }
1107 if (prefix != 0)
1108 {
1109 return responseInvalidFieldRequest();
1110 }
1111 return responseSuccess();
1112 }
1113 case LanParam::IPv6StaticRouter1PrefixValue:
1114 {
1115 std::array<uint8_t, sizeof(in6_addr)> bytes;
1116 if (req.unpack(bytes) != 0 || !req.fullyUnpacked())
1117 {
1118 return responseReqDataLenInvalid();
1119 }
1120 // Accept any prefix value since our prefix length has to be 0
1121 return responseSuccess();
1122 }
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001123 case LanParam::cipherSuitePrivilegeLevels:
1124 {
1125 uint8_t reserved;
1126 std::array<uint4_t, ipmi::maxCSRecords> cipherSuitePrivs;
1127
1128 if (req.unpack(reserved, cipherSuitePrivs) || !req.fullyUnpacked())
1129 {
1130 return responseReqDataLenInvalid();
1131 }
1132
1133 if (reserved)
1134 {
1135 return responseInvalidFieldRequest();
1136 }
1137
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -05001138 uint8_t resp = getCipherConfigObject(csPrivFileName,
1139 csPrivDefaultFileName)
1140 .setCSPrivilegeLevels(channel, cipherSuitePrivs);
jayaprakash Mutyalab741b992019-12-02 17:29:09 +00001141 if (!resp)
1142 {
1143 return responseSuccess();
1144 }
1145 else
1146 {
1147 req.trailingOk = true;
1148 return response(resp);
1149 }
1150 }
Ratan Guptab8e99552017-07-27 07:07:48 +05301151 }
vishwa1eaea4f2016-02-26 11:57:40 -06001152
Johnathan Manteyb87034e2019-09-16 10:50:50 -07001153 if ((parameter >= oemCmdStart) && (parameter <= oemCmdEnd))
1154 {
1155 return setLanOem(channel, parameter, req);
1156 }
1157
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001158 req.trailingOk = true;
1159 return response(ccParamNotSupported);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001160}
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 }
1242 ret.pack(dataRef(addr));
1243 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);
1256 ret.pack(dataRef(mac));
1257 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);
1268 ret.pack(dataRef(netmask));
1269 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{});
1276 ret.pack(dataRef(gateway));
1277 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 }
1287 ret.pack(dataRef(mac));
1288 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 }
1392 ret.pack(dataRef(gateway));
1393 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 }
1403 ret.pack(dataRef(mac));
1404 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{};
1414 ret.pack(dataRef(prefix));
1415 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}