1690a2342SPatrick Venture #pragma once
2690a2342SPatrick Venture 
38a7236aeSJohn Wang #include "app/channel.hpp"
48a7236aeSJohn Wang #include "user_channel/cipher_mgmt.hpp"
58a7236aeSJohn Wang 
6fbc6c9d7SPatrick Williams #include <ipmid/api-types.hpp>
7fbc6c9d7SPatrick Williams #include <ipmid/api.hpp>
8fbc6c9d7SPatrick Williams #include <ipmid/message.hpp>
9fbc6c9d7SPatrick Williams #include <ipmid/message/types.hpp>
10fbc6c9d7SPatrick Williams #include <ipmid/types.hpp>
11fbc6c9d7SPatrick Williams #include <ipmid/utils.hpp>
12fbc6c9d7SPatrick Williams #include <phosphor-logging/elog-errors.hpp>
13fbc6c9d7SPatrick Williams #include <phosphor-logging/elog.hpp>
14fbc6c9d7SPatrick Williams #include <phosphor-logging/log.hpp>
15fbc6c9d7SPatrick Williams #include <sdbusplus/bus.hpp>
16fbc6c9d7SPatrick Williams #include <sdbusplus/exception.hpp>
17*726f2bddSWilliam A. Kennington III #include <stdplus/net/addr/ether.hpp>
18*726f2bddSWilliam A. Kennington III #include <stdplus/net/addr/ip.hpp>
19*726f2bddSWilliam A. Kennington III #include <stdplus/str/conv.hpp>
20fbc6c9d7SPatrick Williams #include <user_channel/channel_layer.hpp>
21fbc6c9d7SPatrick Williams #include <xyz/openbmc_project/Common/error.hpp>
22fbc6c9d7SPatrick Williams #include <xyz/openbmc_project/Network/EthernetInterface/server.hpp>
23fbc6c9d7SPatrick Williams #include <xyz/openbmc_project/Network/IP/server.hpp>
24fbc6c9d7SPatrick Williams #include <xyz/openbmc_project/Network/Neighbor/server.hpp>
25fbc6c9d7SPatrick Williams 
268a7236aeSJohn Wang #include <cinttypes>
278a7236aeSJohn Wang #include <functional>
288a7236aeSJohn Wang #include <optional>
298a7236aeSJohn Wang #include <string>
308a7236aeSJohn Wang #include <string_view>
318a7236aeSJohn Wang #include <unordered_map>
328a7236aeSJohn Wang #include <unordered_set>
338a7236aeSJohn Wang #include <utility>
34690a2342SPatrick Venture 
35690a2342SPatrick Venture namespace ipmi
36690a2342SPatrick Venture {
37690a2342SPatrick Venture namespace transport
38690a2342SPatrick Venture {
39690a2342SPatrick Venture 
408a7236aeSJohn Wang // D-Bus Network Daemon definitions
418a7236aeSJohn Wang constexpr auto PATH_ROOT = "/xyz/openbmc_project/network";
428a7236aeSJohn Wang constexpr auto INTF_ETHERNET = "xyz.openbmc_project.Network.EthernetInterface";
438a7236aeSJohn Wang constexpr auto INTF_IP = "xyz.openbmc_project.Network.IP";
448a7236aeSJohn Wang constexpr auto INTF_IP_CREATE = "xyz.openbmc_project.Network.IP.Create";
458a7236aeSJohn Wang constexpr auto INTF_MAC = "xyz.openbmc_project.Network.MACAddress";
468a7236aeSJohn Wang constexpr auto INTF_NEIGHBOR = "xyz.openbmc_project.Network.Neighbor";
478a7236aeSJohn Wang constexpr auto INTF_NEIGHBOR_CREATE_STATIC =
488a7236aeSJohn Wang     "xyz.openbmc_project.Network.Neighbor.CreateStatic";
498a7236aeSJohn Wang constexpr auto INTF_VLAN = "xyz.openbmc_project.Network.VLAN";
508a7236aeSJohn Wang constexpr auto INTF_VLAN_CREATE = "xyz.openbmc_project.Network.VLAN.Create";
518a7236aeSJohn Wang 
52690a2342SPatrick Venture /** @brief IPMI LAN Parameters */
53690a2342SPatrick Venture enum class LanParam : uint8_t
54690a2342SPatrick Venture {
55690a2342SPatrick Venture     SetStatus = 0,
56690a2342SPatrick Venture     AuthSupport = 1,
57690a2342SPatrick Venture     AuthEnables = 2,
58690a2342SPatrick Venture     IP = 3,
59690a2342SPatrick Venture     IPSrc = 4,
60690a2342SPatrick Venture     MAC = 5,
61690a2342SPatrick Venture     SubnetMask = 6,
62690a2342SPatrick Venture     Gateway1 = 12,
63690a2342SPatrick Venture     Gateway1MAC = 13,
64690a2342SPatrick Venture     VLANId = 20,
65690a2342SPatrick Venture     CiphersuiteSupport = 22,
66690a2342SPatrick Venture     CiphersuiteEntries = 23,
67690a2342SPatrick Venture     cipherSuitePrivilegeLevels = 24,
68690a2342SPatrick Venture     IPFamilySupport = 50,
69690a2342SPatrick Venture     IPFamilyEnables = 51,
70690a2342SPatrick Venture     IPv6Status = 55,
71690a2342SPatrick Venture     IPv6StaticAddresses = 56,
72690a2342SPatrick Venture     IPv6DynamicAddresses = 59,
73690a2342SPatrick Venture     IPv6RouterControl = 64,
74690a2342SPatrick Venture     IPv6StaticRouter1IP = 65,
75690a2342SPatrick Venture     IPv6StaticRouter1MAC = 66,
76690a2342SPatrick Venture     IPv6StaticRouter1PrefixLength = 67,
77690a2342SPatrick Venture     IPv6StaticRouter1PrefixValue = 68,
78690a2342SPatrick Venture };
79690a2342SPatrick Venture 
80690a2342SPatrick Venture /** @brief IPMI IP Origin Types */
81690a2342SPatrick Venture enum class IPSrc : uint8_t
82690a2342SPatrick Venture {
83690a2342SPatrick Venture     Unspecified = 0,
84690a2342SPatrick Venture     Static = 1,
85690a2342SPatrick Venture     DHCP = 2,
86690a2342SPatrick Venture     BIOS = 3,
87690a2342SPatrick Venture     BMC = 4,
88690a2342SPatrick Venture };
89690a2342SPatrick Venture 
90690a2342SPatrick Venture /** @brief IPMI Set Status */
91690a2342SPatrick Venture enum class SetStatus : uint8_t
92690a2342SPatrick Venture {
93690a2342SPatrick Venture     Complete = 0,
94690a2342SPatrick Venture     InProgress = 1,
95690a2342SPatrick Venture     Commit = 2,
96690a2342SPatrick Venture };
97690a2342SPatrick Venture 
98690a2342SPatrick Venture /** @brief IPMI Family Suport Bits */
99690a2342SPatrick Venture namespace IPFamilySupportFlag
100690a2342SPatrick Venture {
101690a2342SPatrick Venture constexpr uint8_t IPv6Only = 0;
102690a2342SPatrick Venture constexpr uint8_t DualStack = 1;
103690a2342SPatrick Venture constexpr uint8_t IPv6Alerts = 2;
104690a2342SPatrick Venture } // namespace IPFamilySupportFlag
105690a2342SPatrick Venture 
106690a2342SPatrick Venture /** @brief IPMI IPFamily Enables Flag */
107690a2342SPatrick Venture enum class IPFamilyEnables : uint8_t
108690a2342SPatrick Venture {
109690a2342SPatrick Venture     IPv4Only = 0,
110690a2342SPatrick Venture     IPv6Only = 1,
111690a2342SPatrick Venture     DualStack = 2,
112690a2342SPatrick Venture };
113690a2342SPatrick Venture 
114690a2342SPatrick Venture /** @brief IPMI IPv6 Dyanmic Status Bits */
115690a2342SPatrick Venture namespace IPv6StatusFlag
116690a2342SPatrick Venture {
117690a2342SPatrick Venture constexpr uint8_t DHCP = 0;
118690a2342SPatrick Venture constexpr uint8_t SLAAC = 1;
119690a2342SPatrick Venture }; // namespace IPv6StatusFlag
120690a2342SPatrick Venture 
121690a2342SPatrick Venture /** @brief IPMI IPv6 Source */
122690a2342SPatrick Venture enum class IPv6Source : uint8_t
123690a2342SPatrick Venture {
124690a2342SPatrick Venture     Static = 0,
125690a2342SPatrick Venture     SLAAC = 1,
126690a2342SPatrick Venture     DHCP = 2,
127690a2342SPatrick Venture };
128690a2342SPatrick Venture 
129690a2342SPatrick Venture /** @brief IPMI IPv6 Address Status */
130690a2342SPatrick Venture enum class IPv6AddressStatus : uint8_t
131690a2342SPatrick Venture {
132690a2342SPatrick Venture     Active = 0,
133690a2342SPatrick Venture     Disabled = 1,
134690a2342SPatrick Venture };
135690a2342SPatrick Venture 
136690a2342SPatrick Venture namespace IPv6RouterControlFlag
137690a2342SPatrick Venture {
138690a2342SPatrick Venture constexpr uint8_t Static = 0;
139690a2342SPatrick Venture constexpr uint8_t Dynamic = 1;
140690a2342SPatrick Venture }; // namespace IPv6RouterControlFlag
141690a2342SPatrick Venture 
142690a2342SPatrick Venture // LAN Handler specific response codes
143690a2342SPatrick Venture constexpr Cc ccParamNotSupported = 0x80;
144690a2342SPatrick Venture constexpr Cc ccParamSetLocked = 0x81;
145690a2342SPatrick Venture constexpr Cc ccParamReadOnly = 0x82;
146690a2342SPatrick Venture 
147690a2342SPatrick Venture // VLANs are a 12-bit value
148690a2342SPatrick Venture constexpr uint16_t VLAN_VALUE_MASK = 0x0fff;
149690a2342SPatrick Venture constexpr uint16_t VLAN_ENABLE_FLAG = 0x8000;
150690a2342SPatrick Venture 
151690a2342SPatrick Venture // Arbitrary v6 Address Limits to prevent too much output in ipmitool
152690a2342SPatrick Venture constexpr uint8_t MAX_IPV6_STATIC_ADDRESSES = 15;
153690a2342SPatrick Venture constexpr uint8_t MAX_IPV6_DYNAMIC_ADDRESSES = 15;
154690a2342SPatrick Venture 
1556d4a44edSJiaqing Zhao // Prefix length limits of phosphor-networkd
1566d4a44edSJiaqing Zhao constexpr uint8_t MIN_IPV6_PREFIX_LENGTH = 1;
1576d4a44edSJiaqing Zhao constexpr uint8_t MAX_IPV6_PREFIX_LENGTH = 128;
1586d4a44edSJiaqing Zhao 
1598a7236aeSJohn Wang /** @brief The dbus parameters for the interface corresponding to a channel
1608a7236aeSJohn Wang  *         This helps reduce the number of mapper lookups we need for each
1618a7236aeSJohn Wang  *         query and simplifies finding the VLAN interface if needed.
1628a7236aeSJohn Wang  */
1638a7236aeSJohn Wang struct ChannelParams
1648a7236aeSJohn Wang {
1658a7236aeSJohn Wang     /** @brief The channel ID */
1668a7236aeSJohn Wang     int id;
1678a7236aeSJohn Wang     /** @brief channel name for the interface */
1688a7236aeSJohn Wang     std::string ifname;
1698a7236aeSJohn Wang     /** @brief Name of the service on the bus */
1708a7236aeSJohn Wang     std::string service;
1718a7236aeSJohn Wang     /** @brief Lower level adapter path that is guaranteed to not be a VLAN */
1728a7236aeSJohn Wang     std::string ifPath;
1738a7236aeSJohn Wang     /** @brief Logical adapter path used for address assignment */
1748a7236aeSJohn Wang     std::string logicalPath;
1758a7236aeSJohn Wang };
1768a7236aeSJohn Wang 
1778a7236aeSJohn Wang /** @brief Determines the ethernet interface name corresponding to a channel
1788a7236aeSJohn Wang  *         Tries to map a VLAN object first so that the address information
1798a7236aeSJohn Wang  *         is accurate. Otherwise it gets the standard ethernet interface.
1808a7236aeSJohn Wang  *
1818a7236aeSJohn Wang  *  @param[in] bus     - The bus object used for lookups
1828a7236aeSJohn Wang  *  @param[in] channel - The channel id corresponding to an ethernet interface
1838a7236aeSJohn Wang  *  @return Ethernet interface service and object path if it exists
1848a7236aeSJohn Wang  */
1855d82f474SPatrick Williams std::optional<ChannelParams> maybeGetChannelParams(sdbusplus::bus_t& bus,
1868a7236aeSJohn Wang                                                    uint8_t channel);
1878a7236aeSJohn Wang 
1888a7236aeSJohn Wang /** @brief A trivial helper around maybeGetChannelParams() that throws an
1898a7236aeSJohn Wang  *         exception when it is unable to acquire parameters for the channel.
1908a7236aeSJohn Wang  *
1918a7236aeSJohn Wang  *  @param[in] bus     - The bus object used for lookups
1928a7236aeSJohn Wang  *  @param[in] channel - The channel id corresponding to an ethernet interface
1938a7236aeSJohn Wang  *  @return Ethernet interface service and object path
1948a7236aeSJohn Wang  */
1955d82f474SPatrick Williams ChannelParams getChannelParams(sdbusplus::bus_t& bus, uint8_t channel);
1968a7236aeSJohn Wang 
1978a7236aeSJohn Wang /** @brief Trivializes using parameter getter functions by providing a bus
1988a7236aeSJohn Wang  *         and channel parameters automatically.
1998a7236aeSJohn Wang  *
2008a7236aeSJohn Wang  *  @param[in] channel - The channel id corresponding to an ethernet interface
2018a7236aeSJohn Wang  *  ...
2028a7236aeSJohn Wang  */
2038a7236aeSJohn Wang template <auto func, typename... Args>
2048a7236aeSJohn Wang auto channelCall(uint8_t channel, Args&&... args)
2058a7236aeSJohn Wang {
2065d82f474SPatrick Williams     sdbusplus::bus_t bus(ipmid_get_sd_bus_connection());
2078a7236aeSJohn Wang     auto params = getChannelParams(bus, channel);
2088a7236aeSJohn Wang     return std::invoke(func, bus, params, std::forward<Args>(args)...);
2098a7236aeSJohn Wang }
2108a7236aeSJohn Wang 
2118a7236aeSJohn Wang /** @brief Generic paramters for different address families */
2128a7236aeSJohn Wang template <int family>
2138a7236aeSJohn Wang struct AddrFamily
214fbc6c9d7SPatrick Williams {};
2158a7236aeSJohn Wang 
2168a7236aeSJohn Wang /** @brief Parameter specialization for IPv4 */
2178a7236aeSJohn Wang template <>
2188a7236aeSJohn Wang struct AddrFamily<AF_INET>
2198a7236aeSJohn Wang {
220*726f2bddSWilliam A. Kennington III     using addr = stdplus::In4Addr;
2218a7236aeSJohn Wang     static constexpr auto protocol =
222523e2d1bSWilly Tu         sdbusplus::server::xyz::openbmc_project::network::IP::Protocol::IPv4;
2238a7236aeSJohn Wang     static constexpr size_t maxStrLen = INET6_ADDRSTRLEN;
2248a7236aeSJohn Wang     static constexpr uint8_t defaultPrefix = 32;
2258a7236aeSJohn Wang     static constexpr char propertyGateway[] = "DefaultGateway";
2268a7236aeSJohn Wang };
2278a7236aeSJohn Wang 
2288a7236aeSJohn Wang /** @brief Parameter specialization for IPv6 */
2298a7236aeSJohn Wang template <>
2308a7236aeSJohn Wang struct AddrFamily<AF_INET6>
2318a7236aeSJohn Wang {
232*726f2bddSWilliam A. Kennington III     using addr = stdplus::In6Addr;
2338a7236aeSJohn Wang     static constexpr auto protocol =
234523e2d1bSWilly Tu         sdbusplus::server::xyz::openbmc_project::network::IP::Protocol::IPv6;
2358a7236aeSJohn Wang     static constexpr size_t maxStrLen = INET6_ADDRSTRLEN;
2368a7236aeSJohn Wang     static constexpr uint8_t defaultPrefix = 128;
2378a7236aeSJohn Wang     static constexpr char propertyGateway[] = "DefaultGateway6";
2388a7236aeSJohn Wang };
2398a7236aeSJohn Wang 
2408a7236aeSJohn Wang /** @brief Interface Neighbor configuration parameters */
2418a7236aeSJohn Wang template <int family>
2428a7236aeSJohn Wang struct IfNeigh
2438a7236aeSJohn Wang {
2448a7236aeSJohn Wang     std::string path;
2458a7236aeSJohn Wang     typename AddrFamily<family>::addr ip;
246*726f2bddSWilliam A. Kennington III     stdplus::EtherAddr mac;
2478a7236aeSJohn Wang };
2488a7236aeSJohn Wang 
2498a7236aeSJohn Wang /** @brief Interface IP Address configuration parameters */
2508a7236aeSJohn Wang template <int family>
2518a7236aeSJohn Wang struct IfAddr
2528a7236aeSJohn Wang {
2538a7236aeSJohn Wang     std::string path;
2548a7236aeSJohn Wang     typename AddrFamily<family>::addr address;
255523e2d1bSWilly Tu     sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin origin;
2568a7236aeSJohn Wang     uint8_t prefix;
2578a7236aeSJohn Wang };
2588a7236aeSJohn Wang 
2598a7236aeSJohn Wang /** @brief Valid address origins for IPv6 */
2608a7236aeSJohn Wang static inline const std::unordered_set<
261523e2d1bSWilly Tu     sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin>
262523e2d1bSWilly Tu     originsV6Static = {sdbusplus::server::xyz::openbmc_project::network::IP::
2638a7236aeSJohn Wang                            AddressOrigin::Static};
2648a7236aeSJohn Wang static inline const std::unordered_set<
265523e2d1bSWilly Tu     sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin>
2668a7236aeSJohn Wang     originsV6Dynamic = {
267523e2d1bSWilly Tu         sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin::
2688a7236aeSJohn Wang             DHCP,
269523e2d1bSWilly Tu         sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin::
2708a7236aeSJohn Wang             SLAAC,
2718a7236aeSJohn Wang };
2728a7236aeSJohn Wang 
2738a7236aeSJohn Wang /** @brief A lazy lookup mechanism for iterating over object properties stored
2748a7236aeSJohn Wang  *         in DBus. This will only perform the object lookup when needed, and
2758a7236aeSJohn Wang  *         retains a cache of previous lookups to speed up future iterations.
2768a7236aeSJohn Wang  */
2778a7236aeSJohn Wang class ObjectLookupCache
2788a7236aeSJohn Wang {
2798a7236aeSJohn Wang   public:
2808a7236aeSJohn Wang     using PropertiesCache = std::unordered_map<std::string, PropertyMap>;
2818a7236aeSJohn Wang 
2828a7236aeSJohn Wang     /** @brief Creates a new ObjectLookupCache for the interface on the bus
2838a7236aeSJohn Wang      *         NOTE: The inputs to this object must outlive the object since
2848a7236aeSJohn Wang      *         they are only referenced by it.
2858a7236aeSJohn Wang      *
2868a7236aeSJohn Wang      *  @param[in] bus    - The bus object used for lookups
2878a7236aeSJohn Wang      *  @param[in] params - The parameters for the channel
2888a7236aeSJohn Wang      *  @param[in] intf   - The interface we are looking up
2898a7236aeSJohn Wang      */
2905d82f474SPatrick Williams     ObjectLookupCache(sdbusplus::bus_t& bus, const ChannelParams& params,
2918a7236aeSJohn Wang                       const char* intf) :
2928a7236aeSJohn Wang         bus(bus),
2938a7236aeSJohn Wang         params(params), intf(intf),
2948a7236aeSJohn Wang         objs(getAllDbusObjects(bus, params.logicalPath, intf, ""))
295fbc6c9d7SPatrick Williams     {}
2968a7236aeSJohn Wang 
2978a7236aeSJohn Wang     class iterator : public ObjectTree::const_iterator
2988a7236aeSJohn Wang     {
2998a7236aeSJohn Wang       public:
3008a7236aeSJohn Wang         using value_type = PropertiesCache::value_type;
3018a7236aeSJohn Wang 
3028a7236aeSJohn Wang         iterator(ObjectTree::const_iterator it, ObjectLookupCache& container) :
3038a7236aeSJohn Wang             ObjectTree::const_iterator(it), container(container),
3048a7236aeSJohn Wang             ret(container.cache.end())
305fbc6c9d7SPatrick Williams         {}
3068a7236aeSJohn Wang         value_type& operator*()
3078a7236aeSJohn Wang         {
3088a7236aeSJohn Wang             ret = container.get(ObjectTree::const_iterator::operator*().first);
3098a7236aeSJohn Wang             return *ret;
3108a7236aeSJohn Wang         }
3118a7236aeSJohn Wang         value_type* operator->()
3128a7236aeSJohn Wang         {
3138a7236aeSJohn Wang             return &operator*();
3148a7236aeSJohn Wang         }
3158a7236aeSJohn Wang 
3168a7236aeSJohn Wang       private:
3178a7236aeSJohn Wang         ObjectLookupCache& container;
3188a7236aeSJohn Wang         PropertiesCache::iterator ret;
3198a7236aeSJohn Wang     };
3208a7236aeSJohn Wang 
3218a7236aeSJohn Wang     iterator begin() noexcept
3228a7236aeSJohn Wang     {
3238a7236aeSJohn Wang         return iterator(objs.begin(), *this);
3248a7236aeSJohn Wang     }
3258a7236aeSJohn Wang 
3268a7236aeSJohn Wang     iterator end() noexcept
3278a7236aeSJohn Wang     {
3288a7236aeSJohn Wang         return iterator(objs.end(), *this);
3298a7236aeSJohn Wang     }
3308a7236aeSJohn Wang 
3318a7236aeSJohn Wang   private:
3325d82f474SPatrick Williams     sdbusplus::bus_t& bus;
3338a7236aeSJohn Wang     const ChannelParams& params;
3348a7236aeSJohn Wang     const char* const intf;
3358a7236aeSJohn Wang     const ObjectTree objs;
3368a7236aeSJohn Wang     PropertiesCache cache;
3378a7236aeSJohn Wang 
3388a7236aeSJohn Wang     /** @brief Gets a cached copy of the object properties if possible
3398a7236aeSJohn Wang      *         Otherwise performs a query on DBus to look them up
3408a7236aeSJohn Wang      *
3418a7236aeSJohn Wang      *  @param[in] path - The object path to lookup
3428a7236aeSJohn Wang      *  @return An iterator for the specified object path + properties
3438a7236aeSJohn Wang      */
3448a7236aeSJohn Wang     PropertiesCache::iterator get(const std::string& path)
3458a7236aeSJohn Wang     {
3468a7236aeSJohn Wang         auto it = cache.find(path);
3478a7236aeSJohn Wang         if (it != cache.end())
3488a7236aeSJohn Wang         {
3498a7236aeSJohn Wang             return it;
3508a7236aeSJohn Wang         }
3518a7236aeSJohn Wang         auto properties = getAllDbusProperties(bus, params.service, path, intf);
3528a7236aeSJohn Wang         return cache.insert({path, std::move(properties)}).first;
3538a7236aeSJohn Wang     }
3548a7236aeSJohn Wang };
3558a7236aeSJohn Wang 
3568a7236aeSJohn Wang /** @brief Searches the ip object lookup cache for an address matching
3578a7236aeSJohn Wang  *         the input parameters. NOTE: The index lacks stability across address
3588a7236aeSJohn Wang  *         changes since the network daemon has no notion of stable indicies.
3598a7236aeSJohn Wang  *
3608a7236aeSJohn Wang  *  @param[in] bus     - The bus object used for lookups
3618a7236aeSJohn Wang  *  @param[in] params  - The parameters for the channel
3628a7236aeSJohn Wang  *  @param[in] idx     - The index of the desired address on the interface
3638a7236aeSJohn Wang  *  @param[in] origins - The allowed origins for the address objects
3648a7236aeSJohn Wang  *  @param[in] ips     - The object lookup cache holding all of the address info
3658a7236aeSJohn Wang  *  @return The address and prefix if it was found
3668a7236aeSJohn Wang  */
3678a7236aeSJohn Wang template <int family>
3688a7236aeSJohn Wang std::optional<IfAddr<family>> findIfAddr(
3695d82f474SPatrick Williams     [[maybe_unused]] sdbusplus::bus_t& bus,
37011d68897SWilly Tu     [[maybe_unused]] const ChannelParams& params, uint8_t idx,
3718a7236aeSJohn Wang     const std::unordered_set<
372523e2d1bSWilly Tu         sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin>&
3738a7236aeSJohn Wang         origins,
3748a7236aeSJohn Wang     ObjectLookupCache& ips)
3758a7236aeSJohn Wang {
3768a7236aeSJohn Wang     for (const auto& [path, properties] : ips)
3778a7236aeSJohn Wang     {
378*726f2bddSWilliam A. Kennington III         std::optional<typename AddrFamily<family>::addr> addr;
379*726f2bddSWilliam A. Kennington III         try
380*726f2bddSWilliam A. Kennington III         {
381*726f2bddSWilliam A. Kennington III             addr.emplace(stdplus::fromStr<typename AddrFamily<family>::addr>(
382*726f2bddSWilliam A. Kennington III                 std::get<std::string>(properties.at("Address"))));
383*726f2bddSWilliam A. Kennington III         }
384*726f2bddSWilliam A. Kennington III         catch (...)
3858a7236aeSJohn Wang         {
3868a7236aeSJohn Wang             continue;
3878a7236aeSJohn Wang         }
3888a7236aeSJohn Wang 
389523e2d1bSWilly Tu         sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin
390523e2d1bSWilly Tu             origin = sdbusplus::server::xyz::openbmc_project::network::IP::
3918a7236aeSJohn Wang                 convertAddressOriginFromString(
3928a7236aeSJohn Wang                     std::get<std::string>(properties.at("Origin")));
3938a7236aeSJohn Wang         if (origins.find(origin) == origins.end())
3948a7236aeSJohn Wang         {
3958a7236aeSJohn Wang             continue;
3968a7236aeSJohn Wang         }
3978a7236aeSJohn Wang 
3988a7236aeSJohn Wang         if (idx > 0)
3998a7236aeSJohn Wang         {
4008a7236aeSJohn Wang             idx--;
4018a7236aeSJohn Wang             continue;
4028a7236aeSJohn Wang         }
4038a7236aeSJohn Wang 
4048a7236aeSJohn Wang         IfAddr<family> ifaddr;
4058a7236aeSJohn Wang         ifaddr.path = path;
4068a7236aeSJohn Wang         ifaddr.address = *addr;
4078a7236aeSJohn Wang         ifaddr.prefix = std::get<uint8_t>(properties.at("PrefixLength"));
4088a7236aeSJohn Wang         ifaddr.origin = origin;
40911d68897SWilly Tu         return ifaddr;
4108a7236aeSJohn Wang     }
4118a7236aeSJohn Wang 
4128a7236aeSJohn Wang     return std::nullopt;
4138a7236aeSJohn Wang }
4148a7236aeSJohn Wang /** @brief Trivial helper around findIfAddr that simplifies calls
4158a7236aeSJohn Wang  *         for one off lookups. Don't use this if you intend to do multiple
4168a7236aeSJohn Wang  *         lookups at a time.
4178a7236aeSJohn Wang  *
4188a7236aeSJohn Wang  *  @param[in] bus     - The bus object used for lookups
4198a7236aeSJohn Wang  *  @param[in] params  - The parameters for the channel
4208a7236aeSJohn Wang  *  @param[in] idx     - The index of the desired address on the interface
4218a7236aeSJohn Wang  *  @param[in] origins - The allowed origins for the address objects
4228a7236aeSJohn Wang  *  @return The address and prefix if it was found
4238a7236aeSJohn Wang  */
4248a7236aeSJohn Wang template <int family>
4258a7236aeSJohn Wang auto getIfAddr(
4265d82f474SPatrick Williams     sdbusplus::bus_t& bus, const ChannelParams& params, uint8_t idx,
4278a7236aeSJohn Wang     const std::unordered_set<
428523e2d1bSWilly Tu         sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin>&
4298a7236aeSJohn Wang         origins)
4308a7236aeSJohn Wang {
4318a7236aeSJohn Wang     ObjectLookupCache ips(bus, params, INTF_IP);
4328a7236aeSJohn Wang     return findIfAddr<family>(bus, params, idx, origins, ips);
4338a7236aeSJohn Wang }
4348a7236aeSJohn Wang 
4358a7236aeSJohn Wang /** @brief Reconfigures the IPv6 address info configured for the interface
4368a7236aeSJohn Wang  *
4378a7236aeSJohn Wang  *  @param[in] bus     - The bus object used for lookups
4388a7236aeSJohn Wang  *  @param[in] params  - The parameters for the channel
4398a7236aeSJohn Wang  *  @param[in] idx     - The address index to operate on
4408a7236aeSJohn Wang  *  @param[in] address - The new address
4418a7236aeSJohn Wang  *  @param[in] prefix  - The new address prefix
4428a7236aeSJohn Wang  */
4435d82f474SPatrick Williams void reconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
444*726f2bddSWilliam A. Kennington III                         uint8_t idx, stdplus::In6Addr address, uint8_t prefix);
4458a7236aeSJohn Wang 
4468a7236aeSJohn Wang /** @brief Retrieves the current gateway for the address family on the system
447d1bd8c48SLei YU  *         NOTE: The gateway is per channel instead of the system wide one.
4488a7236aeSJohn Wang  *
4498a7236aeSJohn Wang  *  @param[in] bus    - The bus object used for lookups
4508a7236aeSJohn Wang  *  @param[in] params - The parameters for the channel
4518a7236aeSJohn Wang  *  @return An address representing the gateway address if it exists
4528a7236aeSJohn Wang  */
4538a7236aeSJohn Wang template <int family>
4548a7236aeSJohn Wang std::optional<typename AddrFamily<family>::addr>
4555d82f474SPatrick Williams     getGatewayProperty(sdbusplus::bus_t& bus, const ChannelParams& params)
4568a7236aeSJohn Wang {
457d1bd8c48SLei YU     auto objPath = "/xyz/openbmc_project/network/" + params.ifname;
458d1bd8c48SLei YU     auto gatewayStr = std::get<std::string>(
459d1bd8c48SLei YU         getDbusProperty(bus, params.service, objPath, INTF_ETHERNET,
4608a7236aeSJohn Wang                         AddrFamily<family>::propertyGateway));
4618a7236aeSJohn Wang     if (gatewayStr.empty())
4628a7236aeSJohn Wang     {
4638a7236aeSJohn Wang         return std::nullopt;
4648a7236aeSJohn Wang     }
465*726f2bddSWilliam A. Kennington III     return stdplus::fromStr<typename AddrFamily<family>::addr>(gatewayStr);
4668a7236aeSJohn Wang }
4678a7236aeSJohn Wang 
4688a7236aeSJohn Wang template <int family>
4698a7236aeSJohn Wang std::optional<IfNeigh<family>>
4705d82f474SPatrick Williams     findStaticNeighbor(sdbusplus::bus_t&, const ChannelParams&,
471*726f2bddSWilliam A. Kennington III                        typename AddrFamily<family>::addr ip,
4728a7236aeSJohn Wang                        ObjectLookupCache& neighbors)
4738a7236aeSJohn Wang {
474523e2d1bSWilly Tu     using sdbusplus::server::xyz::openbmc_project::network::Neighbor;
4758a7236aeSJohn Wang     const auto state =
476523e2d1bSWilly Tu         sdbusplus::common::xyz::openbmc_project::network::convertForMessage(
4778a7236aeSJohn Wang             Neighbor::State::Permanent);
4788a7236aeSJohn Wang     for (const auto& [path, neighbor] : neighbors)
4798a7236aeSJohn Wang     {
480*726f2bddSWilliam A. Kennington III         std::optional<typename AddrFamily<family>::addr> neighIP;
481*726f2bddSWilliam A. Kennington III         try
482*726f2bddSWilliam A. Kennington III         {
483*726f2bddSWilliam A. Kennington III             neighIP.emplace(stdplus::fromStr<typename AddrFamily<family>::addr>(
484*726f2bddSWilliam A. Kennington III                 std::get<std::string>(neighbor.at("IPAddress"))));
485*726f2bddSWilliam A. Kennington III         }
486*726f2bddSWilliam A. Kennington III         catch (...)
4878a7236aeSJohn Wang         {
4888a7236aeSJohn Wang             continue;
4898a7236aeSJohn Wang         }
490*726f2bddSWilliam A. Kennington III         if (*neighIP != ip)
4918a7236aeSJohn Wang         {
4928a7236aeSJohn Wang             continue;
4938a7236aeSJohn Wang         }
4948a7236aeSJohn Wang         if (state != std::get<std::string>(neighbor.at("State")))
4958a7236aeSJohn Wang         {
4968a7236aeSJohn Wang             continue;
4978a7236aeSJohn Wang         }
4988a7236aeSJohn Wang 
4998a7236aeSJohn Wang         IfNeigh<family> ret;
5008a7236aeSJohn Wang         ret.path = path;
5018a7236aeSJohn Wang         ret.ip = ip;
502*726f2bddSWilliam A. Kennington III         ret.mac = stdplus::fromStr<stdplus::EtherAddr>(
503*726f2bddSWilliam A. Kennington III             std::get<std::string>(neighbor.at("MACAddress")));
50411d68897SWilly Tu         return ret;
5058a7236aeSJohn Wang     }
5068a7236aeSJohn Wang 
5078a7236aeSJohn Wang     return std::nullopt;
5088a7236aeSJohn Wang }
5098a7236aeSJohn Wang 
5108a7236aeSJohn Wang template <int family>
5115d82f474SPatrick Williams void createNeighbor(sdbusplus::bus_t& bus, const ChannelParams& params,
512*726f2bddSWilliam A. Kennington III                     typename AddrFamily<family>::addr address,
513*726f2bddSWilliam A. Kennington III                     stdplus::EtherAddr mac)
5148a7236aeSJohn Wang {
515fbc6c9d7SPatrick Williams     auto newreq = bus.new_method_call(params.service.c_str(),
516fbc6c9d7SPatrick Williams                                       params.logicalPath.c_str(),
5178a7236aeSJohn Wang                                       INTF_NEIGHBOR_CREATE_STATIC, "Neighbor");
518*726f2bddSWilliam A. Kennington III     stdplus::ToStrHandle<stdplus::ToStr<stdplus::EtherAddr>> macToStr;
519*726f2bddSWilliam A. Kennington III     stdplus::ToStrHandle<stdplus::ToStr<typename AddrFamily<family>::addr>>
520*726f2bddSWilliam A. Kennington III         addrToStr;
521*726f2bddSWilliam A. Kennington III     newreq.append(addrToStr(address), macToStr(mac));
5228a7236aeSJohn Wang     bus.call_noreply(newreq);
5238a7236aeSJohn Wang }
5248a7236aeSJohn Wang 
5258a7236aeSJohn Wang /** @brief Deletes the dbus object. Ignores empty objects or objects that are
5268a7236aeSJohn Wang  *         missing from the bus.
5278a7236aeSJohn Wang  *
5288a7236aeSJohn Wang  *  @param[in] bus     - The bus object used for lookups
5298a7236aeSJohn Wang  *  @param[in] service - The name of the service
5308a7236aeSJohn Wang  *  @param[in] path    - The path of the object to delete
5318a7236aeSJohn Wang  */
5325d82f474SPatrick Williams void deleteObjectIfExists(sdbusplus::bus_t& bus, const std::string& service,
5338a7236aeSJohn Wang                           const std::string& path);
5348a7236aeSJohn Wang 
535d1bd8c48SLei YU /** @brief Sets the value for the default gateway of the channel
5368a7236aeSJohn Wang  *
5378a7236aeSJohn Wang  *  @param[in] bus     - The bus object used for lookups
5388a7236aeSJohn Wang  *  @param[in] params  - The parameters for the channel
5398a7236aeSJohn Wang  *  @param[in] gateway - Gateway address to apply
5408a7236aeSJohn Wang  */
5418a7236aeSJohn Wang template <int family>
5425d82f474SPatrick Williams void setGatewayProperty(sdbusplus::bus_t& bus, const ChannelParams& params,
543*726f2bddSWilliam A. Kennington III                         typename AddrFamily<family>::addr address)
5448a7236aeSJohn Wang {
5458a7236aeSJohn Wang     // Save the old gateway MAC address if it exists so we can recreate it
5468a7236aeSJohn Wang     auto gateway = getGatewayProperty<family>(bus, params);
5478a7236aeSJohn Wang     std::optional<IfNeigh<family>> neighbor;
5488a7236aeSJohn Wang     if (gateway)
5498a7236aeSJohn Wang     {
5508a7236aeSJohn Wang         ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
5518a7236aeSJohn Wang         neighbor = findStaticNeighbor<family>(bus, params, *gateway, neighbors);
5528a7236aeSJohn Wang     }
5538a7236aeSJohn Wang 
554d1bd8c48SLei YU     auto objPath = "/xyz/openbmc_project/network/" + params.ifname;
555d1bd8c48SLei YU     setDbusProperty(bus, params.service, objPath, INTF_ETHERNET,
5568a7236aeSJohn Wang                     AddrFamily<family>::propertyGateway,
557*726f2bddSWilliam A. Kennington III                     stdplus::toStr(address));
5588a7236aeSJohn Wang 
5598a7236aeSJohn Wang     // Restore the gateway MAC if we had one
5608a7236aeSJohn Wang     if (neighbor)
5618a7236aeSJohn Wang     {
5628a7236aeSJohn Wang         deleteObjectIfExists(bus, params.service, neighbor->path);
5638a7236aeSJohn Wang         createNeighbor<family>(bus, params, address, neighbor->mac);
5648a7236aeSJohn Wang     }
5658a7236aeSJohn Wang }
5668a7236aeSJohn Wang 
56723f44657SJian Zhang /** @enum SolConfParam
56823f44657SJian Zhang  *
56923f44657SJian Zhang  *  using for Set/Get SOL configuration parameters command.
57023f44657SJian Zhang  */
57123f44657SJian Zhang enum class SolConfParam : uint8_t
57223f44657SJian Zhang {
57323f44657SJian Zhang     Progress,       //!< Set In Progress.
57423f44657SJian Zhang     Enable,         //!< SOL Enable.
57523f44657SJian Zhang     Authentication, //!< SOL Authentication.
57623f44657SJian Zhang     Accumulate,     //!< Character Accumulate Interval & Send Threshold.
57723f44657SJian Zhang     Retry,          //!< SOL Retry.
57823f44657SJian Zhang     NonVbitrate,    //!< SOL non-volatile bit rate.
57923f44657SJian Zhang     Vbitrate,       //!< SOL volatile bit rate.
58023f44657SJian Zhang     Channel,        //!< SOL payload channel.
58123f44657SJian Zhang     Port,           //!< SOL payload port.
58223f44657SJian Zhang };
58323f44657SJian Zhang 
58423f44657SJian Zhang constexpr uint8_t ipmiCCParamNotSupported = 0x80;
58523f44657SJian Zhang constexpr uint8_t ipmiCCWriteReadParameter = 0x82;
58623f44657SJian Zhang 
587690a2342SPatrick Venture } // namespace transport
588690a2342SPatrick Venture } // namespace ipmi
589