blob: e98955bc9ef76d2276e9cc75341915145c49b360 [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 Mauery9e801a22018-10-12 13:20:49 -070050template <>
Vernon Maueryd999ffc2018-10-25 09:16:05 -070051std::shared_ptr<Message> Handler::createResponse<PayloadType::IPMI>(
52 std::vector<uint8_t>& output, std::shared_ptr<Message> inMessage)
Tom Josephe6361a22016-08-10 06:56:25 -050053{
Vernon Maueryd999ffc2018-10-25 09:16:05 -070054 auto outMessage = std::make_shared<Message>();
Tom Josephe6361a22016-08-10 06:56:25 -050055 outMessage->payloadType = PayloadType::IPMI;
56
Vernon Mauery9e801a22018-10-12 13:20:49 -070057 outMessage->payload.resize(sizeof(LAN::header::Response) + output.size() +
Tom Josephe6361a22016-08-10 06:56:25 -050058 sizeof(LAN::trailer::Response));
59
Vernon Mauery9e801a22018-10-12 13:20:49 -070060 auto reqHeader =
Vernon Maueryd999ffc2018-10-25 09:16:05 -070061 reinterpret_cast<LAN::header::Request*>(inMessage->payload.data());
Vernon Mauery9e801a22018-10-12 13:20:49 -070062 auto respHeader =
63 reinterpret_cast<LAN::header::Response*>(outMessage->payload.data());
Tom Josephe6361a22016-08-10 06:56:25 -050064
65 // Add IPMI LAN Message Response Header
66 respHeader->rqaddr = reqHeader->rqaddr;
Vernon Mauery9e801a22018-10-12 13:20:49 -070067 respHeader->netfn = reqHeader->netfn | 0x04;
68 respHeader->cs = crc8bit(&(respHeader->rqaddr), 2);
Tom Josephe6361a22016-08-10 06:56:25 -050069 respHeader->rsaddr = reqHeader->rsaddr;
Vernon Mauery9e801a22018-10-12 13:20:49 -070070 respHeader->rqseq = reqHeader->rqseq;
71 respHeader->cmd = reqHeader->cmd;
Tom Josephe6361a22016-08-10 06:56:25 -050072
73 auto assembledSize = sizeof(LAN::header::Response);
74
75 // Copy the output by the execution of the command
76 std::copy(output.begin(), output.end(),
77 outMessage->payload.begin() + assembledSize);
78 assembledSize += output.size();
79
80 // Add the IPMI LAN Message Trailer
Vernon Mauery9e801a22018-10-12 13:20:49 -070081 auto trailer = reinterpret_cast<LAN::trailer::Response*>(
82 outMessage->payload.data() + assembledSize);
Tom Josephe6361a22016-08-10 06:56:25 -050083 trailer->checksum = crc8bit(&respHeader->rsaddr, assembledSize - 3);
84
85 return outMessage;
86}
87
Vernon Maueryd999ffc2018-10-25 09:16:05 -070088std::shared_ptr<Message>
89 Handler::executeCommand(std::shared_ptr<Message> inMessage)
Tom Josephe6361a22016-08-10 06:56:25 -050090{
91 // Get the CommandID to map into the command table
92 auto command = getCommand(inMessage);
93 std::vector<uint8_t> output{};
94
Vernon Maueryd999ffc2018-10-25 09:16:05 -070095 if (inMessage->payloadType == PayloadType::IPMI)
Tom Josephe6361a22016-08-10 06:56:25 -050096 {
Vernon Maueryd999ffc2018-10-25 09:16:05 -070097 if (inMessage->payload.size() <
Vernon Mauery9e801a22018-10-12 13:20:49 -070098 (sizeof(LAN::header::Request) + sizeof(LAN::trailer::Request)))
Tom Josephe6361a22016-08-10 06:56:25 -050099 {
100 return nullptr;
101 }
102
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700103 auto start = inMessage->payload.begin() + sizeof(LAN::header::Request);
104 auto end = inMessage->payload.end() - sizeof(LAN::trailer::Request);
Tom Josephe6361a22016-08-10 06:56:25 -0500105 std::vector<uint8_t> inPayload(start, end);
106
Vernon Mauery9e801a22018-10-12 13:20:49 -0700107 output = std::get<command::Table&>(singletonPool)
108 .executeCommand(command, inPayload, *this);
Tom Josephe6361a22016-08-10 06:56:25 -0500109 }
110 else
111 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700112 output = std::get<command::Table&>(singletonPool)
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700113 .executeCommand(command, inMessage->payload, *this);
Tom Josephe6361a22016-08-10 06:56:25 -0500114 }
115
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700116 std::shared_ptr<Message> outMessage = nullptr;
Tom Josephe6361a22016-08-10 06:56:25 -0500117
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700118 switch (inMessage->payloadType)
Tom Josephe6361a22016-08-10 06:56:25 -0500119 {
120 case PayloadType::IPMI:
121 outMessage = createResponse<PayloadType::IPMI>(output, inMessage);
122 break;
123 case PayloadType::OPEN_SESSION_REQUEST:
124 outMessage = createResponse<PayloadType::OPEN_SESSION_RESPONSE>(
Vernon Mauery9e801a22018-10-12 13:20:49 -0700125 output, inMessage);
Tom Josephe6361a22016-08-10 06:56:25 -0500126 break;
127 case PayloadType::RAKP1:
128 outMessage = createResponse<PayloadType::RAKP2>(output, inMessage);
129 break;
130 case PayloadType::RAKP3:
131 outMessage = createResponse<PayloadType::RAKP4>(output, inMessage);
132 break;
Tom Joseph703adbf2017-03-31 10:50:22 +0530133 case PayloadType::SOL:
134 return outMessage;
135 break;
Tom Josephe6361a22016-08-10 06:56:25 -0500136 default:
137 break;
Tom Josephe6361a22016-08-10 06:56:25 -0500138 }
139
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700140 outMessage->isPacketEncrypted = inMessage->isPacketEncrypted;
141 outMessage->isPacketAuthenticated = inMessage->isPacketAuthenticated;
142 outMessage->rcSessionID = inMessage->rcSessionID;
143 outMessage->bmcSessionID = inMessage->bmcSessionID;
Tom Joseph8dfa0f02017-01-10 15:38:20 +0530144
Tom Josephe6361a22016-08-10 06:56:25 -0500145 return outMessage;
146}
147
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700148uint32_t Handler::getCommand(std::shared_ptr<Message> message)
Tom Josephe6361a22016-08-10 06:56:25 -0500149{
Vernon Mauery9e801a22018-10-12 13:20:49 -0700150 uint32_t command = 0;
Tom Josephe6361a22016-08-10 06:56:25 -0500151
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700152 command |= (static_cast<uint8_t>(message->payloadType) << 16);
153 if (message->payloadType == PayloadType::IPMI)
Tom Josephe6361a22016-08-10 06:56:25 -0500154 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700155 command |=
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700156 ((reinterpret_cast<LAN::header::Request*>(message->payload.data()))
Vernon Mauery9e801a22018-10-12 13:20:49 -0700157 ->netfn)
158 << 8;
159 command |=
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700160 (reinterpret_cast<LAN::header::Request*>(message->payload.data()))
Vernon Mauery9e801a22018-10-12 13:20:49 -0700161 ->cmd;
Tom Josephe6361a22016-08-10 06:56:25 -0500162 }
163
164 return command;
165}
166
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700167void Handler::send(std::shared_ptr<Message> outMessage)
Tom Josephe6361a22016-08-10 06:56:25 -0500168{
Vernon Mauery9e801a22018-10-12 13:20:49 -0700169 auto session =
Vernon Maueryae1fda42018-10-15 12:55:34 -0700170 std::get<session::Manager&>(singletonPool).getSession(sessionID);
Tom Josephe6361a22016-08-10 06:56:25 -0500171
172 // Flatten the packet
Vernon Mauery224f36a2018-10-25 08:52:23 -0700173 auto packet = parser::flatten(outMessage, sessionHeader, session);
Tom Josephe6361a22016-08-10 06:56:25 -0500174
Tom Joseph04b30382017-04-03 01:06:51 +0530175 // Write the packet
Tom Josephe6361a22016-08-10 06:56:25 -0500176 auto writeStatus = channel->write(packet);
177 if (writeStatus < 0)
178 {
Tom Joseph04b30382017-04-03 01:06:51 +0530179 throw std::runtime_error("Error in writing to socket");
Tom Josephe6361a22016-08-10 06:56:25 -0500180 }
Tom Josephe6361a22016-08-10 06:56:25 -0500181}
182
Tom Josephff848492017-03-31 10:43:48 +0530183void Handler::setChannelInSession() const
184{
Vernon Mauery9e801a22018-10-12 13:20:49 -0700185 auto session =
Vernon Maueryae1fda42018-10-15 12:55:34 -0700186 std::get<session::Manager&>(singletonPool).getSession(sessionID);
Tom Josephff848492017-03-31 10:43:48 +0530187
188 session->channelPtr = channel;
189}
190
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800191void Handler::sendSOLPayload(const std::vector<uint8_t>& input)
Tom Joseph22596f22017-03-31 10:52:27 +0530192{
Vernon Mauery9e801a22018-10-12 13:20:49 -0700193 auto session =
Vernon Maueryae1fda42018-10-15 12:55:34 -0700194 std::get<session::Manager&>(singletonPool).getSession(sessionID);
Tom Joseph22596f22017-03-31 10:52:27 +0530195
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700196 auto outMessage = std::make_shared<Message>();
197 outMessage->payloadType = PayloadType::SOL;
198 outMessage->payload = input;
199 outMessage->isPacketEncrypted = session->isCryptAlgoEnabled();
200 outMessage->isPacketAuthenticated = session->isIntegrityAlgoEnabled();
201 outMessage->rcSessionID = session->getRCSessionID();
202 outMessage->bmcSessionID = sessionID;
Tom Joseph22596f22017-03-31 10:52:27 +0530203
204 send(outMessage);
205}
206
Vernon Mauery9e801a22018-10-12 13:20:49 -0700207void Handler::sendUnsolicitedIPMIPayload(uint8_t netfn, uint8_t cmd,
Tom Joseph63d3e492017-03-31 11:01:08 +0530208 const std::vector<uint8_t>& output)
209{
Vernon Mauery9e801a22018-10-12 13:20:49 -0700210 auto session =
Vernon Maueryae1fda42018-10-15 12:55:34 -0700211 std::get<session::Manager&>(singletonPool).getSession(sessionID);
Tom Joseph63d3e492017-03-31 11:01:08 +0530212
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700213 auto outMessage = std::make_shared<Message>();
214 outMessage->payloadType = PayloadType::IPMI;
215 outMessage->isPacketEncrypted = session->isCryptAlgoEnabled();
216 outMessage->isPacketAuthenticated = session->isIntegrityAlgoEnabled();
217 outMessage->rcSessionID = session->getRCSessionID();
218 outMessage->bmcSessionID = sessionID;
Tom Joseph63d3e492017-03-31 11:01:08 +0530219
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700220 outMessage->payload.resize(sizeof(LAN::header::Request) + output.size() +
221 sizeof(LAN::trailer::Request));
Tom Joseph63d3e492017-03-31 11:01:08 +0530222
Vernon Mauery9e801a22018-10-12 13:20:49 -0700223 auto respHeader =
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700224 reinterpret_cast<LAN::header::Request*>(outMessage->payload.data());
Tom Joseph63d3e492017-03-31 11:01:08 +0530225
226 // Add IPMI LAN Message Request Header
227 respHeader->rsaddr = LAN::requesterBMCAddress;
Vernon Mauery9e801a22018-10-12 13:20:49 -0700228 respHeader->netfn = (netfn << 0x02);
229 respHeader->cs = crc8bit(&(respHeader->rsaddr), 2);
Tom Joseph63d3e492017-03-31 11:01:08 +0530230 respHeader->rqaddr = LAN::responderBMCAddress;
Vernon Mauery9e801a22018-10-12 13:20:49 -0700231 respHeader->rqseq = 0;
232 respHeader->cmd = cmd;
Tom Joseph63d3e492017-03-31 11:01:08 +0530233
234 auto assembledSize = sizeof(LAN::header::Request);
235
236 // Copy the output by the execution of the command
Vernon Mauery9e801a22018-10-12 13:20:49 -0700237 std::copy(output.begin(), output.end(),
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700238 outMessage->payload.begin() + assembledSize);
Tom Joseph63d3e492017-03-31 11:01:08 +0530239 assembledSize += output.size();
240
241 // Add the IPMI LAN Message Trailer
Vernon Mauery9e801a22018-10-12 13:20:49 -0700242 auto trailer = reinterpret_cast<LAN::trailer::Request*>(
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700243 outMessage->payload.data() + assembledSize);
Tom Joseph63d3e492017-03-31 11:01:08 +0530244
245 // Calculate the checksum for the field rqaddr in the header to the
246 // command data, 3 corresponds to size of the fields before rqaddr( rsaddr,
247 // netfn, cs).
248 trailer->checksum = crc8bit(&respHeader->rqaddr, assembledSize - 3);
249
250 send(outMessage);
251}
252
Vernon Mauery9e801a22018-10-12 13:20:49 -0700253} // namespace message