Session Commands Implementation
Implements Set Session Privilege Command and Close Session
command.
Change-Id: I18aeee7bcae48db3eb8a61292c9333ca2304dcf1
Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
diff --git a/command/session_cmds.cpp b/command/session_cmds.cpp
new file mode 100644
index 0000000..f30ef78
--- /dev/null
+++ b/command/session_cmds.cpp
@@ -0,0 +1,79 @@
+#include "session_cmds.hpp"
+
+#include <iostream>
+
+#include "endian.hpp"
+#include "main.hpp"
+#include <host-ipmid/ipmid-api.h>
+
+namespace command
+{
+
+std::vector<uint8_t> setSessionPrivilegeLevel(std::vector<uint8_t>& inPayload,
+ const message::Handler& handler)
+{
+ std::cout << ">> setSessionPrivilegeLevel\n";
+
+ std::vector<uint8_t> outPayload(sizeof(SetSessionPrivLevelResp));
+ auto request = reinterpret_cast<SetSessionPrivLevelReq*>(inPayload.data());
+ auto response = reinterpret_cast<SetSessionPrivLevelResp*>
+ (outPayload.data());
+ response->completionCode = IPMI_CC_OK;
+ uint8_t reqPrivilegeLevel = request->reqPrivLevel;
+
+ auto session = (std::get<session::Manager&>(singletonPool).getSession(
+ handler.sessionID)).lock();
+
+ if (reqPrivilegeLevel == 0) // Just return present privilege level
+ {
+ response->newPrivLevel = static_cast<uint8_t>(session->curPrivLevel);
+ }
+ else if (reqPrivilegeLevel <= static_cast<uint8_t>(session->maxPrivLevel))
+ {
+ session->curPrivLevel = static_cast<session::Privilege>
+ (reqPrivilegeLevel);
+ response->newPrivLevel = reqPrivilegeLevel;
+ }
+ else
+ {
+ // Requested level exceeds Channel and/or User Privilege Limit
+ response->completionCode = IPMI_CC_EXCEEDS_USER_PRIV;
+ }
+
+ std::cout << "<< setSessionPrivilegeLevel\n";
+ return outPayload;
+}
+
+std::vector<uint8_t> closeSession(std::vector<uint8_t>& inPayload,
+ const message::Handler& handler)
+{
+ std::cout << ">> closeSession\n";
+
+ std::vector<uint8_t> outPayload(sizeof(CloseSessionResponse));
+ auto request = reinterpret_cast<CloseSessionRequest*>(inPayload.data());
+ auto response = reinterpret_cast<CloseSessionResponse*>(outPayload.data());
+ response->completionCode = IPMI_CC_OK ;
+
+ auto bmcSessionID = endian::from_ipmi(request->sessionID);
+
+ // Session 0 is needed to handle session setup, so session zero is never
+ // closed
+ if (bmcSessionID == session::SESSION_ZERO)
+ {
+ response->completionCode = IPMI_CC_INVALID_SESSIONID;
+ }
+ else
+ {
+ auto status = std::get<session::Manager&>(singletonPool).stopSession
+ (bmcSessionID);
+ if(!status)
+ {
+ response->completionCode = IPMI_CC_INVALID_SESSIONID;
+ }
+ }
+
+ std::cout << "<< closeSession\n";
+ return outPayload;
+}
+
+} // namespace command
diff --git a/command/session_cmds.hpp b/command/session_cmds.hpp
new file mode 100644
index 0000000..00dbfc4
--- /dev/null
+++ b/command/session_cmds.hpp
@@ -0,0 +1,118 @@
+#pragma once
+
+#include <vector>
+
+#include "message_handler.hpp"
+
+namespace command
+{
+
+constexpr uint8_t IPMI_CC_INVALID_PRIV_LEVEL = 0x80;
+constexpr uint8_t IPMI_CC_EXCEEDS_USER_PRIV = 0x81;
+
+/*
+ * @ struct SetSessionPrivLevelReq
+ *
+ * IPMI Request data for Set Session Privilege Level command
+ */
+struct SetSessionPrivLevelReq
+{
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+ uint8_t reqPrivLevel : 4;
+ uint8_t reserved : 4;
+#endif
+
+#if BYTE_ORDER == BIG_ENDIAN
+ uint8_t reserved : 4;
+ uint8_t reqPrivLevel : 4;
+#endif
+
+} __attribute__((packed));
+
+/*
+ * @ struct SetSessionPrivLevelResp
+ *
+ * IPMI Response data for Set Session Privilege Level command
+ */
+struct SetSessionPrivLevelResp
+{
+ uint8_t completionCode;
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+ uint8_t newPrivLevel : 4;
+ uint8_t reserved : 4;
+#endif
+
+#if BYTE_ORDER == BIG_ENDIAN
+ uint8_t reserved : 4;
+ uint8_t newPrivLevel : 4;
+#endif
+
+} __attribute__((packed));
+
+/*
+ * @brief Set Session Privilege Command
+ *
+ * This command is sent in authenticated format. When a session is activated,
+ * the session is set to an initial privilege level. A session that is
+ * activated at a maximum privilege level of Callback is set to an initial
+ * privilege level of Callback and cannot be changed. All other sessions are
+ * initially set to USER level, regardless of the maximum privilege level
+ * requested in the RAKP Message 1.
+ *
+ * This command cannot be used to set a privilege level higher than the lowest
+ * of the privilege level set for the user(via the Set User Access command) and
+ * the privilege limit for the channel that was set via the Set Channel Access
+ * command.
+ *
+ * @param[in] inPayload - Request Data for the command
+ * @param[in] handler - Reference to the Message Handler
+ *
+ * @return Response data for the command
+ */
+std::vector<uint8_t> setSessionPrivilegeLevel(std::vector<uint8_t>& inPayload,
+ const message::Handler& handler);
+
+constexpr uint8_t IPMI_CC_INVALID_SESSIONID = 0x87;
+
+/*
+ * @ struct CloseSessionRequest
+ *
+ * IPMI Request data for Close Session command
+ */
+struct CloseSessionRequest
+{
+ uint32_t sessionID;
+ uint8_t sessionHandle;
+} __attribute__((packed));
+
+/*
+ * @ struct CloseSessionResponse
+ *
+ * IPMI Response data for Close Session command
+ */
+struct CloseSessionResponse
+{
+ uint8_t completionCode;
+} __attribute__((packed));
+
+/*
+ * @brief Close Session Command
+ *
+ * This command is used to immediately terminate a session in progress. It is
+ * typically used to close the session that the user is communicating over,
+ * though it can be used to other terminate sessions in progress (provided that
+ * the user is operating at the appropriate privilege level, or the command is
+ * executed over a local channel - e.g. the system interface). Closing
+ * sessionless session ( session zero) is restricted in this command
+ *
+ * @param[in] inPayload - Request Data for the command
+ * @param[in] handler - Reference to the Message Handler
+ *
+ * @return Response data for the command
+ */
+std::vector<uint8_t> closeSession(std::vector<uint8_t>& inPayload,
+ const message::Handler& handler);
+
+} // namespace command
diff --git a/sessions_manager.cpp b/sessions_manager.cpp
index ff17727..a2d2d8d 100644
--- a/sessions_manager.cpp
+++ b/sessions_manager.cpp
@@ -97,16 +97,17 @@
return getSession(sessionID);
}
-void Manager::stopSession(SessionID bmcSessionID)
+bool Manager::stopSession(SessionID bmcSessionID)
{
- // If the session is valid and not session zero
- if(bmcSessionID != SESSION_ZERO)
+ auto iter = sessionsMap.find(bmcSessionID);
+ if (iter != sessionsMap.end())
{
- auto iter = sessionsMap.find(bmcSessionID);
- if (iter != sessionsMap.end())
- {
- iter->second->state = State::TEAR_DOWN_IN_PROGRESS;
- }
+ iter->second->state = State::TEAR_DOWN_IN_PROGRESS;
+ return true;
+ }
+ else
+ {
+ return false;
}
}
diff --git a/sessions_manager.hpp b/sessions_manager.hpp
index 71bb7e4..8b9a76c 100644
--- a/sessions_manager.hpp
+++ b/sessions_manager.hpp
@@ -60,8 +60,10 @@
*
* @param[in] bmcSessionID - BMC Session ID
*
+ * @return true on success and failure if session ID is invalid
+ *
*/
- void stopSession(SessionID bmcSessionID);
+ bool stopSession(SessionID bmcSessionID);
/*
* @brief Get Session Handle