summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Joseph <tomjoseph@in.ibm.com>2018-08-10 01:05:21 +0530
committerTom Joseph <tomjoseph@in.ibm.com>2018-09-25 15:34:33 +0000
commit1322768c7723b7052bb40fe94646c8189a2e20b3 (patch)
treea96bc62908c04badd04bc8932222478e6714647f
parentc6713cff6f28a6d78146a7406123e66ce1d5d320 (diff)
downloadphosphor-host-ipmid-1322768c7723b7052bb40fe94646c8189a2e20b3.tar.gz
phosphor-host-ipmid-1322768c7723b7052bb40fe94646c8189a2e20b3.zip
Implement Set Channel access command
The only option supported is the access mode for disabling or enabling the network IPMI. Change-Id: I2e6b20c317fec19e1e71b3adfc211e6fb847f737 Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
-rw-r--r--app/channel.cpp124
-rw-r--r--apphandler.cpp4
2 files changed, 128 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;
+}
diff --git a/apphandler.cpp b/apphandler.cpp
index b089331..d59c6ac 100644
--- a/apphandler.cpp
+++ b/apphandler.cpp
@@ -652,5 +652,9 @@ void register_netfn_app_functions()
// <Get Channel Cipher Suites Command>
ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHAN_CIPHER_SUITES, NULL,
getChannelCipherSuites, PRIVILEGE_CALLBACK);
+
+ // <Set Channel Access Command>
+ ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_CHAN_ACCESS, NULL,
+ ipmi_set_channel_access, PRIVILEGE_ADMIN);
return;
}
OpenPOWER on IntegriCloud