blob: 18f83894c11bf4db7e349d01031230d323a0445b [file] [log] [blame]
Tom Joseph4e57ada2016-08-10 06:51:12 -05001#include "message_parsers.hpp"
2
Tom Joseph4e57ada2016-08-10 06:51:12 -05003#include "endian.hpp"
4#include "main.hpp"
5#include "message.hpp"
6#include "sessions_manager.hpp"
7
Vernon Mauery9e801a22018-10-12 13:20:49 -07008#include <memory>
9
Tom Joseph4e57ada2016-08-10 06:51:12 -050010namespace message
11{
12
13namespace parser
14{
15
Vernon Maueryd999ffc2018-10-25 09:16:05 -070016std::tuple<std::shared_ptr<Message>, SessionHeader>
Vernon Mauery9e801a22018-10-12 13:20:49 -070017 unflatten(std::vector<uint8_t>& inPacket)
Tom Joseph4e57ada2016-08-10 06:51:12 -050018{
19 // Check if the packet has atleast the size of the RMCP Header
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +030020 if (inPacket.size() < sizeof(RmcpHeader_t))
Tom Joseph4e57ada2016-08-10 06:51:12 -050021 {
22 throw std::runtime_error("RMCP Header missing");
23 }
24
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +030025 auto rmcpHeaderPtr = reinterpret_cast<RmcpHeader_t*>(inPacket.data());
Tom Joseph4e57ada2016-08-10 06:51:12 -050026
27 // Verify if the fields in the RMCP header conforms to the specification
28 if ((rmcpHeaderPtr->version != RMCP_VERSION) ||
29 (rmcpHeaderPtr->rmcpSeqNum != RMCP_SEQ) ||
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +030030 (rmcpHeaderPtr->classOfMsg < static_cast<uint8_t>(ClassOfMsg::ASF) &&
31 rmcpHeaderPtr->classOfMsg > static_cast<uint8_t>(ClassOfMsg::OEM)))
Tom Joseph4e57ada2016-08-10 06:51:12 -050032 {
33 throw std::runtime_error("RMCP Header is invalid");
34 }
35
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +030036 if (rmcpHeaderPtr->classOfMsg == static_cast<uint8_t>(ClassOfMsg::ASF))
37 {
38#ifndef RMCP_PING
39 throw std::runtime_error("RMCP Ping is not supported");
40#else
41 return std::make_tuple(asfparser::unflatten(inPacket),
42 SessionHeader::IPMI15);
43#endif // RMCP_PING
44 }
45
46 auto sessionHeaderPtr = reinterpret_cast<BasicHeader_t*>(inPacket.data());
47
Tom Joseph4e57ada2016-08-10 06:51:12 -050048 // Read the Session Header and invoke the parser corresponding to the
49 // header type
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +030050 switch (static_cast<SessionHeader>(sessionHeaderPtr->format.formatType))
Tom Joseph4e57ada2016-08-10 06:51:12 -050051 {
52 case SessionHeader::IPMI15:
53 {
54 return std::make_tuple(ipmi15parser::unflatten(inPacket),
55 SessionHeader::IPMI15);
56 }
57 case SessionHeader::IPMI20:
58 {
59 return std::make_tuple(ipmi20parser::unflatten(inPacket),
60 SessionHeader::IPMI20);
61 }
62 default:
63 {
64 throw std::runtime_error("Invalid Session Header");
65 }
66 }
67}
68
Vernon Maueryd999ffc2018-10-25 09:16:05 -070069std::vector<uint8_t> flatten(std::shared_ptr<Message> outMessage,
Vernon Mauery224f36a2018-10-25 08:52:23 -070070 SessionHeader authType,
71 std::shared_ptr<session::Session> session)
Tom Joseph4e57ada2016-08-10 06:51:12 -050072{
73 // Call the flatten routine based on the header type
74 switch (authType)
75 {
76 case SessionHeader::IPMI15:
77 {
78 return ipmi15parser::flatten(outMessage, session);
79 }
80 case SessionHeader::IPMI20:
81 {
82 return ipmi20parser::flatten(outMessage, session);
83 }
84 default:
85 {
86 return {};
87 }
88 }
89}
90
91} // namespace parser
92
93namespace ipmi15parser
94{
95
Vernon Maueryd999ffc2018-10-25 09:16:05 -070096std::shared_ptr<Message> unflatten(std::vector<uint8_t>& inPacket)
Tom Joseph4e57ada2016-08-10 06:51:12 -050097{
Tom Joseph4e57ada2016-08-10 06:51:12 -050098 if (inPacket.size() < sizeof(SessionHeader_t))
99 {
100 throw std::runtime_error("IPMI1.5 Session Header Missing");
101 }
102
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700103 auto message = std::make_shared<Message>();
Tom Joseph4e57ada2016-08-10 06:51:12 -0500104
105 auto header = reinterpret_cast<SessionHeader_t*>(inPacket.data());
106
107 message->payloadType = PayloadType::IPMI;
Tom Joseph6a560762017-01-10 15:30:28 +0530108 message->bmcSessionID = endian::from_ipmi(header->sessId);
109 message->sessionSeqNum = endian::from_ipmi(header->sessSeqNum);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500110 message->isPacketEncrypted = false;
111 message->isPacketAuthenticated = false;
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +0300112 message->rmcpMsgClass =
113 static_cast<ClassOfMsg>(header->base.rmcp.classOfMsg);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500114
115 auto payloadLen = header->payloadLength;
116
Zhikui Ren2b1edef2020-07-24 14:32:13 -0700117 // Confirm the number of data bytes received correlates to
118 // the packet length in the header
119 if (inPacket.size() < (sizeof(SessionHeader_t) + payloadLen))
120 {
121 throw std::runtime_error("Invalid data length");
122 }
123
Vernon Mauery9e801a22018-10-12 13:20:49 -0700124 (message->payload)
125 .assign(inPacket.data() + sizeof(SessionHeader_t),
126 inPacket.data() + sizeof(SessionHeader_t) + payloadLen);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500127
128 return message;
129}
130
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700131std::vector<uint8_t> flatten(std::shared_ptr<Message> outMessage,
Vernon Mauery224f36a2018-10-25 08:52:23 -0700132 std::shared_ptr<session::Session> session)
Tom Joseph4e57ada2016-08-10 06:51:12 -0500133{
134 std::vector<uint8_t> packet(sizeof(SessionHeader_t));
135
136 // Insert Session Header into the Packet
137 auto header = reinterpret_cast<SessionHeader_t*>(packet.data());
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +0300138 header->base.rmcp.version = parser::RMCP_VERSION;
139 header->base.rmcp.reserved = 0x00;
140 header->base.rmcp.rmcpSeqNum = parser::RMCP_SEQ;
141 header->base.rmcp.classOfMsg = static_cast<uint8_t>(ClassOfMsg::IPMI);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500142 header->base.format.formatType =
143 static_cast<uint8_t>(parser::SessionHeader::IPMI15);
144 header->sessSeqNum = 0;
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700145 header->sessId = endian::to_ipmi(outMessage->rcSessionID);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500146
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700147 header->payloadLength = static_cast<uint8_t>(outMessage->payload.size());
Tom Joseph4e57ada2016-08-10 06:51:12 -0500148
149 // Insert the Payload into the Packet
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700150 packet.insert(packet.end(), outMessage->payload.begin(),
151 outMessage->payload.end());
Tom Joseph4e57ada2016-08-10 06:51:12 -0500152
153 // Insert the Session Trailer
154 packet.resize(packet.size() + sizeof(SessionTrailer_t));
Vernon Mauery9e801a22018-10-12 13:20:49 -0700155 auto trailer =
156 reinterpret_cast<SessionTrailer_t*>(packet.data() + packet.size());
Tom Joseph4e57ada2016-08-10 06:51:12 -0500157 trailer->legacyPad = 0x00;
158
159 return packet;
160}
161
162} // namespace ipmi15parser
163
164namespace ipmi20parser
165{
166
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700167std::shared_ptr<Message> unflatten(std::vector<uint8_t>& inPacket)
Tom Joseph4e57ada2016-08-10 06:51:12 -0500168{
169 // Check if the packet has atleast the Session Header
170 if (inPacket.size() < sizeof(SessionHeader_t))
171 {
172 throw std::runtime_error("IPMI2.0 Session Header Missing");
173 }
174
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700175 auto message = std::make_shared<Message>();
Tom Joseph4e57ada2016-08-10 06:51:12 -0500176
177 auto header = reinterpret_cast<SessionHeader_t*>(inPacket.data());
178
Vernon Mauery9e801a22018-10-12 13:20:49 -0700179 message->payloadType = static_cast<PayloadType>(header->payloadType & 0x3F);
Tom Joseph6a560762017-01-10 15:30:28 +0530180 message->bmcSessionID = endian::from_ipmi(header->sessId);
181 message->sessionSeqNum = endian::from_ipmi(header->sessSeqNum);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500182 message->isPacketEncrypted =
183 ((header->payloadType & PAYLOAD_ENCRYPT_MASK) ? true : false);
184 message->isPacketAuthenticated =
185 ((header->payloadType & PAYLOAD_AUTH_MASK) ? true : false);
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +0300186 message->rmcpMsgClass =
187 static_cast<ClassOfMsg>(header->base.rmcp.classOfMsg);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500188
Tom Joseph6a560762017-01-10 15:30:28 +0530189 auto payloadLen = endian::from_ipmi(header->payloadLength);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500190
Tom Joseph5fa487c2017-01-20 12:42:39 +0530191 if (message->isPacketAuthenticated)
Tom Joseph64703f42017-01-10 17:03:48 +0530192 {
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700193 if (!(internal::verifyPacketIntegrity(inPacket, message, payloadLen)))
Tom Joseph64703f42017-01-10 17:03:48 +0530194 {
195 throw std::runtime_error("Packet Integrity check failed");
196 }
197 }
198
Tom Joseph78478a82017-01-26 14:24:29 +0530199 // Decrypt the payload if the payload is encrypted
200 if (message->isPacketEncrypted)
201 {
202 // Assign the decrypted payload to the IPMI Message
Vernon Mauery9e801a22018-10-12 13:20:49 -0700203 message->payload =
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700204 internal::decryptPayload(inPacket, message, payloadLen);
Tom Joseph78478a82017-01-26 14:24:29 +0530205 }
206 else
207 {
208 message->payload.assign(inPacket.begin() + sizeof(SessionHeader_t),
209 inPacket.begin() + sizeof(SessionHeader_t) +
Vernon Mauery9e801a22018-10-12 13:20:49 -0700210 payloadLen);
Tom Joseph78478a82017-01-26 14:24:29 +0530211 }
212
Tom Joseph4e57ada2016-08-10 06:51:12 -0500213 return message;
214}
215
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700216std::vector<uint8_t> flatten(std::shared_ptr<Message> outMessage,
Vernon Mauery224f36a2018-10-25 08:52:23 -0700217 std::shared_ptr<session::Session> session)
Tom Joseph4e57ada2016-08-10 06:51:12 -0500218{
219 std::vector<uint8_t> packet(sizeof(SessionHeader_t));
220
221 SessionHeader_t* header = reinterpret_cast<SessionHeader_t*>(packet.data());
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +0300222 header->base.rmcp.version = parser::RMCP_VERSION;
223 header->base.rmcp.reserved = 0x00;
224 header->base.rmcp.rmcpSeqNum = parser::RMCP_SEQ;
225 header->base.rmcp.classOfMsg = static_cast<uint8_t>(ClassOfMsg::IPMI);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500226 header->base.format.formatType =
227 static_cast<uint8_t>(parser::SessionHeader::IPMI20);
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700228 header->payloadType = static_cast<uint8_t>(outMessage->payloadType);
229 header->sessId = endian::to_ipmi(outMessage->rcSessionID);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500230
231 // Add session sequence number
232 internal::addSequenceNumber(packet, session);
233
Tom Joseph1404bca2017-01-26 14:17:02 +0530234 size_t payloadLen = 0;
235
Tom Joseph75362832017-01-26 15:17:04 +0530236 // Encrypt the payload if needed
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700237 if (outMessage->isPacketEncrypted)
Tom Joseph75362832017-01-26 15:17:04 +0530238 {
239 header->payloadType |= PAYLOAD_ENCRYPT_MASK;
240 auto cipherPayload = internal::encryptPayload(outMessage);
241 payloadLen = cipherPayload.size();
242 header->payloadLength = endian::to_ipmi<uint16_t>(cipherPayload.size());
243
244 // Insert the encrypted payload into the outgoing IPMI packet
245 packet.insert(packet.end(), cipherPayload.begin(), cipherPayload.end());
246 }
247 else
248 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700249 header->payloadLength =
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700250 endian::to_ipmi<uint16_t>(outMessage->payload.size());
251 payloadLen = outMessage->payload.size();
Tom Joseph75362832017-01-26 15:17:04 +0530252
253 // Insert the Payload into the Packet
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700254 packet.insert(packet.end(), outMessage->payload.begin(),
255 outMessage->payload.end());
Tom Joseph75362832017-01-26 15:17:04 +0530256 }
Tom Joseph4e57ada2016-08-10 06:51:12 -0500257
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700258 if (outMessage->isPacketAuthenticated)
Tom Joseph64703f42017-01-10 17:03:48 +0530259 {
Tom Josephb882dbb2019-02-09 23:13:48 +0530260 header = reinterpret_cast<SessionHeader_t*>(packet.data());
261 header->payloadType |= PAYLOAD_AUTH_MASK;
Tom Joseph1404bca2017-01-26 14:17:02 +0530262 internal::addIntegrityData(packet, outMessage, payloadLen);
Tom Joseph64703f42017-01-10 17:03:48 +0530263 }
264
Tom Joseph4e57ada2016-08-10 06:51:12 -0500265 return packet;
266}
267
268namespace internal
269{
270
Vernon Mauery224f36a2018-10-25 08:52:23 -0700271void addSequenceNumber(std::vector<uint8_t>& packet,
272 std::shared_ptr<session::Session> session)
Tom Joseph4e57ada2016-08-10 06:51:12 -0500273{
274 SessionHeader_t* header = reinterpret_cast<SessionHeader_t*>(packet.data());
275
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +0530276 if (header->sessId == session::sessionZero)
Tom Joseph4e57ada2016-08-10 06:51:12 -0500277 {
278 header->sessSeqNum = 0x00;
279 }
280 else
281 {
Vernon Mauery224f36a2018-10-25 08:52:23 -0700282 auto seqNum = session->sequenceNums.increment();
Tom Joseph6a560762017-01-10 15:30:28 +0530283 header->sessSeqNum = endian::to_ipmi(seqNum);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500284 }
285}
286
Tom Joseph64703f42017-01-10 17:03:48 +0530287bool verifyPacketIntegrity(const std::vector<uint8_t>& packet,
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700288 const std::shared_ptr<Message> message,
289 size_t payloadLen)
Tom Joseph64703f42017-01-10 17:03:48 +0530290{
Tom Joseph64703f42017-01-10 17:03:48 +0530291 /*
292 * Padding bytes are added to cause the number of bytes in the data range
293 * covered by the AuthCode(Integrity Data) field to be a multiple of 4 bytes
294 * .If present each integrity Pad byte is set to FFh. The following logic
295 * calculates the number of padding bytes added in the IPMI packet.
296 */
Tom Joseph5a2d3ce2017-02-01 20:18:37 +0530297 auto paddingLen = 4 - ((payloadLen + 2) & 3);
Tom Joseph64703f42017-01-10 17:03:48 +0530298
299 auto sessTrailerPos = sizeof(SessionHeader_t) + payloadLen + paddingLen;
300
Zhikui Ren2b1edef2020-07-24 14:32:13 -0700301 // verify packet size includes trailer struct starts at sessTrailerPos
302 if (packet.size() < (sessTrailerPos + sizeof(SessionTrailer_t)))
303 {
304 return false;
305 }
306
Vernon Mauery9e801a22018-10-12 13:20:49 -0700307 auto trailer = reinterpret_cast<const SessionTrailer_t*>(packet.data() +
308 sessTrailerPos);
Tom Joseph64703f42017-01-10 17:03:48 +0530309
310 // Check trailer->padLength against paddingLen, both should match up,
311 // return false if the lengths don't match
Tom Joseph5fa487c2017-01-20 12:42:39 +0530312 if (trailer->padLength != paddingLen)
Tom Joseph64703f42017-01-10 17:03:48 +0530313 {
314 return false;
315 }
316
Vernon Maueryae1fda42018-10-15 12:55:34 -0700317 auto session = std::get<session::Manager&>(singletonPool)
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700318 .getSession(message->bmcSessionID);
Tom Joseph64703f42017-01-10 17:03:48 +0530319
320 auto integrityAlgo = session->getIntegrityAlgo();
321
322 // Check if Integrity data length is as expected, check integrity data
323 // length is same as the length expected for the Integrity Algorithm that
324 // was negotiated during the session open process.
Tom Joseph5fa487c2017-01-20 12:42:39 +0530325 if ((packet.size() - sessTrailerPos - sizeof(SessionTrailer_t)) !=
Vernon Mauery9e801a22018-10-12 13:20:49 -0700326 integrityAlgo->authCodeLength)
Tom Joseph64703f42017-01-10 17:03:48 +0530327 {
328 return false;
329 }
330
331 auto integrityIter = packet.cbegin();
332 std::advance(integrityIter, sessTrailerPos + sizeof(SessionTrailer_t));
333
334 // The integrity data is calculated from the AuthType/Format field up to and
335 // including the field that immediately precedes the AuthCode field itself.
336 size_t length = packet.size() - integrityAlgo->authCodeLength -
337 message::parser::RMCP_SESSION_HEADER_SIZE;
338
339 return integrityAlgo->verifyIntegrityData(packet, length, integrityIter);
340}
341
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700342void addIntegrityData(std::vector<uint8_t>& packet,
343 const std::shared_ptr<Message> message, size_t payloadLen)
Tom Joseph64703f42017-01-10 17:03:48 +0530344{
Tom Joseph64703f42017-01-10 17:03:48 +0530345 // The following logic calculates the number of padding bytes to be added to
346 // IPMI packet. If needed each integrity Pad byte is set to FFh.
Tom Joseph5a2d3ce2017-02-01 20:18:37 +0530347 auto paddingLen = 4 - ((payloadLen + 2) & 3);
Tom Joseph64703f42017-01-10 17:03:48 +0530348 packet.insert(packet.end(), paddingLen, 0xFF);
349
350 packet.resize(packet.size() + sizeof(SessionTrailer_t));
351
Vernon Mauery9e801a22018-10-12 13:20:49 -0700352 auto trailer = reinterpret_cast<SessionTrailer_t*>(
353 packet.data() + packet.size() - sizeof(SessionTrailer_t));
Tom Joseph64703f42017-01-10 17:03:48 +0530354
355 trailer->padLength = paddingLen;
356 trailer->nextHeader = parser::RMCP_MESSAGE_CLASS_IPMI;
357
Vernon Maueryae1fda42018-10-15 12:55:34 -0700358 auto session = std::get<session::Manager&>(singletonPool)
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700359 .getSession(message->bmcSessionID);
Tom Joseph64703f42017-01-10 17:03:48 +0530360
Vernon Mauery9e801a22018-10-12 13:20:49 -0700361 auto integrityData =
362 session->getIntegrityAlgo()->generateIntegrityData(packet);
Tom Joseph64703f42017-01-10 17:03:48 +0530363
364 packet.insert(packet.end(), integrityData.begin(), integrityData.end());
365}
366
Tom Joseph78478a82017-01-26 14:24:29 +0530367std::vector<uint8_t> decryptPayload(const std::vector<uint8_t>& packet,
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700368 const std::shared_ptr<Message> message,
369 size_t payloadLen)
Tom Joseph78478a82017-01-26 14:24:29 +0530370{
Vernon Maueryae1fda42018-10-15 12:55:34 -0700371 auto session = std::get<session::Manager&>(singletonPool)
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700372 .getSession(message->bmcSessionID);
Tom Joseph78478a82017-01-26 14:24:29 +0530373
Vernon Mauery9e801a22018-10-12 13:20:49 -0700374 return session->getCryptAlgo()->decryptPayload(
375 packet, sizeof(SessionHeader_t), payloadLen);
Tom Joseph78478a82017-01-26 14:24:29 +0530376}
377
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700378std::vector<uint8_t> encryptPayload(std::shared_ptr<Message> message)
Tom Joseph75362832017-01-26 15:17:04 +0530379{
Vernon Maueryae1fda42018-10-15 12:55:34 -0700380 auto session = std::get<session::Manager&>(singletonPool)
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700381 .getSession(message->bmcSessionID);
Tom Joseph75362832017-01-26 15:17:04 +0530382
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700383 return session->getCryptAlgo()->encryptPayload(message->payload);
Tom Joseph75362832017-01-26 15:17:04 +0530384}
385
Tom Joseph4e57ada2016-08-10 06:51:12 -0500386} // namespace internal
387
388} // namespace ipmi20parser
389
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +0300390#ifdef RMCP_PING
391namespace asfparser
392{
393std::shared_ptr<Message> unflatten(std::vector<uint8_t>& inPacket)
394{
395 auto message = std::make_shared<Message>();
396
397 auto header = reinterpret_cast<AsfMessagePing_t*>(inPacket.data());
398
399 message->payloadType = PayloadType::IPMI;
400 message->rmcpMsgClass = ClassOfMsg::ASF;
401 message->asfMsgTag = header->msgTag;
402
403 return message;
404}
405
406std::vector<uint8_t> flatten(uint8_t asfMsgTag)
407{
408 std::vector<uint8_t> packet(sizeof(AsfMessagePong_t));
409
410 // Insert RMCP header into the Packet
411 auto header = reinterpret_cast<AsfMessagePong_t*>(packet.data());
412 header->ping.rmcp.version = parser::RMCP_VERSION;
413 header->ping.rmcp.reserved = 0x00;
414 header->ping.rmcp.rmcpSeqNum = parser::RMCP_SEQ;
415 header->ping.rmcp.classOfMsg = static_cast<uint8_t>(ClassOfMsg::ASF);
416
417 // No OEM-specific capabilities exist, therefore the second
418 // IANA Enterprise Number contains the same IANA(4542)
419 header->ping.iana = header->iana = endian::to_ipmi(parser::ASF_IANA);
420 header->ping.msgType = static_cast<uint8_t>(RmcpMsgType::PONG);
421 header->ping.msgTag = asfMsgTag;
422 header->ping.reserved = 0x00;
423 header->ping.dataLen =
424 parser::RMCP_ASF_PONG_DATA_LEN; // as per spec 13.2.4,
425
426 header->iana = parser::ASF_IANA;
427 header->oemDefined = 0x00;
428 header->suppEntities = parser::ASF_SUPP_ENT;
429 header->suppInteract = parser::ASF_SUPP_INT;
430 header->reserved1 = 0x00;
431 header->reserved2 = 0x00;
432
433 return packet;
434}
435
436} // namespace asfparser
437#endif // RMCP_PING
438
Tom Joseph4e57ada2016-08-10 06:51:12 -0500439} // namespace message