blob: f5c4a1bbfd26f6c1359011f141c939ec76ebbdff [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
George Liu7b7f25f2022-07-04 17:07:32 +080011#include <phosphor-logging/lg2.hpp>
George Liubc8958f2022-07-04 09:29:49 +080012
13#include <memory>
Tom Josephe6361a22016-08-10 06:56:25 -050014#include <string>
15#include <vector>
16
Tom Josephe6361a22016-08-10 06:56:25 -050017namespace message
18{
19
Vernon Mauery8d6f2002018-11-07 09:55:53 -080020bool Handler::receive()
Tom Josephe6361a22016-08-10 06:56:25 -050021{
22 std::vector<uint8_t> packet;
23 auto readStatus = 0;
24
25 // Read the packet
26 std::tie(readStatus, packet) = channel->read();
27
28 // Read of the packet failed
29 if (readStatus < 0)
30 {
George Liu7b7f25f2022-07-04 17:07:32 +080031 lg2::error("Error in Read status: {STATUS}", "STATUS", readStatus);
Vernon Mauery8d6f2002018-11-07 09:55:53 -080032 return false;
Tom Josephe6361a22016-08-10 06:56:25 -050033 }
34
35 // Unflatten the packet
Vernon Mauery8d6f2002018-11-07 09:55:53 -080036 std::tie(inMessage, sessionHeader) = parser::unflatten(packet);
Tom Josephe6361a22016-08-10 06:56:25 -050037
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +030038 return true;
39}
40
41void Handler::updSessionData(std::shared_ptr<Message>& inMessage)
42{
Lei YU0a4dde42022-07-12 19:42:15 +080043 session = session::Manager::get().getSession(inMessage->bmcSessionID);
Tom Josephe6361a22016-08-10 06:56:25 -050044
Vernon Mauery8d6f2002018-11-07 09:55:53 -080045 sessionID = inMessage->bmcSessionID;
46 inMessage->rcSessionID = session->getRCSessionID();
Tom Josephe6361a22016-08-10 06:56:25 -050047 session->updateLastTransactionTime();
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +053048 session->channelPtr = channel;
49 session->remotePort(channel->getPort());
Rajashekar Gade Reddy9979e992020-02-07 19:18:34 +053050 uint32_t ipAddr = 0;
51 channel->getRemoteAddress(ipAddr);
52 session->remoteIPAddr(ipAddr);
Tom Josephe6361a22016-08-10 06:56:25 -050053}
54
Vernon Mauery8d6f2002018-11-07 09:55:53 -080055Handler::~Handler()
56{
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +030057 try
Vernon Mauery8d6f2002018-11-07 09:55:53 -080058 {
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +030059#ifdef RMCP_PING
60 if (ClassOfMsg::ASF == inMessage->rmcpMsgClass)
Vernon Mauery8d6f2002018-11-07 09:55:53 -080061 {
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +030062 sendASF();
Vernon Mauery8d6f2002018-11-07 09:55:53 -080063 }
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +030064 else
65#endif // RMCP_PING
Vernon Mauery8d6f2002018-11-07 09:55:53 -080066 {
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +030067 if (outPayload)
68 {
69 std::shared_ptr<Message> outMessage =
70 inMessage->createResponse(*outPayload);
71 if (!outMessage)
72 {
73 return;
74 }
75 send(outMessage);
76 }
Vernon Mauery8d6f2002018-11-07 09:55:53 -080077 }
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +030078 }
79 catch (const std::exception& e)
80 {
81 // send failed, most likely due to a session closure
George Liu7b7f25f2022-07-04 17:07:32 +080082 lg2::info("Async RMCP+ reply failed: {ERROR}", "ERROR", e);
Vernon Mauery8d6f2002018-11-07 09:55:53 -080083 }
84}
85
86void Handler::processIncoming()
87{
88 // Read the incoming IPMI packet
89 if (!receive())
90 {
91 return;
92 }
93
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +030094#ifdef RMCP_PING
Vernon Mauery8d6f2002018-11-07 09:55:53 -080095 // Execute the Command, possibly asynchronously
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +030096 if (ClassOfMsg::ASF != inMessage->rmcpMsgClass)
97#endif // RMCP_PING
98 {
99 updSessionData(inMessage);
100 executeCommand();
101 }
Vernon Mauery8d6f2002018-11-07 09:55:53 -0800102
103 // send happens during the destructor if a payload was set
104}
105
106void Handler::executeCommand()
Tom Josephe6361a22016-08-10 06:56:25 -0500107{
108 // Get the CommandID to map into the command table
Vernon Mauery7f268e42018-10-26 10:26:01 -0700109 auto command = inMessage->getCommand();
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700110 if (inMessage->payloadType == PayloadType::IPMI)
Tom Josephe6361a22016-08-10 06:56:25 -0500111 {
Richard Marian Thomaiyar8af90eb2019-03-03 15:13:33 +0530112 // Process PayloadType::IPMI only if ipmi is enabled or for sessionless
113 // or for session establisbment command
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +0530114 if (this->sessionID == session::sessionZero ||
Richard Marian Thomaiyar8af90eb2019-03-03 15:13:33 +0530115 session->sessionUserPrivAccess.ipmiEnabled)
Tom Josephe6361a22016-08-10 06:56:25 -0500116 {
Richard Marian Thomaiyar8af90eb2019-03-03 15:13:33 +0530117 if (inMessage->payload.size() <
118 (sizeof(LAN::header::Request) + sizeof(LAN::trailer::Request)))
119 {
120 return;
121 }
Tom Josephe6361a22016-08-10 06:56:25 -0500122
Patrick Williams099fb092023-05-10 07:50:31 -0500123 auto start = inMessage->payload.begin() +
124 sizeof(LAN::header::Request);
Richard Marian Thomaiyar8af90eb2019-03-03 15:13:33 +0530125 auto end = inMessage->payload.end() - sizeof(LAN::trailer::Request);
126 std::vector<uint8_t> inPayload(start, end);
Vernon Mauery2085ae02021-06-10 11:51:00 -0700127 command::Table::get().executeCommand(command, inPayload,
128 shared_from_this());
Richard Marian Thomaiyar8af90eb2019-03-03 15:13:33 +0530129 }
130 else
131 {
132 std::vector<uint8_t> payload{IPMI_CC_INSUFFICIENT_PRIVILEGE};
133 outPayload = std::move(payload);
134 }
Tom Josephe6361a22016-08-10 06:56:25 -0500135 }
136 else
137 {
Vernon Mauery2085ae02021-06-10 11:51:00 -0700138 command::Table::get().executeCommand(command, inMessage->payload,
139 shared_from_this());
Tom Josephe6361a22016-08-10 06:56:25 -0500140 }
Tom Josephe6361a22016-08-10 06:56:25 -0500141}
142
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +0300143void Handler::writeData(const std::vector<uint8_t>& packet)
144{
145 auto writeStatus = channel->write(packet);
146 if (writeStatus < 0)
147 {
148 throw std::runtime_error("Error in writing to socket");
149 }
150}
151
152#ifdef RMCP_PING
153void Handler::sendASF()
154{
155 // Flatten the packet
156 auto packet = asfparser::flatten(inMessage->asfMsgTag);
157
158 // Write the packet
159 writeData(packet);
160}
161#endif // RMCP_PING
162
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700163void Handler::send(std::shared_ptr<Message> outMessage)
Tom Josephe6361a22016-08-10 06:56:25 -0500164{
Tom Josephe6361a22016-08-10 06:56:25 -0500165 // Flatten the packet
Vernon Mauery224f36a2018-10-25 08:52:23 -0700166 auto packet = parser::flatten(outMessage, sessionHeader, session);
Tom Josephe6361a22016-08-10 06:56:25 -0500167
Tom Joseph04b30382017-04-03 01:06:51 +0530168 // Write the packet
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +0300169 writeData(packet);
Tom Josephe6361a22016-08-10 06:56:25 -0500170}
171
Tom Josephff848492017-03-31 10:43:48 +0530172void Handler::setChannelInSession() const
173{
Tom Josephff848492017-03-31 10:43:48 +0530174 session->channelPtr = channel;
175}
176
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800177void Handler::sendSOLPayload(const std::vector<uint8_t>& input)
Tom Joseph22596f22017-03-31 10:52:27 +0530178{
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700179 auto outMessage = std::make_shared<Message>();
180 outMessage->payloadType = PayloadType::SOL;
181 outMessage->payload = input;
182 outMessage->isPacketEncrypted = session->isCryptAlgoEnabled();
183 outMessage->isPacketAuthenticated = session->isIntegrityAlgoEnabled();
184 outMessage->rcSessionID = session->getRCSessionID();
185 outMessage->bmcSessionID = sessionID;
Tom Joseph22596f22017-03-31 10:52:27 +0530186
187 send(outMessage);
188}
189
Vernon Mauery9e801a22018-10-12 13:20:49 -0700190void Handler::sendUnsolicitedIPMIPayload(uint8_t netfn, uint8_t cmd,
Tom Joseph63d3e492017-03-31 11:01:08 +0530191 const std::vector<uint8_t>& output)
192{
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700193 auto outMessage = std::make_shared<Message>();
194 outMessage->payloadType = PayloadType::IPMI;
195 outMessage->isPacketEncrypted = session->isCryptAlgoEnabled();
196 outMessage->isPacketAuthenticated = session->isIntegrityAlgoEnabled();
197 outMessage->rcSessionID = session->getRCSessionID();
198 outMessage->bmcSessionID = sessionID;
Tom Joseph63d3e492017-03-31 11:01:08 +0530199
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700200 outMessage->payload.resize(sizeof(LAN::header::Request) + output.size() +
201 sizeof(LAN::trailer::Request));
Tom Joseph63d3e492017-03-31 11:01:08 +0530202
Vernon Mauery9e801a22018-10-12 13:20:49 -0700203 auto respHeader =
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700204 reinterpret_cast<LAN::header::Request*>(outMessage->payload.data());
Tom Joseph63d3e492017-03-31 11:01:08 +0530205
206 // Add IPMI LAN Message Request Header
207 respHeader->rsaddr = LAN::requesterBMCAddress;
Vernon Mauery9e801a22018-10-12 13:20:49 -0700208 respHeader->netfn = (netfn << 0x02);
209 respHeader->cs = crc8bit(&(respHeader->rsaddr), 2);
Tom Joseph63d3e492017-03-31 11:01:08 +0530210 respHeader->rqaddr = LAN::responderBMCAddress;
Vernon Mauery9e801a22018-10-12 13:20:49 -0700211 respHeader->rqseq = 0;
212 respHeader->cmd = cmd;
Tom Joseph63d3e492017-03-31 11:01:08 +0530213
214 auto assembledSize = sizeof(LAN::header::Request);
215
216 // Copy the output by the execution of the command
Vernon Mauery9e801a22018-10-12 13:20:49 -0700217 std::copy(output.begin(), output.end(),
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700218 outMessage->payload.begin() + assembledSize);
Tom Joseph63d3e492017-03-31 11:01:08 +0530219 assembledSize += output.size();
220
221 // Add the IPMI LAN Message Trailer
Vernon Mauery9e801a22018-10-12 13:20:49 -0700222 auto trailer = reinterpret_cast<LAN::trailer::Request*>(
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700223 outMessage->payload.data() + assembledSize);
Tom Joseph63d3e492017-03-31 11:01:08 +0530224
225 // Calculate the checksum for the field rqaddr in the header to the
226 // command data, 3 corresponds to size of the fields before rqaddr( rsaddr,
227 // netfn, cs).
228 trailer->checksum = crc8bit(&respHeader->rqaddr, assembledSize - 3);
229
230 send(outMessage);
231}
232
Vernon Mauery9e801a22018-10-12 13:20:49 -0700233} // namespace message