Message parser for parsing IPMI message
IPMI message parser is responsible for parsing IPMI messages. There is
parser for IPMI 1.5 messages and IPMI 2.0 messages.
Change-Id: I24ebb6907abb56bcc25297eee75c06e6cde8355b
Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
diff --git a/message_parsers.hpp b/message_parsers.hpp
new file mode 100644
index 0000000..49a0c5d
--- /dev/null
+++ b/message_parsers.hpp
@@ -0,0 +1,178 @@
+#pragma once
+
+#include "message.hpp"
+#include "session.hpp"
+
+namespace message
+{
+
+namespace parser
+{
+
+constexpr size_t RMCP_VERSION = 6;
+
+// RMCP Messages with class=IPMI should be sent with an RMCP Sequence
+// Number of FFh to indicate that an RMCP ACK message should not be
+// generated by the message receiver.
+constexpr size_t RMCP_SEQ = 0xFF;
+
+// RMCP Message Class 7h is for IPMI
+constexpr size_t RMCP_MESSAGE_CLASS_IPMI = 7;
+
+// Maximum packet size that we'll handle
+constexpr uint32_t MESSAGE_MAX_PACKET_LENGTH = 512;
+
+enum class SessionHeader
+{
+ IPMI15 = 0x00,
+ IPMI20 = 0x06,
+ INVALID = 0xFF,
+};
+
+struct BasicHeader_t
+{
+ // RMCP Header
+ uint8_t version;
+ uint8_t reserved;
+ uint8_t rmcpSeqNum;
+ uint8_t classOfMsg;
+
+ // IPMI partial session header
+ union
+ {
+ uint8_t reserved1: 4;
+ uint8_t authType: 4;
+ uint8_t formatType;
+ } format;
+} __attribute__((packed));
+
+/*
+ * @brief Unflatten an incoming packet and prepare the IPMI message
+ *
+ * @param[in] inPacket - Incoming IPMI packet
+ *
+ * @return A tuple with IPMI message and the session header type to sent the
+ * response packet. In case of success incoming message and session
+ * header type. In case of failure nullptr and session header type
+ * would be invalid.
+ */
+std::tuple<std::unique_ptr<Message>, SessionHeader> unflatten(
+ std::vector<uint8_t>& inPacket);
+
+/*
+ * @brief Flatten an IPMI message and generate the IPMI packet with the
+ * session header
+ *
+ * @param[in] outMessage - IPMI message to be flattened
+ * @param[in] authType - Session header type to be added to the IPMI
+ * packet
+ *
+ * @return IPMI packet on success
+ */
+std::vector<uint8_t> flatten(Message& outMessage,
+ SessionHeader authType,
+ session::Session& session);
+
+} // namespace parser
+
+namespace ipmi15parser
+{
+
+struct SessionHeader_t
+{
+ struct parser::BasicHeader_t base;
+ uint32_t sessSeqNum;
+ uint32_t sessId;
+ // <Optional Field: AuthCode>
+ uint8_t payloadLength;
+} __attribute__((packed));
+
+struct SessionTrailer_t
+{
+ uint8_t legacyPad;
+} __attribute__((packed));
+
+/*
+ * @brief Unflatten an incoming packet and prepare the IPMI message
+ *
+ * @param[in] inPacket - Incoming IPMI packet
+ *
+ * @return IPMI message in the packet on success
+ */
+std::unique_ptr<Message> unflatten(std::vector<uint8_t>& inPacket);
+
+/*
+ * @brief Flatten an IPMI message and generate the IPMI packet with the
+ * session header
+ *
+ * @param[in] outMessage - IPMI message to be flattened
+ *
+ * @return IPMI packet on success
+ */
+std::vector<uint8_t> flatten(Message& outMessage, session::Session& session);
+
+} // namespace ipmi15parser
+
+namespace ipmi20parser
+{
+
+constexpr size_t MAX_INTEGRITY_DATA_LENGTH = 12;
+constexpr size_t PAYLOAD_ENCRYPT_MASK = 0x80;
+constexpr size_t PAYLOAD_AUTH_MASK = 0x40;
+
+struct SessionHeader_t
+{
+ struct parser::BasicHeader_t base;
+
+ uint8_t payloadType;
+
+ uint32_t sessId;
+ uint32_t sessSeqNum;
+ uint16_t payloadLength;
+} __attribute__((packed));
+
+struct SessionTrailer_t
+{
+ // Integrity Pad
+ uint8_t padLength;
+ uint8_t nextHeader;
+ // AuthCode (Integrity Data)
+ uint8_t authCode[MAX_INTEGRITY_DATA_LENGTH];
+} __attribute__((packed));
+
+/*
+ * @brief Unflatten an incoming packet and prepare the IPMI message
+ *
+ * @param[in] inPacket - Incoming IPMI packet
+ *
+ * @return IPMI message in the packet on success
+ */
+std::unique_ptr<Message> unflatten(std::vector<uint8_t>& inPacket);
+
+/*
+ * @brief Flatten an IPMI message and generate the IPMI packet with the
+ * session header
+ *
+ * @param[in] outMessage - IPMI message to be flattened
+ *
+ * @return IPMI packet on success
+ */
+std::vector<uint8_t> flatten(Message& outMessage, session::Session& session);
+
+namespace internal
+{
+
+/*
+ * @brief Add sequence number to the message
+ *
+ * @param[in] packet - outgoing packet to which to add sequence number
+ * @param[in] session - session handle
+ *
+ */
+void addSequenceNumber(std::vector<uint8_t>& packet, session::Session& session);
+
+} // namespace internal
+
+} // namespace ipmi20parser
+
+} // namespace message