transport: Match on response in pldm_transport_send_recv_msg()

pldm_send_recv() does not verify the corrected match of a PLDM response
message with the request message by comparing the Instance ID as
pldm_recv(). This will cause the PLDM command of the pldmtool receives
the response message of the other PLDM command from other services. The
pldm_transport_send_recv_msg() which is called by pldm_send_recv()
method should check the Instance ID of the response to verify the match.

Tested:

1. Run pldmtool while pldmd service continuously polls multiple pldm
   sensors.
2. The pldmtool should not be failed with PLDM_ERROR_INVALID_LENGTH
   error.

Signed-off-by: Thu Nguyen <thu@os.amperecomputing.com>
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Change-Id: I491db086cf2a0dff1981f2959d1dab936d46d2db
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c3f77af..fccb5bd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -29,3 +29,4 @@
 
 1. requester: Make pldm_open() return existing fd
 2. transport: Prevent sticking in waiting for response
+3. transport: Match on response in pldm_transport_send_recv_msg()
diff --git a/include/libpldm/transport.h b/include/libpldm/transport.h
index e5464b8..7127335 100644
--- a/include/libpldm/transport.h
+++ b/include/libpldm/transport.h
@@ -87,6 +87,11 @@
  * @brief Synchronously send a PLDM request and receive the response. Control is
  * 	  returned to the caller once the response is received.
  *
+ * pldm_transport_send_recv() will discard messages received on the underlying transport instance
+ * that are not a response that matches the request. Do not use this function if you're attempting
+ * to use the transport instance asynchronously, as this discard behaviour will affect other
+ * responses that you may care about.
+ *
  * @pre The pldm transport instance must be initialised; otherwise,
  * 	PLDM_REQUESTER_INVALID_SETUP is returned. If the transport requires a
  * 	TID to transport specific identifier mapping, this must already be set
diff --git a/src/transport/transport.c b/src/transport/transport.c
index d4608a7..77a33f8 100644
--- a/src/transport/transport.c
+++ b/src/transport/transport.c
@@ -160,16 +160,19 @@
 	static const struct timeval max_response_interval = {
 		.tv_sec = 4, .tv_usec = 800000
 	};
+	const struct pldm_msg_hdr *req_hdr;
 	struct timeval remaining;
+	pldm_requester_rc_t rc;
 	struct timeval now;
 	struct timeval end;
-	pldm_requester_rc_t rc;
 	int ret;
 
-	if (!resp_msg_len) {
+	if (req_msg_len < sizeof(*req_hdr) || !resp_msg_len) {
 		return PLDM_REQUESTER_INVALID_SETUP;
 	}
 
+	req_hdr = pldm_req_msg;
+
 	rc = pldm_transport_send_msg(transport, tid, pldm_req_msg, req_msg_len);
 	if (rc != PLDM_REQUESTER_SUCCESS) {
 		return rc;
@@ -197,7 +200,13 @@
 		rc = pldm_transport_recv_msg(transport, tid, pldm_resp_msg,
 					     resp_msg_len);
 		if (rc == PLDM_REQUESTER_SUCCESS) {
-			return rc;
+			const struct pldm_msg_hdr *resp_hdr = *pldm_resp_msg;
+			if (req_hdr->instance_id == resp_hdr->instance_id) {
+				return rc;
+			}
+
+			/* This isn't the message we wanted */
+			free(*pldm_resp_msg);
 		}
 
 		ret = clock_gettimeval(CLOCK_MONOTONIC, &now);