int mctp_base_protocol_interpret()

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;
}