blob: c5d64fb3e27c7ca2618b680d28075d4b8e6909c1 [file] [log] [blame]
#include "payload_cmds.hpp"
#include "main.hpp"
#include "sol/sol_manager.hpp"
#include "sol_cmds.hpp"
#include <ipmid/api.h>
#include <ipmid/api-types.hpp>
#include <phosphor-logging/log.hpp>
namespace sol
{
namespace command
{
using namespace phosphor::logging;
std::vector<uint8_t> activatePayload(const std::vector<uint8_t>& inPayload,
const message::Handler& handler)
{
std::vector<uint8_t> outPayload(sizeof(ActivatePayloadResponse));
auto request =
reinterpret_cast<const ActivatePayloadRequest*>(inPayload.data());
auto response =
reinterpret_cast<ActivatePayloadResponse*>(outPayload.data());
if (inPayload.size() != sizeof(ActivatePayloadRequest))
{
response->completionCode = ipmi::ccReqDataLenInvalid;
outPayload.resize(sizeof(response->completionCode));
return outPayload;
}
response->completionCode = IPMI_CC_OK;
// SOL is the payload currently supported for activation.
if (static_cast<uint8_t>(message::PayloadType::SOL) != request->payloadType)
{
response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
return outPayload;
}
if (!std::get<sol::Manager&>(singletonPool).enable)
{
response->completionCode = IPMI_CC_PAYLOAD_TYPE_DISABLED;
return outPayload;
}
// Only one instance of SOL is currently supported.
if (request->payloadInstance != 1)
{
response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
return outPayload;
}
auto session = std::get<session::Manager&>(singletonPool)
.getSession(handler.sessionID);
if (!request->encryption && session->isCryptAlgoEnabled())
{
response->completionCode = IPMI_CC_PAYLOAD_WITHOUT_ENCRYPTION;
return outPayload;
}
// Is SOL Payload enabled for this user & channel.
auto userId = ipmi::ipmiUserGetUserId(session->userName);
ipmi::PayloadAccess payloadAccess = {};
if ((ipmi::ipmiUserGetUserPayloadAccess(session->channelNum(), userId,
payloadAccess) != IPMI_CC_OK) ||
!(payloadAccess.stdPayloadEnables1[static_cast<uint8_t>(
message::PayloadType::SOL)]))
{
response->completionCode = IPMI_CC_PAYLOAD_TYPE_DISABLED;
return outPayload;
}
auto status = std::get<sol::Manager&>(singletonPool)
.isPayloadActive(request->payloadInstance);
if (status)
{
response->completionCode = IPMI_CC_PAYLOAD_ALREADY_ACTIVE;
return outPayload;
}
// Set the current command's socket channel to the session
handler.setChannelInSession();
// Start the SOL payload
try
{
std::get<sol::Manager&>(singletonPool)
.startPayloadInstance(request->payloadInstance, handler.sessionID);
}
catch (std::exception& e)
{
log<level::ERR>(e.what());
response->completionCode = IPMI_CC_UNSPECIFIED_ERROR;
return outPayload;
}
response->inPayloadSize = endian::to_ipmi<uint16_t>(MAX_PAYLOAD_SIZE);
response->outPayloadSize = endian::to_ipmi<uint16_t>(MAX_PAYLOAD_SIZE);
response->portNum = endian::to_ipmi<uint16_t>(IPMI_STD_PORT);
// VLAN addressing is not used
response->vlanNum = 0xFFFF;
return outPayload;
}
std::vector<uint8_t> deactivatePayload(const std::vector<uint8_t>& inPayload,
const message::Handler& handler)
{
std::vector<uint8_t> outPayload(sizeof(DeactivatePayloadResponse));
auto request =
reinterpret_cast<const DeactivatePayloadRequest*>(inPayload.data());
auto response =
reinterpret_cast<DeactivatePayloadResponse*>(outPayload.data());
response->completionCode = IPMI_CC_OK;
if (inPayload.size() != sizeof(DeactivatePayloadRequest))
{
response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
return outPayload;
}
// SOL is the payload currently supported for deactivation
if (static_cast<uint8_t>(message::PayloadType::SOL) != request->payloadType)
{
response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
return outPayload;
}
// Only one instance of SOL is supported
if (request->payloadInstance != 1)
{
response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
return outPayload;
}
auto status = std::get<sol::Manager&>(singletonPool)
.isPayloadActive(request->payloadInstance);
if (!status)
{
response->completionCode = IPMI_CC_PAYLOAD_DEACTIVATED;
return outPayload;
}
try
{
auto& context = std::get<sol::Manager&>(singletonPool)
.getContext(request->payloadInstance);
auto sessionID = context.sessionID;
std::get<sol::Manager&>(singletonPool)
.stopPayloadInstance(request->payloadInstance);
try
{
activating(request->payloadInstance, sessionID);
}
catch (std::exception& e)
{
log<level::INFO>(e.what());
/*
* In case session has been closed (like in the case of inactivity
* timeout), then activating function would throw an exception,
* since sessionID is not found. IPMI success completion code is
* returned, since the session is closed.
*/
return outPayload;
}
}
catch (std::exception& e)
{
log<level::ERR>(e.what());
response->completionCode = IPMI_CC_UNSPECIFIED_ERROR;
return outPayload;
}
return outPayload;
}
std::vector<uint8_t> getPayloadStatus(const std::vector<uint8_t>& inPayload,
const message::Handler& handler)
{
std::vector<uint8_t> outPayload(sizeof(GetPayloadStatusResponse));
auto request =
reinterpret_cast<const GetPayloadStatusRequest*>(inPayload.data());
auto response =
reinterpret_cast<GetPayloadStatusResponse*>(outPayload.data());
// SOL is the payload currently supported for payload status
if (static_cast<uint8_t>(message::PayloadType::SOL) != request->payloadType)
{
response->completionCode = IPMI_CC_UNSPECIFIED_ERROR;
return outPayload;
}
response->completionCode = IPMI_CC_OK;
constexpr size_t maxSolPayloadInstances = 1;
response->capacity = maxSolPayloadInstances;
// Currently we support only one SOL session
response->instance1 =
std::get<sol::Manager&>(singletonPool).isPayloadActive(1);
return outPayload;
}
std::vector<uint8_t> getPayloadInfo(const std::vector<uint8_t>& inPayload,
const message::Handler& handler)
{
std::vector<uint8_t> outPayload(sizeof(GetPayloadInfoResponse));
auto request =
reinterpret_cast<const GetPayloadInfoRequest*>(inPayload.data());
auto response =
reinterpret_cast<GetPayloadInfoResponse*>(outPayload.data());
if (inPayload.size() != sizeof(GetPayloadInfoRequest))
{
response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
return outPayload;
}
// SOL is the payload currently supported for payload status & only one
// instance of SOL is supported.
if (static_cast<uint8_t>(message::PayloadType::SOL) !=
request->payloadType ||
request->payloadInstance != 1)
{
response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
return outPayload;
}
auto status = std::get<sol::Manager&>(singletonPool)
.isPayloadActive(request->payloadInstance);
if (status)
{
auto& context = std::get<sol::Manager&>(singletonPool)
.getContext(request->payloadInstance);
response->sessionID = context.sessionID;
}
else
{
// No active payload - return session id as 0
response->sessionID = 0;
}
response->completionCode = IPMI_CC_OK;
return outPayload;
}
} // namespace command
} // namespace sol