summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--transporthandler.cpp400
1 files changed, 400 insertions, 0 deletions
diff --git a/transporthandler.cpp b/transporthandler.cpp
index 61065ad..1a06ae5 100644
--- a/transporthandler.cpp
+++ b/transporthandler.cpp
@@ -89,6 +89,10 @@ constexpr Cc ccParamReadOnly = 0x82;
constexpr uint16_t VLAN_VALUE_MASK = 0x0fff;
constexpr uint16_t VLAN_ENABLE_FLAG = 0x8000;
+// Arbitrary v6 Address Limits to prevent too much output in ipmitool
+constexpr uint8_t MAX_IPV6_STATIC_ADDRESSES = 15;
+constexpr uint8_t MAX_IPV6_DYNAMIC_ADDRESSES = 15;
+
// D-Bus Network Daemon definitions
constexpr auto PATH_ROOT = "/xyz/openbmc_project/network";
constexpr auto PATH_SYSTEMCONFIG = "/xyz/openbmc_project/network/config";
@@ -122,12 +126,31 @@ struct AddrFamily<AF_INET>
static constexpr char propertyGateway[] = "DefaultGateway";
};
+/** @brief Parameter specialization for IPv6 */
+template <>
+struct AddrFamily<AF_INET6>
+{
+ using addr = in6_addr;
+ static constexpr auto protocol = IP::Protocol::IPv6;
+ static constexpr size_t maxStrLen = INET6_ADDRSTRLEN;
+ static constexpr uint8_t defaultPrefix = 128;
+ static constexpr char propertyGateway[] = "DefaultGateway6";
+};
+
/** @brief Valid address origins for IPv4 */
const std::unordered_set<IP::AddressOrigin> originsV4 = {
IP::AddressOrigin::Static,
IP::AddressOrigin::DHCP,
};
+/** @brief Valid address origins for IPv6 */
+const std::unordered_set<IP::AddressOrigin> originsV6Static = {
+ IP::AddressOrigin::Static};
+const std::unordered_set<IP::AddressOrigin> originsV6Dynamic = {
+ IP::AddressOrigin::DHCP,
+ IP::AddressOrigin::SLAAC,
+};
+
/** @brief Interface IP Address configuration parameters */
template <int family>
struct IfAddr
@@ -162,6 +185,16 @@ enum class LanParam : uint8_t
VLANId = 20,
CiphersuiteSupport = 22,
CiphersuiteEntries = 23,
+ IPFamilySupport = 50,
+ IPFamilyEnables = 51,
+ IPv6Status = 55,
+ IPv6StaticAddresses = 56,
+ IPv6DynamicAddresses = 59,
+ IPv6RouterControl = 64,
+ IPv6StaticRouter1IP = 65,
+ IPv6StaticRouter1MAC = 66,
+ IPv6StaticRouter1PrefixLength = 67,
+ IPv6StaticRouter1PrefixValue = 68,
};
static constexpr uint8_t oemCmdStart = 192;
@@ -185,6 +218,50 @@ enum class SetStatus : uint8_t
Commit = 2,
};
+/** @brief IPMI Family Suport Bits */
+namespace IPFamilySupportFlag
+{
+constexpr uint8_t IPv6Only = 0;
+constexpr uint8_t DualStack = 1;
+constexpr uint8_t IPv6Alerts = 2;
+} // namespace IPFamilySupportFlag
+
+/** @brief IPMI IPFamily Enables Flag */
+enum class IPFamilyEnables : uint8_t
+{
+ IPv4Only = 0,
+ IPv6Only = 1,
+ DualStack = 2,
+};
+
+/** @brief IPMI IPv6 Dyanmic Status Bits */
+namespace IPv6StatusFlag
+{
+constexpr uint8_t DHCP = 0;
+constexpr uint8_t SLAAC = 1;
+}; // namespace IPv6StatusFlag
+
+/** @brief IPMI IPv6 Source */
+enum class IPv6Source : uint8_t
+{
+ Static = 0,
+ SLAAC = 1,
+ DHCP = 2,
+};
+
+/** @brief IPMI IPv6 Address Status */
+enum class IPv6AddressStatus : uint8_t
+{
+ Active = 0,
+ Disabled = 1,
+};
+
+namespace IPv6RouterControlFlag
+{
+constexpr uint8_t Static = 0;
+constexpr uint8_t Dynamic = 1;
+}; // namespace IPv6RouterControlFlag
+
/** @brief A trivial helper used to determine if two PODs are equal
*
* @params[in] a - The first object to compare
@@ -888,6 +965,97 @@ void reconfigureGatewayMAC(sdbusplus::bus::bus& bus,
createNeighbor<family>(bus, params, *gateway, mac);
}
+/** @brief Deconfigures the IPv6 address info configured for the interface
+ *
+ * @param[in] bus - The bus object used for lookups
+ * @param[in] params - The parameters for the channel
+ * @param[in] idx - The address index to operate on
+ */
+void deconfigureIfAddr6(sdbusplus::bus::bus& bus, const ChannelParams& params,
+ uint8_t idx)
+{
+ auto ifaddr = getIfAddr<AF_INET6>(bus, params, idx, originsV6Static);
+ if (ifaddr)
+ {
+ deleteObjectIfExists(bus, params.service, ifaddr->path);
+ }
+}
+
+/** @brief Reconfigures the IPv6 address info configured for the interface
+ *
+ * @param[in] bus - The bus object used for lookups
+ * @param[in] params - The parameters for the channel
+ * @param[in] idx - The address index to operate on
+ * @param[in] address - The new address
+ * @param[in] prefix - The new address prefix
+ */
+void reconfigureIfAddr6(sdbusplus::bus::bus& bus, const ChannelParams& params,
+ uint8_t idx, const in6_addr& address, uint8_t prefix)
+{
+ deconfigureIfAddr6(bus, params, idx);
+ createIfAddr<AF_INET6>(bus, params, address, prefix);
+}
+
+/** @brief Converts the AddressOrigin into an IPv6Source
+ *
+ * @param[in] origin - The DBus Address Origin to convert
+ * @return The IPv6Source version of the origin
+ */
+IPv6Source originToSourceType(IP::AddressOrigin origin)
+{
+ switch (origin)
+ {
+ case IP::AddressOrigin::Static:
+ return IPv6Source::Static;
+ case IP::AddressOrigin::DHCP:
+ return IPv6Source::DHCP;
+ case IP::AddressOrigin::SLAAC:
+ return IPv6Source::SLAAC;
+ default:
+ {
+ auto originStr = sdbusplus::xyz::openbmc_project::Network::server::
+ convertForMessage(origin);
+ log<level::ERR>(
+ "Invalid IP::AddressOrigin conversion to IPv6Source",
+ entry("ORIGIN=%s", originStr.c_str()));
+ elog<InternalFailure>();
+ }
+ }
+}
+
+/** @brief Packs the IPMI message response with IPv6 address data
+ *
+ * @param[out] ret - The IPMI response payload to be packed
+ * @param[in] channel - The channel id corresponding to an ethernet interface
+ * @param[in] set - The set selector for determining address index
+ * @param[in] origins - Set of valid origins for address filtering
+ */
+void getLanIPv6Address(message::Payload& ret, uint8_t channel, uint8_t set,
+ const std::unordered_set<IP::AddressOrigin>& origins)
+{
+ auto source = IPv6Source::Static;
+ bool enabled = false;
+ in6_addr addr{};
+ uint8_t prefix = AddrFamily<AF_INET6>::defaultPrefix;
+ auto status = IPv6AddressStatus::Disabled;
+
+ auto ifaddr = channelCall<getIfAddr<AF_INET6>>(channel, set, origins);
+ if (ifaddr)
+ {
+ source = originToSourceType(ifaddr->origin);
+ enabled = true;
+ addr = ifaddr->address;
+ prefix = ifaddr->prefix;
+ status = IPv6AddressStatus::Active;
+ }
+
+ ret.pack(set);
+ ret.pack(static_cast<uint4_t>(source), uint3_t{}, enabled);
+ ret.pack(std::string_view(reinterpret_cast<char*>(&addr), sizeof(addr)));
+ ret.pack(prefix);
+ ret.pack(static_cast<uint8_t>(status));
+}
+
/** @brief Gets the vlan ID configured on the interface
*
* @param[in] bus - The bus object used for lookups
@@ -987,9 +1155,21 @@ void reconfigureVLAN(sdbusplus::bus::bus& bus, ChannelParams& params,
// Save info from the old logical interface
ObjectLookupCache ips(bus, params, INTF_IP);
auto ifaddr4 = findIfAddr<AF_INET>(bus, params, 0, originsV4, ips);
+ std::vector<IfAddr<AF_INET6>> ifaddrs6;
+ for (uint8_t i = 0; i < MAX_IPV6_STATIC_ADDRESSES; ++i)
+ {
+ auto ifaddr6 =
+ findIfAddr<AF_INET6>(bus, params, i, originsV6Static, ips);
+ if (!ifaddr6)
+ {
+ break;
+ }
+ ifaddrs6.push_back(std::move(*ifaddr6));
+ }
auto dhcp = getDHCPProperty(bus, params);
ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
auto neighbor4 = findGatewayNeighbor<AF_INET>(bus, params, neighbors);
+ auto neighbor6 = findGatewayNeighbor<AF_INET6>(bus, params, neighbors);
deconfigureChannel(bus, params);
createVLAN(bus, params, vlan);
@@ -1000,10 +1180,18 @@ void reconfigureVLAN(sdbusplus::bus::bus& bus, ChannelParams& params,
{
createIfAddr<AF_INET>(bus, params, ifaddr4->address, ifaddr4->prefix);
}
+ for (const auto& ifaddr6 : ifaddrs6)
+ {
+ createIfAddr<AF_INET6>(bus, params, ifaddr6.address, ifaddr6.prefix);
+ }
if (neighbor4)
{
createNeighbor<AF_INET>(bus, params, neighbor4->ip, neighbor4->mac);
}
+ if (neighbor6)
+ {
+ createNeighbor<AF_INET6>(bus, params, neighbor6->ip, neighbor6->mac);
+ }
}
/** @brief Turns a prefix into a netmask
@@ -1287,10 +1475,132 @@ RspType<> setLan(uint4_t channelBits, uint4_t, uint8_t parameter,
}
case LanParam::CiphersuiteSupport:
case LanParam::CiphersuiteEntries:
+ case LanParam::IPFamilySupport:
+ {
+ req.trailingOk = true;
+ return response(ccParamReadOnly);
+ }
+ case LanParam::IPFamilyEnables:
+ {
+ uint8_t enables;
+ if (req.unpack(enables) != 0 || !req.fullyUnpacked())
+ {
+ return responseReqDataLenInvalid();
+ }
+ switch (static_cast<IPFamilyEnables>(enables))
+ {
+ case IPFamilyEnables::DualStack:
+ return responseSuccess();
+ case IPFamilyEnables::IPv4Only:
+ case IPFamilyEnables::IPv6Only:
+ return response(ccParamNotSupported);
+ }
+ return response(ccParamNotSupported);
+ }
+ case LanParam::IPv6Status:
+ {
+ req.trailingOk = true;
+ return response(ccParamReadOnly);
+ }
+ case LanParam::IPv6StaticAddresses:
+ {
+ uint8_t set;
+ uint7_t rsvd;
+ bool enabled;
+ in6_addr ip;
+ std::array<uint8_t, sizeof(ip)> ipbytes;
+ uint8_t prefix;
+ uint8_t status;
+ if (req.unpack(set, rsvd, enabled, ipbytes, prefix, status) != 0 ||
+ !req.fullyUnpacked())
+ {
+ return responseReqDataLenInvalid();
+ }
+ copyInto(ip, ipbytes);
+ if (enabled)
+ {
+ channelCall<reconfigureIfAddr6>(channel, set, ip, prefix);
+ }
+ else
+ {
+ channelCall<deconfigureIfAddr6>(channel, set);
+ }
+ return responseSuccess();
+ }
+ case LanParam::IPv6DynamicAddresses:
{
req.trailingOk = true;
return response(ccParamReadOnly);
}
+ case LanParam::IPv6RouterControl:
+ {
+ std::bitset<8> control;
+ if (req.unpack(control) != 0 || !req.fullyUnpacked())
+ {
+ return responseReqDataLenInvalid();
+ }
+ std::bitset<8> expected;
+ if (channelCall<getDHCPProperty>(channel))
+ {
+ expected[IPv6RouterControlFlag::Dynamic] = 1;
+ }
+ else
+ {
+ expected[IPv6RouterControlFlag::Static] = 1;
+ }
+ if (expected != control)
+ {
+ return responseInvalidFieldRequest();
+ }
+ return responseSuccess();
+ }
+ case LanParam::IPv6StaticRouter1IP:
+ {
+ in6_addr gateway;
+ std::array<uint8_t, sizeof(gateway)> bytes;
+ if (req.unpack(bytes) != 0 || !req.fullyUnpacked())
+ {
+ return responseReqDataLenInvalid();
+ }
+ copyInto(gateway, bytes);
+ channelCall<setGatewayProperty<AF_INET6>>(channel, gateway);
+ return responseSuccess();
+ }
+ case LanParam::IPv6StaticRouter1MAC:
+ {
+ ether_addr mac;
+ std::array<uint8_t, sizeof(mac)> bytes;
+ if (req.unpack(bytes) != 0 || !req.fullyUnpacked())
+ {
+ return responseReqDataLenInvalid();
+ }
+ copyInto(mac, bytes);
+ channelCall<reconfigureGatewayMAC<AF_INET6>>(channel, mac);
+ return responseSuccess();
+ }
+ case LanParam::IPv6StaticRouter1PrefixLength:
+ {
+ uint8_t prefix;
+ if (req.unpack(prefix) != 0 || !req.fullyUnpacked())
+ {
+ return responseReqDataLenInvalid();
+ }
+ if (prefix != 0)
+ {
+ return responseInvalidFieldRequest();
+ }
+ return responseSuccess();
+ }
+ case LanParam::IPv6StaticRouter1PrefixValue:
+ {
+ std::array<uint8_t, sizeof(in6_addr)> bytes;
+ if (req.unpack(bytes) != 0 || !req.fullyUnpacked())
+ {
+ return responseReqDataLenInvalid();
+ }
+ // Accept any prefix value since our prefix length has to be 0
+ return responseSuccess();
+ }
}
if ((parameter >= oemCmdStart) && (parameter <= oemCmdEnd))
@@ -1456,6 +1766,96 @@ RspType<message::Payload> getLan(uint4_t channelBits, uint3_t, bool revOnly,
ret.pack(cipherList);
return responseSuccess(std::move(ret));
}
+ case LanParam::IPFamilySupport:
+ {
+ std::bitset<8> support;
+ support[IPFamilySupportFlag::IPv6Only] = 0;
+ support[IPFamilySupportFlag::DualStack] = 1;
+ support[IPFamilySupportFlag::IPv6Alerts] = 1;
+ ret.pack(support);
+ return responseSuccess(std::move(ret));
+ }
+ case LanParam::IPFamilyEnables:
+ {
+ ret.pack(static_cast<uint8_t>(IPFamilyEnables::DualStack));
+ return responseSuccess(std::move(ret));
+ }
+ case LanParam::IPv6Status:
+ {
+ ret.pack(MAX_IPV6_STATIC_ADDRESSES);
+ ret.pack(MAX_IPV6_DYNAMIC_ADDRESSES);
+ std::bitset<8> support;
+ support[IPv6StatusFlag::DHCP] = 1;
+ support[IPv6StatusFlag::SLAAC] = 1;
+ ret.pack(support);
+ return responseSuccess(std::move(ret));
+ }
+ case LanParam::IPv6StaticAddresses:
+ {
+ if (set >= MAX_IPV6_STATIC_ADDRESSES)
+ {
+ return responseParmOutOfRange();
+ }
+ getLanIPv6Address(ret, channel, set, originsV6Static);
+ return responseSuccess(std::move(ret));
+ }
+ case LanParam::IPv6DynamicAddresses:
+ {
+ if (set >= MAX_IPV6_DYNAMIC_ADDRESSES)
+ {
+ return responseParmOutOfRange();
+ }
+ getLanIPv6Address(ret, channel, set, originsV6Dynamic);
+ return responseSuccess(std::move(ret));
+ }
+ case LanParam::IPv6RouterControl:
+ {
+ std::bitset<8> control;
+ if (channelCall<getDHCPProperty>(channel))
+ {
+ control[IPv6RouterControlFlag::Dynamic] = 1;
+ }
+ else
+ {
+ control[IPv6RouterControlFlag::Static] = 1;
+ }
+ ret.pack(control);
+ return responseSuccess(std::move(ret));
+ }
+ case LanParam::IPv6StaticRouter1IP:
+ {
+ in6_addr gateway{};
+ if (!channelCall<getDHCPProperty>(channel))
+ {
+ gateway =
+ channelCall<getGatewayProperty<AF_INET6>>(channel).value_or(
+ in6_addr{});
+ }
+ ret.pack(dataRef(gateway));
+ return responseSuccess(std::move(ret));
+ }
+ case LanParam::IPv6StaticRouter1MAC:
+ {
+ ether_addr mac{};
+ auto neighbor = channelCall<getGatewayNeighbor<AF_INET6>>(channel);
+ if (neighbor)
+ {
+ mac = neighbor->mac;
+ }
+ ret.pack(dataRef(mac));
+ return responseSuccess(std::move(ret));
+ }
+ case LanParam::IPv6StaticRouter1PrefixLength:
+ {
+ ret.pack(UINT8_C(0));
+ return responseSuccess(std::move(ret));
+ }
+ case LanParam::IPv6StaticRouter1PrefixValue:
+ {
+ in6_addr prefix{};
+ ret.pack(dataRef(prefix));
+ return responseSuccess(std::move(ret));
+ }
}
if ((parameter >= oemCmdStart) && (parameter <= oemCmdEnd))
OpenPOWER on IntegriCloud