summaryrefslogtreecommitdiffstats
path: root/app/channel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'app/channel.cpp')
-rw-r--r--app/channel.cpp124
1 files changed, 124 insertions, 0 deletions
diff --git a/app/channel.cpp b/app/channel.cpp
index 2fee5cc..6db987f 100644
--- a/app/channel.cpp
+++ b/app/channel.cpp
@@ -7,6 +7,7 @@
#include <arpa/inet.h>
+#include <boost/process/child.hpp>
#include <fstream>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
@@ -260,3 +261,126 @@ ipmi_ret_t getChannelCipherSuites(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
return IPMI_CC_OK;
}
+
+template <typename... ArgTypes>
+static int executeCmd(const char* path, ArgTypes&&... tArgs)
+{
+ boost::process::child execProg(path, const_cast<char*>(tArgs)...);
+ execProg.wait();
+ return execProg.exit_code();
+}
+
+/** @brief Enable the network IPMI service on the specified ethernet interface.
+ *
+ * @param[in] intf - ethernet interface on which to enable IPMI
+ */
+void enableNetworkIPMI(const std::string& intf)
+{
+ // Check if there is a iptable filter to drop IPMI packets for the
+ // interface.
+ auto retCode =
+ executeCmd("/usr/sbin/iptables", "-C", "INPUT", "-p", "udp", "-i",
+ intf.c_str(), "--dport", "623", "-j", "DROP");
+
+ // If the iptable filter exists, delete the filter.
+ if (!retCode)
+ {
+ auto response =
+ executeCmd("/usr/sbin/iptables", "-D", "INPUT", "-p", "udp", "-i",
+ intf.c_str(), "--dport", "623", "-j", "DROP");
+
+ if (response)
+ {
+ log<level::ERR>("Dropping the iptables filter failed",
+ entry("INTF=%s", intf.c_str()),
+ entry("RETURN_CODE:%d", response));
+ }
+ }
+}
+
+/** @brief Disable the network IPMI service on the specified ethernet interface.
+ *
+ * @param[in] intf - ethernet interface on which to disable IPMI
+ */
+void disableNetworkIPMI(const std::string& intf)
+{
+ // Check if there is a iptable filter to drop IPMI packets for the
+ // interface.
+ auto retCode =
+ executeCmd("/usr/sbin/iptables", "-C", "INPUT", "-p", "udp", "-i",
+ intf.c_str(), "--dport", "623", "-j", "DROP");
+
+ // If the iptable filter does not exist, add filter to drop network IPMI
+ // packets
+ if (retCode)
+ {
+ auto response =
+ executeCmd("/usr/sbin/iptables", "-I", "INPUT", "-p", "udp", "-i",
+ intf.c_str(), "--dport", "623", "-j", "DROP");
+
+ if (response)
+ {
+ log<level::ERR>("Inserting iptables filter failed",
+ entry("INTF=%s", intf.c_str()),
+ entry("RETURN_CODE:%d", response));
+ }
+ }
+}
+
+/** @struct SetChannelAccessRequest
+ *
+ * IPMI payload for Set Channel access command request.
+ */
+struct SetChannelAccessRequest
+{
+ uint8_t channelNumber; //!< Channel number
+ uint8_t accessMode; //!< Access mode for IPMI messaging
+ uint8_t privLevel; //!< Channel Privilege Level
+} __attribute__((packed));
+
+ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request,
+ ipmi_response_t response,
+ ipmi_data_len_t data_len,
+ ipmi_context_t context)
+{
+ auto requestData =
+ reinterpret_cast<const SetChannelAccessRequest*>(request);
+
+ int channel = requestData->channelNumber;
+ // Validate the channel number corresponds to any of the network channel.
+ auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
+ if (ethdevice.empty())
+ {
+ *data_len = 0;
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
+ // Bits[2:0] indicates the Access Mode, this mask field will extract the
+ // access mode from the command data.
+ static constexpr auto accessModeMask = 0x07;
+ auto accessMode = requestData->accessMode & accessModeMask;
+ static constexpr auto disabled = 0;
+ static constexpr auto enabled = 2;
+
+ try
+ {
+ if (accessMode == enabled)
+ {
+ enableNetworkIPMI(ethdevice);
+ }
+ else if (accessMode == disabled)
+ {
+ disableNetworkIPMI(ethdevice);
+ }
+ }
+ catch (const sdbusplus::exception::SdBusError& e)
+ {
+ log<level::ERR>(e.what());
+ *data_len = 0;
+ return IPMI_CC_UNSPECIFIED_ERROR;
+ }
+
+ return IPMI_CC_OK;
+}
OpenPOWER on IntegriCloud