diff options
author | Tom Joseph <tomjoseph@in.ibm.com> | 2018-08-10 01:05:21 +0530 |
---|---|---|
committer | Tom Joseph <tomjoseph@in.ibm.com> | 2018-09-25 15:34:33 +0000 |
commit | 1322768c7723b7052bb40fe94646c8189a2e20b3 (patch) | |
tree | a96bc62908c04badd04bc8932222478e6714647f | |
parent | c6713cff6f28a6d78146a7406123e66ce1d5d320 (diff) | |
download | phosphor-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.cpp | 124 | ||||
-rw-r--r-- | apphandler.cpp | 4 |
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; } |