summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am6
-rw-r--r--apphandler.cpp11
-rw-r--r--user_channel/channel_layer.cpp131
-rw-r--r--user_channel/channel_layer.hpp275
-rw-r--r--user_channel/channel_mgmt.cpp1027
-rw-r--r--user_channel/channel_mgmt.hpp334
-rw-r--r--user_channel/channelcommands.cpp391
-rw-r--r--user_channel/channelcommands.hpp32
8 files changed, 2205 insertions, 2 deletions
diff --git a/Makefile.am b/Makefile.am
index 5e03648..966dbe4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -67,7 +67,9 @@ libuserlayer_LTLIBRARIES = libuserlayer.la
libuserlayer_la_SOURCES = \
user_channel/user_layer.cpp \
user_channel/user_mgmt.cpp \
- user_channel/passwd_mgr.cpp
+ user_channel/passwd_mgr.cpp \
+ user_channel/channel_mgmt.cpp \
+ user_channel/channel_layer.cpp
libuserlayer_la_LDFLAGS = $(SYSTEMD_LIBS) $(libmapper_LIBS) \
$(PHOSPHOR_LOGGING_LIBS) $(PHOSPHOR_DBUS_INTERFACES_LIBS) -lstdc++fs \
@@ -99,6 +101,7 @@ libipmi20_la_SOURCES = \
read_fru_data.cpp \
sensordatahandler.cpp \
user_channel/usercommands.cpp \
+ user_channel/channelcommands.cpp \
$(libipmi20_BUILT_LIST)
@CODE_COVERAGE_RULES@
@@ -138,6 +141,7 @@ libsysintfcmds_la_CXXFLAGS = $(SYSTEMD_CFLAGS) \
nobase_include_HEADERS = \
host-ipmid/iana.hpp \
user_channel/user_layer.hpp \
+ user_channel/channel_layer.hpp \
host-ipmid/ipmid-api.h \
host-ipmid/ipmid-host-cmd.hpp \
host-ipmid/ipmid-host-cmd-utils.hpp \
diff --git a/apphandler.cpp b/apphandler.cpp
index 370e0c3..bd4b5c3 100644
--- a/apphandler.cpp
+++ b/apphandler.cpp
@@ -6,6 +6,7 @@
#include "sys_info_param.hpp"
#include "transporthandler.hpp"
#include "types.hpp"
+#include "user_channel/channelcommands.hpp"
#include "user_channel/usercommands.hpp"
#include "utils.hpp"
@@ -1122,6 +1123,11 @@ void register_netfn_app_functions()
ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_ACPI, NULL,
ipmi_app_get_acpi_power_state, PRIVILEGE_ADMIN);
+// TODO: Below code and associated api's need to be removed later.
+// Its commented for now to avoid merge conflicts with upstream
+// changes and smooth upstream upgrades.
+#if 0
+>>>>>>> IPMI Channel commands implementation
// <Get Channel Access>
ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHANNEL_ACCESS, NULL,
ipmi_get_channel_access, PRIVILEGE_USER);
@@ -1129,6 +1135,7 @@ void register_netfn_app_functions()
// <Get Channel Info Command>
ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHAN_INFO, NULL,
ipmi_app_channel_info, PRIVILEGE_USER);
+#endif
// <Get System GUID Command>
ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_SYS_GUID, NULL,
@@ -1137,13 +1144,15 @@ 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);
+#if 0
// <Set Channel Access Command>
ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_CHAN_ACCESS, NULL,
ipmi_set_channel_access, PRIVILEGE_ADMIN);
-
+#endif
// <Get System Info Command>
ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_SYSTEM_INFO, NULL,
ipmi_app_get_system_info, PRIVILEGE_USER);
ipmi::registerUserIpmiFunctions();
+ ipmi::registerChannelFunctions();
return;
}
diff --git a/user_channel/channel_layer.cpp b/user_channel/channel_layer.cpp
new file mode 100644
index 0000000..32f4ded
--- /dev/null
+++ b/user_channel/channel_layer.cpp
@@ -0,0 +1,131 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include "channel_layer.hpp"
+
+#include "channel_mgmt.hpp"
+
+#include <phosphor-logging/log.hpp>
+
+namespace ipmi
+{
+
+bool doesDeviceExist(const uint8_t& chNum)
+{
+ // TODO: This is not the reliable way to find the device
+ // associated with ethernet interface as the channel number to
+ // eth association is not done. Need to revisit later
+ struct stat fileStat;
+ std::string devName("/sys/class/net/eth");
+ devName += std::to_string(chNum - 1);
+
+ if (stat(devName.data(), &fileStat) != 0)
+ {
+ phosphor::logging::log<phosphor::logging::level::DEBUG>(
+ "Ethernet device not found");
+ return false;
+ }
+
+ return true;
+}
+
+bool isValidPrivLimit(const uint8_t& privLimit)
+{
+ return ((privLimit >= PRIVILEGE_CALLBACK) && (privLimit <= PRIVILEGE_OEM));
+}
+
+bool isValidAccessMode(const uint8_t& accessMode)
+{
+ return (
+ (accessMode >= static_cast<uint8_t>(EChannelAccessMode::disabled)) &&
+ (accessMode <= static_cast<uint8_t>(EChannelAccessMode::shared)));
+}
+
+bool isValidChannel(const uint8_t& chNum)
+{
+ return getChannelConfigObject().isValidChannel(chNum);
+}
+
+bool isValidAuthType(const uint8_t& chNum, const EAuthType& authType)
+{
+ return getChannelConfigObject().isValidAuthType(chNum, authType);
+}
+
+EChannelSessSupported getChannelSessionSupport(const uint8_t& chNum)
+{
+ return getChannelConfigObject().getChannelSessionSupport(chNum);
+}
+
+int getChannelActiveSessions(const uint8_t& chNum)
+{
+ return getChannelConfigObject().getChannelActiveSessions(chNum);
+}
+
+ipmi_ret_t ipmiChannelInit()
+{
+ getChannelConfigObject();
+ return IPMI_CC_OK;
+}
+
+ipmi_ret_t getChannelInfo(const uint8_t& chNum, ChannelInfo& chInfo)
+{
+ return getChannelConfigObject().getChannelInfo(chNum, chInfo);
+}
+
+ipmi_ret_t getChannelAccessData(const uint8_t& chNum,
+ ChannelAccess& chAccessData)
+{
+ return getChannelConfigObject().getChannelAccessData(chNum, chAccessData);
+}
+
+ipmi_ret_t setChannelAccessData(const uint8_t& chNum,
+ const ChannelAccess& chAccessData,
+ const uint8_t& setFlag)
+{
+ return getChannelConfigObject().setChannelAccessData(chNum, chAccessData,
+ setFlag);
+}
+
+ipmi_ret_t getChannelAccessPersistData(const uint8_t& chNum,
+ ChannelAccess& chAccessData)
+{
+ return getChannelConfigObject().getChannelAccessPersistData(chNum,
+ chAccessData);
+}
+
+ipmi_ret_t setChannelAccessPersistData(const uint8_t& chNum,
+ const ChannelAccess& chAccessData,
+ const uint8_t& setFlag)
+{
+ return getChannelConfigObject().setChannelAccessPersistData(
+ chNum, chAccessData, setFlag);
+}
+
+ipmi_ret_t getChannelAuthTypeSupported(const uint8_t& chNum,
+ uint8_t& authTypeSupported)
+{
+ return getChannelConfigObject().getChannelAuthTypeSupported(
+ chNum, authTypeSupported);
+}
+
+ipmi_ret_t getChannelEnabledAuthType(const uint8_t& chNum, const uint8_t& priv,
+ EAuthType& authType)
+{
+ return getChannelConfigObject().getChannelEnabledAuthType(chNum, priv,
+ authType);
+}
+
+} // namespace ipmi
diff --git a/user_channel/channel_layer.hpp b/user_channel/channel_layer.hpp
new file mode 100644
index 0000000..4c931df
--- /dev/null
+++ b/user_channel/channel_layer.hpp
@@ -0,0 +1,275 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#pragma once
+#include <host-ipmid/ipmid-api.h>
+
+#include <string>
+
+namespace ipmi
+{
+
+static constexpr uint8_t maxIpmiChannels = 16;
+
+// IPMI return codes specific to channel
+enum ipmi_channel_return_codes
+{
+ IPMI_CC_ACTION_NOT_SUPPORTED_FOR_CHANNEL = 0x82,
+ IPMI_CC_ACCESS_MODE_NOT_SUPPORTED_FOR_CHANEL = 0x83
+};
+
+// IPMI Spec: Channel Protocol Type
+enum class EChannelProtocolType : uint8_t
+{
+ na = 0x00,
+ ipmbV10 = 0x01,
+ icmbV11 = 0x02,
+ reserved = 0x03,
+ ipmiSmbus = 0x04,
+ kcs = 0x05,
+ smic = 0x06,
+ bt10 = 0x07,
+ bt15 = 0x08,
+ tMode = 0x09,
+ oem = 0x1C,
+};
+
+// IPMI Spec: Channel Medium Type
+enum class EChannelMediumType : uint8_t
+{
+ reserved = 0x00,
+ ipmb = 0x01,
+ icmbV10 = 0x02,
+ icmbV09 = 0x03,
+ lan8032 = 0x04,
+ serial = 0x05,
+ otherLan = 0x06,
+ pciSmbus = 0x07,
+ smbusV11 = 0x08,
+ smbusV20 = 0x09,
+ usbV1x = 0x0A,
+ usbV2x = 0x0B,
+ systemInterface = 0x0C,
+ oem = 0x60,
+ unknown = 0x82,
+};
+
+// IPMI Spec: Channel Session Type
+enum class EChannelSessSupported : uint8_t
+{
+ none = 0,
+ single = 1,
+ multi = 2,
+ any = 3,
+};
+
+// IPMI Spec: Channel Access Mode
+enum class EChannelAccessMode : uint8_t
+{
+ disabled = 0,
+ preboot = 1,
+ alwaysAvail = 2,
+ shared = 3,
+};
+
+// IPMI Spec 2.0 : Authentication Types
+enum class EAuthType : uint8_t
+{
+ none = (1 << 0x0),
+ md2 = (1 << 0x1),
+ md5 = (1 << 0x2),
+ reserved = (1 << 0x3),
+ straightPasswd = (1 << 0x4),
+ oem = (1 << 0x5),
+};
+
+// IPMI Spec: Access mode for channel access set/get
+typedef enum
+{
+ doNotSet = 0x00,
+ nvData = 0x01,
+ activeData = 0x02,
+ reserved = 0x03,
+} EChannelActionType;
+
+enum AccessSetFlag
+{
+ setAccessMode = (1 << 0),
+ setUserAuthEnabled = (1 << 1),
+ setMsgAuthEnabled = (1 << 2),
+ setAlertingEnabled = (1 << 3),
+ setPrivLimit = (1 << 4),
+};
+
+// Struct to store channel access data
+struct ChannelAccess
+{
+ uint8_t accessMode;
+ bool userAuthDisabled;
+ bool perMsgAuthDisabled;
+ bool alertingDisabled;
+ uint8_t privLimit;
+};
+
+// Struct store channel info data
+struct ChannelInfo
+{
+ uint8_t mediumType;
+ uint8_t protocolType;
+ uint8_t sessionSupported;
+ bool isIpmi; // Is session IPMI
+ // This is used in Get LAN Configuration parameter.
+ // This holds the supported AuthTypes for a given channel.
+ uint8_t authTypeSupported;
+};
+
+/** @brief determines valid channel
+ *
+ * @param[in] chNum- channel number
+ *
+ * @return true if valid, false otherwise
+ */
+bool isValidChannel(const uint8_t& chNum);
+
+/** @brief determines whether channel device exist
+ *
+ * @param[in] chNum - channel number
+ *
+ * @return true if valid, false otherwise
+ */
+bool doesDeviceExist(const uint8_t& chNum);
+
+/** @brief determines whether privilege limit is valid
+ *
+ * @param[in] privLimit - Privilege limit
+ *
+ * @return true if valid, false otherwise
+ */
+bool isValidPrivLimit(const uint8_t& privLimit);
+
+/** @brief determines whether access mode is valid
+ *
+ * @param[in] accessMode - Access mode
+ *
+ * @return true if valid, false otherwise
+ */
+bool isValidAccessMode(const uint8_t& accessMode);
+
+/** @brief determines valid authentication type based on channel number
+ *
+ * @param[in] chNum - channel number
+ * @param[in] authType - authentication type
+ *
+ * @return true if valid, false otherwise
+ */
+bool isValidAuthType(const uint8_t& chNum, const EAuthType& authType);
+
+/** @brief determines supported session type of a channel
+ *
+ * @param[in] chNum - channel number
+ *
+ * @return EChannelSessSupported - supported session type
+ */
+EChannelSessSupported getChannelSessionSupport(const uint8_t& chNum);
+
+/** @brief determines number of active sessions on a channel
+ *
+ * @param[in] chNum - channel number
+ *
+ * @return numer of active sessions
+ */
+int getChannelActiveSessions(const uint8_t& chNum);
+
+/** @brief initializes channel management
+ *
+ * @return IPMI_CC_OK for success, others for failure.
+ */
+ipmi_ret_t ipmiChannelInit();
+
+/** @brief provides channel info details
+ *
+ * @param[in] chNum - channel number
+ * @param[out] chInfo - channel info details
+ *
+ * @return IPMI_CC_OK for success, others for failure.
+ */
+ipmi_ret_t getChannelInfo(const uint8_t& chNum, ChannelInfo& chInfo);
+
+/** @brief provides channel access data
+ *
+ * @param[in] chNum - channel number
+ * @param[out] chAccessData -channel access data
+ *
+ * @return IPMI_CC_OK for success, others for failure.
+ */
+ipmi_ret_t getChannelAccessData(const uint8_t& chNum,
+ ChannelAccess& chAccessData);
+
+/** @brief to set channel access data
+ *
+ * @param[in] chNum - channel number
+ * @param[in] chAccessData - channel access data
+ * @param[in] setFlag - flag to indicate updatable fields
+ *
+ * @return IPMI_CC_OK for success, others for failure.
+ */
+ipmi_ret_t setChannelAccessData(const uint8_t& chNum,
+ const ChannelAccess& chAccessData,
+ const uint8_t& setFlag);
+
+/** @brief to get channel access data persistent data
+ *
+ * @param[in] chNum - channel number
+ * @param[out] chAccessData - channel access data
+ *
+ * @return IPMI_CC_OK for success, others for failure.
+ */
+ipmi_ret_t getChannelAccessPersistData(const uint8_t& chNum,
+ ChannelAccess& chAccessData);
+
+/** @brief to set channel access data persistent data
+ *
+ * @param[in] chNum - channel number
+ * @param[in] chAccessData - channel access data
+ * @param[in] setFlag - flag to indicate updatable fields
+ *
+ * @return IPMI_CC_OK for success, others for failure.
+ */
+ipmi_ret_t setChannelAccessPersistData(const uint8_t& chNum,
+ const ChannelAccess& chAccessData,
+ const uint8_t& setFlag);
+
+/** @brief provides supported authentication type for the channel
+ *
+ * @param[in] chNum - channel number
+ * @param[out] authTypeSupported - supported authentication type
+ *
+ * @return IPMI_CC_OK for success, others for failure.
+ */
+ipmi_ret_t getChannelAuthTypeSupported(const uint8_t& chNum,
+ uint8_t& authTypeSupported);
+
+/** @brief provides enabled authentication type for the channel
+ *
+ * @param[in] chNum - channel number
+ * @param[in] priv - privilege
+ * @param[out] authType - enabled authentication type
+ *
+ * @return IPMI_CC_OK for success, others for failure.
+ */
+ipmi_ret_t getChannelEnabledAuthType(const uint8_t& chNum, const uint8_t& priv,
+ EAuthType& authType);
+
+} // namespace ipmi
diff --git a/user_channel/channel_mgmt.cpp b/user_channel/channel_mgmt.cpp
new file mode 100644
index 0000000..0db54b6
--- /dev/null
+++ b/user_channel/channel_mgmt.cpp
@@ -0,0 +1,1027 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include "channel_mgmt.hpp"
+
+#include "apphandler.hpp"
+
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <boost/interprocess/sync/scoped_lock.hpp>
+#include <cerrno>
+#include <experimental/filesystem>
+#include <fstream>
+#include <phosphor-logging/log.hpp>
+#include <unordered_map>
+
+namespace ipmi
+{
+
+using namespace phosphor::logging;
+
+static constexpr const char* channelAccessDefaultFilename =
+ "/usr/share/ipmi-providers/channel_access.json";
+static constexpr const char* channelConfigDefaultFilename =
+ "/usr/share/ipmi-providers/channel_config.json";
+static constexpr const char* channelNvDataFilename =
+ "/var/lib/ipmi/channel_access_nv.json";
+static constexpr const char* channelVolatileDataFilename =
+ "/run/ipmi/channel_access_volatile.json";
+
+// STRING DEFINES: Should sync with key's in JSON
+static constexpr const char* nameString = "name";
+static constexpr const char* isValidString = "is_valid";
+static constexpr const char* activeSessionsString = "active_sessions";
+static constexpr const char* channelInfoString = "channel_info";
+static constexpr const char* mediumTypeString = "medium_type";
+static constexpr const char* protocolTypeString = "protocol_type";
+static constexpr const char* sessionSupportedString = "session_supported";
+static constexpr const char* isIpmiString = "is_ipmi";
+static constexpr const char* authTypeSupportedString = "auth_type_supported";
+static constexpr const char* accessModeString = "access_mode";
+static constexpr const char* userAuthDisabledString = "user_auth_disabled";
+static constexpr const char* perMsgAuthDisabledString = "per_msg_auth_disabled";
+static constexpr const char* alertingDisabledString = "alerting_disabled";
+static constexpr const char* privLimitString = "priv_limit";
+static constexpr const char* authTypeEnabledString = "auth_type_enabled";
+
+// Default values
+static constexpr const char* defaultChannelName = "RESERVED";
+static constexpr const uint8_t defaultMediumType =
+ static_cast<uint8_t>(EChannelMediumType::reserved);
+static constexpr const uint8_t defaultProtocolType =
+ static_cast<uint8_t>(EChannelProtocolType::reserved);
+static constexpr const uint8_t defaultSessionSupported =
+ static_cast<uint8_t>(EChannelSessSupported::none);
+static constexpr const uint8_t defaultAuthType =
+ static_cast<uint8_t>(EAuthType::none);
+static constexpr const bool defaultIsIpmiState = false;
+
+// String mappings use in JSON config file
+static std::unordered_map<std::string, EChannelMediumType> mediumTypeMap = {
+ {"reserved", EChannelMediumType::reserved},
+ {"ipmb", EChannelMediumType::ipmb},
+ {"icmb-v1.0", EChannelMediumType::icmbV10},
+ {"icmb-v0.9", EChannelMediumType::icmbV09},
+ {"lan-802.3", EChannelMediumType::lan8032},
+ {"serial", EChannelMediumType::serial},
+ {"other-lan", EChannelMediumType::otherLan},
+ {"pci-smbus", EChannelMediumType::pciSmbus},
+ {"smbus-v1.0", EChannelMediumType::smbusV11},
+ {"smbus-v2.0", EChannelMediumType::smbusV20},
+ {"usb-1x", EChannelMediumType::usbV1x},
+ {"usb-2x", EChannelMediumType::usbV2x},
+ {"system-interface", EChannelMediumType::systemInterface},
+ {"oem", EChannelMediumType::oem},
+ {"unknown", EChannelMediumType::unknown}};
+
+static std::unordered_map<std::string, EChannelProtocolType> protocolTypeMap = {
+ {"na", EChannelProtocolType::na},
+ {"ipmb-1.0", EChannelProtocolType::ipmbV10},
+ {"icmb-2.0", EChannelProtocolType::icmbV11},
+ {"reserved", EChannelProtocolType::reserved},
+ {"ipmi-smbus", EChannelProtocolType::ipmiSmbus},
+ {"kcs", EChannelProtocolType::kcs},
+ {"smic", EChannelProtocolType::smic},
+ {"bt-10", EChannelProtocolType::bt10},
+ {"bt-15", EChannelProtocolType::bt15},
+ {"tmode", EChannelProtocolType::tMode},
+ {"oem", EChannelProtocolType::oem}};
+
+static std::array<std::string, 4> accessModeList = {
+ "disabled", "pre-boot", "always_available", "shared"};
+
+static std::array<std::string, 4> sessionSupportList = {
+ "session-less", "single-session", "multi-session", "session-based"};
+
+static std::array<std::string, PRIVILEGE_OEM + 1> privList = {
+ "priv-reserved", "priv-callback", "priv-user",
+ "priv-operator", "priv-admin", "priv-oem"};
+
+ChannelConfig& getChannelConfigObject()
+{
+ static ChannelConfig channelConfig;
+ return channelConfig;
+}
+
+ChannelConfig::ChannelConfig() : bus(ipmid_get_sd_bus_connection())
+{
+ std::ofstream mutexCleanUpFile;
+ mutexCleanUpFile.open(ipmiChMutexCleanupLockFile,
+ std::ofstream::out | std::ofstream::app);
+ if (!mutexCleanUpFile.good())
+ {
+ log<level::DEBUG>("Unable to open mutex cleanup file");
+ return;
+ }
+ mutexCleanUpFile.close();
+ mutexCleanupLock =
+ boost::interprocess::file_lock(ipmiChMutexCleanupLockFile);
+ if (mutexCleanupLock.try_lock())
+ {
+ boost::interprocess::named_recursive_mutex::remove(ipmiChannelMutex);
+ channelMutex =
+ std::make_unique<boost::interprocess::named_recursive_mutex>(
+ boost::interprocess::open_or_create, ipmiChannelMutex);
+ mutexCleanupLock.lock_sharable();
+ }
+ else
+ {
+ mutexCleanupLock.lock_sharable();
+ channelMutex =
+ std::make_unique<boost::interprocess::named_recursive_mutex>(
+ boost::interprocess::open_or_create, ipmiChannelMutex);
+ }
+
+ initChannelPersistData();
+}
+
+bool ChannelConfig::isValidChannel(const uint8_t& chNum)
+{
+ if (chNum > maxIpmiChannels)
+ {
+ log<level::DEBUG>("Invalid channel ID - Out of range");
+ return false;
+ }
+
+ if (channelData[chNum].isChValid == false)
+ {
+ log<level::DEBUG>("Channel is not valid");
+ return false;
+ }
+
+ return true;
+}
+
+EChannelSessSupported
+ ChannelConfig::getChannelSessionSupport(const uint8_t& chNum)
+{
+ EChannelSessSupported chSessSupport =
+ (EChannelSessSupported)channelData[chNum].chInfo.sessionSupported;
+ return chSessSupport;
+}
+
+bool ChannelConfig::isValidAuthType(const uint8_t& chNum,
+ const EAuthType& authType)
+{
+ if ((authType < EAuthType::md2) || (authType > EAuthType::oem))
+ {
+ log<level::DEBUG>("Invalid authentication type");
+ return false;
+ }
+
+ uint8_t authTypeSupported = channelData[chNum].chInfo.authTypeSupported;
+ if (!(authTypeSupported & (1 << static_cast<uint8_t>(authType))))
+ {
+ log<level::DEBUG>("Authentication type is not supported.");
+ return false;
+ }
+
+ return true;
+}
+
+int ChannelConfig::getChannelActiveSessions(const uint8_t& chNum)
+{
+ // TODO: TEMPORARY FIX
+ // Channels active session count is managed separatly
+ // by monitoring channel session which includes LAN and
+ // RAKP layer changes. This will be updated, once the
+ // authentication part is implemented.
+ return channelData[chNum].activeSessCount;
+}
+
+ipmi_ret_t ChannelConfig::getChannelInfo(const uint8_t& chNum,
+ ChannelInfo& chInfo)
+{
+ if (!isValidChannel(chNum))
+ {
+ log<level::DEBUG>("Invalid channel");
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ std::copy_n(reinterpret_cast<uint8_t*>(&channelData[chNum].chInfo),
+ sizeof(channelData[chNum].chInfo),
+ reinterpret_cast<uint8_t*>(&chInfo));
+
+ return IPMI_CC_OK;
+}
+
+ipmi_ret_t ChannelConfig::getChannelAccessData(const uint8_t& chNum,
+ ChannelAccess& chAccessData)
+{
+ if (!isValidChannel(chNum))
+ {
+ log<level::DEBUG>("Invalid channel");
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
+ {
+ log<level::DEBUG>("Session-less channel doesn't have access data.");
+ return IPMI_CC_ACTION_NOT_SUPPORTED_FOR_CHANNEL;
+ }
+
+ if (checkAndReloadVolatileData() != 0)
+ {
+ return IPMI_CC_UNSPECIFIED_ERROR;
+ }
+
+ std::copy_n(
+ reinterpret_cast<uint8_t*>(&channelData[chNum].chAccess.chVolatileData),
+ sizeof(channelData[chNum].chAccess.chVolatileData),
+ reinterpret_cast<uint8_t*>(&chAccessData));
+
+ return IPMI_CC_OK;
+}
+
+ipmi_ret_t
+ ChannelConfig::setChannelAccessData(const uint8_t& chNum,
+ const ChannelAccess& chAccessData,
+ const uint8_t& setFlag)
+{
+ if (!isValidChannel(chNum))
+ {
+ log<level::DEBUG>("Invalid channel");
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
+ {
+ log<level::DEBUG>("Session-less channel doesn't have access data.");
+ return IPMI_CC_ACTION_NOT_SUPPORTED_FOR_CHANNEL;
+ }
+
+ if ((setFlag & setAccessMode) &&
+ (!isValidAccessMode(chAccessData.accessMode)))
+ {
+ log<level::DEBUG>("Invalid access mode specified");
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
+ channelLock{*channelMutex};
+
+ if (checkAndReloadVolatileData() != 0)
+ {
+ return IPMI_CC_UNSPECIFIED_ERROR;
+ }
+
+ if (setFlag & setAccessMode)
+ {
+ channelData[chNum].chAccess.chVolatileData.accessMode =
+ chAccessData.accessMode;
+ }
+ if (setFlag & setUserAuthEnabled)
+ {
+ channelData[chNum].chAccess.chVolatileData.userAuthDisabled =
+ chAccessData.userAuthDisabled;
+ }
+ if (setFlag & setMsgAuthEnabled)
+ {
+ channelData[chNum].chAccess.chVolatileData.perMsgAuthDisabled =
+ chAccessData.perMsgAuthDisabled;
+ }
+ if (setFlag & setAlertingEnabled)
+ {
+ channelData[chNum].chAccess.chVolatileData.alertingDisabled =
+ chAccessData.alertingDisabled;
+ }
+ if (setFlag & setPrivLimit)
+ {
+ channelData[chNum].chAccess.chVolatileData.privLimit =
+ chAccessData.privLimit;
+ }
+
+ // Write Volatile data to file
+ if (writeChannelVolatileData() != 0)
+ {
+ log<level::DEBUG>("Failed to update the channel volatile data");
+ return IPMI_CC_UNSPECIFIED_ERROR;
+ }
+ return IPMI_CC_OK;
+}
+
+ipmi_ret_t
+ ChannelConfig::getChannelAccessPersistData(const uint8_t& chNum,
+ ChannelAccess& chAccessData)
+{
+ if (!isValidChannel(chNum))
+ {
+ log<level::DEBUG>("Invalid channel");
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
+ {
+ log<level::DEBUG>("Session-less channel doesn't have access data.");
+ return IPMI_CC_ACTION_NOT_SUPPORTED_FOR_CHANNEL;
+ }
+
+ if (checkAndReloadNVData() != 0)
+ {
+ return IPMI_CC_UNSPECIFIED_ERROR;
+ }
+
+ std::copy_n(reinterpret_cast<uint8_t*>(
+ &channelData[chNum].chAccess.chNonVolatileData),
+ sizeof(channelData[chNum].chAccess.chNonVolatileData),
+ reinterpret_cast<uint8_t*>(&chAccessData));
+
+ return IPMI_CC_OK;
+}
+
+ipmi_ret_t ChannelConfig::setChannelAccessPersistData(
+ const uint8_t& chNum, const ChannelAccess& chAccessData,
+ const uint8_t& setFlag)
+{
+ if (!isValidChannel(chNum))
+ {
+ log<level::DEBUG>("Invalid channel");
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
+ {
+ log<level::DEBUG>("Session-less channel doesn't have access data.");
+ return IPMI_CC_ACTION_NOT_SUPPORTED_FOR_CHANNEL;
+ }
+
+ if ((setFlag & setAccessMode) &&
+ (!isValidAccessMode(chAccessData.accessMode)))
+ {
+ log<level::DEBUG>("Invalid access mode specified");
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
+ channelLock{*channelMutex};
+
+ if (checkAndReloadNVData() != 0)
+ {
+ return IPMI_CC_UNSPECIFIED_ERROR;
+ }
+
+ if (setFlag & setAccessMode)
+ {
+ channelData[chNum].chAccess.chNonVolatileData.accessMode =
+ chAccessData.accessMode;
+ }
+ if (setFlag & setUserAuthEnabled)
+ {
+ channelData[chNum].chAccess.chNonVolatileData.userAuthDisabled =
+ chAccessData.userAuthDisabled;
+ }
+ if (setFlag & setMsgAuthEnabled)
+ {
+ channelData[chNum].chAccess.chNonVolatileData.perMsgAuthDisabled =
+ chAccessData.perMsgAuthDisabled;
+ }
+ if (setFlag & setAlertingEnabled)
+ {
+ channelData[chNum].chAccess.chNonVolatileData.alertingDisabled =
+ chAccessData.alertingDisabled;
+ }
+ if (setFlag & setPrivLimit)
+ {
+ channelData[chNum].chAccess.chNonVolatileData.privLimit =
+ chAccessData.privLimit;
+ }
+
+ // Write persistent data to file
+ if (writeChannelPersistData() != 0)
+ {
+ log<level::DEBUG>("Failed to update the presist data file");
+ return IPMI_CC_UNSPECIFIED_ERROR;
+ }
+ return IPMI_CC_OK;
+}
+
+ipmi_ret_t
+ ChannelConfig::getChannelAuthTypeSupported(const uint8_t& chNum,
+ uint8_t& authTypeSupported)
+{
+ if (!isValidChannel(chNum))
+ {
+ log<level::DEBUG>("Invalid channel");
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ authTypeSupported = channelData[chNum].chInfo.authTypeSupported;
+ return IPMI_CC_OK;
+}
+
+ipmi_ret_t ChannelConfig::getChannelEnabledAuthType(const uint8_t& chNum,
+ const uint8_t& priv,
+ EAuthType& authType)
+{
+ if (!isValidChannel(chNum))
+ {
+ log<level::DEBUG>("Invalid channel");
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
+ {
+ log<level::DEBUG>("Sessionless channel doesn't have access data.");
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ if (!isValidPrivLimit(priv))
+ {
+ log<level::DEBUG>("Invalid privilege specified.");
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ // TODO: Hardcoded for now. Need to implement.
+ authType = EAuthType::none;
+
+ return IPMI_CC_OK;
+}
+
+std::time_t ChannelConfig::getUpdatedFileTime(const std::string& fileName)
+{
+ struct stat fileStat;
+ if (stat(fileName.c_str(), &fileStat) != 0)
+ {
+ log<level::DEBUG>("Error in getting last updated time stamp");
+ return -EIO;
+ }
+ return fileStat.st_mtime;
+}
+
+EChannelAccessMode
+ ChannelConfig::convertToAccessModeIndex(const std::string& mode)
+{
+ auto iter = std::find(accessModeList.begin(), accessModeList.end(), mode);
+ if (iter == accessModeList.end())
+ {
+ log<level::ERR>("Invalid access mode.",
+ entry("MODE_STR=%s", mode.c_str()));
+ throw std::invalid_argument("Invalid access mode.");
+ }
+
+ return static_cast<EChannelAccessMode>(
+ std::distance(accessModeList.begin(), iter));
+}
+
+std::string ChannelConfig::convertToAccessModeString(const uint8_t& value)
+{
+ if (accessModeList.size() <= value)
+ {
+ log<level::ERR>("Invalid access mode.", entry("MODE_IDX=%d", value));
+ throw std::invalid_argument("Invalid access mode.");
+ }
+
+ return accessModeList.at(value);
+}
+
+CommandPrivilege
+ ChannelConfig::convertToPrivLimitIndex(const std::string& value)
+{
+ auto iter = std::find(privList.begin(), privList.end(), value);
+ if (iter == privList.end())
+ {
+ log<level::ERR>("Invalid privilege.",
+ entry("PRIV_STR=%s", value.c_str()));
+ throw std::invalid_argument("Invalid privilege.");
+ }
+
+ return static_cast<CommandPrivilege>(std::distance(privList.begin(), iter));
+}
+
+std::string ChannelConfig::convertToPrivLimitString(const uint8_t& value)
+{
+ if (privList.size() <= value)
+ {
+ log<level::ERR>("Invalid privilege.", entry("PRIV_IDX=%d", value));
+ throw std::invalid_argument("Invalid privilege.");
+ }
+
+ return privList.at(value);
+}
+
+EChannelSessSupported
+ ChannelConfig::convertToSessionSupportIndex(const std::string& value)
+{
+ auto iter =
+ std::find(sessionSupportList.begin(), sessionSupportList.end(), value);
+ if (iter == sessionSupportList.end())
+ {
+ log<level::ERR>("Invalid session supported.",
+ entry("SESS_STR=%s", value.c_str()));
+ throw std::invalid_argument("Invalid session supported.");
+ }
+
+ return static_cast<EChannelSessSupported>(
+ std::distance(sessionSupportList.begin(), iter));
+}
+
+EChannelMediumType
+ ChannelConfig::convertToMediumTypeIndex(const std::string& value)
+{
+ std::unordered_map<std::string, EChannelMediumType>::iterator it =
+ mediumTypeMap.find(value);
+ if (it == mediumTypeMap.end())
+ {
+ log<level::ERR>("Invalid medium type.",
+ entry("MEDIUM_STR=%s", value.c_str()));
+ throw std::invalid_argument("Invalid medium type.");
+ }
+
+ return static_cast<EChannelMediumType>(it->second);
+}
+
+EChannelProtocolType
+ ChannelConfig::convertToProtocolTypeIndex(const std::string& value)
+{
+ std::unordered_map<std::string, EChannelProtocolType>::iterator it =
+ protocolTypeMap.find(value);
+ if (it == protocolTypeMap.end())
+ {
+ log<level::ERR>("Invalid protocol type.",
+ entry("PROTO_STR=%s", value.c_str()));
+ throw std::invalid_argument("Invalid protocol type.");
+ }
+
+ return static_cast<EChannelProtocolType>(it->second);
+}
+
+Json ChannelConfig::readJsonFile(const std::string& configFile)
+{
+ std::ifstream jsonFile(configFile);
+ if (!jsonFile.good())
+ {
+ log<level::ERR>("JSON file not found");
+ return nullptr;
+ }
+
+ Json data = nullptr;
+ try
+ {
+ data = Json::parse(jsonFile, nullptr, false);
+ }
+ catch (Json::parse_error& e)
+ {
+ log<level::DEBUG>("Corrupted channel config.",
+ entry("MSG: %s", e.what()));
+ throw std::runtime_error("Corrupted channel config file");
+ }
+
+ return data;
+}
+
+int ChannelConfig::writeJsonFile(const std::string& configFile,
+ const Json& jsonData)
+{
+ std::ofstream jsonFile(configFile);
+ if (!jsonFile.good())
+ {
+ log<level::ERR>("JSON file not found");
+ return -EIO;
+ }
+
+ // Write JSON to file
+ jsonFile << jsonData;
+
+ jsonFile.flush();
+ return 0;
+}
+
+void ChannelConfig::setDefaultChannelConfig(const uint8_t& chNum,
+ const std::string& chName)
+{
+ channelData[chNum].chName = chName;
+ channelData[chNum].chID = chNum;
+ channelData[chNum].isChValid = false;
+ channelData[chNum].activeSessCount = 0;
+
+ channelData[chNum].chInfo.mediumType = defaultMediumType;
+ channelData[chNum].chInfo.protocolType = defaultProtocolType;
+ channelData[chNum].chInfo.sessionSupported = defaultSessionSupported;
+ channelData[chNum].chInfo.isIpmi = defaultIsIpmiState;
+ channelData[chNum].chInfo.authTypeSupported = defaultAuthType;
+}
+
+int ChannelConfig::loadChannelConfig()
+{
+ boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
+ channelLock{*channelMutex};
+
+ Json data = readJsonFile(channelConfigDefaultFilename);
+ if (data == nullptr)
+ {
+ log<level::DEBUG>("Error in opening IPMI Channel data file");
+ return -EIO;
+ }
+
+ try
+ {
+ // Fill in global structure
+ for (uint8_t chNum = 0; chNum < maxIpmiChannels; chNum++)
+ {
+ std::fill(reinterpret_cast<uint8_t*>(&channelData[chNum]),
+ reinterpret_cast<uint8_t*>(&channelData[chNum]) +
+ sizeof(ChannelData),
+ 0);
+ std::string chKey = std::to_string(chNum);
+ Json jsonChData = data[chKey].get<Json>();
+ if (jsonChData.is_null())
+ {
+ log<level::WARNING>(
+ "Channel not configured so loading default.",
+ entry("CHANNEL_NUM:%d", chNum));
+ // If user didn't want to configure specific channel (say
+ // reserved channel), then load that index with default values.
+ std::string chName(defaultChannelName);
+ setDefaultChannelConfig(chNum, chName);
+ }
+ else
+ {
+ std::string chName = jsonChData[nameString].get<std::string>();
+ channelData[chNum].chName = chName;
+ channelData[chNum].chID = chNum;
+ channelData[chNum].isChValid =
+ jsonChData[isValidString].get<bool>();
+ channelData[chNum].activeSessCount =
+ jsonChData.value(activeSessionsString, 0);
+ Json jsonChInfo = jsonChData[channelInfoString].get<Json>();
+ if (jsonChInfo.is_null())
+ {
+ log<level::ERR>("Invalid/corrupted channel config file");
+ return -EBADMSG;
+ }
+ else
+ {
+ std::string medTypeStr =
+ jsonChInfo[mediumTypeString].get<std::string>();
+ channelData[chNum].chInfo.mediumType = static_cast<uint8_t>(
+ convertToMediumTypeIndex(medTypeStr));
+ std::string protoTypeStr =
+ jsonChInfo[protocolTypeString].get<std::string>();
+ channelData[chNum].chInfo.protocolType =
+ static_cast<uint8_t>(
+ convertToProtocolTypeIndex(protoTypeStr));
+ std::string sessStr =
+ jsonChInfo[sessionSupportedString].get<std::string>();
+ channelData[chNum].chInfo.sessionSupported =
+ static_cast<uint8_t>(
+ convertToSessionSupportIndex(sessStr));
+ channelData[chNum].chInfo.isIpmi =
+ jsonChInfo[isIpmiString].get<bool>();
+ channelData[chNum].chInfo.authTypeSupported =
+ defaultAuthType;
+ }
+ }
+ }
+ }
+ catch (const Json::exception& e)
+ {
+ log<level::DEBUG>("Json Exception caught.", entry("MSG:%s", e.what()));
+ return -EBADMSG;
+ }
+ catch (const std::invalid_argument& e)
+ {
+ log<level::ERR>("Corrupted config.", entry("MSG:%s", e.what()));
+ return -EBADMSG;
+ }
+
+ return 0;
+}
+
+int ChannelConfig::readChannelVolatileData()
+{
+ boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
+ channelLock{*channelMutex};
+
+ Json data = readJsonFile(channelVolatileDataFilename);
+ if (data == nullptr)
+ {
+ log<level::DEBUG>("Error in opening IPMI Channel data file");
+ return -EIO;
+ }
+
+ try
+ {
+ // Fill in global structure
+ for (auto it = data.begin(); it != data.end(); ++it)
+ {
+ std::string chKey = it.key();
+ uint8_t chNum = std::stoi(chKey, nullptr, 10);
+ if ((chNum < 0) || (chNum > maxIpmiChannels))
+ {
+ log<level::DEBUG>(
+ "Invalid channel access entry in config file");
+ throw std::out_of_range("Out of range - channel number");
+ }
+ Json jsonChData = it.value();
+ if (!jsonChData.is_null())
+ {
+ std::string accModeStr =
+ jsonChData[accessModeString].get<std::string>();
+ channelData[chNum].chAccess.chVolatileData.accessMode =
+ static_cast<uint8_t>(convertToAccessModeIndex(accModeStr));
+ channelData[chNum].chAccess.chVolatileData.userAuthDisabled =
+ jsonChData[userAuthDisabledString].get<bool>();
+ channelData[chNum].chAccess.chVolatileData.perMsgAuthDisabled =
+ jsonChData[perMsgAuthDisabledString].get<bool>();
+ channelData[chNum].chAccess.chVolatileData.alertingDisabled =
+ jsonChData[alertingDisabledString].get<bool>();
+ std::string privStr =
+ jsonChData[privLimitString].get<std::string>();
+ channelData[chNum].chAccess.chVolatileData.privLimit =
+ static_cast<uint8_t>(convertToPrivLimitIndex(privStr));
+ }
+ else
+ {
+ log<level::ERR>(
+ "Invalid/corrupted volatile channel access file",
+ entry("FILE: %s", channelVolatileDataFilename));
+ throw std::runtime_error(
+ "Corrupted volatile channel access file");
+ }
+ }
+ }
+ catch (const Json::exception& e)
+ {
+ log<level::DEBUG>("Json Exception caught.", entry("MSG:%s", e.what()));
+ throw std::runtime_error("Corrupted volatile channel access file");
+ }
+ catch (const std::invalid_argument& e)
+ {
+ log<level::ERR>("Corrupted config.", entry("MSG:%s", e.what()));
+ throw std::runtime_error("Corrupted volatile channel access file");
+ }
+
+ // Update the timestamp
+ voltFileLastUpdatedTime = getUpdatedFileTime(channelVolatileDataFilename);
+ return 0;
+}
+
+int ChannelConfig::readChannelPersistData()
+{
+ boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
+ channelLock{*channelMutex};
+
+ Json data = readJsonFile(channelNvDataFilename);
+ if (data == nullptr)
+ {
+ log<level::DEBUG>("Error in opening IPMI Channel data file");
+ return -EIO;
+ }
+
+ try
+ {
+ // Fill in global structure
+ for (auto it = data.begin(); it != data.end(); ++it)
+ {
+ std::string chKey = it.key();
+ uint8_t chNum = std::stoi(chKey, nullptr, 10);
+ if ((chNum < 0) || (chNum > maxIpmiChannels))
+ {
+ log<level::DEBUG>(
+ "Invalid channel access entry in config file");
+ throw std::out_of_range("Out of range - channel number");
+ }
+ Json jsonChData = it.value();
+ if (!jsonChData.is_null())
+ {
+ std::string accModeStr =
+ jsonChData[accessModeString].get<std::string>();
+ channelData[chNum].chAccess.chNonVolatileData.accessMode =
+ static_cast<uint8_t>(convertToAccessModeIndex(accModeStr));
+ channelData[chNum].chAccess.chNonVolatileData.userAuthDisabled =
+ jsonChData[userAuthDisabledString].get<bool>();
+ channelData[chNum]
+ .chAccess.chNonVolatileData.perMsgAuthDisabled =
+ jsonChData[perMsgAuthDisabledString].get<bool>();
+ channelData[chNum].chAccess.chNonVolatileData.alertingDisabled =
+ jsonChData[alertingDisabledString].get<bool>();
+ std::string privStr =
+ jsonChData[privLimitString].get<std::string>();
+ channelData[chNum].chAccess.chNonVolatileData.privLimit =
+ static_cast<uint8_t>(convertToPrivLimitIndex(privStr));
+ }
+ else
+ {
+ log<level::ERR>("Invalid/corrupted nv channel access file",
+ entry("FILE:%s", channelNvDataFilename));
+ throw std::runtime_error("Corrupted nv channel access file");
+ }
+ }
+ }
+ catch (const Json::exception& e)
+ {
+ log<level::DEBUG>("Json Exception caught.", entry("MSG:%s", e.what()));
+ throw std::runtime_error("Corrupted nv channel access file");
+ }
+ catch (const std::invalid_argument& e)
+ {
+ log<level::ERR>("Corrupted config.", entry("MSG: %s", e.what()));
+ throw std::runtime_error("Corrupted nv channel access file");
+ }
+
+ // Update the timestamp
+ nvFileLastUpdatedTime = getUpdatedFileTime(channelNvDataFilename);
+ return 0;
+}
+
+int ChannelConfig::writeChannelVolatileData()
+{
+ boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
+ channelLock{*channelMutex};
+ Json outData;
+
+ try
+ {
+ for (uint8_t chNum = 0; chNum < maxIpmiChannels; chNum++)
+ {
+ if (getChannelSessionSupport(chNum) != EChannelSessSupported::none)
+ {
+ Json jsonObj;
+ std::string chKey = std::to_string(chNum);
+ std::string accModeStr = convertToAccessModeString(
+ channelData[chNum].chAccess.chVolatileData.accessMode);
+ jsonObj[accessModeString] = accModeStr;
+ jsonObj[userAuthDisabledString] =
+ channelData[chNum].chAccess.chVolatileData.userAuthDisabled;
+ jsonObj[perMsgAuthDisabledString] =
+ channelData[chNum]
+ .chAccess.chVolatileData.perMsgAuthDisabled;
+ jsonObj[alertingDisabledString] =
+ channelData[chNum].chAccess.chVolatileData.alertingDisabled;
+ std::string privStr = convertToPrivLimitString(
+ channelData[chNum].chAccess.chVolatileData.privLimit);
+ jsonObj[privLimitString] = privStr;
+
+ outData[chKey] = jsonObj;
+ }
+ }
+ }
+ catch (const std::invalid_argument& e)
+ {
+ log<level::ERR>("Corrupted config.", entry("MSG: %s", e.what()));
+ return -EINVAL;
+ }
+
+ if (writeJsonFile(channelVolatileDataFilename, outData) != 0)
+ {
+ log<level::DEBUG>("Error in write JSON data to file");
+ return -EIO;
+ }
+
+ // Update the timestamp
+ voltFileLastUpdatedTime = getUpdatedFileTime(channelVolatileDataFilename);
+ return 0;
+}
+
+int ChannelConfig::writeChannelPersistData()
+{
+ boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
+ channelLock{*channelMutex};
+ Json outData;
+
+ try
+ {
+ for (uint8_t chNum = 0; chNum < maxIpmiChannels; chNum++)
+ {
+ if (getChannelSessionSupport(chNum) != EChannelSessSupported::none)
+ {
+ Json jsonObj;
+ std::string chKey = std::to_string(chNum);
+ std::string accModeStr = convertToAccessModeString(
+ channelData[chNum].chAccess.chNonVolatileData.accessMode);
+ jsonObj[accessModeString] = accModeStr;
+ jsonObj[userAuthDisabledString] =
+ channelData[chNum]
+ .chAccess.chNonVolatileData.userAuthDisabled;
+ jsonObj[perMsgAuthDisabledString] =
+ channelData[chNum]
+ .chAccess.chNonVolatileData.perMsgAuthDisabled;
+ jsonObj[alertingDisabledString] =
+ channelData[chNum]
+ .chAccess.chNonVolatileData.alertingDisabled;
+ std::string privStr = convertToPrivLimitString(
+ channelData[chNum].chAccess.chNonVolatileData.privLimit);
+ jsonObj[privLimitString] = privStr;
+
+ outData[chKey] = jsonObj;
+ }
+ }
+ }
+ catch (const std::invalid_argument& e)
+ {
+ log<level::ERR>("Corrupted config.", entry("MSG: %s", e.what()));
+ return -EINVAL;
+ }
+
+ if (writeJsonFile(channelNvDataFilename, outData) != 0)
+ {
+ log<level::DEBUG>("Error in write JSON data to file");
+ return -EIO;
+ }
+
+ // Update the timestamp
+ nvFileLastUpdatedTime = getUpdatedFileTime(channelNvDataFilename);
+ return 0;
+}
+
+int ChannelConfig::checkAndReloadNVData()
+{
+ std::time_t updateTime = getUpdatedFileTime(channelNvDataFilename);
+ int ret = 0;
+ if (updateTime != nvFileLastUpdatedTime || updateTime == -EIO)
+ {
+ try
+ {
+ ret = readChannelPersistData();
+ }
+ catch (const std::exception& e)
+ {
+ log<level::ERR>("Exception caught in readChannelPersistData.",
+ entry("MSG=%s", e.what()));
+ ret = -EIO;
+ }
+ }
+ return ret;
+}
+
+int ChannelConfig::checkAndReloadVolatileData()
+{
+ std::time_t updateTime = getUpdatedFileTime(channelVolatileDataFilename);
+ int ret = 0;
+ if (updateTime != voltFileLastUpdatedTime || updateTime == -EIO)
+ {
+ try
+ {
+ ret = readChannelVolatileData();
+ }
+ catch (const std::exception& e)
+ {
+ log<level::ERR>("Exception caught in readChannelVolatileData.",
+ entry("MSG=%s", e.what()));
+ ret = -EIO;
+ }
+ }
+ return ret;
+}
+
+void ChannelConfig::initChannelPersistData()
+{
+ /* Always read the channel config */
+ if (loadChannelConfig() != 0)
+ {
+ log<level::ERR>("Failed to read channel config file");
+ throw std::ios_base::failure("Failed to load channel configuration");
+ }
+
+ /* Populate the channel persist data */
+ if (readChannelPersistData() != 0)
+ {
+ // Copy default NV data to RW location
+ std::experimental::filesystem::copy_file(channelAccessDefaultFilename,
+ channelNvDataFilename);
+
+ // Load the channel access NV data
+ if (readChannelPersistData() != 0)
+ {
+ log<level::ERR>("Failed to read channel access NV data");
+ throw std::ios_base::failure(
+ "Failed to read channel access NV configuration");
+ }
+ }
+
+ // First check the volatile data file
+ // If not present, load the default values
+ if (readChannelVolatileData() != 0)
+ {
+ // Copy default volatile data to temporary location
+ // NV file(channelNvDataFilename) must have created by now.
+ std::experimental::filesystem::copy_file(channelNvDataFilename,
+ channelVolatileDataFilename);
+
+ // Load the channel access volatile data
+ if (readChannelVolatileData() != 0)
+ {
+ log<level::ERR>("Failed to read channel access volatile data");
+ throw std::ios_base::failure(
+ "Failed to read channel access volatile configuration");
+ }
+ }
+ return;
+}
+
+} // namespace ipmi
diff --git a/user_channel/channel_mgmt.hpp b/user_channel/channel_mgmt.hpp
new file mode 100644
index 0000000..053fa39
--- /dev/null
+++ b/user_channel/channel_mgmt.hpp
@@ -0,0 +1,334 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#pragma once
+#include "channel_layer.hpp"
+
+#include <boost/interprocess/sync/file_lock.hpp>
+#include <boost/interprocess/sync/named_recursive_mutex.hpp>
+#include <cstdint>
+#include <ctime>
+#include <nlohmann/json.hpp>
+#include <sdbusplus/bus.hpp>
+
+namespace ipmi
+{
+
+using Json = nlohmann::json;
+
+static constexpr const char* ipmiChannelMutex = "ipmi_channel_mutex";
+static constexpr const char* ipmiChMutexCleanupLockFile =
+ "/var/lib/ipmi/ipmi_channel_mutex_cleanup";
+
+struct ChannelAccessData
+{
+ ChannelAccess chNonVolatileData;
+ ChannelAccess chVolatileData;
+};
+
+struct ChannelData
+{
+ std::string chName;
+ uint8_t chID;
+ bool isChValid;
+ uint8_t activeSessCount;
+ ChannelInfo chInfo;
+ ChannelAccessData chAccess;
+};
+
+class ChannelConfig;
+
+ChannelConfig& getChannelConfigObject();
+
+class ChannelConfig
+{
+ public:
+ ChannelConfig(const ChannelConfig&) = delete;
+ ChannelConfig& operator=(const ChannelConfig&) = delete;
+ ChannelConfig(ChannelConfig&&) = delete;
+ ChannelConfig& operator=(ChannelConfig&&) = delete;
+
+ ~ChannelConfig() = default;
+ ChannelConfig();
+
+ /** @brief determines valid channel
+ *
+ * @param[in] chNum - channel number
+ *
+ * @return true if valid, false otherwise
+ */
+ bool isValidChannel(const uint8_t& chNum);
+
+ /** @brief determines valid authentication type
+ *
+ * @param[in] chNum - channel number
+ * @param[in] authType - authentication type
+ *
+ * @return true if valid, false otherwise
+ */
+ bool isValidAuthType(const uint8_t& chNum, const EAuthType& authType);
+
+ /** @brief determines supported session type of a channel
+ *
+ * @param[in] chNum - channel number
+ *
+ * @return EChannelSessSupported - supported session type
+ */
+ EChannelSessSupported getChannelSessionSupport(const uint8_t& chNum);
+
+ /** @brief determines number of active sessions on a channel
+ *
+ * @param[in] chNum - channel number
+ *
+ * @return numer of active sessions
+ */
+ int getChannelActiveSessions(const uint8_t& chNum);
+
+ /** @brief provides channel info details
+ *
+ * @param[in] chNum - channel number
+ * @param[out] chInfo - channel info details
+ *
+ * @return IPMI_CC_OK for success, others for failure.
+ */
+ ipmi_ret_t getChannelInfo(const uint8_t& chNum, ChannelInfo& chInfo);
+
+ /** @brief provides channel access data
+ *
+ * @param[in] chNum - channel number
+ * @param[out] chAccessData - channel access data
+ *
+ * @return IPMI_CC_OK for success, others for failure.
+ */
+ ipmi_ret_t getChannelAccessData(const uint8_t& chNum,
+ ChannelAccess& chAccessData);
+
+ /** @brief to set channel access data
+ *
+ * @param[in] chNum - channel number
+ * @param[in] chAccessData - channel access data
+ * @param[in] setFlag - flag to indicate updatable fields
+ *
+ * @return IPMI_CC_OK for success, others for failure.
+ */
+ ipmi_ret_t setChannelAccessData(const uint8_t& chNum,
+ const ChannelAccess& chAccessData,
+ const uint8_t& setFlag);
+
+ /** @brief to get channel access data persistent data
+ *
+ * @param[in] chNum - channel number
+ * @param[out] chAccessData - channel access data
+ *
+ * @return IPMI_CC_OK for success, others for failure.
+ */
+ ipmi_ret_t getChannelAccessPersistData(const uint8_t& chNum,
+ ChannelAccess& chAccessData);
+
+ /** @brief to set channel access data persistent data
+ *
+ * @param[in] chNum - channel number
+ * @param[in] chAccessData - channel access data
+ * @param[in] setFlag - flag to indicate updatable fields
+ *
+ * @return IPMI_CC_OK for success, others for failure.
+ */
+ ipmi_ret_t setChannelAccessPersistData(const uint8_t& chNum,
+ const ChannelAccess& chAccessData,
+ const uint8_t& setFlag);
+
+ /** @brief provides supported authentication type for the channel
+ *
+ * @param[in] chNum - channel number
+ * @param[out] authTypeSupported - supported authentication type
+ *
+ * @return IPMI_CC_OK for success, others for failure.
+ */
+ ipmi_ret_t getChannelAuthTypeSupported(const uint8_t& chNum,
+ uint8_t& authTypeSupported);
+
+ /** @brief provides enabled authentication type for the channel
+ *
+ * @param[in] chNum - channel number
+ * @param[in] priv - privilege
+ * @param[out] authType - enabled authentication type
+ *
+ * @return IPMI_CC_OK for success, others for failure.
+ */
+ ipmi_ret_t getChannelEnabledAuthType(const uint8_t& chNum,
+ const uint8_t& priv,
+ EAuthType& authType);
+
+ std::unique_ptr<boost::interprocess::named_recursive_mutex> channelMutex{
+ nullptr};
+
+ private:
+ ChannelData channelData[maxIpmiChannels];
+ std::time_t nvFileLastUpdatedTime;
+ std::time_t voltFileLastUpdatedTime;
+ std::time_t getUpdatedFileTime(const std::string& fileName);
+ boost::interprocess::file_lock mutexCleanupLock;
+ sdbusplus::bus::bus bus;
+
+ /** @brief function to initialize persistent channel configuration
+ *
+ */
+ void initChannelPersistData();
+
+ /** @brief function to set default channel configuration based on channel
+ * number
+ *
+ * @param[in] chNum - channel number
+ * @param[in] chName - channel name
+ */
+ void setDefaultChannelConfig(const uint8_t& chNum,
+ const std::string& chName);
+
+ /** @brief function to load all channel configuration
+ *
+ * @return 0 for success, -errno for failure.
+ */
+ int loadChannelConfig();
+
+ /** @brief function to read persistent channel data
+ *
+ * @return 0 for success, -errno for failure.
+ */
+ int readChannelPersistData();
+
+ /** @brief function to write persistent channel configuration to config file
+ *
+ * @return 0 for success, -errno for failure.
+ */
+ int writeChannelPersistData();
+
+ /** @brief function to read volatile channel data
+ *
+ * @return 0 for success, -errno for failure.
+ */
+ int readChannelVolatileData();
+
+ /** @brief function to write volatile channel configuration to config file
+ *
+ * @return 0 for success, -errno for failure.
+ */
+ int writeChannelVolatileData();
+
+ /** @brief function to check and reload persistent channel data
+ *
+ * @return 0 for success, -errno for failure.
+ */
+ int checkAndReloadNVData();
+
+ /** @brief function to check and reload volatile channel data
+ *
+ * @return 0 for success, -errno for failure.
+ */
+ int checkAndReloadVolatileData();
+
+ /** @brief function to read json config file
+ *
+ * @param[in] configFile - configuration file name
+ *
+ * @return Json object
+ */
+ Json readJsonFile(const std::string& configFile);
+
+ /** @brief function to write json config file
+ *
+ * @param[in] configFile - configuration file name
+ * @param[in] jsonData - json object
+ *
+ * @return 0 for success, -errno for failure.
+ */
+ int writeJsonFile(const std::string& configFile, const Json& jsonData);
+
+ /** @brief function to convert system access mode to Channel access mode
+ * type
+ *
+ * @param[in] mode - access mode in string
+ *
+ * @return Channel access mode.
+ */
+ EChannelAccessMode convertToAccessModeIndex(const std::string& mode);
+
+ /** @brief function to convert access mode value to string
+ *
+ * @param[in] value - acess mode value
+ *
+ * @return access mode in string
+ */
+ std::string convertToAccessModeString(const uint8_t& value);
+
+ /** @brief conver to channel privilege from system privilege
+ *
+ * @param[in] value - privilege value
+ *
+ * @return Channel privilege
+ */
+ CommandPrivilege convertToPrivLimitIndex(const std::string& value);
+
+ /** @brief function to convert privilege value to string
+ *
+ * @param[in] value - privilege value
+ *
+ * @return privilege in string
+ */
+ std::string convertToPrivLimitString(const uint8_t& value);
+
+ /** @brief function to convert session support string to value type
+ *
+ * @param[in] value - session support type in string
+ *
+ * @return support session type
+ */
+ EChannelSessSupported
+ convertToSessionSupportIndex(const std::string& value);
+
+ /** @brief function to convert medium type string to value type
+ *
+ * @param[in] value - medium type in string
+ *
+ * @return channel medium type
+ */
+ EChannelMediumType convertToMediumTypeIndex(const std::string& value);
+
+ /** @brief function to convert protocol type string to value type
+ *
+ * @param[in] value - protocol type in string
+ *
+ * @return channel protocol type
+ */
+ EChannelProtocolType convertToProtocolTypeIndex(const std::string& value);
+
+ /** @brief function to convert channel number to channel index
+ *
+ * @param[in] chNum - channel number
+ *
+ * @return channel index
+ */
+ uint8_t convertToChannelIndexNumber(const uint8_t& chNum);
+
+ /** @brief function to convert channel name to network interface name
+ *
+ * @param[in] value - channel interface name - ipmi centric
+ *
+ * @return network channel interface name
+ */
+ std::string convertToNetInterface(const std::string& value);
+};
+
+} // namespace ipmi
diff --git a/user_channel/channelcommands.cpp b/user_channel/channelcommands.cpp
new file mode 100644
index 0000000..c5ef8b7
--- /dev/null
+++ b/user_channel/channelcommands.cpp
@@ -0,0 +1,391 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include "channelcommands.hpp"
+
+#include "apphandler.hpp"
+#include "channel_layer.hpp"
+
+#include <phosphor-logging/log.hpp>
+#include <regex>
+
+using namespace phosphor::logging;
+
+namespace ipmi
+{
+
+struct setChannelAccessReq
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+ uint8_t chNum : 4;
+ uint8_t reserved_1 : 4;
+ uint8_t accessMode : 3;
+ uint8_t usrAuthDisabled : 1;
+ uint8_t msgAuthDisabled : 1;
+ uint8_t alertDisabled : 1;
+ uint8_t accessSetMode : 2;
+ uint8_t privLimit : 4;
+ uint8_t reserved_2 : 2;
+ uint8_t privSetMode : 2;
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+ uint8_t reserved_1 : 4;
+ uint8_t chNum : 4;
+ uint8_t accessSetMode : 2;
+ uint8_t alertDisabled : 1;
+ uint8_t msgAuthDisabled : 1;
+ uint8_t usrAuthDisabled : 1;
+ uint8_t accessMode : 3;
+ uint8_t privSetMode : 2;
+ uint8_t reserved_2 : 2;
+ uint8_t privLimit : 4;
+#endif
+
+} __attribute__((packed));
+
+struct getChannelAccessReq
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+ uint8_t chNum : 4;
+ uint8_t reserved_1 : 4;
+ uint8_t reserved_2 : 6;
+ uint8_t accessSetMode : 2;
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+ uint8_t reserved_1 : 4;
+ uint8_t chNum : 4;
+ uint8_t accessSetMode : 2;
+ uint8_t reserved_2 : 6;
+#endif
+} __attribute__((packed));
+
+struct getChannelAccessResp
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+ uint8_t accessMode : 3;
+ uint8_t usrAuthDisabled : 1;
+ uint8_t msgAuthDisabled : 1;
+ uint8_t alertDisabled : 1;
+ uint8_t reserved_1 : 2;
+ uint8_t privLimit : 4;
+ uint8_t reserved_2 : 4;
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+ uint8_t reserved_1 : 2;
+ uint8_t alertDisabled : 1;
+ uint8_t msgAuthDisabled : 1;
+ uint8_t usrAuthDisabled : 1;
+ uint8_t accessMode : 3;
+ uint8_t reserved_2 : 4;
+ uint8_t privLimit : 4;
+#endif
+} __attribute__((packed));
+
+struct getChannelInfoReq
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+ uint8_t chNum : 4;
+ uint8_t reserved_1 : 4;
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+ uint8_t reserved_1 : 4;
+ uint8_t chNum : 4;
+#endif
+} __attribute__((packed));
+
+struct getChannelInfoResp
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+ uint8_t chNum : 4;
+ uint8_t reserved_1 : 4;
+ uint8_t mediumType : 7;
+ uint8_t reserved_2 : 1;
+ uint8_t msgProtType : 5;
+ uint8_t reserved_3 : 3;
+ uint8_t actSessCount : 6;
+ uint8_t sessType : 2;
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+ uint8_t reserved_1 : 4;
+ uint8_t chNum : 4;
+ uint8_t reserved_2 : 1;
+ uint8_t mediumType : 7;
+ uint8_t reserved_3 : 3;
+ uint8_t msgProtType : 5;
+ uint8_t sessType : 2;
+ uint8_t actSessCount : 6;
+#endif
+ uint8_t vendorId[3];
+ uint8_t auxChInfo[2];
+} __attribute__((packed));
+
+ipmi_ret_t ipmiSetChannelAccess(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)
+{
+ const setChannelAccessReq* req = static_cast<setChannelAccessReq*>(request);
+ size_t reqLength = *data_len;
+
+ *data_len = 0;
+
+ if (reqLength != sizeof(*req))
+ {
+ log<level::DEBUG>("Set channel access - Invalid Length");
+ return IPMI_CC_REQ_DATA_LEN_INVALID;
+ }
+
+ // TODO: Self channel number (0xE) has to be determined.
+ uint8_t chNum = req->chNum;
+ if (!isValidChannel(chNum))
+ {
+ log<level::DEBUG>("Set channel access - Parameter out of range");
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ if (EChannelSessSupported::none == getChannelSessionSupport(chNum))
+ {
+ log<level::DEBUG>("Set channel access - No support on channel");
+ return IPMI_CC_ACTION_NOT_SUPPORTED_FOR_CHANNEL;
+ }
+
+ ChannelAccess chActData;
+ ChannelAccess chNVData;
+ uint8_t setActFlag = 0;
+ uint8_t setNVFlag = 0;
+ ipmi_ret_t compCode = IPMI_CC_OK;
+
+ switch (req->accessSetMode)
+ {
+ case doNotSet:
+ // Do nothing
+ break;
+ case nvData:
+ chNVData.accessMode = req->accessMode;
+ chNVData.userAuthDisabled = req->usrAuthDisabled;
+ chNVData.perMsgAuthDisabled = req->msgAuthDisabled;
+ chNVData.alertingDisabled = req->alertDisabled;
+ setNVFlag |= (setAccessMode | setUserAuthEnabled |
+ setMsgAuthEnabled | setAlertingEnabled);
+ break;
+ case activeData:
+ chActData.accessMode = req->accessMode;
+ chActData.userAuthDisabled = req->usrAuthDisabled;
+ chActData.perMsgAuthDisabled = req->msgAuthDisabled;
+ chActData.alertingDisabled = req->alertDisabled;
+ setActFlag |= (setAccessMode | setUserAuthEnabled |
+ setMsgAuthEnabled | setAlertingEnabled);
+ break;
+ case reserved:
+ default:
+ log<level::DEBUG>("Set channel access - Invalid access set mode");
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ switch (req->privSetMode)
+ {
+ case doNotSet:
+ // Do nothing
+ break;
+ case nvData:
+ chNVData.privLimit = req->privLimit;
+ setNVFlag |= setPrivLimit;
+ break;
+ case activeData:
+ chActData.privLimit = req->privLimit;
+ setActFlag |= setPrivLimit;
+ break;
+ case reserved:
+ default:
+ log<level::DEBUG>("Set channel access - Invalid access priv mode");
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ if (setNVFlag != 0)
+ {
+ compCode = setChannelAccessPersistData(chNum, chNVData, setNVFlag);
+ if (compCode != IPMI_CC_OK)
+ {
+ log<level::DEBUG>("Set channel access - Failed to set access data");
+ return compCode;
+ }
+ }
+
+ if (setActFlag != 0)
+ {
+ compCode = setChannelAccessData(chNum, chActData, setActFlag);
+ if (compCode != IPMI_CC_OK)
+ {
+ log<level::DEBUG>("Set channel access - Failed to set access data");
+ return compCode;
+ }
+ }
+
+ return IPMI_CC_OK;
+}
+
+ipmi_ret_t ipmiGetChannelAccess(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)
+{
+ const getChannelAccessReq* req = static_cast<getChannelAccessReq*>(request);
+ size_t reqLength = *data_len;
+
+ *data_len = 0;
+
+ if (reqLength != sizeof(*req))
+ {
+ log<level::DEBUG>("Get channel access - Invalid Length");
+ return IPMI_CC_REQ_DATA_LEN_INVALID;
+ }
+
+ // TODO: Self channel number (0xE) has to be determined.
+ uint8_t chNum = req->chNum;
+ if (!isValidChannel(chNum))
+ {
+ log<level::DEBUG>("Get channel access - Parameter out of range");
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ if ((req->accessSetMode == doNotSet) || (req->accessSetMode == reserved))
+ {
+ log<level::DEBUG>("Get channel access - Invalid Access mode");
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ if (EChannelSessSupported::none == getChannelSessionSupport(chNum))
+ {
+ log<level::DEBUG>("Get channel access - No support on channel");
+ return IPMI_CC_ACTION_NOT_SUPPORTED_FOR_CHANNEL;
+ }
+
+ getChannelAccessResp* resp = static_cast<getChannelAccessResp*>(response);
+
+ std::fill(reinterpret_cast<uint8_t*>(resp),
+ reinterpret_cast<uint8_t*>(resp) + sizeof(*resp), 0);
+
+ ChannelAccess chAccess;
+ ipmi_ret_t compCode = IPMI_CC_OK;
+
+ if (req->accessSetMode == nvData)
+ {
+ compCode = getChannelAccessPersistData(chNum, chAccess);
+ }
+ else if (req->accessSetMode == activeData)
+ {
+ compCode = getChannelAccessData(chNum, chAccess);
+ }
+
+ if (compCode != IPMI_CC_OK)
+ {
+ return compCode;
+ }
+
+ resp->accessMode = chAccess.accessMode;
+ resp->usrAuthDisabled = chAccess.userAuthDisabled;
+ resp->msgAuthDisabled = chAccess.perMsgAuthDisabled;
+ resp->alertDisabled = chAccess.alertingDisabled;
+ resp->privLimit = chAccess.privLimit;
+
+ *data_len = sizeof(*resp);
+ return IPMI_CC_OK;
+}
+
+ipmi_ret_t ipmiGetChannelInfo(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)
+{
+ const getChannelInfoReq* req = static_cast<getChannelInfoReq*>(request);
+ size_t reqLength = *data_len;
+
+ *data_len = 0;
+
+ if (reqLength != sizeof(*req))
+ {
+ log<level::DEBUG>("Get channel info - Invalid Length");
+ return IPMI_CC_REQ_DATA_LEN_INVALID;
+ }
+
+ // TODO: Self channel number (0xE) has to be determined.
+ uint8_t chNum = req->chNum;
+ if (!isValidChannel(chNum))
+ {
+ log<level::DEBUG>("Get channel info - Parameter out of range");
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ // Check the existance of device for session-less channels.
+ if ((EChannelSessSupported::none != getChannelSessionSupport(chNum)) &&
+ (!(doesDeviceExist(chNum))))
+ {
+ log<level::DEBUG>("Get channel info - Device not exist");
+ return IPMI_CC_PARM_OUT_OF_RANGE;
+ }
+
+ getChannelInfoResp* resp = static_cast<getChannelInfoResp*>(response);
+
+ std::fill(reinterpret_cast<uint8_t*>(resp),
+ reinterpret_cast<uint8_t*>(resp) + sizeof(*resp), 0);
+
+ ChannelInfo chInfo;
+ ipmi_ret_t compCode = getChannelInfo(chNum, chInfo);
+ if (compCode != IPMI_CC_OK)
+ {
+ return compCode;
+ }
+
+ resp->chNum = chNum;
+ resp->mediumType = chInfo.mediumType;
+ resp->msgProtType = chInfo.protocolType;
+ resp->actSessCount = getChannelActiveSessions(chNum);
+ resp->sessType = chInfo.sessionSupported;
+
+ // IPMI Spec: The IPMI Enterprise Number is: 7154 (decimal)
+ resp->vendorId[0] = 0xF2;
+ resp->vendorId[1] = 0x1B;
+ resp->vendorId[2] = 0x00;
+
+ // Auxiliary Channel info - byte 1:2
+ // TODO: For System Interface(0xF) and OEM channel types, this needs
+ // to be changed acoordingly.
+ // All other channel types, its reverved
+ resp->auxChInfo[0] = 0x00;
+ resp->auxChInfo[1] = 0x00;
+
+ *data_len = sizeof(*resp);
+
+ return IPMI_CC_OK;
+}
+
+void registerChannelFunctions()
+{
+ ipmiChannelInit();
+
+ ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_CHANNEL_ACCESS, NULL,
+ ipmiSetChannelAccess, PRIVILEGE_ADMIN);
+
+ ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHANNEL_ACCESS, NULL,
+ ipmiGetChannelAccess, PRIVILEGE_USER);
+
+ ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHANNEL_INFO, NULL,
+ ipmiGetChannelInfo, PRIVILEGE_USER);
+ return;
+}
+
+} // namespace ipmi
diff --git a/user_channel/channelcommands.hpp b/user_channel/channelcommands.hpp
new file mode 100644
index 0000000..84d2dcb
--- /dev/null
+++ b/user_channel/channelcommands.hpp
@@ -0,0 +1,32 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#pragma once
+#include <cstdint>
+
+namespace ipmi
+{
+
+// IPMI commands for channel command NETFN:APP.
+enum ipmi_netfn_channel_cmds
+{
+ IPMI_CMD_SET_CHANNEL_ACCESS = 0x40,
+ IPMI_CMD_GET_CHANNEL_ACCESS = 0x41,
+ IPMI_CMD_GET_CHANNEL_INFO = 0x42,
+};
+
+void registerChannelFunctions();
+} // namespace ipmi
OpenPOWER on IntegriCloud