1690a2342SPatrick Venture #pragma once 2690a2342SPatrick Venture 38a7236aeSJohn Wang #include "app/channel.hpp" 48a7236aeSJohn Wang #include "user_channel/cipher_mgmt.hpp" 58a7236aeSJohn Wang 68a7236aeSJohn Wang #include <arpa/inet.h> 78a7236aeSJohn Wang #include <netinet/ether.h> 88a7236aeSJohn Wang 98a7236aeSJohn Wang #include <array> 108a7236aeSJohn Wang #include <bitset> 118a7236aeSJohn Wang #include <cinttypes> 12690a2342SPatrick Venture #include <cstdint> 138a7236aeSJohn Wang #include <cstring> 148a7236aeSJohn Wang #include <fstream> 158a7236aeSJohn Wang #include <functional> 16690a2342SPatrick Venture #include <ipmid/api-types.hpp> 178a7236aeSJohn Wang #include <ipmid/api.hpp> 188a7236aeSJohn Wang #include <ipmid/message.hpp> 198a7236aeSJohn Wang #include <ipmid/message/types.hpp> 208a7236aeSJohn Wang #include <ipmid/types.hpp> 218a7236aeSJohn Wang #include <ipmid/utils.hpp> 228a7236aeSJohn Wang #include <optional> 238a7236aeSJohn Wang #include <phosphor-logging/elog-errors.hpp> 248a7236aeSJohn Wang #include <phosphor-logging/elog.hpp> 258a7236aeSJohn Wang #include <phosphor-logging/log.hpp> 268a7236aeSJohn Wang #include <sdbusplus/bus.hpp> 278a7236aeSJohn Wang #include <sdbusplus/exception.hpp> 288a7236aeSJohn Wang #include <string> 298a7236aeSJohn Wang #include <string_view> 308a7236aeSJohn Wang #include <type_traits> 318a7236aeSJohn Wang #include <unordered_map> 328a7236aeSJohn Wang #include <unordered_set> 338a7236aeSJohn Wang #include <user_channel/channel_layer.hpp> 348a7236aeSJohn Wang #include <utility> 358a7236aeSJohn Wang #include <vector> 368a7236aeSJohn Wang #include <xyz/openbmc_project/Common/error.hpp> 378a7236aeSJohn Wang #include <xyz/openbmc_project/Network/EthernetInterface/server.hpp> 388a7236aeSJohn Wang #include <xyz/openbmc_project/Network/IP/server.hpp> 398a7236aeSJohn Wang #include <xyz/openbmc_project/Network/Neighbor/server.hpp> 40690a2342SPatrick Venture 41690a2342SPatrick Venture namespace ipmi 42690a2342SPatrick Venture { 43690a2342SPatrick Venture namespace transport 44690a2342SPatrick Venture { 45690a2342SPatrick Venture 468a7236aeSJohn Wang // D-Bus Network Daemon definitions 478a7236aeSJohn Wang constexpr auto PATH_ROOT = "/xyz/openbmc_project/network"; 488a7236aeSJohn Wang constexpr auto INTF_ETHERNET = "xyz.openbmc_project.Network.EthernetInterface"; 498a7236aeSJohn Wang constexpr auto INTF_IP = "xyz.openbmc_project.Network.IP"; 508a7236aeSJohn Wang constexpr auto INTF_IP_CREATE = "xyz.openbmc_project.Network.IP.Create"; 518a7236aeSJohn Wang constexpr auto INTF_MAC = "xyz.openbmc_project.Network.MACAddress"; 528a7236aeSJohn Wang constexpr auto INTF_NEIGHBOR = "xyz.openbmc_project.Network.Neighbor"; 538a7236aeSJohn Wang constexpr auto INTF_NEIGHBOR_CREATE_STATIC = 548a7236aeSJohn Wang "xyz.openbmc_project.Network.Neighbor.CreateStatic"; 558a7236aeSJohn Wang constexpr auto INTF_VLAN = "xyz.openbmc_project.Network.VLAN"; 568a7236aeSJohn Wang constexpr auto INTF_VLAN_CREATE = "xyz.openbmc_project.Network.VLAN.Create"; 578a7236aeSJohn Wang 58690a2342SPatrick Venture /** @brief IPMI LAN Parameters */ 59690a2342SPatrick Venture enum class LanParam : uint8_t 60690a2342SPatrick Venture { 61690a2342SPatrick Venture SetStatus = 0, 62690a2342SPatrick Venture AuthSupport = 1, 63690a2342SPatrick Venture AuthEnables = 2, 64690a2342SPatrick Venture IP = 3, 65690a2342SPatrick Venture IPSrc = 4, 66690a2342SPatrick Venture MAC = 5, 67690a2342SPatrick Venture SubnetMask = 6, 68690a2342SPatrick Venture Gateway1 = 12, 69690a2342SPatrick Venture Gateway1MAC = 13, 70690a2342SPatrick Venture VLANId = 20, 71690a2342SPatrick Venture CiphersuiteSupport = 22, 72690a2342SPatrick Venture CiphersuiteEntries = 23, 73690a2342SPatrick Venture cipherSuitePrivilegeLevels = 24, 74690a2342SPatrick Venture IPFamilySupport = 50, 75690a2342SPatrick Venture IPFamilyEnables = 51, 76690a2342SPatrick Venture IPv6Status = 55, 77690a2342SPatrick Venture IPv6StaticAddresses = 56, 78690a2342SPatrick Venture IPv6DynamicAddresses = 59, 79690a2342SPatrick Venture IPv6RouterControl = 64, 80690a2342SPatrick Venture IPv6StaticRouter1IP = 65, 81690a2342SPatrick Venture IPv6StaticRouter1MAC = 66, 82690a2342SPatrick Venture IPv6StaticRouter1PrefixLength = 67, 83690a2342SPatrick Venture IPv6StaticRouter1PrefixValue = 68, 84690a2342SPatrick Venture }; 85690a2342SPatrick Venture 86690a2342SPatrick Venture /** @brief IPMI IP Origin Types */ 87690a2342SPatrick Venture enum class IPSrc : uint8_t 88690a2342SPatrick Venture { 89690a2342SPatrick Venture Unspecified = 0, 90690a2342SPatrick Venture Static = 1, 91690a2342SPatrick Venture DHCP = 2, 92690a2342SPatrick Venture BIOS = 3, 93690a2342SPatrick Venture BMC = 4, 94690a2342SPatrick Venture }; 95690a2342SPatrick Venture 96690a2342SPatrick Venture /** @brief IPMI Set Status */ 97690a2342SPatrick Venture enum class SetStatus : uint8_t 98690a2342SPatrick Venture { 99690a2342SPatrick Venture Complete = 0, 100690a2342SPatrick Venture InProgress = 1, 101690a2342SPatrick Venture Commit = 2, 102690a2342SPatrick Venture }; 103690a2342SPatrick Venture 104690a2342SPatrick Venture /** @brief IPMI Family Suport Bits */ 105690a2342SPatrick Venture namespace IPFamilySupportFlag 106690a2342SPatrick Venture { 107690a2342SPatrick Venture constexpr uint8_t IPv6Only = 0; 108690a2342SPatrick Venture constexpr uint8_t DualStack = 1; 109690a2342SPatrick Venture constexpr uint8_t IPv6Alerts = 2; 110690a2342SPatrick Venture } // namespace IPFamilySupportFlag 111690a2342SPatrick Venture 112690a2342SPatrick Venture /** @brief IPMI IPFamily Enables Flag */ 113690a2342SPatrick Venture enum class IPFamilyEnables : uint8_t 114690a2342SPatrick Venture { 115690a2342SPatrick Venture IPv4Only = 0, 116690a2342SPatrick Venture IPv6Only = 1, 117690a2342SPatrick Venture DualStack = 2, 118690a2342SPatrick Venture }; 119690a2342SPatrick Venture 120690a2342SPatrick Venture /** @brief IPMI IPv6 Dyanmic Status Bits */ 121690a2342SPatrick Venture namespace IPv6StatusFlag 122690a2342SPatrick Venture { 123690a2342SPatrick Venture constexpr uint8_t DHCP = 0; 124690a2342SPatrick Venture constexpr uint8_t SLAAC = 1; 125690a2342SPatrick Venture }; // namespace IPv6StatusFlag 126690a2342SPatrick Venture 127690a2342SPatrick Venture /** @brief IPMI IPv6 Source */ 128690a2342SPatrick Venture enum class IPv6Source : uint8_t 129690a2342SPatrick Venture { 130690a2342SPatrick Venture Static = 0, 131690a2342SPatrick Venture SLAAC = 1, 132690a2342SPatrick Venture DHCP = 2, 133690a2342SPatrick Venture }; 134690a2342SPatrick Venture 135690a2342SPatrick Venture /** @brief IPMI IPv6 Address Status */ 136690a2342SPatrick Venture enum class IPv6AddressStatus : uint8_t 137690a2342SPatrick Venture { 138690a2342SPatrick Venture Active = 0, 139690a2342SPatrick Venture Disabled = 1, 140690a2342SPatrick Venture }; 141690a2342SPatrick Venture 142690a2342SPatrick Venture namespace IPv6RouterControlFlag 143690a2342SPatrick Venture { 144690a2342SPatrick Venture constexpr uint8_t Static = 0; 145690a2342SPatrick Venture constexpr uint8_t Dynamic = 1; 146690a2342SPatrick Venture }; // namespace IPv6RouterControlFlag 147690a2342SPatrick Venture 148690a2342SPatrick Venture // LAN Handler specific response codes 149690a2342SPatrick Venture constexpr Cc ccParamNotSupported = 0x80; 150690a2342SPatrick Venture constexpr Cc ccParamSetLocked = 0x81; 151690a2342SPatrick Venture constexpr Cc ccParamReadOnly = 0x82; 152690a2342SPatrick Venture 153690a2342SPatrick Venture // VLANs are a 12-bit value 154690a2342SPatrick Venture constexpr uint16_t VLAN_VALUE_MASK = 0x0fff; 155690a2342SPatrick Venture constexpr uint16_t VLAN_ENABLE_FLAG = 0x8000; 156690a2342SPatrick Venture 157690a2342SPatrick Venture // Arbitrary v6 Address Limits to prevent too much output in ipmitool 158690a2342SPatrick Venture constexpr uint8_t MAX_IPV6_STATIC_ADDRESSES = 15; 159690a2342SPatrick Venture constexpr uint8_t MAX_IPV6_DYNAMIC_ADDRESSES = 15; 160690a2342SPatrick Venture 161*6d4a44edSJiaqing Zhao // Prefix length limits of phosphor-networkd 162*6d4a44edSJiaqing Zhao constexpr uint8_t MIN_IPV4_PREFIX_LENGTH = 1; 163*6d4a44edSJiaqing Zhao constexpr uint8_t MAX_IPV4_PREFIX_LENGTH = 32; 164*6d4a44edSJiaqing Zhao constexpr uint8_t MIN_IPV6_PREFIX_LENGTH = 1; 165*6d4a44edSJiaqing Zhao constexpr uint8_t MAX_IPV6_PREFIX_LENGTH = 128; 166*6d4a44edSJiaqing Zhao 1678a7236aeSJohn Wang /** @brief The dbus parameters for the interface corresponding to a channel 1688a7236aeSJohn Wang * This helps reduce the number of mapper lookups we need for each 1698a7236aeSJohn Wang * query and simplifies finding the VLAN interface if needed. 1708a7236aeSJohn Wang */ 1718a7236aeSJohn Wang struct ChannelParams 1728a7236aeSJohn Wang { 1738a7236aeSJohn Wang /** @brief The channel ID */ 1748a7236aeSJohn Wang int id; 1758a7236aeSJohn Wang /** @brief channel name for the interface */ 1768a7236aeSJohn Wang std::string ifname; 1778a7236aeSJohn Wang /** @brief Name of the service on the bus */ 1788a7236aeSJohn Wang std::string service; 1798a7236aeSJohn Wang /** @brief Lower level adapter path that is guaranteed to not be a VLAN */ 1808a7236aeSJohn Wang std::string ifPath; 1818a7236aeSJohn Wang /** @brief Logical adapter path used for address assignment */ 1828a7236aeSJohn Wang std::string logicalPath; 1838a7236aeSJohn Wang }; 1848a7236aeSJohn Wang 1858a7236aeSJohn Wang /** @brief A trivial helper used to determine if two PODs are equal 1868a7236aeSJohn Wang * 1878a7236aeSJohn Wang * @params[in] a - The first object to compare 1888a7236aeSJohn Wang * @params[in] b - The second object to compare 1898a7236aeSJohn Wang * @return True if the objects are the same bytewise 1908a7236aeSJohn Wang */ 1918a7236aeSJohn Wang template <typename T> 1928a7236aeSJohn Wang bool equal(const T& a, const T& b) 1938a7236aeSJohn Wang { 1948a7236aeSJohn Wang static_assert(std::is_trivially_copyable_v<T>); 1958a7236aeSJohn Wang return std::memcmp(&a, &b, sizeof(T)) == 0; 1968a7236aeSJohn Wang } 1978a7236aeSJohn Wang 1988a7236aeSJohn Wang /** @brief Copies bytes from an array into a trivially copyable container 1998a7236aeSJohn Wang * 2008a7236aeSJohn Wang * @params[out] t - The container receiving the data 2018a7236aeSJohn Wang * @params[in] bytes - The data to copy 2028a7236aeSJohn Wang */ 2038a7236aeSJohn Wang template <size_t N, typename T> 2048a7236aeSJohn Wang void copyInto(T& t, const std::array<uint8_t, N>& bytes) 2058a7236aeSJohn Wang { 2068a7236aeSJohn Wang static_assert(std::is_trivially_copyable_v<T>); 2078a7236aeSJohn Wang static_assert(N == sizeof(T)); 2088a7236aeSJohn Wang std::memcpy(&t, bytes.data(), bytes.size()); 2098a7236aeSJohn Wang } 2108a7236aeSJohn Wang 2118a7236aeSJohn Wang /** @brief Gets a generic view of the bytes in the input container 2128a7236aeSJohn Wang * 2138a7236aeSJohn Wang * @params[in] t - The data to reference 2148a7236aeSJohn Wang * @return A string_view referencing the bytes in the container 2158a7236aeSJohn Wang */ 2168a7236aeSJohn Wang template <typename T> 2178a7236aeSJohn Wang std::string_view dataRef(const T& t) 2188a7236aeSJohn Wang { 2198a7236aeSJohn Wang static_assert(std::is_trivially_copyable_v<T>); 2208a7236aeSJohn Wang return {reinterpret_cast<const char*>(&t), sizeof(T)}; 2218a7236aeSJohn Wang } 2228a7236aeSJohn Wang 2238a7236aeSJohn Wang /** @brief Determines the ethernet interface name corresponding to a channel 2248a7236aeSJohn Wang * Tries to map a VLAN object first so that the address information 2258a7236aeSJohn Wang * is accurate. Otherwise it gets the standard ethernet interface. 2268a7236aeSJohn Wang * 2278a7236aeSJohn Wang * @param[in] bus - The bus object used for lookups 2288a7236aeSJohn Wang * @param[in] channel - The channel id corresponding to an ethernet interface 2298a7236aeSJohn Wang * @return Ethernet interface service and object path if it exists 2308a7236aeSJohn Wang */ 2318a7236aeSJohn Wang std::optional<ChannelParams> maybeGetChannelParams(sdbusplus::bus::bus& bus, 2328a7236aeSJohn Wang uint8_t channel); 2338a7236aeSJohn Wang 2348a7236aeSJohn Wang /** @brief A trivial helper around maybeGetChannelParams() that throws an 2358a7236aeSJohn Wang * exception when it is unable to acquire parameters for the channel. 2368a7236aeSJohn Wang * 2378a7236aeSJohn Wang * @param[in] bus - The bus object used for lookups 2388a7236aeSJohn Wang * @param[in] channel - The channel id corresponding to an ethernet interface 2398a7236aeSJohn Wang * @return Ethernet interface service and object path 2408a7236aeSJohn Wang */ 2418a7236aeSJohn Wang ChannelParams getChannelParams(sdbusplus::bus::bus& bus, uint8_t channel); 2428a7236aeSJohn Wang 2438a7236aeSJohn Wang /** @brief Trivializes using parameter getter functions by providing a bus 2448a7236aeSJohn Wang * and channel parameters automatically. 2458a7236aeSJohn Wang * 2468a7236aeSJohn Wang * @param[in] channel - The channel id corresponding to an ethernet interface 2478a7236aeSJohn Wang * ... 2488a7236aeSJohn Wang */ 2498a7236aeSJohn Wang template <auto func, typename... Args> 2508a7236aeSJohn Wang auto channelCall(uint8_t channel, Args&&... args) 2518a7236aeSJohn Wang { 2528a7236aeSJohn Wang sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection()); 2538a7236aeSJohn Wang auto params = getChannelParams(bus, channel); 2548a7236aeSJohn Wang return std::invoke(func, bus, params, std::forward<Args>(args)...); 2558a7236aeSJohn Wang } 2568a7236aeSJohn Wang 2578a7236aeSJohn Wang /** @brief Generic paramters for different address families */ 2588a7236aeSJohn Wang template <int family> 2598a7236aeSJohn Wang struct AddrFamily 2608a7236aeSJohn Wang { 2618a7236aeSJohn Wang }; 2628a7236aeSJohn Wang 2638a7236aeSJohn Wang /** @brief Parameter specialization for IPv4 */ 2648a7236aeSJohn Wang template <> 2658a7236aeSJohn Wang struct AddrFamily<AF_INET> 2668a7236aeSJohn Wang { 2678a7236aeSJohn Wang using addr = in_addr; 2688a7236aeSJohn Wang static constexpr auto protocol = 2698a7236aeSJohn Wang sdbusplus::xyz::openbmc_project::Network::server::IP::Protocol::IPv4; 2708a7236aeSJohn Wang static constexpr size_t maxStrLen = INET6_ADDRSTRLEN; 2718a7236aeSJohn Wang static constexpr uint8_t defaultPrefix = 32; 2728a7236aeSJohn Wang static constexpr char propertyGateway[] = "DefaultGateway"; 2738a7236aeSJohn Wang }; 2748a7236aeSJohn Wang 2758a7236aeSJohn Wang /** @brief Parameter specialization for IPv6 */ 2768a7236aeSJohn Wang template <> 2778a7236aeSJohn Wang struct AddrFamily<AF_INET6> 2788a7236aeSJohn Wang { 2798a7236aeSJohn Wang using addr = in6_addr; 2808a7236aeSJohn Wang static constexpr auto protocol = 2818a7236aeSJohn Wang sdbusplus::xyz::openbmc_project::Network::server::IP::Protocol::IPv6; 2828a7236aeSJohn Wang static constexpr size_t maxStrLen = INET6_ADDRSTRLEN; 2838a7236aeSJohn Wang static constexpr uint8_t defaultPrefix = 128; 2848a7236aeSJohn Wang static constexpr char propertyGateway[] = "DefaultGateway6"; 2858a7236aeSJohn Wang }; 2868a7236aeSJohn Wang 2878a7236aeSJohn Wang /** @brief Interface Neighbor configuration parameters */ 2888a7236aeSJohn Wang template <int family> 2898a7236aeSJohn Wang struct IfNeigh 2908a7236aeSJohn Wang { 2918a7236aeSJohn Wang std::string path; 2928a7236aeSJohn Wang typename AddrFamily<family>::addr ip; 2938a7236aeSJohn Wang ether_addr mac; 2948a7236aeSJohn Wang }; 2958a7236aeSJohn Wang 2968a7236aeSJohn Wang /** @brief Interface IP Address configuration parameters */ 2978a7236aeSJohn Wang template <int family> 2988a7236aeSJohn Wang struct IfAddr 2998a7236aeSJohn Wang { 3008a7236aeSJohn Wang std::string path; 3018a7236aeSJohn Wang typename AddrFamily<family>::addr address; 3028a7236aeSJohn Wang sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin origin; 3038a7236aeSJohn Wang uint8_t prefix; 3048a7236aeSJohn Wang }; 3058a7236aeSJohn Wang 3068a7236aeSJohn Wang /** @brief Valid address origins for IPv6 */ 3078a7236aeSJohn Wang static inline const std::unordered_set< 3088a7236aeSJohn Wang sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin> 3098a7236aeSJohn Wang originsV6Static = {sdbusplus::xyz::openbmc_project::Network::server::IP:: 3108a7236aeSJohn Wang AddressOrigin::Static}; 3118a7236aeSJohn Wang static inline const std::unordered_set< 3128a7236aeSJohn Wang sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin> 3138a7236aeSJohn Wang originsV6Dynamic = { 3148a7236aeSJohn Wang sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin:: 3158a7236aeSJohn Wang DHCP, 3168a7236aeSJohn Wang sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin:: 3178a7236aeSJohn Wang SLAAC, 3188a7236aeSJohn Wang }; 3198a7236aeSJohn Wang 3208a7236aeSJohn Wang /** @brief A lazy lookup mechanism for iterating over object properties stored 3218a7236aeSJohn Wang * in DBus. This will only perform the object lookup when needed, and 3228a7236aeSJohn Wang * retains a cache of previous lookups to speed up future iterations. 3238a7236aeSJohn Wang */ 3248a7236aeSJohn Wang class ObjectLookupCache 3258a7236aeSJohn Wang { 3268a7236aeSJohn Wang public: 3278a7236aeSJohn Wang using PropertiesCache = std::unordered_map<std::string, PropertyMap>; 3288a7236aeSJohn Wang 3298a7236aeSJohn Wang /** @brief Creates a new ObjectLookupCache for the interface on the bus 3308a7236aeSJohn Wang * NOTE: The inputs to this object must outlive the object since 3318a7236aeSJohn Wang * they are only referenced by it. 3328a7236aeSJohn Wang * 3338a7236aeSJohn Wang * @param[in] bus - The bus object used for lookups 3348a7236aeSJohn Wang * @param[in] params - The parameters for the channel 3358a7236aeSJohn Wang * @param[in] intf - The interface we are looking up 3368a7236aeSJohn Wang */ 3378a7236aeSJohn Wang ObjectLookupCache(sdbusplus::bus::bus& bus, const ChannelParams& params, 3388a7236aeSJohn Wang const char* intf) : 3398a7236aeSJohn Wang bus(bus), 3408a7236aeSJohn Wang params(params), intf(intf), 3418a7236aeSJohn Wang objs(getAllDbusObjects(bus, params.logicalPath, intf, "")) 3428a7236aeSJohn Wang { 3438a7236aeSJohn Wang } 3448a7236aeSJohn Wang 3458a7236aeSJohn Wang class iterator : public ObjectTree::const_iterator 3468a7236aeSJohn Wang { 3478a7236aeSJohn Wang public: 3488a7236aeSJohn Wang using value_type = PropertiesCache::value_type; 3498a7236aeSJohn Wang 3508a7236aeSJohn Wang iterator(ObjectTree::const_iterator it, ObjectLookupCache& container) : 3518a7236aeSJohn Wang ObjectTree::const_iterator(it), container(container), 3528a7236aeSJohn Wang ret(container.cache.end()) 3538a7236aeSJohn Wang { 3548a7236aeSJohn Wang } 3558a7236aeSJohn Wang value_type& operator*() 3568a7236aeSJohn Wang { 3578a7236aeSJohn Wang ret = container.get(ObjectTree::const_iterator::operator*().first); 3588a7236aeSJohn Wang return *ret; 3598a7236aeSJohn Wang } 3608a7236aeSJohn Wang value_type* operator->() 3618a7236aeSJohn Wang { 3628a7236aeSJohn Wang return &operator*(); 3638a7236aeSJohn Wang } 3648a7236aeSJohn Wang 3658a7236aeSJohn Wang private: 3668a7236aeSJohn Wang ObjectLookupCache& container; 3678a7236aeSJohn Wang PropertiesCache::iterator ret; 3688a7236aeSJohn Wang }; 3698a7236aeSJohn Wang 3708a7236aeSJohn Wang iterator begin() noexcept 3718a7236aeSJohn Wang { 3728a7236aeSJohn Wang return iterator(objs.begin(), *this); 3738a7236aeSJohn Wang } 3748a7236aeSJohn Wang 3758a7236aeSJohn Wang iterator end() noexcept 3768a7236aeSJohn Wang { 3778a7236aeSJohn Wang return iterator(objs.end(), *this); 3788a7236aeSJohn Wang } 3798a7236aeSJohn Wang 3808a7236aeSJohn Wang private: 3818a7236aeSJohn Wang sdbusplus::bus::bus& bus; 3828a7236aeSJohn Wang const ChannelParams& params; 3838a7236aeSJohn Wang const char* const intf; 3848a7236aeSJohn Wang const ObjectTree objs; 3858a7236aeSJohn Wang PropertiesCache cache; 3868a7236aeSJohn Wang 3878a7236aeSJohn Wang /** @brief Gets a cached copy of the object properties if possible 3888a7236aeSJohn Wang * Otherwise performs a query on DBus to look them up 3898a7236aeSJohn Wang * 3908a7236aeSJohn Wang * @param[in] path - The object path to lookup 3918a7236aeSJohn Wang * @return An iterator for the specified object path + properties 3928a7236aeSJohn Wang */ 3938a7236aeSJohn Wang PropertiesCache::iterator get(const std::string& path) 3948a7236aeSJohn Wang { 3958a7236aeSJohn Wang auto it = cache.find(path); 3968a7236aeSJohn Wang if (it != cache.end()) 3978a7236aeSJohn Wang { 3988a7236aeSJohn Wang return it; 3998a7236aeSJohn Wang } 4008a7236aeSJohn Wang auto properties = getAllDbusProperties(bus, params.service, path, intf); 4018a7236aeSJohn Wang return cache.insert({path, std::move(properties)}).first; 4028a7236aeSJohn Wang } 4038a7236aeSJohn Wang }; 4048a7236aeSJohn Wang 4058a7236aeSJohn Wang /** @brief Turns an IP address string into the network byte order form 4068a7236aeSJohn Wang * NOTE: This version strictly validates family matches 4078a7236aeSJohn Wang * 4088a7236aeSJohn Wang * @param[in] address - The string form of the address 4098a7236aeSJohn Wang * @return A network byte order address or none if conversion failed 4108a7236aeSJohn Wang */ 4118a7236aeSJohn Wang template <int family> 4128a7236aeSJohn Wang std::optional<typename AddrFamily<family>::addr> 4138a7236aeSJohn Wang maybeStringToAddr(const char* address) 4148a7236aeSJohn Wang { 4158a7236aeSJohn Wang typename AddrFamily<family>::addr ret; 4168a7236aeSJohn Wang if (inet_pton(family, address, &ret) == 1) 4178a7236aeSJohn Wang { 4188a7236aeSJohn Wang return ret; 4198a7236aeSJohn Wang } 4208a7236aeSJohn Wang return std::nullopt; 4218a7236aeSJohn Wang } 4228a7236aeSJohn Wang 4238a7236aeSJohn Wang /** @brief Turns an IP address string into the network byte order form 4248a7236aeSJohn Wang * NOTE: This version strictly validates family matches 4258a7236aeSJohn Wang * 4268a7236aeSJohn Wang * @param[in] address - The string form of the address 4278a7236aeSJohn Wang * @return A network byte order address 4288a7236aeSJohn Wang */ 4298a7236aeSJohn Wang template <int family> 4308a7236aeSJohn Wang typename AddrFamily<family>::addr stringToAddr(const char* address) 4318a7236aeSJohn Wang { 4328a7236aeSJohn Wang auto ret = maybeStringToAddr<family>(address); 4338a7236aeSJohn Wang if (!ret) 4348a7236aeSJohn Wang { 4358a7236aeSJohn Wang phosphor::logging::log<phosphor::logging::level::ERR>( 4368a7236aeSJohn Wang "Failed to convert IP Address", 4378a7236aeSJohn Wang phosphor::logging::entry("FAMILY=%d", family), 4388a7236aeSJohn Wang phosphor::logging::entry("ADDRESS=%s", address)); 4398a7236aeSJohn Wang phosphor::logging::elog< 4408a7236aeSJohn Wang sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>(); 4418a7236aeSJohn Wang } 4428a7236aeSJohn Wang return *ret; 4438a7236aeSJohn Wang } 4448a7236aeSJohn Wang 4458a7236aeSJohn Wang /** @brief Turns an IP address in network byte order into a string 4468a7236aeSJohn Wang * 4478a7236aeSJohn Wang * @param[in] address - The string form of the address 4488a7236aeSJohn Wang * @return A network byte order address 4498a7236aeSJohn Wang */ 4508a7236aeSJohn Wang template <int family> 4518a7236aeSJohn Wang std::string addrToString(const typename AddrFamily<family>::addr& address) 4528a7236aeSJohn Wang { 4538a7236aeSJohn Wang std::string ret(AddrFamily<family>::maxStrLen, '\0'); 4548a7236aeSJohn Wang inet_ntop(family, &address, ret.data(), ret.size()); 4558a7236aeSJohn Wang ret.resize(strlen(ret.c_str())); 4568a7236aeSJohn Wang return ret; 4578a7236aeSJohn Wang } 4588a7236aeSJohn Wang 4598a7236aeSJohn Wang /** @brief Converts a human readable MAC string into MAC bytes 4608a7236aeSJohn Wang * 4618a7236aeSJohn Wang * @param[in] mac - The MAC string 4628a7236aeSJohn Wang * @return MAC in bytes 4638a7236aeSJohn Wang */ 4648a7236aeSJohn Wang ether_addr stringToMAC(const char* mac); 4658a7236aeSJohn Wang /** @brief Searches the ip object lookup cache for an address matching 4668a7236aeSJohn Wang * the input parameters. NOTE: The index lacks stability across address 4678a7236aeSJohn Wang * changes since the network daemon has no notion of stable indicies. 4688a7236aeSJohn Wang * 4698a7236aeSJohn Wang * @param[in] bus - The bus object used for lookups 4708a7236aeSJohn Wang * @param[in] params - The parameters for the channel 4718a7236aeSJohn Wang * @param[in] idx - The index of the desired address on the interface 4728a7236aeSJohn Wang * @param[in] origins - The allowed origins for the address objects 4738a7236aeSJohn Wang * @param[in] ips - The object lookup cache holding all of the address info 4748a7236aeSJohn Wang * @return The address and prefix if it was found 4758a7236aeSJohn Wang */ 4768a7236aeSJohn Wang template <int family> 4778a7236aeSJohn Wang std::optional<IfAddr<family>> findIfAddr( 4788a7236aeSJohn Wang sdbusplus::bus::bus& bus, const ChannelParams& params, uint8_t idx, 4798a7236aeSJohn Wang const std::unordered_set< 4808a7236aeSJohn Wang sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin>& 4818a7236aeSJohn Wang origins, 4828a7236aeSJohn Wang ObjectLookupCache& ips) 4838a7236aeSJohn Wang { 4848a7236aeSJohn Wang for (const auto& [path, properties] : ips) 4858a7236aeSJohn Wang { 4868a7236aeSJohn Wang const auto& addrStr = std::get<std::string>(properties.at("Address")); 4878a7236aeSJohn Wang auto addr = maybeStringToAddr<family>(addrStr.c_str()); 4888a7236aeSJohn Wang if (!addr) 4898a7236aeSJohn Wang { 4908a7236aeSJohn Wang continue; 4918a7236aeSJohn Wang } 4928a7236aeSJohn Wang 4938a7236aeSJohn Wang sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin 4948a7236aeSJohn Wang origin = sdbusplus::xyz::openbmc_project::Network::server::IP:: 4958a7236aeSJohn Wang convertAddressOriginFromString( 4968a7236aeSJohn Wang std::get<std::string>(properties.at("Origin"))); 4978a7236aeSJohn Wang if (origins.find(origin) == origins.end()) 4988a7236aeSJohn Wang { 4998a7236aeSJohn Wang continue; 5008a7236aeSJohn Wang } 5018a7236aeSJohn Wang 5028a7236aeSJohn Wang if (idx > 0) 5038a7236aeSJohn Wang { 5048a7236aeSJohn Wang idx--; 5058a7236aeSJohn Wang continue; 5068a7236aeSJohn Wang } 5078a7236aeSJohn Wang 5088a7236aeSJohn Wang IfAddr<family> ifaddr; 5098a7236aeSJohn Wang ifaddr.path = path; 5108a7236aeSJohn Wang ifaddr.address = *addr; 5118a7236aeSJohn Wang ifaddr.prefix = std::get<uint8_t>(properties.at("PrefixLength")); 5128a7236aeSJohn Wang ifaddr.origin = origin; 5138a7236aeSJohn Wang return std::move(ifaddr); 5148a7236aeSJohn Wang } 5158a7236aeSJohn Wang 5168a7236aeSJohn Wang return std::nullopt; 5178a7236aeSJohn Wang } 5188a7236aeSJohn Wang /** @brief Trivial helper around findIfAddr that simplifies calls 5198a7236aeSJohn Wang * for one off lookups. Don't use this if you intend to do multiple 5208a7236aeSJohn Wang * lookups at a time. 5218a7236aeSJohn Wang * 5228a7236aeSJohn Wang * @param[in] bus - The bus object used for lookups 5238a7236aeSJohn Wang * @param[in] params - The parameters for the channel 5248a7236aeSJohn Wang * @param[in] idx - The index of the desired address on the interface 5258a7236aeSJohn Wang * @param[in] origins - The allowed origins for the address objects 5268a7236aeSJohn Wang * @return The address and prefix if it was found 5278a7236aeSJohn Wang */ 5288a7236aeSJohn Wang template <int family> 5298a7236aeSJohn Wang auto getIfAddr( 5308a7236aeSJohn Wang sdbusplus::bus::bus& bus, const ChannelParams& params, uint8_t idx, 5318a7236aeSJohn Wang const std::unordered_set< 5328a7236aeSJohn Wang sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin>& 5338a7236aeSJohn Wang origins) 5348a7236aeSJohn Wang { 5358a7236aeSJohn Wang ObjectLookupCache ips(bus, params, INTF_IP); 5368a7236aeSJohn Wang return findIfAddr<family>(bus, params, idx, origins, ips); 5378a7236aeSJohn Wang } 5388a7236aeSJohn Wang 5398a7236aeSJohn Wang /** @brief Determines if the ethernet interface is using DHCP 5408a7236aeSJohn Wang * 5418a7236aeSJohn Wang * @param[in] bus - The bus object used for lookups 5428a7236aeSJohn Wang * @param[in] params - The parameters for the channel 5438a7236aeSJohn Wang * @return DHCPConf enumeration 5448a7236aeSJohn Wang */ 5458a7236aeSJohn Wang sdbusplus::xyz::openbmc_project::Network::server::EthernetInterface::DHCPConf 5468a7236aeSJohn Wang getDHCPProperty(sdbusplus::bus::bus& bus, const ChannelParams& params); 5478a7236aeSJohn Wang 5488a7236aeSJohn Wang /** @brief Sets the DHCP v6 state on the given interface 5498a7236aeSJohn Wang * 5508a7236aeSJohn Wang * @param[in] bus - The bus object used for lookups 5518a7236aeSJohn Wang * @param[in] params - The parameters for the channel 5528a7236aeSJohn Wang * @param[in] requestedDhcp - DHCP state to assign (none, v6, both) 5538a7236aeSJohn Wang * @param[in] defaultMode - True: Use algorithmic assignment 5548a7236aeSJohn Wang * False: requestedDhcp assigned unconditionally 5558a7236aeSJohn Wang */ 5568a7236aeSJohn Wang void setDHCPv6Property(sdbusplus::bus::bus& bus, const ChannelParams& params, 5578a7236aeSJohn Wang const sdbusplus::xyz::openbmc_project::Network::server:: 5588a7236aeSJohn Wang EthernetInterface::DHCPConf requestedDhcp, 5598a7236aeSJohn Wang const bool defaultMode); 5608a7236aeSJohn Wang 5618a7236aeSJohn Wang /** @brief Reconfigures the IPv6 address info configured for the interface 5628a7236aeSJohn Wang * 5638a7236aeSJohn Wang * @param[in] bus - The bus object used for lookups 5648a7236aeSJohn Wang * @param[in] params - The parameters for the channel 5658a7236aeSJohn Wang * @param[in] idx - The address index to operate on 5668a7236aeSJohn Wang * @param[in] address - The new address 5678a7236aeSJohn Wang * @param[in] prefix - The new address prefix 5688a7236aeSJohn Wang */ 5698a7236aeSJohn Wang void reconfigureIfAddr6(sdbusplus::bus::bus& bus, const ChannelParams& params, 5708a7236aeSJohn Wang uint8_t idx, const in6_addr& address, uint8_t prefix); 5718a7236aeSJohn Wang 5728a7236aeSJohn Wang /** @brief Retrieves the current gateway for the address family on the system 573d1bd8c48SLei YU * NOTE: The gateway is per channel instead of the system wide one. 5748a7236aeSJohn Wang * 5758a7236aeSJohn Wang * @param[in] bus - The bus object used for lookups 5768a7236aeSJohn Wang * @param[in] params - The parameters for the channel 5778a7236aeSJohn Wang * @return An address representing the gateway address if it exists 5788a7236aeSJohn Wang */ 5798a7236aeSJohn Wang template <int family> 5808a7236aeSJohn Wang std::optional<typename AddrFamily<family>::addr> 5818a7236aeSJohn Wang getGatewayProperty(sdbusplus::bus::bus& bus, const ChannelParams& params) 5828a7236aeSJohn Wang { 583d1bd8c48SLei YU auto objPath = "/xyz/openbmc_project/network/" + params.ifname; 584d1bd8c48SLei YU auto gatewayStr = std::get<std::string>( 585d1bd8c48SLei YU getDbusProperty(bus, params.service, objPath, INTF_ETHERNET, 5868a7236aeSJohn Wang AddrFamily<family>::propertyGateway)); 5878a7236aeSJohn Wang if (gatewayStr.empty()) 5888a7236aeSJohn Wang { 5898a7236aeSJohn Wang return std::nullopt; 5908a7236aeSJohn Wang } 5918a7236aeSJohn Wang return stringToAddr<family>(gatewayStr.c_str()); 5928a7236aeSJohn Wang } 5938a7236aeSJohn Wang 5948a7236aeSJohn Wang template <int family> 5958a7236aeSJohn Wang std::optional<IfNeigh<family>> 5968a7236aeSJohn Wang findStaticNeighbor(sdbusplus::bus::bus& bus, const ChannelParams& params, 5978a7236aeSJohn Wang const typename AddrFamily<family>::addr& ip, 5988a7236aeSJohn Wang ObjectLookupCache& neighbors) 5998a7236aeSJohn Wang { 6008a7236aeSJohn Wang using sdbusplus::xyz::openbmc_project::Network::server::Neighbor; 6018a7236aeSJohn Wang const auto state = 6028a7236aeSJohn Wang sdbusplus::xyz::openbmc_project::Network::server::convertForMessage( 6038a7236aeSJohn Wang Neighbor::State::Permanent); 6048a7236aeSJohn Wang for (const auto& [path, neighbor] : neighbors) 6058a7236aeSJohn Wang { 6068a7236aeSJohn Wang const auto& ipStr = std::get<std::string>(neighbor.at("IPAddress")); 6078a7236aeSJohn Wang auto neighIP = maybeStringToAddr<family>(ipStr.c_str()); 6088a7236aeSJohn Wang if (!neighIP) 6098a7236aeSJohn Wang { 6108a7236aeSJohn Wang continue; 6118a7236aeSJohn Wang } 6128a7236aeSJohn Wang if (!equal(*neighIP, ip)) 6138a7236aeSJohn Wang { 6148a7236aeSJohn Wang continue; 6158a7236aeSJohn Wang } 6168a7236aeSJohn Wang if (state != std::get<std::string>(neighbor.at("State"))) 6178a7236aeSJohn Wang { 6188a7236aeSJohn Wang continue; 6198a7236aeSJohn Wang } 6208a7236aeSJohn Wang 6218a7236aeSJohn Wang IfNeigh<family> ret; 6228a7236aeSJohn Wang ret.path = path; 6238a7236aeSJohn Wang ret.ip = ip; 6248a7236aeSJohn Wang const auto& macStr = std::get<std::string>(neighbor.at("MACAddress")); 6258a7236aeSJohn Wang ret.mac = stringToMAC(macStr.c_str()); 6268a7236aeSJohn Wang return std::move(ret); 6278a7236aeSJohn Wang } 6288a7236aeSJohn Wang 6298a7236aeSJohn Wang return std::nullopt; 6308a7236aeSJohn Wang } 6318a7236aeSJohn Wang 6328a7236aeSJohn Wang template <int family> 6338a7236aeSJohn Wang void createNeighbor(sdbusplus::bus::bus& bus, const ChannelParams& params, 6348a7236aeSJohn Wang const typename AddrFamily<family>::addr& address, 6358a7236aeSJohn Wang const ether_addr& mac) 6368a7236aeSJohn Wang { 6378a7236aeSJohn Wang auto newreq = 6388a7236aeSJohn Wang bus.new_method_call(params.service.c_str(), params.logicalPath.c_str(), 6398a7236aeSJohn Wang INTF_NEIGHBOR_CREATE_STATIC, "Neighbor"); 6408a7236aeSJohn Wang std::string macStr = ether_ntoa(&mac); 6418a7236aeSJohn Wang newreq.append(addrToString<family>(address), macStr); 6428a7236aeSJohn Wang bus.call_noreply(newreq); 6438a7236aeSJohn Wang } 6448a7236aeSJohn Wang 6458a7236aeSJohn Wang /** @brief Deletes the dbus object. Ignores empty objects or objects that are 6468a7236aeSJohn Wang * missing from the bus. 6478a7236aeSJohn Wang * 6488a7236aeSJohn Wang * @param[in] bus - The bus object used for lookups 6498a7236aeSJohn Wang * @param[in] service - The name of the service 6508a7236aeSJohn Wang * @param[in] path - The path of the object to delete 6518a7236aeSJohn Wang */ 6528a7236aeSJohn Wang void deleteObjectIfExists(sdbusplus::bus::bus& bus, const std::string& service, 6538a7236aeSJohn Wang const std::string& path); 6548a7236aeSJohn Wang 655d1bd8c48SLei YU /** @brief Sets the value for the default gateway of the channel 6568a7236aeSJohn Wang * 6578a7236aeSJohn Wang * @param[in] bus - The bus object used for lookups 6588a7236aeSJohn Wang * @param[in] params - The parameters for the channel 6598a7236aeSJohn Wang * @param[in] gateway - Gateway address to apply 6608a7236aeSJohn Wang */ 6618a7236aeSJohn Wang template <int family> 6628a7236aeSJohn Wang void setGatewayProperty(sdbusplus::bus::bus& bus, const ChannelParams& params, 6638a7236aeSJohn Wang const typename AddrFamily<family>::addr& address) 6648a7236aeSJohn Wang { 6658a7236aeSJohn Wang // Save the old gateway MAC address if it exists so we can recreate it 6668a7236aeSJohn Wang auto gateway = getGatewayProperty<family>(bus, params); 6678a7236aeSJohn Wang std::optional<IfNeigh<family>> neighbor; 6688a7236aeSJohn Wang if (gateway) 6698a7236aeSJohn Wang { 6708a7236aeSJohn Wang ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR); 6718a7236aeSJohn Wang neighbor = findStaticNeighbor<family>(bus, params, *gateway, neighbors); 6728a7236aeSJohn Wang } 6738a7236aeSJohn Wang 674d1bd8c48SLei YU auto objPath = "/xyz/openbmc_project/network/" + params.ifname; 675d1bd8c48SLei YU setDbusProperty(bus, params.service, objPath, INTF_ETHERNET, 6768a7236aeSJohn Wang AddrFamily<family>::propertyGateway, 6778a7236aeSJohn Wang addrToString<family>(address)); 6788a7236aeSJohn Wang 6798a7236aeSJohn Wang // Restore the gateway MAC if we had one 6808a7236aeSJohn Wang if (neighbor) 6818a7236aeSJohn Wang { 6828a7236aeSJohn Wang deleteObjectIfExists(bus, params.service, neighbor->path); 6838a7236aeSJohn Wang createNeighbor<family>(bus, params, address, neighbor->mac); 6848a7236aeSJohn Wang } 6858a7236aeSJohn Wang } 6868a7236aeSJohn Wang 68723f44657SJian Zhang /** @enum SolConfParam 68823f44657SJian Zhang * 68923f44657SJian Zhang * using for Set/Get SOL configuration parameters command. 69023f44657SJian Zhang */ 69123f44657SJian Zhang enum class SolConfParam : uint8_t 69223f44657SJian Zhang { 69323f44657SJian Zhang Progress, //!< Set In Progress. 69423f44657SJian Zhang Enable, //!< SOL Enable. 69523f44657SJian Zhang Authentication, //!< SOL Authentication. 69623f44657SJian Zhang Accumulate, //!< Character Accumulate Interval & Send Threshold. 69723f44657SJian Zhang Retry, //!< SOL Retry. 69823f44657SJian Zhang NonVbitrate, //!< SOL non-volatile bit rate. 69923f44657SJian Zhang Vbitrate, //!< SOL volatile bit rate. 70023f44657SJian Zhang Channel, //!< SOL payload channel. 70123f44657SJian Zhang Port, //!< SOL payload port. 70223f44657SJian Zhang }; 70323f44657SJian Zhang 70423f44657SJian Zhang constexpr uint8_t ipmiCCParamNotSupported = 0x80; 70523f44657SJian Zhang constexpr uint8_t ipmiCCWriteReadParameter = 0x82; 70623f44657SJian Zhang 707690a2342SPatrick Venture } // namespace transport 708690a2342SPatrick Venture } // namespace ipmi 709