summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apphandler.cpp275
-rw-r--r--include/ipmid/sessiondef.hpp3
2 files changed, 277 insertions, 1 deletions
diff --git a/apphandler.cpp b/apphandler.cpp
index f187d95..03cd255 100644
--- a/apphandler.cpp
+++ b/apphandler.cpp
@@ -949,6 +949,277 @@ ipmi::RspType<> ipmiAppCloseSession(uint32_t reqSessionId,
return ipmi::responseInvalidFieldRequest();
}
+uint8_t getTotalSessionCount()
+{
+ uint8_t count = 0, ch = 1;
+
+ while (ch < ipmi::maxIpmiChannels &&
+ count < session::maxNetworkInstanceSupported)
+ {
+ ipmi::ChannelInfo chInfo;
+ ipmi::getChannelInfo(ch, chInfo);
+ if (static_cast<ipmi::EChannelMediumType>(chInfo.mediumType) ==
+ ipmi::EChannelMediumType::lan8032)
+ {
+ count++;
+ }
+ ch++;
+ }
+ return count * session::maxSessionCountPerChannel;
+}
+
+/**
+ * @brief get session info request data.
+ *
+ * This function validates the request data and retrive request session id,
+ * session handle.
+ *
+ * @param[in] sessionIndex - request session index
+ * @param[in] payload - input payload
+ * @param[in] reqSessionId - unpacked session Id will be asigned
+ * @param[in] reqSessionHandle - unpacked session handle will be asigned
+ *
+ * @return success completion code if request data is valid
+ * else return the correcponding error completion code.
+ **/
+uint8_t getSessionInfoRequestData(const uint8_t sessionIndex,
+ ipmi::message::Payload& payload,
+ uint32_t& reqSessionId,
+ uint8_t& reqSessionHandle)
+{
+ if (sessionIndex == session::sessionZero ||
+ ((sessionIndex > session::maxSessionCountPerChannel) &&
+ (sessionIndex < session::searchSessionByHandle)))
+ {
+ return ipmi::ccInvalidFieldRequest;
+ }
+
+ switch (sessionIndex)
+ {
+ case session::searchSessionByHandle:
+
+ if ((payload.unpack(reqSessionHandle)) ||
+ (!payload.fullyUnpacked()))
+ {
+ return ipmi::ccReqDataLenInvalid;
+ }
+
+ if ((reqSessionHandle == session::sessionZero) ||
+ ((reqSessionHandle & session::multiIntfaceSessionHandleMask) >
+ session::maxSessionCountPerChannel))
+ {
+ return session::ccInvalidSessionHandle;
+ }
+ break;
+
+ case session::searchSessionById:
+
+ if ((payload.unpack(reqSessionId)) || (!payload.fullyUnpacked()))
+ {
+ return ipmi::ccReqDataLenInvalid;
+ }
+
+ if (reqSessionId == session::sessionZero)
+ {
+ return session::ccInvalidSessionId;
+ }
+ break;
+
+ default:
+ if (!payload.fullyUnpacked())
+ {
+ return ipmi::ccReqDataLenInvalid;
+ }
+ break;
+ }
+ return ipmi::ccSuccess;
+}
+
+uint8_t getSessionState(std::shared_ptr<sdbusplus::asio::connection>& busp,
+ const std::string& service, const std::string& objPath,
+ uint8_t& sessionState)
+{
+ try
+ {
+ sessionState = std::get<uint8_t>(ipmi::getDbusProperty(
+ *busp, service, objPath, session::sessionIntf, "State"));
+ }
+ catch (sdbusplus::exception::SdBusError& e)
+ {
+ log<level::ERR>("Failed to fetch state property ",
+ entry("SERVICE=%s", service.c_str()),
+ entry("OBJECTPATH=%s", objPath.c_str()),
+ entry("INTERFACE=%s", session::sessionIntf),
+ entry("ERRMSG=%s", e.what()));
+ return ipmi::ccUnspecifiedError;
+ }
+
+ return ipmi::ccSuccess;
+}
+
+static constexpr uint8_t macAddrLen = 6;
+struct GetSessionInfoRes
+{
+ uint8_t sessionHandle;
+ uint8_t totalSessionCount;
+ uint8_t activeSessionCount;
+ uint8_t userID;
+ uint8_t privLevel;
+ uint8_t channelNumber;
+ uint32_t remoteIpAddr;
+ std::array<uint8_t, macAddrLen> macAddr = {0};
+ uint16_t remotePort;
+};
+
+uint8_t
+ fillGetSessionInfoRes(std::shared_ptr<sdbusplus::asio::connection>& busp,
+ const std::string& service,
+ const std::string& objPath,
+ struct GetSessionInfoRes& resp, uint8_t& sessionState)
+{
+ try
+ {
+ ipmi::PropertyMap sessionProps = ipmi::getAllDbusProperties(
+ *busp, service, objPath, session::sessionIntf);
+
+ sessionState = std::get<uint8_t>(sessionProps.at("State"));
+ if (sessionState == static_cast<uint8_t>(session::State::active))
+ {
+ resp.sessionHandle =
+ std::get<uint8_t>(sessionProps["SessionHandle"]);
+ resp.userID = std::get<uint8_t>(sessionProps["UserID"]);
+ resp.privLevel =
+ std::get<uint8_t>(sessionProps["CurrentPrivilege"]);
+ resp.channelNumber = std::get<uint8_t>(sessionProps["ChannelNum"]);
+ resp.remoteIpAddr =
+ std::get<uint32_t>(sessionProps["RemoteIPAddr"]);
+ resp.remotePort = std::get<uint16_t>(sessionProps["RemotePort"]);
+ }
+ }
+ catch (sdbusplus::exception::SdBusError& e)
+ {
+ log<level::ERR>("Failed to fetch state property ",
+ entry("SERVICE=%s", service.c_str()),
+ entry("OBJECTPATH=%s", objPath.c_str()),
+ entry("INTERFACE=%s", session::sessionIntf),
+ entry("ERRMSG=%s", e.what()));
+ return ipmi::ccUnspecifiedError;
+ }
+
+ return ipmi::ccSuccess;
+}
+
+ipmi::RspType<
+ uint8_t, // session handle,
+ uint8_t, // total session count
+ uint8_t, // active session count
+ std::optional<std::tuple<uint8_t, // user ID
+ uint8_t, // privilege level
+ uint8_t, // channel number
+ uint32_t, // remote ip address,
+ std::array<uint8_t, macAddrLen>, // mac address
+ uint16_t // remote port
+ >>>
+ ipmiAppGetSessionInfo(uint8_t sessionIndex, ipmi::message::Payload& payload)
+{
+ uint32_t reqSessionId = 0;
+ uint8_t reqSessionHandle = session::defaultSessionHandle;
+ // initializing state to 0xff as 0 represents state as inactive.
+ uint8_t state = 0xFF;
+
+ uint8_t completionCode = getSessionInfoRequestData(
+ sessionIndex, payload, reqSessionId, reqSessionHandle);
+
+ if (completionCode)
+ {
+ return ipmi::response(completionCode);
+ }
+ struct GetSessionInfoRes res = {0};
+ res.totalSessionCount = getTotalSessionCount();
+ res.activeSessionCount = 0;
+ auto busp = getSdBus();
+
+ try
+ {
+ uint8_t index = 0;
+ ipmi::ObjectTree objectTree = ipmi::getAllDbusObjects(
+ *busp, session::sessionManagerRootPath, session::sessionIntf);
+
+ for (auto& objectTreeItr : objectTree)
+ {
+ uint32_t sessionId = 0;
+ uint8_t sessionHandle = session::defaultSessionHandle;
+ std::string objectPath = objectTreeItr.first;
+
+ if (!parseCloseSessionInputPayload(objectPath, sessionId,
+ sessionHandle))
+ {
+ continue;
+ }
+ index++;
+ auto& serviceMap = objectTreeItr.second;
+ auto itr = serviceMap.begin();
+
+ if (serviceMap.size() != 1)
+ {
+ return ipmi::responseUnspecifiedError();
+ }
+
+ std::string service = itr->first;
+ uint8_t sessionState = 0;
+ completionCode =
+ getSessionState(busp, service, objectPath, sessionState);
+ if (completionCode)
+ {
+ return ipmi::response(completionCode);
+ }
+
+ if (sessionState == static_cast<uint8_t>(session::State::active))
+ {
+ res.activeSessionCount++;
+ }
+
+ if (index != sessionIndex && reqSessionId != sessionId &&
+ reqSessionHandle != sessionHandle)
+ {
+ continue;
+ }
+
+ completionCode =
+ fillGetSessionInfoRes(busp, service, objectPath, res, state);
+
+ if (completionCode)
+ {
+ return ipmi::response(completionCode);
+ }
+ }
+ }
+
+ 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();
+ }
+
+ if (state == static_cast<uint8_t>(session::State::active))
+ {
+ return ipmi::responseSuccess(
+ res.sessionHandle, res.totalSessionCount, res.activeSessionCount,
+ std::make_tuple(res.userID, res.privLevel, res.channelNumber,
+ res.remoteIpAddr, res.macAddr, res.remotePort));
+ }
+ else if (state == static_cast<uint8_t>(session::State::tearDownInProgress))
+ {
+ res.sessionHandle = 0;
+ return ipmi::responseSuccess(res.sessionHandle, res.totalSessionCount,
+ res.activeSessionCount, std::nullopt);
+ }
+
+ return ipmi::responseInvalidFieldRequest();
+}
+
static std::unique_ptr<SysInfoParamStore> sysInfoParamStore;
static std::string sysInfoReadSystemName()
@@ -1366,6 +1637,10 @@ void register_netfn_app_functions()
ipmi::app::cmdResetWatchdogTimer,
ipmi::Privilege::Operator, ipmiAppResetWatchdogTimer);
+ ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
+ ipmi::app::cmdGetSessionInfo,
+ ipmi::Privilege::Callback, ipmiAppGetSessionInfo);
+
// <Set Watchdog Timer>
ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
ipmi::app::cmdSetWatchdogTimer,
diff --git a/include/ipmid/sessiondef.hpp b/include/ipmid/sessiondef.hpp
index 48ee4c6..7802fb9 100644
--- a/include/ipmid/sessiondef.hpp
+++ b/include/ipmid/sessiondef.hpp
@@ -32,7 +32,8 @@ static constexpr uint8_t defaultSessionHandle = 0xFF;
static constexpr uint8_t maxNetworkInstanceSupported = 4;
static constexpr uint8_t ccInvalidSessionId = 0x87;
static constexpr uint8_t ccInvalidSessionHandle = 0x88;
-
+static constexpr uint8_t searchSessionByHandle = 0xFE;
+static constexpr uint8_t searchSessionById = 0xFF;
// MSB BIT 7 BIT 6 assigned for netipmid instance in session handle.
static constexpr uint8_t multiIntfaceSessionHandleMask = 0x3F;
OpenPOWER on IntegriCloud