blob: 512b17c2a2c74a076273af3b7c212e57f6c3f29e [file] [log] [blame]
#pragma once
#include "main.hpp"
#include "session.hpp"
#include <boost/asio/steady_timer.hpp>
#include <ipmid/api.hpp>
#include <ipmid/sessiondef.hpp>
#include <chrono>
#include <map>
#include <memory>
#include <mutex>
#include <string>
namespace session
{
enum class RetrieveOption
{
BMC_SESSION_ID,
RC_SESSION_ID,
};
static constexpr size_t maxSessionHandles = multiIntfaceSessionHandleMask;
/**
* @class Manager
*
* Manager class acts a manager for the IPMI sessions and provides interfaces
* to start a session, stop a session and get reference to the session objects.
*
*/
class Manager
{
private:
struct Private
{};
public:
// BMC Session ID is the key for the map
using SessionMap = std::map<SessionID, std::shared_ptr<Session>>;
Manager() = delete;
Manager(std::shared_ptr<boost::asio::io_context>& io, const Private&) :
io(io), timer(*io){};
~Manager() = default;
Manager(const Manager&) = delete;
Manager& operator=(const Manager&) = delete;
Manager(Manager&&) = default;
Manager& operator=(Manager&&) = default;
/**
* @brief Get a reference to the singleton Manager
*
* @return Manager reference
*/
static Manager& get()
{
static std::shared_ptr<Manager> ptr = nullptr;
if (!ptr)
{
std::shared_ptr<boost::asio::io_context> io = getIo();
ptr = std::make_shared<Manager>(io, Private());
if (!ptr)
{
throw std::runtime_error("failed to create session manager");
}
}
return *ptr;
}
/**
* @brief Start an IPMI session
*
* @param[in] remoteConsoleSessID - Remote Console Session ID mentioned
* in the Open SessionRequest Command
* @param[in] priv - Privilege level requested
* @param[in] authAlgo - Authentication Algorithm
* @param[in] intAlgo - Integrity Algorithm
* @param[in] cryptAlgo - Confidentiality Algorithm
*
* @return session handle on success and nullptr on failure
*
*/
std::shared_ptr<Session>
startSession(SessionID remoteConsoleSessID, Privilege priv,
cipher::rakp_auth::Algorithms authAlgo,
cipher::integrity::Algorithms intAlgo,
cipher::crypt::Algorithms cryptAlgo);
/**
* @brief Stop IPMI Session
*
* @param[in] bmcSessionID - BMC Session ID
*
* @return true on success and failure if session ID is invalid
*
*/
bool stopSession(SessionID bmcSessionID);
/**
* @brief Get Session Handle
*
* @param[in] sessionID - Session ID
* @param[in] option - Select between BMC Session ID and Remote Console
* Session ID, Default option is BMC Session ID
*
* @return session handle on success and nullptr on failure
*
*/
std::shared_ptr<Session>
getSession(SessionID sessionID,
RetrieveOption option = RetrieveOption::BMC_SESSION_ID);
uint8_t getActiveSessionCount() const;
uint8_t getSessionHandle(SessionID bmcSessionID) const;
uint8_t storeSessionHandle(SessionID bmcSessionID);
uint32_t getSessionIDbyHandle(uint8_t sessionHandle) const;
void managerInit(const std::string& channel);
uint8_t getNetworkInstance(void);
/**
* @brief Clean Session Stale Entries
*
* Schedules cleaning the inactive sessions entries from the Session Map
*/
void scheduleSessionCleaner(const std::chrono::microseconds& grace);
private:
/**
* @brief reclaim system resources by limiting idle sessions
*
* Limits on active, authenticated sessions are calculated independently
* from in-setup sessions, which are not required to be authenticated. This
* will prevent would-be DoS attacks by calling a bunch of Open Session
* requests to fill up all available sessions. Too many active sessions will
* trigger a shorter timeout, but is unaffected by setup session counts.
*
* For active sessions, grace time is inversely proportional to (the number
* of active sessions beyond max sessions per channel)^3
*
* For sessions in setup, grace time is inversely proportional to (the
* number of total sessions beyond max sessions per channel)^3, with a max
* of 3 seconds
*/
void cleanStaleEntries();
std::shared_ptr<boost::asio::io_context> io;
boost::asio::steady_timer timer;
std::array<uint32_t, session::maxSessionHandles> sessionHandleMap = {0};
/**
* @brief Session Manager keeps the session objects as a sorted
* associative container with Session ID as the unique key
*/
SessionMap sessionsMap;
std::unique_ptr<sdbusplus::server::manager_t> objManager = nullptr;
std::string chName{}; // Channel Name
uint8_t ipmiNetworkInstance = 0;
void setNetworkInstance(void);
};
} // namespace session