open: checking received msg id against expectation

Check the received IPMI response message id against
the id expected given the IPMI request.  They need to
match.  It is possible that request A times out,
request B is sent, and then request A responds to the
request B.  The value for request B may be behind it
in the queue.

Note: This may only be possible if the file is kept
open between multiple IPMI messages (a common
occurrence).

Resolves: #82

Signed-off-by: Patrick Venture <venture@google.com>
This commit is contained in:
Patrick Venture 2018-12-04 16:47:09 -08:00 committed by Alexander Amelkin
parent 3bfa1da201
commit 51634fd77c

View File

@ -342,48 +342,61 @@ ipmi_openipmi_send_cmd(struct ipmi_intf *intf, struct ipmi_rq *req)
read_timeout.tv_sec = IPMI_OPENIPMI_READ_TIMEOUT; read_timeout.tv_sec = IPMI_OPENIPMI_READ_TIMEOUT;
read_timeout.tv_usec = 0; read_timeout.tv_usec = 0;
do { do {
retval = select(intf->fd + 1, &rset, NULL, NULL, &read_timeout); do {
} while (retval < 0 && errno == EINTR); retval = select(intf->fd + 1, &rset, NULL, NULL, &read_timeout);
if (retval < 0) { } while (retval < 0 && errno == EINTR);
lperror(LOG_ERR, "I/O Error"); if (retval < 0) {
if (data) { lperror(LOG_ERR, "I/O Error");
free(data); if (data) {
data = NULL; free(data);
} data = NULL;
return NULL; }
} else if (retval == 0) { return NULL;
lprintf(LOG_ERR, "No data available"); } else if (retval == 0) {
if (data) { lprintf(LOG_ERR, "No data available");
free(data);
data = NULL;
}
return NULL;
}
if (FD_ISSET(intf->fd, &rset) == 0) {
lprintf(LOG_ERR, "No data available");
if (data) {
free(data);
data = NULL;
}
return NULL;
}
recv.addr = (unsigned char *)&addr;
recv.addr_len = sizeof(addr);
recv.msg.data = rsp.data;
recv.msg.data_len = sizeof(rsp.data);
/* get data */
if (ioctl(intf->fd, IPMICTL_RECEIVE_MSG_TRUNC, &recv) < 0) {
lperror(LOG_ERR, "Error receiving message");
if (errno != EMSGSIZE) {
if (data) { if (data) {
free(data); free(data);
data = NULL; data = NULL;
} }
return NULL; return NULL;
} }
} if (FD_ISSET(intf->fd, &rset) == 0) {
lprintf(LOG_ERR, "No data available");
if (data) {
free(data);
data = NULL;
}
return NULL;
}
recv.addr = (unsigned char *)&addr;
recv.addr_len = sizeof(addr);
recv.msg.data = rsp.data;
recv.msg.data_len = sizeof(rsp.data);
/* get data */
if (ioctl(intf->fd, IPMICTL_RECEIVE_MSG_TRUNC, &recv) < 0) {
lperror(LOG_ERR, "Error receiving message");
if (errno != EMSGSIZE) {
if (data) {
free(data);
data = NULL;
}
return NULL;
}
}
/* If the message received wasn't expected, try to grab the
* next message until it's out of messages. -EAGAIN is
* returned if the list empty, but basically if it returns a
* message, check if it's alright.
*/
if (_req.msgid != recv.msgid) {
lprintf(LOG_NOTICE,
"Received a response with unexpected ID %ld vs. %ld",
recv.msgid, _req.msgid);
}
} while (_req.msgid != recv.msgid);
if (verbose > 4) { if (verbose > 4) {
fprintf(stderr, "Got message:"); fprintf(stderr, "Got message:");