blob: 58630d9378ff22796b1d2ea4bfe0274b91c6bde1 [file] [log] [blame]
Tom Josephe6361a22016-08-10 06:56:25 -05001#include "message_handler.hpp"
2
Vernon Mauery9e801a22018-10-12 13:20:49 -07003#include "command_table.hpp"
4#include "main.hpp"
5#include "message.hpp"
6#include "message_parsers.hpp"
7#include "sessions_manager.hpp"
8
Tom Josephe6361a22016-08-10 06:56:25 -05009#include <sys/socket.h>
10
Tom Josephe6361a22016-08-10 06:56:25 -050011#include <memory>
Vernon Maueryfc37e592018-12-19 14:55:15 -080012#include <phosphor-logging/log.hpp>
Tom Josephe6361a22016-08-10 06:56:25 -050013#include <string>
14#include <vector>
15
Vernon Maueryfc37e592018-12-19 14:55:15 -080016using namespace phosphor::logging;
17
Tom Josephe6361a22016-08-10 06:56:25 -050018namespace message
19{
20
Vernon Maueryd999ffc2018-10-25 09:16:05 -070021std::shared_ptr<Message> Handler::receive()
Tom Josephe6361a22016-08-10 06:56:25 -050022{
23 std::vector<uint8_t> packet;
24 auto readStatus = 0;
25
26 // Read the packet
27 std::tie(readStatus, packet) = channel->read();
28
29 // Read of the packet failed
30 if (readStatus < 0)
31 {
Vernon Maueryfc37e592018-12-19 14:55:15 -080032 log<level::ERR>("Error in Read", entry("STATUS=%x", readStatus));
Tom Josephe6361a22016-08-10 06:56:25 -050033 return nullptr;
34 }
35
36 // Unflatten the packet
Vernon Maueryd999ffc2018-10-25 09:16:05 -070037 std::shared_ptr<Message> message;
Tom Josephe6361a22016-08-10 06:56:25 -050038 std::tie(message, sessionHeader) = parser::unflatten(packet);
39
Vernon Maueryae1fda42018-10-15 12:55:34 -070040 auto session = std::get<session::Manager&>(singletonPool)
41 .getSession(message->bmcSessionID);
Tom Josephe6361a22016-08-10 06:56:25 -050042
43 sessionID = message->bmcSessionID;
44 message->rcSessionID = session->getRCSessionID();
45 session->updateLastTransactionTime();
46
47 return message;
48}
49
Vernon Maueryd999ffc2018-10-25 09:16:05 -070050std::shared_ptr<Message>
51 Handler::executeCommand(std::shared_ptr<Message> inMessage)
Tom Josephe6361a22016-08-10 06:56:25 -050052{
53 // Get the CommandID to map into the command table
Vernon Mauery7f268e42018-10-26 10:26:01 -070054 auto command = inMessage->getCommand();
Tom Josephe6361a22016-08-10 06:56:25 -050055 std::vector<uint8_t> output{};
56
Vernon Maueryd999ffc2018-10-25 09:16:05 -070057 if (inMessage->payloadType == PayloadType::IPMI)
Tom Josephe6361a22016-08-10 06:56:25 -050058 {
Vernon Maueryd999ffc2018-10-25 09:16:05 -070059 if (inMessage->payload.size() <
Vernon Mauery9e801a22018-10-12 13:20:49 -070060 (sizeof(LAN::header::Request) + sizeof(LAN::trailer::Request)))
Tom Josephe6361a22016-08-10 06:56:25 -050061 {
62 return nullptr;
63 }
64
Vernon Maueryd999ffc2018-10-25 09:16:05 -070065 auto start = inMessage->payload.begin() + sizeof(LAN::header::Request);
66 auto end = inMessage->payload.end() - sizeof(LAN::trailer::Request);
Tom Josephe6361a22016-08-10 06:56:25 -050067 std::vector<uint8_t> inPayload(start, end);
68
Vernon Mauery9e801a22018-10-12 13:20:49 -070069 output = std::get<command::Table&>(singletonPool)
70 .executeCommand(command, inPayload, *this);
Tom Josephe6361a22016-08-10 06:56:25 -050071 }
72 else
73 {
Vernon Mauery9e801a22018-10-12 13:20:49 -070074 output = std::get<command::Table&>(singletonPool)
Vernon Maueryd999ffc2018-10-25 09:16:05 -070075 .executeCommand(command, inMessage->payload, *this);
Tom Josephe6361a22016-08-10 06:56:25 -050076 }
Vernon Mauery7f268e42018-10-26 10:26:01 -070077 return inMessage->createResponse(output);
Tom Josephe6361a22016-08-10 06:56:25 -050078}
79
Vernon Maueryd999ffc2018-10-25 09:16:05 -070080void Handler::send(std::shared_ptr<Message> outMessage)
Tom Josephe6361a22016-08-10 06:56:25 -050081{
Vernon Mauery9e801a22018-10-12 13:20:49 -070082 auto session =
Vernon Maueryae1fda42018-10-15 12:55:34 -070083 std::get<session::Manager&>(singletonPool).getSession(sessionID);
Tom Josephe6361a22016-08-10 06:56:25 -050084
85 // Flatten the packet
Vernon Mauery224f36a2018-10-25 08:52:23 -070086 auto packet = parser::flatten(outMessage, sessionHeader, session);
Tom Josephe6361a22016-08-10 06:56:25 -050087
Tom Joseph04b30382017-04-03 01:06:51 +053088 // Write the packet
Tom Josephe6361a22016-08-10 06:56:25 -050089 auto writeStatus = channel->write(packet);
90 if (writeStatus < 0)
91 {
Tom Joseph04b30382017-04-03 01:06:51 +053092 throw std::runtime_error("Error in writing to socket");
Tom Josephe6361a22016-08-10 06:56:25 -050093 }
Tom Josephe6361a22016-08-10 06:56:25 -050094}
95
Tom Josephff848492017-03-31 10:43:48 +053096void Handler::setChannelInSession() const
97{
Vernon Mauery9e801a22018-10-12 13:20:49 -070098 auto session =
Vernon Maueryae1fda42018-10-15 12:55:34 -070099 std::get<session::Manager&>(singletonPool).getSession(sessionID);
Tom Josephff848492017-03-31 10:43:48 +0530100
101 session->channelPtr = channel;
102}
103
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800104void Handler::sendSOLPayload(const std::vector<uint8_t>& input)
Tom Joseph22596f22017-03-31 10:52:27 +0530105{
Vernon Mauery9e801a22018-10-12 13:20:49 -0700106 auto session =
Vernon Maueryae1fda42018-10-15 12:55:34 -0700107 std::get<session::Manager&>(singletonPool).getSession(sessionID);
Tom Joseph22596f22017-03-31 10:52:27 +0530108
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700109 auto outMessage = std::make_shared<Message>();
110 outMessage->payloadType = PayloadType::SOL;
111 outMessage->payload = input;
112 outMessage->isPacketEncrypted = session->isCryptAlgoEnabled();
113 outMessage->isPacketAuthenticated = session->isIntegrityAlgoEnabled();
114 outMessage->rcSessionID = session->getRCSessionID();
115 outMessage->bmcSessionID = sessionID;
Tom Joseph22596f22017-03-31 10:52:27 +0530116
117 send(outMessage);
118}
119
Vernon Mauery9e801a22018-10-12 13:20:49 -0700120void Handler::sendUnsolicitedIPMIPayload(uint8_t netfn, uint8_t cmd,
Tom Joseph63d3e492017-03-31 11:01:08 +0530121 const std::vector<uint8_t>& output)
122{
Vernon Mauery9e801a22018-10-12 13:20:49 -0700123 auto session =
Vernon Maueryae1fda42018-10-15 12:55:34 -0700124 std::get<session::Manager&>(singletonPool).getSession(sessionID);
Tom Joseph63d3e492017-03-31 11:01:08 +0530125
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700126 auto outMessage = std::make_shared<Message>();
127 outMessage->payloadType = PayloadType::IPMI;
128 outMessage->isPacketEncrypted = session->isCryptAlgoEnabled();
129 outMessage->isPacketAuthenticated = session->isIntegrityAlgoEnabled();
130 outMessage->rcSessionID = session->getRCSessionID();
131 outMessage->bmcSessionID = sessionID;
Tom Joseph63d3e492017-03-31 11:01:08 +0530132
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700133 outMessage->payload.resize(sizeof(LAN::header::Request) + output.size() +
134 sizeof(LAN::trailer::Request));
Tom Joseph63d3e492017-03-31 11:01:08 +0530135
Vernon Mauery9e801a22018-10-12 13:20:49 -0700136 auto respHeader =
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700137 reinterpret_cast<LAN::header::Request*>(outMessage->payload.data());
Tom Joseph63d3e492017-03-31 11:01:08 +0530138
139 // Add IPMI LAN Message Request Header
140 respHeader->rsaddr = LAN::requesterBMCAddress;
Vernon Mauery9e801a22018-10-12 13:20:49 -0700141 respHeader->netfn = (netfn << 0x02);
142 respHeader->cs = crc8bit(&(respHeader->rsaddr), 2);
Tom Joseph63d3e492017-03-31 11:01:08 +0530143 respHeader->rqaddr = LAN::responderBMCAddress;
Vernon Mauery9e801a22018-10-12 13:20:49 -0700144 respHeader->rqseq = 0;
145 respHeader->cmd = cmd;
Tom Joseph63d3e492017-03-31 11:01:08 +0530146
147 auto assembledSize = sizeof(LAN::header::Request);
148
149 // Copy the output by the execution of the command
Vernon Mauery9e801a22018-10-12 13:20:49 -0700150 std::copy(output.begin(), output.end(),
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700151 outMessage->payload.begin() + assembledSize);
Tom Joseph63d3e492017-03-31 11:01:08 +0530152 assembledSize += output.size();
153
154 // Add the IPMI LAN Message Trailer
Vernon Mauery9e801a22018-10-12 13:20:49 -0700155 auto trailer = reinterpret_cast<LAN::trailer::Request*>(
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700156 outMessage->payload.data() + assembledSize);
Tom Joseph63d3e492017-03-31 11:01:08 +0530157
158 // Calculate the checksum for the field rqaddr in the header to the
159 // command data, 3 corresponds to size of the fields before rqaddr( rsaddr,
160 // netfn, cs).
161 trailer->checksum = crc8bit(&respHeader->rqaddr, assembledSize - 3);
162
163 send(outMessage);
164}
165
Vernon Mauery9e801a22018-10-12 13:20:49 -0700166} // namespace message