blob: b48cbd010a3dc48c437507e963656fb6b2120a21 [file] [log] [blame]
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001#include "app/channel.hpp"
2
Patrick Venture0b02be92018-08-31 11:55:55 -07003#include <arpa/inet.h>
William A. Kennington IIIc514d872019-04-06 18:19:38 -07004#include <netinet/ether.h>
Patrick Venture0b02be92018-08-31 11:55:55 -07005
William A. Kennington IIIc514d872019-04-06 18:19:38 -07006#include <array>
7#include <bitset>
8#include <cinttypes>
9#include <cstdint>
10#include <cstring>
Johnathan Manteyaffadb52019-10-07 10:13:53 -070011#include <fstream>
William A. Kennington IIIc514d872019-04-06 18:19:38 -070012#include <functional>
Vernon Mauerye08fbff2019-04-03 09:19:34 -070013#include <ipmid/api.hpp>
William A. Kennington IIIc514d872019-04-06 18:19:38 -070014#include <ipmid/message.hpp>
15#include <ipmid/message/types.hpp>
16#include <ipmid/types.hpp>
Vernon Mauery6a98fe72019-03-11 15:57:48 -070017#include <ipmid/utils.hpp>
William A. Kennington IIIc514d872019-04-06 18:19:38 -070018#include <optional>
Patrick Venture3a5071a2018-09-12 13:27:42 -070019#include <phosphor-logging/elog-errors.hpp>
William A. Kennington IIIc514d872019-04-06 18:19:38 -070020#include <phosphor-logging/elog.hpp>
Patrick Venture3a5071a2018-09-12 13:27:42 -070021#include <phosphor-logging/log.hpp>
William A. Kennington IIIc514d872019-04-06 18:19:38 -070022#include <sdbusplus/bus.hpp>
23#include <sdbusplus/exception.hpp>
tomjose26e17732016-03-03 08:52:51 -060024#include <string>
William A. Kennington IIIc514d872019-04-06 18:19:38 -070025#include <string_view>
26#include <type_traits>
27#include <unordered_map>
28#include <unordered_set>
29#include <user_channel/channel_layer.hpp>
30#include <utility>
31#include <vector>
Patrick Venture3a5071a2018-09-12 13:27:42 -070032#include <xyz/openbmc_project/Common/error.hpp>
William A. Kennington IIIc514d872019-04-06 18:19:38 -070033#include <xyz/openbmc_project/Network/IP/server.hpp>
Patrick Venture3a5071a2018-09-12 13:27:42 -070034
William A. Kennington IIIc514d872019-04-06 18:19:38 -070035using phosphor::logging::commit;
36using phosphor::logging::elog;
37using phosphor::logging::entry;
38using phosphor::logging::level;
39using phosphor::logging::log;
40using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
41using sdbusplus::xyz::openbmc_project::Network::server::IP;
42
Johnathan Manteyaffadb52019-10-07 10:13:53 -070043namespace cipher
44{
45
46std::vector<uint8_t> getCipherList()
47{
48 std::vector<uint8_t> cipherList;
49
50 std::ifstream jsonFile(cipher::configFile);
51 if (!jsonFile.is_open())
52 {
53 log<level::ERR>("Channel Cipher suites file not found");
54 elog<InternalFailure>();
55 }
56
57 auto data = Json::parse(jsonFile, nullptr, false);
58 if (data.is_discarded())
59 {
60 log<level::ERR>("Parsing channel cipher suites JSON failed");
61 elog<InternalFailure>();
62 }
63
64 // Byte 1 is reserved
65 cipherList.push_back(0x00);
66
67 for (const auto& record : data)
68 {
69 cipherList.push_back(record.value(cipher, 0));
70 }
71
72 return cipherList;
73}
74} // namespace cipher
75
76namespace ipmi
77{
78namespace transport
79{
80
William A. Kennington IIIc514d872019-04-06 18:19:38 -070081// LAN Handler specific response codes
82constexpr Cc ccParamNotSupported = 0x80;
83constexpr Cc ccParamSetLocked = 0x81;
84constexpr Cc ccParamReadOnly = 0x82;
85
86// VLANs are a 12-bit value
87constexpr uint16_t VLAN_VALUE_MASK = 0x0fff;
88constexpr uint16_t VLAN_ENABLE_FLAG = 0x8000;
89
90// D-Bus Network Daemon definitions
91constexpr auto PATH_ROOT = "/xyz/openbmc_project/network";
92constexpr auto PATH_SYSTEMCONFIG = "/xyz/openbmc_project/network/config";
93
94constexpr auto INTF_SYSTEMCONFIG =
95 "xyz.openbmc_project.Network.SystemConfiguration";
96constexpr auto INTF_ETHERNET = "xyz.openbmc_project.Network.EthernetInterface";
97constexpr auto INTF_IP = "xyz.openbmc_project.Network.IP";
98constexpr auto INTF_IP_CREATE = "xyz.openbmc_project.Network.IP.Create";
99constexpr auto INTF_MAC = "xyz.openbmc_project.Network.MACAddress";
100constexpr auto INTF_VLAN = "xyz.openbmc_project.Network.VLAN";
101constexpr auto INTF_VLAN_CREATE = "xyz.openbmc_project.Network.VLAN.Create";
102
103/** @brief Generic paramters for different address families */
104template <int family>
105struct AddrFamily
106{
107};
108
109/** @brief Parameter specialization for IPv4 */
110template <>
111struct AddrFamily<AF_INET>
112{
113 using addr = in_addr;
114 static constexpr auto protocol = IP::Protocol::IPv4;
115 static constexpr size_t maxStrLen = INET6_ADDRSTRLEN;
116 static constexpr uint8_t defaultPrefix = 32;
117 static constexpr char propertyGateway[] = "DefaultGateway";
118};
119
120/** @brief Valid address origins for IPv4 */
121const std::unordered_set<IP::AddressOrigin> originsV4 = {
122 IP::AddressOrigin::Static,
123 IP::AddressOrigin::DHCP,
124};
125
126/** @brief Interface IP Address configuration parameters */
127template <int family>
128struct IfAddr
129{
130 std::string path;
131 typename AddrFamily<family>::addr address;
132 IP::AddressOrigin origin;
133 uint8_t prefix;
134};
135
136/** @brief IPMI LAN Parameters */
137enum class LanParam : uint8_t
138{
139 SetStatus = 0,
140 AuthSupport = 1,
141 AuthEnables = 2,
142 IP = 3,
143 IPSrc = 4,
144 MAC = 5,
145 SubnetMask = 6,
146 Gateway1 = 12,
147 VLANId = 20,
148 CiphersuiteSupport = 22,
149 CiphersuiteEntries = 23,
150};
151
152/** @brief IPMI IP Origin Types */
153enum class IPSrc : uint8_t
154{
155 Unspecified = 0,
156 Static = 1,
157 DHCP = 2,
158 BIOS = 3,
159 BMC = 4,
160};
161
162/** @brief IPMI Set Status */
163enum class SetStatus : uint8_t
164{
165 Complete = 0,
166 InProgress = 1,
167 Commit = 2,
168};
169
170/** @brief Copies bytes from an array into a trivially copyable container
171 *
172 * @params[out] t - The container receiving the data
173 * @params[in] bytes - The data to copy
174 */
175template <size_t N, typename T>
176void copyInto(T& t, const std::array<uint8_t, N>& bytes)
177{
178 static_assert(std::is_trivially_copyable_v<T>);
179 static_assert(N == sizeof(T));
180 std::memcpy(&t, bytes.data(), bytes.size());
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800181}
182
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700183/** @brief Gets a generic view of the bytes in the input container
184 *
185 * @params[in] t - The data to reference
186 * @return A string_view referencing the bytes in the container
187 */
188template <typename T>
189std::string_view dataRef(const T& t)
tomjose26e17732016-03-03 08:52:51 -0600190{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700191 static_assert(std::is_trivially_copyable_v<T>);
192 return {reinterpret_cast<const char*>(&t), sizeof(T)};
193}
Ratan Gupta533d03b2017-07-30 10:39:22 +0530194
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700195/** @brief The dbus parameters for the interface corresponding to a channel
196 * This helps reduce the number of mapper lookups we need for each
197 * query and simplifies finding the VLAN interface if needed.
198 */
199struct ChannelParams
200{
201 /** @brief The channel ID */
202 int id;
203 /** @brief channel name for the interface */
204 std::string ifname;
205 /** @brief Name of the service on the bus */
206 std::string service;
207 /** @brief Lower level adapter path that is guaranteed to not be a VLAN */
208 std::string ifPath;
209 /** @brief Logical adapter path used for address assignment */
210 std::string logicalPath;
211};
212
213/** @brief Determines the ethernet interface name corresponding to a channel
214 * Tries to map a VLAN object first so that the address information
215 * is accurate. Otherwise it gets the standard ethernet interface.
216 *
217 * @param[in] bus - The bus object used for lookups
218 * @param[in] channel - The channel id corresponding to an ethernet interface
219 * @return Ethernet interface service and object path if it exists
220 */
221std::optional<ChannelParams> maybeGetChannelParams(sdbusplus::bus::bus& bus,
222 uint8_t channel)
223{
224 auto ifname = getChannelName(channel);
225 if (ifname.empty())
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800226 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700227 return std::nullopt;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800228 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800229
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700230 // Enumerate all VLAN + ETHERNET interfaces
231 auto req = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF,
232 "GetSubTree");
233 req.append(PATH_ROOT, 0,
234 std::vector<std::string>{INTF_VLAN, INTF_ETHERNET});
235 auto reply = bus.call(req);
236 ObjectTree objs;
237 reply.read(objs);
238
239 ChannelParams params;
240 for (const auto& [path, impls] : objs)
241 {
242 if (path.find(ifname) == path.npos)
243 {
244 continue;
245 }
246 for (const auto& [service, intfs] : impls)
247 {
248 bool vlan = false;
249 bool ethernet = false;
250 for (const auto& intf : intfs)
251 {
252 if (intf == INTF_VLAN)
253 {
254 vlan = true;
255 }
256 else if (intf == INTF_ETHERNET)
257 {
258 ethernet = true;
259 }
260 }
261 if (params.service.empty() && (vlan || ethernet))
262 {
263 params.service = service;
264 }
265 if (params.ifPath.empty() && !vlan && ethernet)
266 {
267 params.ifPath = path;
268 }
269 if (params.logicalPath.empty() && vlan)
270 {
271 params.logicalPath = path;
272 }
273 }
274 }
275
276 // We must have a path for the underlying interface
277 if (params.ifPath.empty())
278 {
279 return std::nullopt;
280 }
281 // We don't have a VLAN so the logical path is the same
282 if (params.logicalPath.empty())
283 {
284 params.logicalPath = params.ifPath;
285 }
286
287 params.id = channel;
288 params.ifname = std::move(ifname);
289 return std::move(params);
290}
291
292/** @brief A trivial helper around maybeGetChannelParams() that throws an
293 * exception when it is unable to acquire parameters for the channel.
294 *
295 * @param[in] bus - The bus object used for lookups
296 * @param[in] channel - The channel id corresponding to an ethernet interface
297 * @return Ethernet interface service and object path
298 */
299ChannelParams getChannelParams(sdbusplus::bus::bus& bus, uint8_t channel)
300{
301 auto params = maybeGetChannelParams(bus, channel);
302 if (!params)
303 {
304 log<level::ERR>("Failed to get channel params",
305 entry("CHANNEL=%" PRIu8, channel));
306 elog<InternalFailure>();
307 }
308 return std::move(*params);
309}
310
311/** @brief Wraps the phosphor logging method to insert some additional metadata
312 *
313 * @param[in] params - The parameters for the channel
314 * ...
315 */
316template <auto level, typename... Args>
317auto logWithChannel(const ChannelParams& params, Args&&... args)
318{
319 return log<level>(std::forward<Args>(args)...,
320 entry("CHANNEL=%d", params.id),
321 entry("IFNAME=%s", params.ifname.c_str()));
322}
323template <auto level, typename... Args>
324auto logWithChannel(const std::optional<ChannelParams>& params, Args&&... args)
325{
326 if (params)
327 {
328 return logWithChannel<level>(*params, std::forward<Args>(args)...);
329 }
330 return log<level>(std::forward<Args>(args)...);
331}
332
333/** @brief Trivializes using parameter getter functions by providing a bus
334 * and channel parameters automatically.
335 *
336 * @param[in] channel - The channel id corresponding to an ethernet interface
337 * ...
338 */
339template <auto func, typename... Args>
340auto channelCall(uint8_t channel, Args&&... args)
341{
342 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
343 auto params = getChannelParams(bus, channel);
344 return std::invoke(func, bus, params, std::forward<Args>(args)...);
345}
346
347/** @brief Determines if the ethernet interface is using DHCP
348 *
349 * @param[in] bus - The bus object used for lookups
350 * @param[in] params - The parameters for the channel
351 * @return True if DHCP is enabled, false otherwise
352 */
353bool getDHCPProperty(sdbusplus::bus::bus& bus, const ChannelParams& params)
354{
355 return std::get<bool>(getDbusProperty(
356 bus, params.service, params.logicalPath, INTF_ETHERNET, "DHCPEnabled"));
357}
358
359/** @brief Sets the system value for DHCP on the given interface
360 *
361 * @param[in] bus - The bus object used for lookups
362 * @param[in] params - The parameters for the channel
363 * @param[in] on - Whether or not to enable DHCP
364 */
365void setDHCPProperty(sdbusplus::bus::bus& bus, const ChannelParams& params,
366 bool on)
367{
368 setDbusProperty(bus, params.service, params.logicalPath, INTF_ETHERNET,
369 "DHCPEnabled", on);
370}
371
372/** @brief Converts a human readable MAC string into MAC bytes
373 *
374 * @param[in] mac - The MAC string
375 * @return MAC in bytes
376 */
377ether_addr stringToMAC(const char* mac)
378{
379 const ether_addr* ret = ether_aton(mac);
380 if (ret == nullptr)
381 {
382 log<level::ERR>("Invalid MAC Address", entry("MAC=%s", mac));
383 elog<InternalFailure>();
384 }
385 return *ret;
386}
387
388/** @brief Determines the MAC of the ethernet interface
389 *
390 * @param[in] bus - The bus object used for lookups
391 * @param[in] params - The parameters for the channel
392 * @return The configured mac address
393 */
394ether_addr getMACProperty(sdbusplus::bus::bus& bus, const ChannelParams& params)
395{
396 auto macStr = std::get<std::string>(getDbusProperty(
397 bus, params.service, params.ifPath, INTF_MAC, "MACAddress"));
398 return stringToMAC(macStr.c_str());
399}
400
401/** @brief Sets the system value for MAC address on the given interface
402 *
403 * @param[in] bus - The bus object used for lookups
404 * @param[in] params - The parameters for the channel
405 * @param[in] mac - MAC address to apply
406 */
407void setMACProperty(sdbusplus::bus::bus& bus, const ChannelParams& params,
408 const ether_addr& mac)
409{
410 std::string macStr = ether_ntoa(&mac);
411 setDbusProperty(bus, params.service, params.ifPath, INTF_MAC, "MACAddress",
412 macStr);
413}
414
415/** @brief Turns an IP address string into the network byte order form
416 * NOTE: This version strictly validates family matches
417 *
418 * @param[in] address - The string form of the address
419 * @return A network byte order address or none if conversion failed
420 */
421template <int family>
422std::optional<typename AddrFamily<family>::addr>
423 maybeStringToAddr(const char* address)
424{
425 typename AddrFamily<family>::addr ret;
426 if (inet_pton(family, address, &ret) == 1)
427 {
428 return ret;
429 }
430 return std::nullopt;
431}
432
433/** @brief Turns an IP address string into the network byte order form
434 * NOTE: This version strictly validates family matches
435 *
436 * @param[in] address - The string form of the address
437 * @return A network byte order address
438 */
439template <int family>
440typename AddrFamily<family>::addr stringToAddr(const char* address)
441{
442 auto ret = maybeStringToAddr<family>(address);
443 if (!ret)
444 {
445 log<level::ERR>("Failed to convert IP Address",
446 entry("FAMILY=%d", family),
447 entry("ADDRESS=%s", address));
448 elog<InternalFailure>();
449 }
450 return *ret;
451}
452
453/** @brief Turns an IP address in network byte order into a string
454 *
455 * @param[in] address - The string form of the address
456 * @return A network byte order address
457 */
458template <int family>
459std::string addrToString(const typename AddrFamily<family>::addr& address)
460{
461 std::string ret(AddrFamily<family>::maxStrLen, '\0');
462 inet_ntop(family, &address, ret.data(), ret.size());
463 ret.resize(strlen(ret.c_str()));
464 return ret;
465}
466
467/** @brief Retrieves the current gateway for the address family on the system
468 * NOTE: The gateway is currently system wide and not per channel
469 *
470 * @param[in] bus - The bus object used for lookups
471 * @param[in] params - The parameters for the channel
472 * @return An address representing the gateway address if it exists
473 */
474template <int family>
475std::optional<typename AddrFamily<family>::addr>
476 getGatewayProperty(sdbusplus::bus::bus& bus, const ChannelParams& params)
477{
478 auto gatewayStr = std::get<std::string>(getDbusProperty(
479 bus, params.service, PATH_SYSTEMCONFIG, INTF_SYSTEMCONFIG,
480 AddrFamily<family>::propertyGateway));
481 if (gatewayStr.empty())
482 {
483 return std::nullopt;
484 }
485 return stringToAddr<family>(gatewayStr.c_str());
486}
487
488/** @brief Sets the system wide value for the default gateway
489 *
490 * @param[in] bus - The bus object used for lookups
491 * @param[in] params - The parameters for the channel
492 * @param[in] gateway - Gateway address to apply
493 */
494template <int family>
495void setGatewayProperty(sdbusplus::bus::bus& bus, const ChannelParams& params,
496 const typename AddrFamily<family>::addr& address)
497{
498 setDbusProperty(bus, params.service, PATH_SYSTEMCONFIG, INTF_SYSTEMCONFIG,
499 AddrFamily<family>::propertyGateway,
500 addrToString<family>(address));
501}
502
503/** @brief A lazy lookup mechanism for iterating over object properties stored
504 * in DBus. This will only perform the object lookup when needed, and
505 * retains a cache of previous lookups to speed up future iterations.
506 */
507class ObjectLookupCache
508{
509 public:
510 using PropertiesCache = std::unordered_map<std::string, PropertyMap>;
511
512 /** @brief Creates a new ObjectLookupCache for the interface on the bus
513 * NOTE: The inputs to this object must outlive the object since
514 * they are only referenced by it.
515 *
516 * @param[in] bus - The bus object used for lookups
517 * @param[in] params - The parameters for the channel
518 * @param[in] intf - The interface we are looking up
519 */
520 ObjectLookupCache(sdbusplus::bus::bus& bus, const ChannelParams& params,
521 const char* intf) :
522 bus(bus),
523 params(params), intf(intf),
524 objs(getAllDbusObjects(bus, params.logicalPath, intf, ""))
525 {
526 }
527
528 class iterator : public ObjectTree::const_iterator
529 {
530 public:
531 using value_type = PropertiesCache::value_type;
532
533 iterator(ObjectTree::const_iterator it, ObjectLookupCache& container) :
534 ObjectTree::const_iterator(it), container(container),
535 ret(container.cache.end())
536 {
537 }
538 value_type& operator*()
539 {
540 ret = container.get(ObjectTree::const_iterator::operator*().first);
541 return *ret;
542 }
543 value_type* operator->()
544 {
545 return &operator*();
546 }
547
548 private:
549 ObjectLookupCache& container;
550 PropertiesCache::iterator ret;
551 };
552
553 iterator begin() noexcept
554 {
555 return iterator(objs.begin(), *this);
556 }
557
558 iterator end() noexcept
559 {
560 return iterator(objs.end(), *this);
561 }
562
563 private:
564 sdbusplus::bus::bus& bus;
565 const ChannelParams& params;
566 const char* const intf;
567 const ObjectTree objs;
568 PropertiesCache cache;
569
570 /** @brief Gets a cached copy of the object properties if possible
571 * Otherwise performs a query on DBus to look them up
572 *
573 * @param[in] path - The object path to lookup
574 * @return An iterator for the specified object path + properties
575 */
576 PropertiesCache::iterator get(const std::string& path)
577 {
578 auto it = cache.find(path);
579 if (it != cache.end())
580 {
581 return it;
582 }
583 auto properties = getAllDbusProperties(bus, params.service, path, intf);
584 return cache.insert({path, std::move(properties)}).first;
585 }
586};
587
588/** @brief Searches the ip object lookup cache for an address matching
589 * the input parameters. NOTE: The index lacks stability across address
590 * changes since the network daemon has no notion of stable indicies.
591 *
592 * @param[in] bus - The bus object used for lookups
593 * @param[in] params - The parameters for the channel
594 * @param[in] idx - The index of the desired address on the interface
595 * @param[in] origins - The allowed origins for the address objects
596 * @param[in] ips - The object lookup cache holding all of the address info
597 * @return The address and prefix if it was found
598 */
599template <int family>
600std::optional<IfAddr<family>>
601 findIfAddr(sdbusplus::bus::bus& bus, const ChannelParams& params,
602 uint8_t idx,
603 const std::unordered_set<IP::AddressOrigin>& origins,
604 ObjectLookupCache& ips)
605{
606 for (const auto& [path, properties] : ips)
607 {
608 const auto& addrStr = std::get<std::string>(properties.at("Address"));
609 auto addr = maybeStringToAddr<family>(addrStr.c_str());
610 if (!addr)
611 {
612 continue;
613 }
614
615 IP::AddressOrigin origin = IP::convertAddressOriginFromString(
616 std::get<std::string>(properties.at("Origin")));
617 if (origins.find(origin) == origins.end())
618 {
619 continue;
620 }
621
622 if (idx > 0)
623 {
624 idx--;
625 continue;
626 }
627
628 IfAddr<family> ifaddr;
629 ifaddr.path = path;
630 ifaddr.address = *addr;
631 ifaddr.prefix = std::get<uint8_t>(properties.at("PrefixLength"));
632 ifaddr.origin = origin;
633 return std::move(ifaddr);
634 }
635
636 return std::nullopt;
637}
638
639/** @brief Trivial helper around findIfAddr that simplifies calls
640 * for one off lookups. Don't use this if you intend to do multiple
641 * lookups at a time.
642 *
643 * @param[in] bus - The bus object used for lookups
644 * @param[in] params - The parameters for the channel
645 * @param[in] idx - The index of the desired address on the interface
646 * @param[in] origins - The allowed origins for the address objects
647 * @return The address and prefix if it was found
648 */
649template <int family>
650auto getIfAddr(sdbusplus::bus::bus& bus, const ChannelParams& params,
651 uint8_t idx,
652 const std::unordered_set<IP::AddressOrigin>& origins)
653{
654 ObjectLookupCache ips(bus, params, INTF_IP);
655 return findIfAddr<family>(bus, params, idx, origins, ips);
656}
657
658/** @brief Deletes the dbus object. Ignores empty objects or objects that are
659 * missing from the bus.
660 *
661 * @param[in] bus - The bus object used for lookups
662 * @param[in] service - The name of the service
663 * @param[in] path - The path of the object to delete
664 */
665void deleteObjectIfExists(sdbusplus::bus::bus& bus, const std::string& service,
666 const std::string& path)
667{
668 if (path.empty())
669 {
670 return;
671 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530672 try
tomjose26e17732016-03-03 08:52:51 -0600673 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700674 auto req = bus.new_method_call(service.c_str(), path.c_str(),
675 ipmi::DELETE_INTERFACE, "Delete");
676 bus.call_noreply(req);
677 }
678 catch (const sdbusplus::exception::SdBusError& e)
679 {
680 if (strcmp(e.name(), "org.freedesktop.DBus.Error.UnknownObject") != 0)
tomjose26e17732016-03-03 08:52:51 -0600681 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700682 // We want to rethrow real errors
683 throw;
tomjose26e17732016-03-03 08:52:51 -0600684 }
685 }
tomjose26e17732016-03-03 08:52:51 -0600686}
687
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700688/** @brief Sets the address info configured for the interface
689 * If a previous address path exists then it will be removed
690 * before the new address is added.
691 *
692 * @param[in] bus - The bus object used for lookups
693 * @param[in] params - The parameters for the channel
694 * @param[in] address - The address of the new IP
695 * @param[in] prefix - The prefix of the new IP
696 */
697template <int family>
698void createIfAddr(sdbusplus::bus::bus& bus, const ChannelParams& params,
699 const typename AddrFamily<family>::addr& address,
700 uint8_t prefix)
Tom Josepha30c8d32018-03-22 02:15:03 +0530701{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700702 auto newreq =
703 bus.new_method_call(params.service.c_str(), params.logicalPath.c_str(),
704 INTF_IP_CREATE, "IP");
705 std::string protocol =
706 sdbusplus::xyz::openbmc_project::Network::server::convertForMessage(
707 AddrFamily<family>::protocol);
708 newreq.append(protocol, addrToString<family>(address), prefix, "");
709 bus.call_noreply(newreq);
710}
Tom Josepha30c8d32018-03-22 02:15:03 +0530711
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700712/** @brief Trivial helper for getting the IPv4 address from getIfAddrs()
713 *
714 * @param[in] bus - The bus object used for lookups
715 * @param[in] params - The parameters for the channel
716 * @return The address and prefix if found
717 */
718auto getIfAddr4(sdbusplus::bus::bus& bus, const ChannelParams& params)
Tom Josepha30c8d32018-03-22 02:15:03 +0530719{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700720 return getIfAddr<AF_INET>(bus, params, 0, originsV4);
721}
Tom Josepha30c8d32018-03-22 02:15:03 +0530722
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700723/** @brief Reconfigures the IPv4 address info configured for the interface
724 *
725 * @param[in] bus - The bus object used for lookups
726 * @param[in] params - The parameters for the channel
727 * @param[in] address - The new address if specified
728 * @param[in] prefix - The new address prefix if specified
729 */
730void reconfigureIfAddr4(sdbusplus::bus::bus& bus, const ChannelParams& params,
731 const std::optional<in_addr>& address,
732 std::optional<uint8_t> prefix)
733{
734 auto ifaddr = getIfAddr4(bus, params);
735 if (!ifaddr && !address)
Tom Josepha30c8d32018-03-22 02:15:03 +0530736 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700737 log<level::ERR>("Missing address for IPv4 assignment");
Tom Josepha30c8d32018-03-22 02:15:03 +0530738 elog<InternalFailure>();
739 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700740 uint8_t fallbackPrefix = AddrFamily<AF_INET>::defaultPrefix;
741 if (ifaddr)
Tom Josepha30c8d32018-03-22 02:15:03 +0530742 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700743 fallbackPrefix = ifaddr->prefix;
744 deleteObjectIfExists(bus, params.service, ifaddr->path);
745 }
746 createIfAddr<AF_INET>(bus, params, address.value_or(ifaddr->address),
747 prefix.value_or(fallbackPrefix));
748}
749
750/** @brief Gets the vlan ID configured on the interface
751 *
752 * @param[in] bus - The bus object used for lookups
753 * @param[in] params - The parameters for the channel
754 * @return VLAN id or the standard 0 for no VLAN
755 */
756uint16_t getVLANProperty(sdbusplus::bus::bus& bus, const ChannelParams& params)
757{
758 // VLAN devices will always have a separate logical object
759 if (params.ifPath == params.logicalPath)
760 {
761 return 0;
762 }
763
764 auto vlan = std::get<uint32_t>(getDbusProperty(
765 bus, params.service, params.logicalPath, INTF_VLAN, "Id"));
766 if ((vlan & VLAN_VALUE_MASK) != vlan)
767 {
768 logWithChannel<level::ERR>(params, "networkd returned an invalid vlan",
769 entry("VLAN=%" PRIu32, vlan));
Tom Josepha30c8d32018-03-22 02:15:03 +0530770 elog<InternalFailure>();
771 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700772 return vlan;
Tom Josepha30c8d32018-03-22 02:15:03 +0530773}
774
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700775/** @brief Deletes all of the possible configuration parameters for a channel
776 *
777 * @param[in] bus - The bus object used for lookups
778 * @param[in] params - The parameters for the channel
779 */
780void deconfigureChannel(sdbusplus::bus::bus& bus, ChannelParams& params)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500781{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700782 // Delete all objects associated with the interface
783 auto objreq = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF,
784 "GetSubTree");
785 objreq.append(PATH_ROOT, 0, std::vector<std::string>{DELETE_INTERFACE});
786 auto objreply = bus.call(objreq);
787 ObjectTree objs;
788 objreply.read(objs);
789 for (const auto& [path, impls] : objs)
790 {
791 if (path.find(params.ifname) == path.npos)
792 {
793 continue;
794 }
795 for (const auto& [service, intfs] : impls)
796 {
797 deleteObjectIfExists(bus, service, path);
798 }
799 // Update params to reflect the deletion of vlan
800 if (path == params.logicalPath)
801 {
802 params.logicalPath = params.ifPath;
803 }
804 }
805
806 // Clear out any settings on the lower physical interface
807 setDHCPProperty(bus, params, false);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500808}
809
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700810/** @brief Creates a new VLAN on the specified interface
811 *
812 * @param[in] bus - The bus object used for lookups
813 * @param[in] params - The parameters for the channel
814 * @param[in] vlan - The id of the new vlan
815 */
816void createVLAN(sdbusplus::bus::bus& bus, ChannelParams& params, uint16_t vlan)
Ratan Guptab8e99552017-07-27 07:07:48 +0530817{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700818 if (vlan == 0)
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530819 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700820 return;
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530821 }
822
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700823 auto req = bus.new_method_call(params.service.c_str(), PATH_ROOT,
824 INTF_VLAN_CREATE, "VLAN");
825 req.append(params.ifname, static_cast<uint32_t>(vlan));
826 auto reply = bus.call(req);
827 sdbusplus::message::object_path newPath;
828 reply.read(newPath);
829 params.logicalPath = std::move(newPath);
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530830}
831
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700832/** @brief Performs the necessary reconfiguration to change the VLAN
833 *
834 * @param[in] bus - The bus object used for lookups
835 * @param[in] params - The parameters for the channel
836 * @param[in] vlan - The new vlan id to use
837 */
838void reconfigureVLAN(sdbusplus::bus::bus& bus, ChannelParams& params,
839 uint16_t vlan)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500840{
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700841 // Unfortunatetly we don't have built-in functions to migrate our interface
842 // customizations to new VLAN interfaces, or have some kind of decoupling.
843 // We therefore must retain all of our old information, setup the new VLAN
844 // configuration, then restore the old info.
Nan Li3d0df912016-10-18 19:51:41 +0800845
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700846 // Save info from the old logical interface
847 ObjectLookupCache ips(bus, params, INTF_IP);
848 auto ifaddr4 = findIfAddr<AF_INET>(bus, params, 0, originsV4, ips);
849 auto dhcp = getDHCPProperty(bus, params);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500850
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700851 deconfigureChannel(bus, params);
852 createVLAN(bus, params, vlan);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500853
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700854 // Re-establish the saved settings
855 setDHCPProperty(bus, params, dhcp);
856 if (ifaddr4)
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800857 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700858 createIfAddr<AF_INET>(bus, params, ifaddr4->address, ifaddr4->prefix);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800859 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700860}
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800861
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700862/** @brief Turns a prefix into a netmask
863 *
864 * @param[in] prefix - The prefix length
865 * @return The netmask
866 */
867in_addr prefixToNetmask(uint8_t prefix)
868{
869 if (prefix > 32)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500870 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700871 log<level::ERR>("Invalid prefix", entry("PREFIX=%" PRIu8, prefix));
872 elog<InternalFailure>();
873 }
874 if (prefix == 0)
875 {
876 // Avoids 32-bit lshift by 32 UB
877 return {};
878 }
879 return {htobe32(~UINT32_C(0) << (32 - prefix))};
880}
881
882/** @brief Turns a a netmask into a prefix length
883 *
884 * @param[in] netmask - The netmask in byte form
885 * @return The prefix length
886 */
887uint8_t netmaskToPrefix(in_addr netmask)
888{
889 uint32_t x = be32toh(netmask.s_addr);
890 if ((~x & (~x + 1)) != 0)
891 {
892 char maskStr[INET_ADDRSTRLEN];
893 inet_ntop(AF_INET, &netmask, maskStr, sizeof(maskStr));
894 log<level::ERR>("Invalid netmask", entry("NETMASK=%s", maskStr));
895 elog<InternalFailure>();
896 }
897 return 32 - __builtin_ctz(x);
898}
899
900// We need to store this value so it can be returned to the client
901// It is volatile so safe to store in daemon memory.
902static std::unordered_map<uint8_t, SetStatus> setStatus;
903
904// Until we have good support for fixed versions of IPMI tool
905// we need to return the VLAN id for disabled VLANs. The value is only
906// used for verification that a disable operation succeeded and will only
907// be sent if our system indicates that vlans are disabled.
908static std::unordered_map<uint8_t, uint16_t> lastDisabledVlan;
909
910/** @brief Gets the set status for the channel if it exists
911 * Otherise populates and returns the default value.
912 *
913 * @param[in] channel - The channel id corresponding to an ethernet interface
914 * @return A reference to the SetStatus for the channel
915 */
916SetStatus& getSetStatus(uint8_t channel)
917{
918 auto it = setStatus.find(channel);
919 if (it != setStatus.end())
920 {
921 return it->second;
922 }
923 return setStatus[channel] = SetStatus::Complete;
924}
925
926RspType<> setLan(uint4_t channelBits, uint4_t, uint8_t parameter,
927 message::Payload& req)
928{
929 auto channel = static_cast<uint8_t>(channelBits);
930 if (!doesDeviceExist(channel))
931 {
932 req.trailingOk = true;
933 return responseInvalidFieldRequest();
934 }
935
936 switch (static_cast<LanParam>(parameter))
937 {
938 case LanParam::SetStatus:
939 {
940 uint2_t flag;
941 uint6_t rsvd;
942 if (req.unpack(flag, rsvd) != 0 || !req.fullyUnpacked())
943 {
944 return responseReqDataLenInvalid();
945 }
946 auto status = static_cast<SetStatus>(static_cast<uint8_t>(flag));
947 switch (status)
948 {
949 case SetStatus::Complete:
950 {
951 getSetStatus(channel) = status;
952 return responseSuccess();
953 }
954 case SetStatus::InProgress:
955 {
956 auto& storedStatus = getSetStatus(channel);
957 if (storedStatus == SetStatus::InProgress)
958 {
959 return response(ccParamSetLocked);
960 }
961 storedStatus = status;
962 return responseSuccess();
963 }
964 case SetStatus::Commit:
965 if (getSetStatus(channel) != SetStatus::InProgress)
966 {
967 return responseInvalidFieldRequest();
968 }
969 return responseSuccess();
970 }
971 return response(ccParamNotSupported);
972 }
973 case LanParam::AuthSupport:
974 {
975 req.trailingOk = true;
976 return response(ccParamReadOnly);
977 }
978 case LanParam::AuthEnables:
979 {
980 req.trailingOk = true;
981 return response(ccParamNotSupported);
982 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800983 case LanParam::IP:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600984 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700985 in_addr ip;
986 std::array<uint8_t, sizeof(ip)> bytes;
987 if (req.unpack(bytes) != 0 || !req.fullyUnpacked())
988 {
989 return responseReqDataLenInvalid();
990 }
991 copyInto(ip, bytes);
992 channelCall<reconfigureIfAddr4>(channel, ip, std::nullopt);
993 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +0530994 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700995 case LanParam::IPSrc:
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530996 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -0700997 uint4_t flag;
998 uint4_t rsvd;
999 if (req.unpack(flag, rsvd) != 0 || !req.fullyUnpacked())
1000 {
1001 return responseReqDataLenInvalid();
1002 }
1003 switch (static_cast<IPSrc>(static_cast<uint8_t>(flag)))
1004 {
1005 case IPSrc::DHCP:
1006 {
1007 channelCall<setDHCPProperty>(channel, true);
1008 return responseSuccess();
1009 }
1010 case IPSrc::Unspecified:
1011 case IPSrc::Static:
1012 case IPSrc::BIOS:
1013 case IPSrc::BMC:
1014 {
1015 channelCall<setDHCPProperty>(channel, false);
1016 return responseSuccess();
1017 }
1018 }
1019 return response(ccParamNotSupported);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +05301020 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001021 case LanParam::MAC:
Ratan Guptab8e99552017-07-27 07:07:48 +05301022 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001023 ether_addr mac;
1024 std::array<uint8_t, sizeof(mac)> bytes;
1025 if (req.unpack(bytes) != 0 || !req.fullyUnpacked())
Suryakanth Sekar0a327e12019-08-08 14:30:19 +05301026 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001027 return responseReqDataLenInvalid();
Suryakanth Sekar0a327e12019-08-08 14:30:19 +05301028 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001029 copyInto(mac, bytes);
1030 channelCall<setMACProperty>(channel, mac);
1031 return responseSuccess();
Ratan Gupta533d03b2017-07-30 10:39:22 +05301032 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001033 case LanParam::SubnetMask:
Ratan Guptab8e99552017-07-27 07:07:48 +05301034 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001035 in_addr netmask;
1036 std::array<uint8_t, sizeof(netmask)> bytes;
1037 if (req.unpack(bytes) != 0 || !req.fullyUnpacked())
Ratan Guptab8e99552017-07-27 07:07:48 +05301038 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001039 return responseReqDataLenInvalid();
Ratan Guptab8e99552017-07-27 07:07:48 +05301040 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001041 copyInto(netmask, bytes);
1042 channelCall<reconfigureIfAddr4>(channel, std::nullopt,
1043 netmaskToPrefix(netmask));
1044 return responseSuccess();
Ratan Guptab8e99552017-07-27 07:07:48 +05301045 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001046 case LanParam::Gateway1:
Ratan Guptab8e99552017-07-27 07:07:48 +05301047 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001048 in_addr gateway;
1049 std::array<uint8_t, sizeof(gateway)> bytes;
1050 if (req.unpack(bytes) != 0 || !req.fullyUnpacked())
1051 {
1052 return responseReqDataLenInvalid();
1053 }
1054 copyInto(gateway, bytes);
1055 channelCall<setGatewayProperty<AF_INET>>(channel, gateway);
1056 return responseSuccess();
1057 }
1058 case LanParam::VLANId:
1059 {
1060 uint16_t vlanData;
1061 if (req.unpack(vlanData) != 0 || !req.fullyUnpacked())
1062 {
1063 return responseReqDataLenInvalid();
1064 }
1065 if ((vlanData & VLAN_ENABLE_FLAG) == 0)
1066 {
1067 lastDisabledVlan[channel] = vlanData & VLAN_VALUE_MASK;
1068 vlanData = 0;
1069 }
1070 channelCall<reconfigureVLAN>(channel, vlanData & VLAN_VALUE_MASK);
1071 return responseSuccess();
1072 }
1073 case LanParam::CiphersuiteSupport:
1074 case LanParam::CiphersuiteEntries:
1075 {
1076 req.trailingOk = true;
1077 return response(ccParamReadOnly);
Ratan Guptab8e99552017-07-27 07:07:48 +05301078 }
Ratan Guptab8e99552017-07-27 07:07:48 +05301079 }
vishwa1eaea4f2016-02-26 11:57:40 -06001080
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001081 req.trailingOk = true;
1082 return response(ccParamNotSupported);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001083}
1084
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001085RspType<message::Payload> getLan(uint4_t channelBits, uint3_t, bool revOnly,
1086 uint8_t parameter, uint8_t set, uint8_t block)
Ratan Guptab8e99552017-07-27 07:07:48 +05301087{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001088 message::Payload ret;
1089 constexpr uint8_t current_revision = 0x11;
1090 ret.pack(current_revision);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001091
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001092 if (revOnly)
Suryakanth Sekare4054402019-08-08 15:16:52 +05301093 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001094 return responseSuccess(std::move(ret));
Suryakanth Sekare4054402019-08-08 15:16:52 +05301095 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001096
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001097 auto channel = static_cast<uint8_t>(channelBits);
1098 if (!doesDeviceExist(channel))
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001099 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001100 return responseInvalidFieldRequest();
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001101 }
1102
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001103 static std::vector<uint8_t> cipherList;
1104 static bool listInit = false;
1105 if (!listInit)
1106 {
1107 try
1108 {
1109 cipherList = cipher::getCipherList();
1110 listInit = true;
1111 }
1112 catch (const std::exception& e)
1113 {
1114 }
1115 }
1116
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001117 switch (static_cast<LanParam>(parameter))
Tom Josepha30c8d32018-03-22 02:15:03 +05301118 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001119 case LanParam::SetStatus:
Tom Josepha30c8d32018-03-22 02:15:03 +05301120 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001121 SetStatus status;
1122 try
1123 {
1124 status = setStatus.at(channel);
1125 }
1126 catch (const std::out_of_range&)
1127 {
1128 status = SetStatus::Complete;
1129 }
1130 ret.pack(static_cast<uint2_t>(status), uint6_t{});
1131 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301132 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001133 case LanParam::AuthSupport:
Tom Josepha30c8d32018-03-22 02:15:03 +05301134 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001135 std::bitset<6> support;
1136 ret.pack(support, uint2_t{});
1137 return responseSuccess(std::move(ret));
Tom Josepha30c8d32018-03-22 02:15:03 +05301138 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001139 case LanParam::AuthEnables:
vishwa1eaea4f2016-02-26 11:57:40 -06001140 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001141 std::bitset<6> enables;
1142 ret.pack(enables, uint2_t{}); // Callback
1143 ret.pack(enables, uint2_t{}); // User
1144 ret.pack(enables, uint2_t{}); // Operator
1145 ret.pack(enables, uint2_t{}); // Admin
1146 ret.pack(enables, uint2_t{}); // OEM
1147 return responseSuccess(std::move(ret));
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001148 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001149 case LanParam::IP:
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001150 {
1151 auto ifaddr = channelCall<getIfAddr4>(channel);
1152 in_addr addr{};
1153 if (ifaddr)
1154 {
1155 addr = ifaddr->address;
1156 }
1157 ret.pack(dataRef(addr));
1158 return responseSuccess(std::move(ret));
1159 }
1160 case LanParam::IPSrc:
1161 {
1162 auto src = IPSrc::Static;
1163 if (channelCall<getDHCPProperty>(channel))
1164 {
1165 src = IPSrc::DHCP;
1166 }
1167 ret.pack(static_cast<uint4_t>(src), uint4_t{});
1168 return responseSuccess(std::move(ret));
1169 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -08001170 case LanParam::MAC:
William A. Kennington III39f94ef2018-11-19 22:36:16 -08001171 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001172 ether_addr mac = channelCall<getMACProperty>(channel);
1173 ret.pack(dataRef(mac));
1174 return responseSuccess(std::move(ret));
1175 }
1176 case LanParam::SubnetMask:
1177 {
1178 auto ifaddr = channelCall<getIfAddr4>(channel);
1179 uint8_t prefix = AddrFamily<AF_INET>::defaultPrefix;
1180 if (ifaddr)
Ratan Guptab8e99552017-07-27 07:07:48 +05301181 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001182 prefix = ifaddr->prefix;
1183 }
1184 in_addr netmask = prefixToNetmask(prefix);
1185 ret.pack(dataRef(netmask));
1186 return responseSuccess(std::move(ret));
1187 }
1188 case LanParam::Gateway1:
1189 {
1190 auto gateway =
1191 channelCall<getGatewayProperty<AF_INET>>(channel).value_or(
1192 in_addr{});
1193 ret.pack(dataRef(gateway));
1194 return responseSuccess(std::move(ret));
1195 }
1196 case LanParam::VLANId:
1197 {
1198 uint16_t vlan = channelCall<getVLANProperty>(channel);
1199 if (vlan != 0)
1200 {
1201 vlan |= VLAN_ENABLE_FLAG;
Ratan Guptab8e99552017-07-27 07:07:48 +05301202 }
1203 else
1204 {
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001205 vlan = lastDisabledVlan[channel];
Ratan Guptab8e99552017-07-27 07:07:48 +05301206 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001207 ret.pack(vlan);
1208 return responseSuccess(std::move(ret));
Adriana Kobylak342df102016-02-10 13:48:16 -06001209 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001210 case LanParam::CiphersuiteSupport:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001211 {
1212 if (!listInit)
1213 {
1214 return responseUnspecifiedError();
1215 }
1216 ret.pack(static_cast<uint8_t>(cipherList.size() - 1));
1217 return responseSuccess(std::move(ret));
1218 }
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001219 case LanParam::CiphersuiteEntries:
Johnathan Manteyaffadb52019-10-07 10:13:53 -07001220 {
1221 if (!listInit)
1222 {
1223 return responseUnspecifiedError();
1224 }
1225 ret.pack(cipherList);
1226 return responseSuccess(std::move(ret));
1227 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001228 }
1229
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001230 return response(ccParamNotSupported);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001231}
1232
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001233} // namespace transport
1234} // namespace ipmi
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301235
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001236void register_netfn_transport_functions() __attribute__((constructor));
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301237
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001238void register_netfn_transport_functions()
1239{
William A. Kennington IIIc514d872019-04-06 18:19:38 -07001240 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1241 ipmi::transport::cmdSetLanConfigParameters,
1242 ipmi::Privilege::Admin, ipmi::transport::setLan);
1243 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
1244 ipmi::transport::cmdGetLanConfigParameters,
1245 ipmi::Privilege::Admin, ipmi::transport::getLan);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001246}