summaryrefslogtreecommitdiffstats
path: root/user_channel
diff options
context:
space:
mode:
authorAppaRao Puli <apparao.puli@intel.com>2018-05-24 16:45:30 +0530
committerRichard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>2018-11-20 10:09:26 +0530
commit071f3f2f298ab4a4799b7fcdba3255dfd999452d (patch)
treee56a267bf7e4eca8efc008d3a3d8b4b405268fcd /user_channel
parentb849110d32da5ca61f165abf553eac5b383d4f69 (diff)
downloadphosphor-host-ipmid-071f3f2f298ab4a4799b7fcdba3255dfd999452d.tar.gz
phosphor-host-ipmid-071f3f2f298ab4a4799b7fcdba3255dfd999452d.zip
IPMI Channel commands implementation
IPMI Channel commands implemenation - squashed commit e9a75d8dd6e89d17381f0310c7930586c6b79996 Author: AppaRao Puli <apparao.puli@intel.com> Date: Thu Jul 5 14:47:22 2018 +0530 Channel layer separation De-coupling the channel management from ipmi channel commands implementation. This gives flexibility to load only needed stuff in different modules(host-ipmi or netipmid) Change-Id: Ib334562beb9325f7768ed6a15475cae15af17b19 Signed-off-by: AppaRao Puli <apparao.puli@intel.com> Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com> commit 726ddf2af678ea6773f4b4b918fbd49be8c83e6a Author: AppaRao Puli <apparao.puli@intel.com> Date: Thu May 24 16:45:30 2018 +0530 IPMI Channel commands implementation Following IPMI channel commands are implemented. 1) Set channel access (0x40) 2) Get channel access (0x41) 3) Get channel info (0x42) Also added code supported for LAN configuration parameters 1) Authentication Type Support (selector #1) 2) Authentication Type Enables (selector #2) Change-Id: Ic4156378c7756eca383dc3da52114fd119346ca6 Signed-off-by: AppaRao Puli <apparao.puli@intel.com> Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com> Change-Id: Ic4156378c7756eca383dc3da52114fd119346ca6 Signed-off-by: AppaRao Puli <apparao.puli@intel.com> Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
Diffstat (limited to 'user_channel')
-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
6 files changed, 2190 insertions, 0 deletions
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