in core/mctp/mctp_base_protocol.c [38:111]
int mctp_base_protocol_interpret (const uint8_t *buf, size_t buf_len, uint8_t dest_addr,
uint8_t *source_addr, bool *som, bool *eom, uint8_t *src_eid, uint8_t *dest_eid,
const uint8_t **payload, size_t *payload_len, uint8_t *msg_tag, uint8_t *packet_seq,
uint8_t *crc, uint8_t *msg_type, uint8_t *tag_owner)
{
const struct mctp_base_protocol_transport_header *header =
(const struct mctp_base_protocol_transport_header*) buf;
size_t packet_len;
if ((buf == NULL) || (source_addr == NULL) || (som == NULL) || (eom == NULL) ||
(src_eid == NULL) || (dest_eid == NULL) || (payload == NULL) || (payload_len == NULL) ||
(msg_tag == NULL) || (packet_seq == NULL) || (crc == NULL) || (msg_type == NULL) ||
(tag_owner == NULL)) {
return MCTP_BASE_PROTOCOL_INVALID_ARGUMENT;
}
if (buf_len < sizeof (struct mctp_base_protocol_transport_header)) {
return MCTP_BASE_PROTOCOL_PKT_TOO_SHORT;
}
/* There at least exists a transport header, so parse out those details. */
*source_addr = (header->source_addr >> 1);
*dest_eid = header->destination_eid;
*src_eid = header->source_eid;
*som = header->som;
*eom = header->eom;
*packet_seq = header->packet_seq;
*msg_tag = header->msg_tag;
*tag_owner = header->tag_owner;
/* Check that the packet is well formed. */
if ((header->cmd_code != SMBUS_CMD_CODE_MCTP) || (header->rsvd != 0) ||
(header->header_version != MCTP_BASE_PROTOCOL_SUPPORTED_HDR_VERSION) ||
(header->destination_eid == header->source_eid)) {
return MCTP_BASE_PROTOCOL_INVALID_PKT;
}
/* While MCTP requires that all packets contain the optional PEC byte, not all implementations
* follow this requirement, so treat the PEC as optional. The PEC byte will be checked if it's
* present, but parsing will not fail if it's not present. */
packet_len = header->byte_count + MCTP_BASE_PROTOCOL_SMBUS_OVERHEAD_NO_PEC;
/* A packet must contain a payload, so one that only contains a header is invalid. This check
* ensures there is at least one byte of payload. */
if (packet_len <= sizeof (struct mctp_base_protocol_transport_header)) {
return MCTP_BASE_PROTOCOL_PKT_TOO_SHORT;
}
/* Confirm that the packet length does not overflow the buffer containing the packet. */
if (buf_len < packet_len) {
return MCTP_BASE_PROTOCOL_PKT_LENGTH_MISMATCH;
}
*payload = &buf[sizeof (struct mctp_base_protocol_transport_header)];
*payload_len = packet_len - sizeof (struct mctp_base_protocol_transport_header);
if (header->som) {
const struct mctp_base_protocol_message_header *msg_header =
(const struct mctp_base_protocol_message_header*) *payload;
*msg_type = msg_header->msg_type;
}
if (buf_len > packet_len) {
/* There are extra bytes in the buffer beyond the packet length. The packet contains a PEC
* byte that must be checked.*/
*crc = checksum_crc8 ((dest_addr << 1), buf, packet_len);
if (*crc != buf[packet_len]) {
return MCTP_BASE_PROTOCOL_BAD_CHECKSUM;
}
}
return 0;
}