diff options
author | Patrick Venture <venture@google.com> | 2018-12-04 16:47:09 -0800 |
---|---|---|
committer | Alexander Amelkin <mocbuhtig@amelkin.msk.ru> | 2019-02-20 18:29:09 +0300 |
commit | 51634fd77c836e3cb5acd9b9b72e7ede20321d56 (patch) | |
tree | b5fd48fa919493d15c8b792f95fedd610885d8be | |
parent | 3bfa1da201997efb5d728b6d1bcbc0825175b5b2 (diff) | |
download | ipmitool-51634fd77c836e3cb5acd9b9b72e7ede20321d56.tar.gz |
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>
-rw-r--r-- | src/plugins/open/open.c | 83 |
1 files changed, 48 insertions, 35 deletions
diff --git a/src/plugins/open/open.c b/src/plugins/open/open.c index 4fdabeb..8761a6d 100644 --- a/src/plugins/open/open.c +++ b/src/plugins/open/open.c @@ -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_usec = 0; do { - retval = select(intf->fd + 1, &rset, NULL, NULL, &read_timeout); - } while (retval < 0 && errno == EINTR); - if (retval < 0) { - lperror(LOG_ERR, "I/O Error"); - if (data) { - free(data); - data = NULL; - } - return NULL; - } else if (retval == 0) { - lprintf(LOG_ERR, "No data available"); - if (data) { - 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; + do { + retval = select(intf->fd + 1, &rset, NULL, NULL, &read_timeout); + } while (retval < 0 && errno == EINTR); + if (retval < 0) { + lperror(LOG_ERR, "I/O Error"); + if (data) { + free(data); + data = NULL; + } + return NULL; + } else if (retval == 0) { + lprintf(LOG_ERR, "No data available"); + if (data) { + free(data); + data = NULL; + } + return 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 (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) { fprintf(stderr, "Got message:"); |