Implemented close session cmd in host interface
This command can close any session via host interface.
Tested:
Close the existing valid session by session id
ipmitool raw 0x6 0x3c <valid sesssion id >
Response : 00 // success
Close the existing valid session by session handle
ipmitool raw 0x6 0x3c <zero session id> <valid session handle>
Response : 00 // success
Close the session by zero session id
ipmitool raw 0x6 0x3c <zero session id>
Response : 0x87 // inavlid session id
Close the session by zero session handle
ipmitool raw 0x6 0x3c <zero session id> <zero session handle>
Response : 0x88 // inavlid session handle
Close an inactive session.
ipmitool raw 0x6 0x3c <valid session id>
Response : 0xcc // invalid data field in request
Close an inactive session.
ipmitool raw 0x6 0x3c <zero session id> <valid session hnadle>
Response : 0xcc // invalid data field in request
Signed-off-by: Rajashekar Gade Reddy <raja.sekhar.reddy.gade@linux.intel.com>
Change-Id: I8af290001d8effbbcdbbe2dd93aabf1b015e7a88
diff --git a/apphandler.cpp b/apphandler.cpp
index c5a608d..0c8eb92 100644
--- a/apphandler.cpp
+++ b/apphandler.cpp
@@ -20,6 +20,8 @@
#include <filesystem>
#include <fstream>
#include <ipmid/api.hpp>
+#include <ipmid/sessiondef.hpp>
+#include <ipmid/sessionhelper.hpp>
#include <ipmid/types.hpp>
#include <ipmid/utils.hpp>
#include <memory>
@@ -842,6 +844,112 @@
return ipmi::responseSuccess(uuid);
}
+/**
+ * @brief set the session state as teardown
+ *
+ * This function is to set the session state to tear down in progress if the
+ * state is active.
+ *
+ * @param[in] busp - Dbus obj
+ * @param[in] service - service name
+ * @param[in] obj - object path
+ *
+ * @return success completion code if it sets the session state to
+ * tearDownInProgress else return the corresponding error completion code.
+ **/
+uint8_t setSessionState(std::shared_ptr<sdbusplus::asio::connection>& busp,
+ const std::string& service, const std::string& obj)
+{
+ try
+ {
+ uint8_t sessionState = std::get<uint8_t>(ipmi::getDbusProperty(
+ *busp, service, obj, session::sessionIntf, "State"));
+
+ if (sessionState == static_cast<uint8_t>(session::State::active))
+ {
+ ipmi::setDbusProperty(
+ *busp, service, obj, session::sessionIntf, "State",
+ static_cast<uint8_t>(session::State::tearDownInProgress));
+ return ipmi::ccSuccess;
+ }
+ }
+ catch (std::exception& e)
+ {
+ log<level::ERR>("Failed in getting session state property",
+ entry("service=%s", service.c_str()),
+ entry("object path=%s", obj.c_str()),
+ entry("interface=%s", session::sessionIntf));
+ return ipmi::ccUnspecifiedError;
+ }
+
+ return ipmi::ccInvalidFieldRequest;
+}
+
+ipmi::RspType<> ipmiAppCloseSession(uint32_t reqSessionId,
+ std::optional<uint8_t> requestSessionHandle)
+{
+ auto busp = getSdBus();
+ uint8_t reqSessionHandle =
+ requestSessionHandle.value_or(session::defaultSessionHandle);
+
+ if (reqSessionId == session::sessionZero &&
+ reqSessionHandle == session::defaultSessionHandle)
+ {
+ return ipmi::response(session::ccInvalidSessionId);
+ }
+
+ if (reqSessionId == session::sessionZero &&
+ reqSessionHandle == session::invalidSessionHandle)
+ {
+ return ipmi::response(session::ccInvalidSessionHandle);
+ }
+
+ if (reqSessionId != session::sessionZero &&
+ reqSessionHandle != session::defaultSessionHandle)
+ {
+ return ipmi::response(ipmi::ccInvalidFieldRequest);
+ }
+
+ try
+ {
+ ipmi::ObjectTree objectTree = ipmi::getAllDbusObjects(
+ *busp, session::sessionManagerRootPath, session::sessionIntf);
+
+ for (auto& objectTreeItr : objectTree)
+ {
+ const std::string obj = objectTreeItr.first;
+
+ if (isSessionObjectMatched(obj, reqSessionId, reqSessionHandle))
+ {
+ auto& serviceMap = objectTreeItr.second;
+
+ // Session id and session handle are unique for each session.
+ // Session id and handler are retrived from the object path and
+ // object path will be unique for each session. Checking if
+ // multiple objects exist with same object path under multiple
+ // services.
+ if (serviceMap.size() != 1)
+ {
+ return ipmi::responseUnspecifiedError();
+ }
+
+ auto itr = serviceMap.begin();
+ const std::string service = itr->first;
+ return ipmi::response(setSessionState(busp, service, obj));
+ }
+ }
+ }
+ catch (sdbusplus::exception::SdBusError& e)
+ {
+ log<level::ERR>("Failed to fetch object from dbus",
+ entry("INTERFACE=%s", session::sessionIntf),
+ entry("ERRMSG=%s", e.what()));
+ return ipmi::responseUnspecifiedError();
+ }
+
+ return ipmi::responseInvalidFieldRequest();
+}
+
static std::unique_ptr<SysInfoParamStore> sysInfoParamStore;
static std::string sysInfoReadSystemName()
@@ -1175,6 +1283,10 @@
ipmi::app::cmdSetWatchdogTimer,
ipmi::Privilege::Operator, ipmiSetWatchdogTimer);
+ ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
+ ipmi::app::cmdCloseSession, ipmi::Privilege::Callback,
+ ipmiAppCloseSession);
+
// <Get Watchdog Timer>
ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
ipmi::app::cmdGetWatchdogTimer,