1 #pragma once 2 3 #include "app/channel.hpp" 4 #include "user_channel/cipher_mgmt.hpp" 5 6 #include <arpa/inet.h> 7 #include <netinet/ether.h> 8 9 #include <array> 10 #include <bitset> 11 #include <cinttypes> 12 #include <cstdint> 13 #include <cstring> 14 #include <fstream> 15 #include <functional> 16 #include <ipmid/api-types.hpp> 17 #include <ipmid/api.hpp> 18 #include <ipmid/message.hpp> 19 #include <ipmid/message/types.hpp> 20 #include <ipmid/types.hpp> 21 #include <ipmid/utils.hpp> 22 #include <optional> 23 #include <phosphor-logging/elog-errors.hpp> 24 #include <phosphor-logging/elog.hpp> 25 #include <phosphor-logging/log.hpp> 26 #include <sdbusplus/bus.hpp> 27 #include <sdbusplus/exception.hpp> 28 #include <string> 29 #include <string_view> 30 #include <type_traits> 31 #include <unordered_map> 32 #include <unordered_set> 33 #include <user_channel/channel_layer.hpp> 34 #include <utility> 35 #include <vector> 36 #include <xyz/openbmc_project/Common/error.hpp> 37 #include <xyz/openbmc_project/Network/EthernetInterface/server.hpp> 38 #include <xyz/openbmc_project/Network/IP/server.hpp> 39 #include <xyz/openbmc_project/Network/Neighbor/server.hpp> 40 41 namespace ipmi 42 { 43 namespace transport 44 { 45 46 // D-Bus Network Daemon definitions 47 constexpr auto PATH_ROOT = "/xyz/openbmc_project/network"; 48 constexpr auto INTF_ETHERNET = "xyz.openbmc_project.Network.EthernetInterface"; 49 constexpr auto INTF_IP = "xyz.openbmc_project.Network.IP"; 50 constexpr auto INTF_IP_CREATE = "xyz.openbmc_project.Network.IP.Create"; 51 constexpr auto INTF_MAC = "xyz.openbmc_project.Network.MACAddress"; 52 constexpr auto INTF_NEIGHBOR = "xyz.openbmc_project.Network.Neighbor"; 53 constexpr auto INTF_NEIGHBOR_CREATE_STATIC = 54 "xyz.openbmc_project.Network.Neighbor.CreateStatic"; 55 constexpr auto INTF_VLAN = "xyz.openbmc_project.Network.VLAN"; 56 constexpr auto INTF_VLAN_CREATE = "xyz.openbmc_project.Network.VLAN.Create"; 57 58 /** @brief IPMI LAN Parameters */ 59 enum class LanParam : uint8_t 60 { 61 SetStatus = 0, 62 AuthSupport = 1, 63 AuthEnables = 2, 64 IP = 3, 65 IPSrc = 4, 66 MAC = 5, 67 SubnetMask = 6, 68 Gateway1 = 12, 69 Gateway1MAC = 13, 70 VLANId = 20, 71 CiphersuiteSupport = 22, 72 CiphersuiteEntries = 23, 73 cipherSuitePrivilegeLevels = 24, 74 IPFamilySupport = 50, 75 IPFamilyEnables = 51, 76 IPv6Status = 55, 77 IPv6StaticAddresses = 56, 78 IPv6DynamicAddresses = 59, 79 IPv6RouterControl = 64, 80 IPv6StaticRouter1IP = 65, 81 IPv6StaticRouter1MAC = 66, 82 IPv6StaticRouter1PrefixLength = 67, 83 IPv6StaticRouter1PrefixValue = 68, 84 }; 85 86 /** @brief IPMI IP Origin Types */ 87 enum class IPSrc : uint8_t 88 { 89 Unspecified = 0, 90 Static = 1, 91 DHCP = 2, 92 BIOS = 3, 93 BMC = 4, 94 }; 95 96 /** @brief IPMI Set Status */ 97 enum class SetStatus : uint8_t 98 { 99 Complete = 0, 100 InProgress = 1, 101 Commit = 2, 102 }; 103 104 /** @brief IPMI Family Suport Bits */ 105 namespace IPFamilySupportFlag 106 { 107 constexpr uint8_t IPv6Only = 0; 108 constexpr uint8_t DualStack = 1; 109 constexpr uint8_t IPv6Alerts = 2; 110 } // namespace IPFamilySupportFlag 111 112 /** @brief IPMI IPFamily Enables Flag */ 113 enum class IPFamilyEnables : uint8_t 114 { 115 IPv4Only = 0, 116 IPv6Only = 1, 117 DualStack = 2, 118 }; 119 120 /** @brief IPMI IPv6 Dyanmic Status Bits */ 121 namespace IPv6StatusFlag 122 { 123 constexpr uint8_t DHCP = 0; 124 constexpr uint8_t SLAAC = 1; 125 }; // namespace IPv6StatusFlag 126 127 /** @brief IPMI IPv6 Source */ 128 enum class IPv6Source : uint8_t 129 { 130 Static = 0, 131 SLAAC = 1, 132 DHCP = 2, 133 }; 134 135 /** @brief IPMI IPv6 Address Status */ 136 enum class IPv6AddressStatus : uint8_t 137 { 138 Active = 0, 139 Disabled = 1, 140 }; 141 142 namespace IPv6RouterControlFlag 143 { 144 constexpr uint8_t Static = 0; 145 constexpr uint8_t Dynamic = 1; 146 }; // namespace IPv6RouterControlFlag 147 148 // LAN Handler specific response codes 149 constexpr Cc ccParamNotSupported = 0x80; 150 constexpr Cc ccParamSetLocked = 0x81; 151 constexpr Cc ccParamReadOnly = 0x82; 152 153 // VLANs are a 12-bit value 154 constexpr uint16_t VLAN_VALUE_MASK = 0x0fff; 155 constexpr uint16_t VLAN_ENABLE_FLAG = 0x8000; 156 157 // Arbitrary v6 Address Limits to prevent too much output in ipmitool 158 constexpr uint8_t MAX_IPV6_STATIC_ADDRESSES = 15; 159 constexpr uint8_t MAX_IPV6_DYNAMIC_ADDRESSES = 15; 160 161 // Prefix length limits of phosphor-networkd 162 constexpr uint8_t MIN_IPV4_PREFIX_LENGTH = 1; 163 constexpr uint8_t MAX_IPV4_PREFIX_LENGTH = 32; 164 constexpr uint8_t MIN_IPV6_PREFIX_LENGTH = 1; 165 constexpr uint8_t MAX_IPV6_PREFIX_LENGTH = 128; 166 167 /** @brief The dbus parameters for the interface corresponding to a channel 168 * This helps reduce the number of mapper lookups we need for each 169 * query and simplifies finding the VLAN interface if needed. 170 */ 171 struct ChannelParams 172 { 173 /** @brief The channel ID */ 174 int id; 175 /** @brief channel name for the interface */ 176 std::string ifname; 177 /** @brief Name of the service on the bus */ 178 std::string service; 179 /** @brief Lower level adapter path that is guaranteed to not be a VLAN */ 180 std::string ifPath; 181 /** @brief Logical adapter path used for address assignment */ 182 std::string logicalPath; 183 }; 184 185 /** @brief A trivial helper used to determine if two PODs are equal 186 * 187 * @params[in] a - The first object to compare 188 * @params[in] b - The second object to compare 189 * @return True if the objects are the same bytewise 190 */ 191 template <typename T> 192 bool equal(const T& a, const T& b) 193 { 194 static_assert(std::is_trivially_copyable_v<T>); 195 return std::memcmp(&a, &b, sizeof(T)) == 0; 196 } 197 198 /** @brief Copies bytes from an array into a trivially copyable container 199 * 200 * @params[out] t - The container receiving the data 201 * @params[in] bytes - The data to copy 202 */ 203 template <size_t N, typename T> 204 void copyInto(T& t, const std::array<uint8_t, N>& bytes) 205 { 206 static_assert(std::is_trivially_copyable_v<T>); 207 static_assert(N == sizeof(T)); 208 std::memcpy(&t, bytes.data(), bytes.size()); 209 } 210 211 /** @brief Gets a generic view of the bytes in the input container 212 * 213 * @params[in] t - The data to reference 214 * @return A string_view referencing the bytes in the container 215 */ 216 template <typename T> 217 std::string_view dataRef(const T& t) 218 { 219 static_assert(std::is_trivially_copyable_v<T>); 220 return {reinterpret_cast<const char*>(&t), sizeof(T)}; 221 } 222 223 /** @brief Determines the ethernet interface name corresponding to a channel 224 * Tries to map a VLAN object first so that the address information 225 * is accurate. Otherwise it gets the standard ethernet interface. 226 * 227 * @param[in] bus - The bus object used for lookups 228 * @param[in] channel - The channel id corresponding to an ethernet interface 229 * @return Ethernet interface service and object path if it exists 230 */ 231 std::optional<ChannelParams> maybeGetChannelParams(sdbusplus::bus_t& bus, 232 uint8_t channel); 233 234 /** @brief A trivial helper around maybeGetChannelParams() that throws an 235 * exception when it is unable to acquire parameters for the channel. 236 * 237 * @param[in] bus - The bus object used for lookups 238 * @param[in] channel - The channel id corresponding to an ethernet interface 239 * @return Ethernet interface service and object path 240 */ 241 ChannelParams getChannelParams(sdbusplus::bus_t& bus, uint8_t channel); 242 243 /** @brief Trivializes using parameter getter functions by providing a bus 244 * and channel parameters automatically. 245 * 246 * @param[in] channel - The channel id corresponding to an ethernet interface 247 * ... 248 */ 249 template <auto func, typename... Args> 250 auto channelCall(uint8_t channel, Args&&... args) 251 { 252 sdbusplus::bus_t bus(ipmid_get_sd_bus_connection()); 253 auto params = getChannelParams(bus, channel); 254 return std::invoke(func, bus, params, std::forward<Args>(args)...); 255 } 256 257 /** @brief Generic paramters for different address families */ 258 template <int family> 259 struct AddrFamily 260 { 261 }; 262 263 /** @brief Parameter specialization for IPv4 */ 264 template <> 265 struct AddrFamily<AF_INET> 266 { 267 using addr = in_addr; 268 static constexpr auto protocol = 269 sdbusplus::xyz::openbmc_project::Network::server::IP::Protocol::IPv4; 270 static constexpr size_t maxStrLen = INET6_ADDRSTRLEN; 271 static constexpr uint8_t defaultPrefix = 32; 272 static constexpr char propertyGateway[] = "DefaultGateway"; 273 }; 274 275 /** @brief Parameter specialization for IPv6 */ 276 template <> 277 struct AddrFamily<AF_INET6> 278 { 279 using addr = in6_addr; 280 static constexpr auto protocol = 281 sdbusplus::xyz::openbmc_project::Network::server::IP::Protocol::IPv6; 282 static constexpr size_t maxStrLen = INET6_ADDRSTRLEN; 283 static constexpr uint8_t defaultPrefix = 128; 284 static constexpr char propertyGateway[] = "DefaultGateway6"; 285 }; 286 287 /** @brief Interface Neighbor configuration parameters */ 288 template <int family> 289 struct IfNeigh 290 { 291 std::string path; 292 typename AddrFamily<family>::addr ip; 293 ether_addr mac; 294 }; 295 296 /** @brief Interface IP Address configuration parameters */ 297 template <int family> 298 struct IfAddr 299 { 300 std::string path; 301 typename AddrFamily<family>::addr address; 302 sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin origin; 303 uint8_t prefix; 304 }; 305 306 /** @brief Valid address origins for IPv6 */ 307 static inline const std::unordered_set< 308 sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin> 309 originsV6Static = {sdbusplus::xyz::openbmc_project::Network::server::IP:: 310 AddressOrigin::Static}; 311 static inline const std::unordered_set< 312 sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin> 313 originsV6Dynamic = { 314 sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin:: 315 DHCP, 316 sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin:: 317 SLAAC, 318 }; 319 320 /** @brief A lazy lookup mechanism for iterating over object properties stored 321 * in DBus. This will only perform the object lookup when needed, and 322 * retains a cache of previous lookups to speed up future iterations. 323 */ 324 class ObjectLookupCache 325 { 326 public: 327 using PropertiesCache = std::unordered_map<std::string, PropertyMap>; 328 329 /** @brief Creates a new ObjectLookupCache for the interface on the bus 330 * NOTE: The inputs to this object must outlive the object since 331 * they are only referenced by it. 332 * 333 * @param[in] bus - The bus object used for lookups 334 * @param[in] params - The parameters for the channel 335 * @param[in] intf - The interface we are looking up 336 */ 337 ObjectLookupCache(sdbusplus::bus_t& bus, const ChannelParams& params, 338 const char* intf) : 339 bus(bus), 340 params(params), intf(intf), 341 objs(getAllDbusObjects(bus, params.logicalPath, intf, "")) 342 { 343 } 344 345 class iterator : public ObjectTree::const_iterator 346 { 347 public: 348 using value_type = PropertiesCache::value_type; 349 350 iterator(ObjectTree::const_iterator it, ObjectLookupCache& container) : 351 ObjectTree::const_iterator(it), container(container), 352 ret(container.cache.end()) 353 { 354 } 355 value_type& operator*() 356 { 357 ret = container.get(ObjectTree::const_iterator::operator*().first); 358 return *ret; 359 } 360 value_type* operator->() 361 { 362 return &operator*(); 363 } 364 365 private: 366 ObjectLookupCache& container; 367 PropertiesCache::iterator ret; 368 }; 369 370 iterator begin() noexcept 371 { 372 return iterator(objs.begin(), *this); 373 } 374 375 iterator end() noexcept 376 { 377 return iterator(objs.end(), *this); 378 } 379 380 private: 381 sdbusplus::bus_t& bus; 382 const ChannelParams& params; 383 const char* const intf; 384 const ObjectTree objs; 385 PropertiesCache cache; 386 387 /** @brief Gets a cached copy of the object properties if possible 388 * Otherwise performs a query on DBus to look them up 389 * 390 * @param[in] path - The object path to lookup 391 * @return An iterator for the specified object path + properties 392 */ 393 PropertiesCache::iterator get(const std::string& path) 394 { 395 auto it = cache.find(path); 396 if (it != cache.end()) 397 { 398 return it; 399 } 400 auto properties = getAllDbusProperties(bus, params.service, path, intf); 401 return cache.insert({path, std::move(properties)}).first; 402 } 403 }; 404 405 /** @brief Turns an IP address string into the network byte order form 406 * NOTE: This version strictly validates family matches 407 * 408 * @param[in] address - The string form of the address 409 * @return A network byte order address or none if conversion failed 410 */ 411 template <int family> 412 std::optional<typename AddrFamily<family>::addr> 413 maybeStringToAddr(const char* address) 414 { 415 typename AddrFamily<family>::addr ret; 416 if (inet_pton(family, address, &ret) == 1) 417 { 418 return ret; 419 } 420 return std::nullopt; 421 } 422 423 /** @brief Turns an IP address string into the network byte order form 424 * NOTE: This version strictly validates family matches 425 * 426 * @param[in] address - The string form of the address 427 * @return A network byte order address 428 */ 429 template <int family> 430 typename AddrFamily<family>::addr stringToAddr(const char* address) 431 { 432 auto ret = maybeStringToAddr<family>(address); 433 if (!ret) 434 { 435 phosphor::logging::log<phosphor::logging::level::ERR>( 436 "Failed to convert IP Address", 437 phosphor::logging::entry("FAMILY=%d", family), 438 phosphor::logging::entry("ADDRESS=%s", address)); 439 phosphor::logging::elog< 440 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>(); 441 } 442 return *ret; 443 } 444 445 /** @brief Turns an IP address in network byte order into a string 446 * 447 * @param[in] address - The string form of the address 448 * @return A network byte order address 449 */ 450 template <int family> 451 std::string addrToString(const typename AddrFamily<family>::addr& address) 452 { 453 std::string ret(AddrFamily<family>::maxStrLen, '\0'); 454 inet_ntop(family, &address, ret.data(), ret.size()); 455 ret.resize(strlen(ret.c_str())); 456 return ret; 457 } 458 459 /** @brief Converts a human readable MAC string into MAC bytes 460 * 461 * @param[in] mac - The MAC string 462 * @return MAC in bytes 463 */ 464 ether_addr stringToMAC(const char* mac); 465 /** @brief Searches the ip object lookup cache for an address matching 466 * the input parameters. NOTE: The index lacks stability across address 467 * changes since the network daemon has no notion of stable indicies. 468 * 469 * @param[in] bus - The bus object used for lookups 470 * @param[in] params - The parameters for the channel 471 * @param[in] idx - The index of the desired address on the interface 472 * @param[in] origins - The allowed origins for the address objects 473 * @param[in] ips - The object lookup cache holding all of the address info 474 * @return The address and prefix if it was found 475 */ 476 template <int family> 477 std::optional<IfAddr<family>> findIfAddr( 478 [[maybe_unused]] sdbusplus::bus_t& bus, 479 [[maybe_unused]] const ChannelParams& params, uint8_t idx, 480 const std::unordered_set< 481 sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin>& 482 origins, 483 ObjectLookupCache& ips) 484 { 485 for (const auto& [path, properties] : ips) 486 { 487 const auto& addrStr = std::get<std::string>(properties.at("Address")); 488 auto addr = maybeStringToAddr<family>(addrStr.c_str()); 489 if (!addr) 490 { 491 continue; 492 } 493 494 sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin 495 origin = sdbusplus::xyz::openbmc_project::Network::server::IP:: 496 convertAddressOriginFromString( 497 std::get<std::string>(properties.at("Origin"))); 498 if (origins.find(origin) == origins.end()) 499 { 500 continue; 501 } 502 503 if (idx > 0) 504 { 505 idx--; 506 continue; 507 } 508 509 IfAddr<family> ifaddr; 510 ifaddr.path = path; 511 ifaddr.address = *addr; 512 ifaddr.prefix = std::get<uint8_t>(properties.at("PrefixLength")); 513 ifaddr.origin = origin; 514 return ifaddr; 515 } 516 517 return std::nullopt; 518 } 519 /** @brief Trivial helper around findIfAddr that simplifies calls 520 * for one off lookups. Don't use this if you intend to do multiple 521 * lookups at a time. 522 * 523 * @param[in] bus - The bus object used for lookups 524 * @param[in] params - The parameters for the channel 525 * @param[in] idx - The index of the desired address on the interface 526 * @param[in] origins - The allowed origins for the address objects 527 * @return The address and prefix if it was found 528 */ 529 template <int family> 530 auto getIfAddr( 531 sdbusplus::bus_t& bus, const ChannelParams& params, uint8_t idx, 532 const std::unordered_set< 533 sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin>& 534 origins) 535 { 536 ObjectLookupCache ips(bus, params, INTF_IP); 537 return findIfAddr<family>(bus, params, idx, origins, ips); 538 } 539 540 /** @brief Determines if the ethernet interface is using DHCP 541 * 542 * @param[in] bus - The bus object used for lookups 543 * @param[in] params - The parameters for the channel 544 * @return DHCPConf enumeration 545 */ 546 sdbusplus::xyz::openbmc_project::Network::server::EthernetInterface::DHCPConf 547 getDHCPProperty(sdbusplus::bus_t& bus, const ChannelParams& params); 548 549 /** @brief Sets the DHCP v6 state on the given interface 550 * 551 * @param[in] bus - The bus object used for lookups 552 * @param[in] params - The parameters for the channel 553 * @param[in] requestedDhcp - DHCP state to assign (none, v6, both) 554 * @param[in] defaultMode - True: Use algorithmic assignment 555 * False: requestedDhcp assigned unconditionally 556 */ 557 void setDHCPv6Property(sdbusplus::bus_t& bus, const ChannelParams& params, 558 const sdbusplus::xyz::openbmc_project::Network::server:: 559 EthernetInterface::DHCPConf requestedDhcp, 560 const bool defaultMode); 561 562 /** @brief Reconfigures the IPv6 address info configured for the interface 563 * 564 * @param[in] bus - The bus object used for lookups 565 * @param[in] params - The parameters for the channel 566 * @param[in] idx - The address index to operate on 567 * @param[in] address - The new address 568 * @param[in] prefix - The new address prefix 569 */ 570 void reconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params, 571 uint8_t idx, const in6_addr& address, uint8_t prefix); 572 573 /** @brief Retrieves the current gateway for the address family on the system 574 * NOTE: The gateway is per channel instead of the system wide one. 575 * 576 * @param[in] bus - The bus object used for lookups 577 * @param[in] params - The parameters for the channel 578 * @return An address representing the gateway address if it exists 579 */ 580 template <int family> 581 std::optional<typename AddrFamily<family>::addr> 582 getGatewayProperty(sdbusplus::bus_t& bus, const ChannelParams& params) 583 { 584 auto objPath = "/xyz/openbmc_project/network/" + params.ifname; 585 auto gatewayStr = std::get<std::string>( 586 getDbusProperty(bus, params.service, objPath, INTF_ETHERNET, 587 AddrFamily<family>::propertyGateway)); 588 if (gatewayStr.empty()) 589 { 590 return std::nullopt; 591 } 592 return stringToAddr<family>(gatewayStr.c_str()); 593 } 594 595 template <int family> 596 std::optional<IfNeigh<family>> 597 findStaticNeighbor(sdbusplus::bus_t&, const ChannelParams&, 598 const typename AddrFamily<family>::addr& ip, 599 ObjectLookupCache& neighbors) 600 { 601 using sdbusplus::xyz::openbmc_project::Network::server::Neighbor; 602 const auto state = 603 sdbusplus::xyz::openbmc_project::Network::server::convertForMessage( 604 Neighbor::State::Permanent); 605 for (const auto& [path, neighbor] : neighbors) 606 { 607 const auto& ipStr = std::get<std::string>(neighbor.at("IPAddress")); 608 auto neighIP = maybeStringToAddr<family>(ipStr.c_str()); 609 if (!neighIP) 610 { 611 continue; 612 } 613 if (!equal(*neighIP, ip)) 614 { 615 continue; 616 } 617 if (state != std::get<std::string>(neighbor.at("State"))) 618 { 619 continue; 620 } 621 622 IfNeigh<family> ret; 623 ret.path = path; 624 ret.ip = ip; 625 const auto& macStr = std::get<std::string>(neighbor.at("MACAddress")); 626 ret.mac = stringToMAC(macStr.c_str()); 627 return ret; 628 } 629 630 return std::nullopt; 631 } 632 633 template <int family> 634 void createNeighbor(sdbusplus::bus_t& bus, const ChannelParams& params, 635 const typename AddrFamily<family>::addr& address, 636 const ether_addr& mac) 637 { 638 auto newreq = 639 bus.new_method_call(params.service.c_str(), params.logicalPath.c_str(), 640 INTF_NEIGHBOR_CREATE_STATIC, "Neighbor"); 641 std::string macStr = ether_ntoa(&mac); 642 newreq.append(addrToString<family>(address), macStr); 643 bus.call_noreply(newreq); 644 } 645 646 /** @brief Deletes the dbus object. Ignores empty objects or objects that are 647 * missing from the bus. 648 * 649 * @param[in] bus - The bus object used for lookups 650 * @param[in] service - The name of the service 651 * @param[in] path - The path of the object to delete 652 */ 653 void deleteObjectIfExists(sdbusplus::bus_t& bus, const std::string& service, 654 const std::string& path); 655 656 /** @brief Sets the value for the default gateway of the channel 657 * 658 * @param[in] bus - The bus object used for lookups 659 * @param[in] params - The parameters for the channel 660 * @param[in] gateway - Gateway address to apply 661 */ 662 template <int family> 663 void setGatewayProperty(sdbusplus::bus_t& bus, const ChannelParams& params, 664 const typename AddrFamily<family>::addr& address) 665 { 666 // Save the old gateway MAC address if it exists so we can recreate it 667 auto gateway = getGatewayProperty<family>(bus, params); 668 std::optional<IfNeigh<family>> neighbor; 669 if (gateway) 670 { 671 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR); 672 neighbor = findStaticNeighbor<family>(bus, params, *gateway, neighbors); 673 } 674 675 auto objPath = "/xyz/openbmc_project/network/" + params.ifname; 676 setDbusProperty(bus, params.service, objPath, INTF_ETHERNET, 677 AddrFamily<family>::propertyGateway, 678 addrToString<family>(address)); 679 680 // Restore the gateway MAC if we had one 681 if (neighbor) 682 { 683 deleteObjectIfExists(bus, params.service, neighbor->path); 684 createNeighbor<family>(bus, params, address, neighbor->mac); 685 } 686 } 687 688 /** @enum SolConfParam 689 * 690 * using for Set/Get SOL configuration parameters command. 691 */ 692 enum class SolConfParam : uint8_t 693 { 694 Progress, //!< Set In Progress. 695 Enable, //!< SOL Enable. 696 Authentication, //!< SOL Authentication. 697 Accumulate, //!< Character Accumulate Interval & Send Threshold. 698 Retry, //!< SOL Retry. 699 NonVbitrate, //!< SOL non-volatile bit rate. 700 Vbitrate, //!< SOL volatile bit rate. 701 Channel, //!< SOL payload channel. 702 Port, //!< SOL payload port. 703 }; 704 705 constexpr uint8_t ipmiCCParamNotSupported = 0x80; 706 constexpr uint8_t ipmiCCWriteReadParameter = 0x82; 707 708 } // namespace transport 709 } // namespace ipmi 710