Compare commits

...

No commits in common. "imports/c8-beta/ipmitool-1.8.18-10.el8" and "c8" have entirely different histories.

13 changed files with 2456 additions and 3 deletions

View File

@ -1 +0,0 @@
ff4781bb78f264d44fa4bf1767f268d4079d87ba SOURCES/ipmitool-1.8.18.tar.bz2

View File

@ -0,0 +1,864 @@
From 260293c0ee5a268bc7fc1483e5304546745122a6 Mon Sep 17 00:00:00 2001
From: Vernon Mauery <vernon.mauery@intel.com>
Date: Mon, 9 Apr 2018 12:28:57 -0700
Subject: [PATCH] lanplus: Auto-select 'best' cipher suite available
Current cipher suites could be ranked as this:
17 > 3 >> all the rest
Cherry-picked-from: 7772254b62826b894ca629df8c597030a98f4f72
Cherry-picked-from: f9c699c712f884c82fc1a62f1f61a8d597ac0cfd
Also fetched some functions/macros for helper.h
Equals to getting include/ipmitool/helper.h changes from commits:
(oldest first)
6c00d44 mc: watchdog get: Update to match IPMI 2.0 spec
e8e94d8 mc: watchdog set: Refactor to reduce complexity
0310208 mc: Code refactor to reduce copy-paste ratio
249e092 general: Make byteswapping arch-independent
5491b12 refix 249e0929: Fix byteswapping helpers
bb1a4cc Refactoring. Improve code reuse ratio.
---
include/ipmitool/helper.h | 58 ++++++++
include/ipmitool/ipmi_channel.h | 47 +++++++
include/ipmitool/ipmi_intf.h | 39 ++++-
lib/ipmi_channel.c | 242 +++++++++++++++-----------------
lib/ipmi_main.c | 23 +--
src/plugins/ipmi_intf.c | 5 +-
src/plugins/lanplus/lanplus.c | 114 +++++++++++----
7 files changed, 360 insertions(+), 168 deletions(-)
diff --git a/include/ipmitool/helper.h b/include/ipmitool/helper.h
index c53736f..6a2e5f4 100644
--- a/include/ipmitool/helper.h
+++ b/include/ipmitool/helper.h
@@ -38,6 +38,8 @@
#include <stdio.h>
#include <string.h>
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
#ifndef TRUE
#define TRUE 1
#endif
@@ -111,6 +113,62 @@ FILE * ipmi_open_file(const char * file, int rw);
void ipmi_start_daemon(struct ipmi_intf *intf);
uint16_t ipmi_get_oem_id(struct ipmi_intf *intf);
+#define IS_SET(v, b) ((v) & (1 << (b)))
+
+/* le16toh(), hto16le(), et. al. don't exist for Windows or Apple */
+/* For portability, let's simply define our own versions here */
+
+/* IPMI is always little-endian */
+static inline uint16_t ipmi16toh(void *ipmi16)
+{
+ uint8_t *ipmi = (uint8_t *)ipmi16;
+ uint16_t h;
+
+ h = ipmi[1] << 8; /* MSB */
+ h |= ipmi[0]; /* LSB */
+
+ return h;
+}
+
+static inline void htoipmi16(uint16_t h, uint8_t *ipmi)
+{
+ ipmi[0] = h & 0xFF; /* LSB */
+ ipmi[1] = h >> 8; /* MSB */
+}
+
+static inline uint32_t ipmi24toh(void *ipmi24)
+{
+ uint8_t *ipmi = (uint8_t *)ipmi24;
+ uint32_t h = 0;
+
+ h = ipmi[2] << 16; /* MSB */
+ h |= ipmi[1] << 8;
+ h |= ipmi[0]; /* LSB */
+
+ return h;
+}
+
+static inline uint32_t ipmi32toh(void *ipmi32)
+{
+ uint8_t *ipmi = ipmi32;
+ uint32_t h;
+
+ h = ipmi[3] << 24; /* MSB */
+ h |= ipmi[2] << 16;
+ h |= ipmi[1] << 8;
+ h |= ipmi[0]; /* LSB */
+
+ return h;
+}
+
+static inline void htoipmi32(uint32_t h, uint8_t *ipmi)
+{
+ ipmi[0] = h & 0xFF; /* LSB */
+ ipmi[1] = (h >> 8) & 0xFF;
+ ipmi[2] = (h >> 16) & 0xFF;
+ ipmi[3] = (h >> 24) & 0xFF; /* MSB */
+}
+
#define ipmi_open_file_read(file) ipmi_open_file(file, 0)
#define ipmi_open_file_write(file) ipmi_open_file(file, 1)
diff --git a/include/ipmitool/ipmi_channel.h b/include/ipmitool/ipmi_channel.h
index 3ade2d5..324c0bb 100644
--- a/include/ipmitool/ipmi_channel.h
+++ b/include/ipmitool/ipmi_channel.h
@@ -37,6 +37,7 @@
# include <config.h>
#endif
#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_intf.h>
#define IPMI_GET_CHANNEL_AUTH_CAP 0x38
@@ -81,6 +82,50 @@ struct channel_access_t {
uint8_t user_level_auth;
};
+/*
+ * The Cipher Suite Record Format from table 22-18 of the IPMI v2.0 spec
+ */
+enum cipher_suite_format_tag {
+ STANDARD_CIPHER_SUITE = 0xc0,
+ OEM_CIPHER_SUITE = 0xc1,
+};
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct std_cipher_suite_record_t {
+ uint8_t start_of_record;
+ uint8_t cipher_suite_id;
+ uint8_t auth_alg;
+ uint8_t integrity_alg;
+ uint8_t crypt_alg;
+} ATTRIBUTE_PACKING;
+struct oem_cipher_suite_record_t {
+ uint8_t start_of_record;
+ uint8_t cipher_suite_id;
+ uint8_t iana[3];
+ uint8_t auth_alg;
+ uint8_t integrity_alg;
+ uint8_t crypt_alg;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+#define CIPHER_ALG_MASK 0x3f
+#define MAX_CIPHER_SUITE_RECORD_OFFSET 0x40
+#define MAX_CIPHER_SUITE_DATA_LEN 0x10
+#define LIST_ALGORITHMS_BY_CIPHER_SUITE 0x80
+
+/* Below is the theoretical maximum number of cipher suites that could be
+ * reported by a BMC. That is with the Get Channel Cipher Suites Command, at 16
+ * bytes at a time and 0x40 requests, it can report 1024 bytes, which is about
+ * 204 standard records or 128 OEM records. Really, we probably don't need more
+ * than about 20, which is the full set of standard records plus a few OEM
+ * records.
+ */
+#define MAX_CIPHER_SUITE_COUNT (MAX_CIPHER_SUITE_RECORD_OFFSET * \
+ MAX_CIPHER_SUITE_DATA_LEN / \
+ sizeof(struct std_cipher_suite_record_t))
+
/*
* The Get Authentication Capabilities response structure
* From table 22-15 of the IPMI v2.0 spec
@@ -135,6 +180,8 @@ struct get_channel_auth_cap_rsp {
int _ipmi_get_channel_access(struct ipmi_intf *intf,
struct channel_access_t *channel_access,
uint8_t get_volatile_settings);
+int ipmi_get_channel_cipher_suites(struct ipmi_intf *intf, const char *payload_type,
+ uint8_t channel, struct cipher_suite_info *suites, size_t *count);
int _ipmi_get_channel_info(struct ipmi_intf *intf,
struct channel_info_t *channel_info);
int _ipmi_set_channel_access(struct ipmi_intf *intf,
diff --git a/include/ipmitool/ipmi_intf.h b/include/ipmitool/ipmi_intf.h
index 0b8c64b..7a07d66 100644
--- a/include/ipmitool/ipmi_intf.h
+++ b/include/ipmitool/ipmi_intf.h
@@ -61,13 +61,45 @@ enum LANPLUS_SESSION_STATE {
#define IPMI_AUTHCODE_BUFFER_SIZE 20
#define IPMI_SIK_BUFFER_SIZE IPMI_MAX_MD_SIZE
+enum cipher_suite_ids {
+ IPMI_LANPLUS_CIPHER_SUITE_0 = 0,
+ IPMI_LANPLUS_CIPHER_SUITE_1 = 1,
+ IPMI_LANPLUS_CIPHER_SUITE_2 = 2,
+ IPMI_LANPLUS_CIPHER_SUITE_3 = 3,
+ IPMI_LANPLUS_CIPHER_SUITE_4 = 4,
+ IPMI_LANPLUS_CIPHER_SUITE_5 = 5,
+ IPMI_LANPLUS_CIPHER_SUITE_6 = 6,
+ IPMI_LANPLUS_CIPHER_SUITE_7 = 7,
+ IPMI_LANPLUS_CIPHER_SUITE_8 = 8,
+ IPMI_LANPLUS_CIPHER_SUITE_9 = 9,
+ IPMI_LANPLUS_CIPHER_SUITE_10 = 10,
+ IPMI_LANPLUS_CIPHER_SUITE_11 = 11,
+ IPMI_LANPLUS_CIPHER_SUITE_12 = 12,
+ IPMI_LANPLUS_CIPHER_SUITE_13 = 13,
+ IPMI_LANPLUS_CIPHER_SUITE_14 = 14,
+#ifdef HAVE_CRYPTO_SHA256
+ IPMI_LANPLUS_CIPHER_SUITE_15 = 15,
+ IPMI_LANPLUS_CIPHER_SUITE_16 = 16,
+ IPMI_LANPLUS_CIPHER_SUITE_17 = 17,
+#endif /* HAVE_CRYPTO_SHA256 */
+ IPMI_LANPLUS_CIPHER_SUITE_RESERVED = 0xff,
+};
+
+struct cipher_suite_info {
+ enum cipher_suite_ids cipher_suite_id;
+ uint8_t auth_alg;
+ uint8_t integrity_alg;
+ uint8_t crypt_alg;
+ uint32_t iana;
+};
+
struct ipmi_session_params {
char * hostname;
uint8_t username[17];
uint8_t authcode_set[IPMI_AUTHCODE_BUFFER_SIZE + 1];
uint8_t authtype_set;
uint8_t privlvl;
- uint8_t cipher_suite_id;
+ enum cipher_suite_ids cipher_suite_id;
char sol_escape_char;
int password;
int port;
@@ -217,7 +249,10 @@ void ipmi_intf_session_set_username(struct ipmi_intf * intf, char * username);
void ipmi_intf_session_set_password(struct ipmi_intf * intf, char * password);
void ipmi_intf_session_set_privlvl(struct ipmi_intf * intf, uint8_t privlvl);
void ipmi_intf_session_set_lookupbit(struct ipmi_intf * intf, uint8_t lookupbit);
-void ipmi_intf_session_set_cipher_suite_id(struct ipmi_intf * intf, uint8_t cipher_suite_id);
+#ifdef IPMI_INTF_LANPLUS
+void ipmi_intf_session_set_cipher_suite_id(struct ipmi_intf * intf,
+ enum cipher_suite_ids cipher_suite_id);
+#endif /* IPMI_INTF_LANPLUS */
void ipmi_intf_session_set_sol_escape_char(struct ipmi_intf * intf, char sol_escape_char);
void ipmi_intf_session_set_kgkey(struct ipmi_intf *intf, const uint8_t *kgkey);
void ipmi_intf_session_set_port(struct ipmi_intf * intf, int port);
diff --git a/lib/ipmi_channel.c b/lib/ipmi_channel.c
index e1fc75f..3ae3104 100644
--- a/lib/ipmi_channel.c
+++ b/lib/ipmi_channel.c
@@ -342,86 +342,116 @@ ipmi_get_channel_auth_cap(struct ipmi_intf *intf, uint8_t channel, uint8_t priv)
return 0;
}
-static int
+static size_t
+parse_channel_cipher_suite_data(uint8_t *cipher_suite_data, size_t data_len,
+ struct cipher_suite_info* suites, size_t nr_suites)
+{
+ size_t count = 0;
+ size_t offset = 0;
+ uint32_t iana;
+ uint8_t auth_alg, integrity_alg, crypt_alg;
+ uint8_t cipher_suite_id;
+
+ memset(suites, 0, sizeof(*suites) * nr_suites);
+
+ while (offset < data_len && count < nr_suites) {
+ auth_alg = IPMI_AUTH_RAKP_NONE;
+ integrity_alg = IPMI_INTEGRITY_NONE;
+ crypt_alg = IPMI_CRYPT_NONE;
+ if (cipher_suite_data[offset] == STANDARD_CIPHER_SUITE) {
+ struct std_cipher_suite_record_t *record =
+ (struct std_cipher_suite_record_t*)(&cipher_suite_data[offset]);
+ /* standard type */
+ iana = 0;
+
+ /* Verify that we have at least a full record left; id + 3 algs */
+ if ((data_len - offset) < sizeof(*record)) {
+ lprintf(LOG_INFO, "Incomplete data record in cipher suite data");
+ break;
+ }
+ cipher_suite_id = record->cipher_suite_id;
+ auth_alg = CIPHER_ALG_MASK & record->auth_alg;
+ integrity_alg = CIPHER_ALG_MASK & record->integrity_alg;
+ crypt_alg = CIPHER_ALG_MASK & record->crypt_alg;
+ offset += sizeof(*record);
+ } else if (cipher_suite_data[offset] == OEM_CIPHER_SUITE) {
+ /* OEM record type */
+ struct oem_cipher_suite_record_t *record =
+ (struct oem_cipher_suite_record_t*)(&cipher_suite_data[offset]);
+ /* Verify that we have at least a full record left
+ * id + iana + 3 algs
+ */
+ if ((data_len - offset) < sizeof(*record)) {
+ lprintf(LOG_INFO, "Incomplete data record in cipher suite data");
+ break;
+ }
+
+ cipher_suite_id = record->cipher_suite_id;
+
+ /* Grab the IANA */
+ iana = ipmi24toh(record->iana);
+ auth_alg = CIPHER_ALG_MASK & record->auth_alg;
+ integrity_alg = CIPHER_ALG_MASK & record->integrity_alg;
+ crypt_alg = CIPHER_ALG_MASK & record->crypt_alg;
+ offset += sizeof(*record);
+ } else {
+ lprintf(LOG_INFO, "Bad start of record byte in cipher suite data (offset %d, value %x)", offset, cipher_suite_data[offset]);
+ break;
+ }
+ suites[count].cipher_suite_id = cipher_suite_id;
+ suites[count].iana = iana;
+ suites[count].auth_alg = auth_alg;
+ suites[count].integrity_alg = integrity_alg;
+ suites[count].crypt_alg = crypt_alg;
+ count++;
+ }
+ return count;
+}
+
+int
ipmi_get_channel_cipher_suites(struct ipmi_intf *intf, const char *payload_type,
- uint8_t channel)
+ uint8_t channel, struct cipher_suite_info *suites, size_t *count)
{
struct ipmi_rs *rsp;
struct ipmi_rq req;
uint8_t rqdata[3];
- uint32_t iana;
- uint8_t auth_alg, integrity_alg, crypt_alg;
- uint8_t cipher_suite_id;
uint8_t list_index = 0;
/* 0x40 sets * 16 bytes per set */
- uint8_t cipher_suite_data[1024];
- uint16_t offset = 0;
- /* how much was returned, total */
- uint16_t cipher_suite_data_length = 0;
+ uint8_t cipher_suite_data[MAX_CIPHER_SUITE_RECORD_OFFSET *
+ MAX_CIPHER_SUITE_DATA_LEN];
+ size_t offset = 0;
+ size_t nr_suites = 0;
+ if (!suites || !count || !*count)
+ return -1;
+
+ nr_suites = *count;
+ *count = 0;
memset(cipher_suite_data, 0, sizeof(cipher_suite_data));
-
+
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP;
req.msg.cmd = IPMI_GET_CHANNEL_CIPHER_SUITES;
req.msg.data = rqdata;
- req.msg.data_len = 3;
+ req.msg.data_len = sizeof(rqdata);
rqdata[0] = channel;
rqdata[1] = ((strncmp(payload_type, "ipmi", 4) == 0)? 0: 1);
- /* Always ask for cipher suite format */
- rqdata[2] = 0x80;
-
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_ERR, "Unable to Get Channel Cipher Suites");
- return -1;
- }
- if (rsp->ccode > 0) {
- lprintf(LOG_ERR, "Get Channel Cipher Suites failed: %s",
- val2str(rsp->ccode, completion_code_vals));
- return -1;
- }
-
-
- /*
- * Grab the returned channel number once. We assume it's the same
- * in future calls.
- */
- if (rsp->data_len >= 1) {
- channel = rsp->data[0];
- }
-
- while ((rsp->data_len > 1) && (rsp->data_len == 17) && (list_index < 0x3F)) {
- /*
- * We got back cipher suite data -- store it.
- * printf("copying data to offset %d\n", offset);
- * printbuf(rsp->data + 1, rsp->data_len - 1, "this is the data");
- */
- memcpy(cipher_suite_data + offset, rsp->data + 1, rsp->data_len - 1);
- offset += rsp->data_len - 1;
-
- /*
- * Increment our list for the next call
- */
- ++list_index;
- rqdata[2] = (rqdata[2] & 0x80) + list_index;
+ do {
+ /* Always ask for cipher suite format */
+ rqdata[2] = LIST_ALGORITHMS_BY_CIPHER_SUITE | list_index;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Unable to Get Channel Cipher Suites");
return -1;
}
- if (rsp->ccode > 0) {
+ if (rsp->ccode || rsp->data_len < 1) {
lprintf(LOG_ERR, "Get Channel Cipher Suites failed: %s",
val2str(rsp->ccode, completion_code_vals));
return -1;
}
- }
-
- /* Copy last chunk */
- if(rsp->data_len > 1) {
/*
* We got back cipher suite data -- store it.
* printf("copying data to offset %d\n", offset);
@@ -429,88 +459,46 @@ ipmi_get_channel_cipher_suites(struct ipmi_intf *intf, const char *payload_type,
*/
memcpy(cipher_suite_data + offset, rsp->data + 1, rsp->data_len - 1);
offset += rsp->data_len - 1;
- }
- /* We can chomp on all our data now. */
- cipher_suite_data_length = offset;
- offset = 0;
+ /*
+ * Increment our list for the next call
+ */
+ ++list_index;
+ } while ((rsp->data_len == (sizeof(uint8_t) + MAX_CIPHER_SUITE_DATA_LEN)) &&
+ (list_index < MAX_CIPHER_SUITE_RECORD_OFFSET));
- if (! csv_output) {
- printf("ID IANA Auth Alg Integrity Alg Confidentiality Alg\n");
- }
- while (offset < cipher_suite_data_length) {
- if (cipher_suite_data[offset++] == 0xC0) {
- /* standard type */
- iana = 0;
+ *count = parse_channel_cipher_suite_data(cipher_suite_data, offset, suites,
+ nr_suites);
+ return 0;
+}
- /* Verify that we have at least a full record left; id + 3 algs */
- if ((cipher_suite_data_length - offset) < 4) {
- lprintf(LOG_ERR, "Incomplete data record in cipher suite data");
- return -1;
- }
- cipher_suite_id = cipher_suite_data[offset++];
- } else if (cipher_suite_data[offset++] == 0xC1) {
- /* OEM record type */
- /* Verify that we have at least a full record left
- * id + iana + 3 algs
- */
- if ((cipher_suite_data_length - offset) < 4) {
- lprintf(LOG_ERR, "Incomplete data record in cipher suite data");
- return -1;
- }
+static int
+ipmi_print_channel_cipher_suites(struct ipmi_intf *intf, const char *payload_type,
+ uint8_t channel)
+{
+ int rc;
+ size_t i = 0;
+ struct cipher_suite_info suites[MAX_CIPHER_SUITE_COUNT];
+ size_t nr_suites = sizeof(*suites);
- cipher_suite_id = cipher_suite_data[offset++];
+ rc = ipmi_get_channel_cipher_suites(intf, payload_type, channel,
+ suites, &nr_suites);
- /* Grab the IANA */
- iana =
- cipher_suite_data[offset] |
- (cipher_suite_data[offset + 1] << 8) |
- (cipher_suite_data[offset + 2] << 16);
- offset += 3;
- } else {
- lprintf(LOG_ERR, "Bad start of record byte in cipher suite data");
- return -1;
- }
+ if (rc < 0)
+ return rc;
- /*
- * Grab the algorithms for this cipher suite. I guess we can't be
- * sure of what order they'll come in. Also, I suppose we default
- * to the NONE algorithm if one were absent. This part of the spec is
- * poorly written -- I have read the errata document. For now, I'm only
- * allowing one algorithm per type (auth, integrity, crypt) because I
- * don't I understand how it could be otherwise.
- */
- auth_alg = IPMI_AUTH_RAKP_NONE;
- integrity_alg = IPMI_INTEGRITY_NONE;
- crypt_alg = IPMI_CRYPT_NONE;
-
- while (((cipher_suite_data[offset] & 0xC0) != 0xC0) &&
- ((cipher_suite_data_length - offset) > 0))
- {
- switch (cipher_suite_data[offset] & 0xC0)
- {
- case 0x00:
- /* Authentication algorithm specifier */
- auth_alg = cipher_suite_data[offset++] & 0x3F;
- break;
- case 0x40:
- /* Interity algorithm specifier */
- integrity_alg = cipher_suite_data[offset++] & 0x3F;
- break;
- case 0x80:
- /* Confidentiality algorithm specifier */
- crypt_alg = cipher_suite_data[offset++] & 0x3F;
- break;
- }
- }
+ if (! csv_output) {
+ printf("ID IANA Auth Alg Integrity Alg Confidentiality Alg\n");
+ }
+ for (i = 0; i < nr_suites; i++) {
/* We have everything we need to spit out a cipher suite record */
printf((csv_output? "%d,%s,%s,%s,%s\n" :
"%-4d %-7s %-15s %-15s %-15s\n"),
- cipher_suite_id,
- iana_string(iana),
- val2str(auth_alg, ipmi_auth_algorithms),
- val2str(integrity_alg, ipmi_integrity_algorithms),
- val2str(crypt_alg, ipmi_encryption_algorithms));
+ suites[i].cipher_suite_id,
+ iana_string(suites[i].iana),
+ val2str(suites[i].auth_alg, ipmi_auth_algorithms),
+ val2str(suites[i].integrity_alg, ipmi_integrity_algorithms),
+ val2str(suites[i].crypt_alg, ipmi_encryption_algorithms));
}
return 0;
}
@@ -973,7 +961,7 @@ ipmi_channel_main(struct ipmi_intf *intf, int argc, char **argv)
return (-1);
}
}
- retval = ipmi_get_channel_cipher_suites(intf,
+ retval = ipmi_print_channel_cipher_suites(intf,
argv[1], /* ipmi | sol */
channel);
} else if (strncmp(argv[0], "setkg", 5) == 0) {
diff --git a/lib/ipmi_main.c b/lib/ipmi_main.c
index 811c80b..6aee102 100644
--- a/lib/ipmi_main.c
+++ b/lib/ipmi_main.c
@@ -323,6 +323,7 @@ ipmi_main(int argc, char ** argv,
uint8_t target_addr = 0;
uint8_t target_channel = 0;
+ uint8_t u8tmp = 0;
uint8_t transit_addr = 0;
uint8_t transit_channel = 0;
uint8_t target_lun = 0;
@@ -347,7 +348,10 @@ ipmi_main(int argc, char ** argv,
char * seloem = NULL;
int port = 0;
int devnum = 0;
- int cipher_suite_id = 3; /* See table 22-19 of the IPMIv2 spec */
+#ifdef IPMI_INTF_LANPLUS
+ /* lookup best cipher suite available */
+ enum cipher_suite_ids cipher_suite_id = IPMI_LANPLUS_CIPHER_SUITE_RESERVED;
+#endif /* IPMI_INTF_LANPLUS */
int argflag, i, found;
int rc = -1;
int ai_family = AF_UNSPEC;
@@ -425,19 +429,18 @@ ipmi_main(int argc, char ** argv,
goto out_free;
}
break;
+#ifdef IPMI_INTF_LANPLUS
case 'C':
- if (str2int(optarg, &cipher_suite_id) != 0) {
- lprintf(LOG_ERR, "Invalid parameter given or out of range for '-C'.");
- rc = -1;
- goto out_free;
- }
- /* add check Cipher is -gt 0 */
- if (cipher_suite_id < 0) {
- lprintf(LOG_ERR, "Cipher suite ID %i is invalid.", cipher_suite_id);
+ /* Cipher Suite ID is a byte as per IPMI specification */
+ if (str2uchar(optarg, &u8tmp) != 0) {
+ lprintf(LOG_ERR, "Invalid parameter given or out of "
+ "range [0-255] for '-C'.");
rc = -1;
goto out_free;
}
+ cipher_suite_id = u8tmp;
break;
+#endif /* IPMI_INTF_LANPLUS */
case 'v':
verbose++;
break;
@@ -870,7 +873,9 @@ ipmi_main(int argc, char ** argv,
ipmi_intf_session_set_lookupbit(ipmi_main_intf, lookupbit);
ipmi_intf_session_set_sol_escape_char(ipmi_main_intf, sol_escape_char);
+#ifdef IPMI_INTF_LANPLUS
ipmi_intf_session_set_cipher_suite_id(ipmi_main_intf, cipher_suite_id);
+#endif /* IPMI_INTF_LANPLUS */
ipmi_main_intf->devnum = devnum;
diff --git a/src/plugins/ipmi_intf.c b/src/plugins/ipmi_intf.c
index 1d9e87b..00b0918 100644
--- a/src/plugins/ipmi_intf.c
+++ b/src/plugins/ipmi_intf.c
@@ -252,11 +252,14 @@ ipmi_intf_session_set_lookupbit(struct ipmi_intf * intf, uint8_t lookupbit)
intf->ssn_params.lookupbit = lookupbit;
}
+#ifdef IPMI_INTF_LANPLUS
void
-ipmi_intf_session_set_cipher_suite_id(struct ipmi_intf * intf, uint8_t cipher_suite_id)
+ipmi_intf_session_set_cipher_suite_id(struct ipmi_intf * intf,
+ enum cipher_suite_ids cipher_suite_id)
{
intf->ssn_params.cipher_suite_id = cipher_suite_id;
}
+#endif /* IPMI_INTF_LANPLUS */
void
ipmi_intf_session_set_sol_escape_char(struct ipmi_intf * intf, char sol_escape_char)
diff --git a/src/plugins/lanplus/lanplus.c b/src/plugins/lanplus/lanplus.c
index a0e388c..3087348 100644
--- a/src/plugins/lanplus/lanplus.c
+++ b/src/plugins/lanplus/lanplus.c
@@ -164,114 +164,109 @@ extern int verbose;
* returns 0 on success
* 1 on failure
*/
-int lanplus_get_requested_ciphers(int cipher_suite_id,
+int lanplus_get_requested_ciphers(enum cipher_suite_ids cipher_suite_id,
uint8_t * auth_alg,
uint8_t * integrity_alg,
uint8_t * crypt_alg)
{
-#ifdef HAVE_CRYPTO_SHA256
- if ((cipher_suite_id < 0) || (cipher_suite_id > 17)) {
- return 1;
- }
-#else
- if ((cipher_suite_id < 0) || (cipher_suite_id > 14))
- return 1;
-#endif /* HAVE_CRYPTO_SHA256 */
/* See table 22-19 for the source of the statement */
switch (cipher_suite_id)
{
- case 0:
+ case IPMI_LANPLUS_CIPHER_SUITE_0:
*auth_alg = IPMI_AUTH_RAKP_NONE;
*integrity_alg = IPMI_INTEGRITY_NONE;
*crypt_alg = IPMI_CRYPT_NONE;
break;
- case 1:
+ case IPMI_LANPLUS_CIPHER_SUITE_1:
*auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1;
*integrity_alg = IPMI_INTEGRITY_NONE;
*crypt_alg = IPMI_CRYPT_NONE;
break;
- case 2:
+ case IPMI_LANPLUS_CIPHER_SUITE_2:
*auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1;
*integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96;
*crypt_alg = IPMI_CRYPT_NONE;
break;
- case 3:
+ case IPMI_LANPLUS_CIPHER_SUITE_3:
*auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1;
*integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96;
*crypt_alg = IPMI_CRYPT_AES_CBC_128;
break;
- case 4:
+ case IPMI_LANPLUS_CIPHER_SUITE_4:
*auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1;
*integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96;
*crypt_alg = IPMI_CRYPT_XRC4_128;
break;
- case 5:
+ case IPMI_LANPLUS_CIPHER_SUITE_5:
*auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1;
*integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96;
*crypt_alg = IPMI_CRYPT_XRC4_40;
break;
- case 6:
+ case IPMI_LANPLUS_CIPHER_SUITE_6:
*auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
*integrity_alg = IPMI_INTEGRITY_NONE;
*crypt_alg = IPMI_CRYPT_NONE;
break;
- case 7:
+ case IPMI_LANPLUS_CIPHER_SUITE_7:
*auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
*integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128;
*crypt_alg = IPMI_CRYPT_NONE;
break;
- case 8:
+ case IPMI_LANPLUS_CIPHER_SUITE_8:
*auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
*integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128;
*crypt_alg = IPMI_CRYPT_AES_CBC_128;
break;
- case 9:
+ case IPMI_LANPLUS_CIPHER_SUITE_9:
*auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
*integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128;
*crypt_alg = IPMI_CRYPT_XRC4_128;
break;
- case 10:
+ case IPMI_LANPLUS_CIPHER_SUITE_10:
*auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
*integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128;
*crypt_alg = IPMI_CRYPT_XRC4_40;
break;
- case 11:
+ case IPMI_LANPLUS_CIPHER_SUITE_11:
*auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
*integrity_alg = IPMI_INTEGRITY_MD5_128;
*crypt_alg = IPMI_CRYPT_NONE;
break;
- case 12:
+ case IPMI_LANPLUS_CIPHER_SUITE_12:
*auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
*integrity_alg = IPMI_INTEGRITY_MD5_128;
*crypt_alg = IPMI_CRYPT_AES_CBC_128;
break;
- case 13:
+ case IPMI_LANPLUS_CIPHER_SUITE_13:
*auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
*integrity_alg = IPMI_INTEGRITY_MD5_128;
*crypt_alg = IPMI_CRYPT_XRC4_128;
break;
- case 14:
+ case IPMI_LANPLUS_CIPHER_SUITE_14:
*auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
*integrity_alg = IPMI_INTEGRITY_MD5_128;
*crypt_alg = IPMI_CRYPT_XRC4_40;
break;
#ifdef HAVE_CRYPTO_SHA256
- case 15:
+ case IPMI_LANPLUS_CIPHER_SUITE_15:
*auth_alg = IPMI_AUTH_RAKP_HMAC_SHA256;
*integrity_alg = IPMI_INTEGRITY_NONE;
*crypt_alg = IPMI_CRYPT_NONE;
break;
- case 16:
+ case IPMI_LANPLUS_CIPHER_SUITE_16:
*auth_alg = IPMI_AUTH_RAKP_HMAC_SHA256;
*integrity_alg = IPMI_INTEGRITY_HMAC_SHA256_128;
*crypt_alg = IPMI_CRYPT_NONE;
break;
- case 17:
+ case IPMI_LANPLUS_CIPHER_SUITE_17:
*auth_alg = IPMI_AUTH_RAKP_HMAC_SHA256;
*integrity_alg = IPMI_INTEGRITY_HMAC_SHA256_128;
*crypt_alg = IPMI_CRYPT_AES_CBC_128;
break;
#endif /* HAVE_CRYPTO_SHA256 */
+ case IPMI_LANPLUS_CIPHER_SUITE_RESERVED:
+ default:
+ return 1;
}
return 0;
@@ -3441,6 +3436,57 @@ ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf)
return 0;
}
+static uint8_t
+ipmi_find_best_cipher_suite(struct ipmi_intf *intf)
+{
+ enum cipher_suite_ids best_suite = IPMI_LANPLUS_CIPHER_SUITE_RESERVED;
+#ifdef HAVE_CRYPTO_SHA256
+ struct cipher_suite_info suites[MAX_CIPHER_SUITE_COUNT];
+ size_t nr_suites = ARRAY_SIZE(suites);
+ /* cipher suite best order is chosen with this criteria:
+ * HMAC-MD5 and MD5 are BAD; xRC4 is bad; AES128 is required
+ * HMAC-SHA256 > HMAC-SHA1
+ * secure authentication > encrypted content
+ *
+ * With xRC4 out, all cipher suites with MD5 out, and cipher suite 3 being
+ * required by the spec, the only better defined standard cipher suite is
+ * 17. So if SHA256 is available, we should try to use that, otherwise,
+ * fall back to 3.
+ */
+ const enum cipher_suite_ids cipher_order_preferred[] = {
+ IPMI_LANPLUS_CIPHER_SUITE_17,
+ IPMI_LANPLUS_CIPHER_SUITE_3,
+ };
+ const size_t nr_preferred = ARRAY_SIZE(cipher_order_preferred);
+ size_t ipref, i;
+
+ if (ipmi_get_channel_cipher_suites(intf, "ipmi", IPMI_LAN_CHANNEL_E,
+ suites, &nr_suites) < 0)
+ {
+ /* default legacy behavior - cipher suite 3 if none is requested */
+ return IPMI_LANPLUS_CIPHER_SUITE_3;
+ }
+ for (ipref = 0; ipref < nr_preferred &&
+ IPMI_LANPLUS_CIPHER_SUITE_RESERVED == best_suite; ipref++)
+ {
+ for (i = 0; i < nr_suites; i++) {
+ if (cipher_order_preferred[ipref] == suites[i].cipher_suite_id) {
+ best_suite = cipher_order_preferred[ipref];
+ break;
+ }
+ }
+ }
+#endif /* HAVE_CRYPTO_SHA256 */
+ if (IPMI_LANPLUS_CIPHER_SUITE_RESERVED == best_suite) {
+ /* IPMI 2.0 spec requires that cipher suite 3 is implemented
+ * so we should always be able to fall back to that if better
+ * options are not available. */
+ best_suite = IPMI_LANPLUS_CIPHER_SUITE_3;
+ }
+ lprintf(LOG_INFO, "Using best available cipher suite %d\n", best_suite);
+ return best_suite;
+}
+
/**
* ipmi_lanplus_open
*/
@@ -3514,6 +3560,16 @@ ipmi_lanplus_open(struct ipmi_intf * intf)
lprintf(LOG_INFO, "This BMC does not support IPMI v2 / RMCP+");
goto fail;
}
+ /*
+ * If no cipher suite was provided, query the channel cipher suite list and
+ * pick the best one available
+ */
+ if (IPMI_LANPLUS_CIPHER_SUITE_RESERVED ==
+ intf->ssn_params.cipher_suite_id)
+ {
+ ipmi_intf_session_set_cipher_suite_id(intf,
+ ipmi_find_best_cipher_suite(intf));
+ }
/*
* If the open/rakp1/rakp3 sequence encounters a timeout, the whole sequence
@@ -3728,7 +3784,7 @@ static int ipmi_lanplus_setup(struct ipmi_intf * intf)
static void ipmi_lanp_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t size)
{
- if (intf->ssn_params.cipher_suite_id == 3) {
+ if (intf->ssn_params.cipher_suite_id == IPMI_LANPLUS_CIPHER_SUITE_3) {
/*
* encrypted payload can only be multiple of 16 bytes
*/
@@ -3746,7 +3802,7 @@ static void ipmi_lanp_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t siz
static void ipmi_lanp_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t size)
{
- if (intf->ssn_params.cipher_suite_id == 3) {
+ if (intf->ssn_params.cipher_suite_id == IPMI_LANPLUS_CIPHER_SUITE_3) {
/*
* encrypted payload can only be multiple of 16 bytes
*/
--
2.20.1

View File

@ -0,0 +1,383 @@
From a1732e68bce148255785e67eb035520729274d86 Mon Sep 17 00:00:00 2001
From: Chrostoper Ertl <chertl@microsoft.com>
Date: Thu, 28 Nov 2019 16:33:59 +0000
Subject: [PATCH] Fixes for CVE-2020-5208
see https://github.com/ipmitool/ipmitool/security/advisories/GHSA-g659-9qxw-p7cp
This patch is combination of following commits:
pick e824c23316ae50beb7f7488f2055ac65e8b341f2 fru: Fix buffer overflow vulnerabilities
pick 840fb1cbb4fb365cb9797300e3374d4faefcdb10 fru: Fix buffer overflow in ipmi_spd_print_fru
pick 41d7026946fafbd4d1ec0bcaca3ea30a6e8eed22 session: Fix buffer overflow in ipmi_get_session_info
pick 9452be87181a6e83cfcc768b3ed8321763db50e4 channel: Fix buffer overflow
pick d45572d71e70840e0d4c50bf48218492b79c1a10 lanp: Fix buffer overflows in get_lan_param_select
pick 7ccea283dd62a05a320c1921e3d8d71a87772637 fru, sdr: Fix id_string buffer overflows
[vdolezal@redhat.com]: fixed memleak of `spd_data` in
lib/dimm_spd.c:ipmi_spd_print_fru()
---
lib/dimm_spd.c | 11 ++++++++++-
lib/ipmi_channel.c | 5 ++++-
lib/ipmi_fru.c | 35 ++++++++++++++++++++++++++++++++---
lib/ipmi_lanp.c | 14 +++++++-------
lib/ipmi_sdr.c | 40 ++++++++++++++++++++++++----------------
lib/ipmi_session.c | 12 ++++++++----
6 files changed, 85 insertions(+), 32 deletions(-)
diff --git a/lib/dimm_spd.c b/lib/dimm_spd.c
index 41e30db..ebcc94c 100644
--- a/lib/dimm_spd.c
+++ b/lib/dimm_spd.c
@@ -1621,7 +1621,7 @@ ipmi_spd_print_fru(struct ipmi_intf * intf, uint8_t id)
struct ipmi_rq req;
struct fru_info fru;
uint8_t *spd_data, msg_data[4];
- int len, offset;
+ uint32_t len, offset;
msg_data[0] = id;
@@ -1697,6 +1697,15 @@ ipmi_spd_print_fru(struct ipmi_intf * intf, uint8_t id)
}
len = rsp->data[0];
+ if(rsp->data_len < 1
+ || len > rsp->data_len - 1
+ || len > fru.size - offset)
+ {
+ printf(" Not enough buffer size");
+ free(spd_data);
+ spd_data = NULL;
+ return -1;
+ }
memcpy(&spd_data[offset], rsp->data + 1, len);
offset += len;
} while (offset < fru.size);
diff --git a/lib/ipmi_channel.c b/lib/ipmi_channel.c
index 3ae3104..80ba522 100644
--- a/lib/ipmi_channel.c
+++ b/lib/ipmi_channel.c
@@ -447,7 +447,10 @@ ipmi_get_channel_cipher_suites(struct ipmi_intf *intf, const char *payload_type,
lprintf(LOG_ERR, "Unable to Get Channel Cipher Suites");
return -1;
}
- if (rsp->ccode || rsp->data_len < 1) {
+ if (rsp->ccode
+ || rsp->data_len < 1
+ || rsp->data_len > sizeof(uint8_t) + MAX_CIPHER_SUITE_DATA_LEN)
+ {
lprintf(LOG_ERR, "Get Channel Cipher Suites failed: %s",
val2str(rsp->ccode, completion_code_vals));
return -1;
diff --git a/lib/ipmi_fru.c b/lib/ipmi_fru.c
index cf00eff..98bc984 100644
--- a/lib/ipmi_fru.c
+++ b/lib/ipmi_fru.c
@@ -615,7 +615,10 @@ int
read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
uint32_t offset, uint32_t length, uint8_t *frubuf)
{
- uint32_t off = offset, tmp, finish;
+ uint32_t off = offset;
+ uint32_t tmp;
+ uint32_t finish;
+ uint32_t size_left_in_buffer;
struct ipmi_rs * rsp;
struct ipmi_rq req;
uint8_t msg_data[4];
@@ -628,10 +631,12 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
finish = offset + length;
if (finish > fru->size) {
+ memset(frubuf + fru->size, 0, length - fru->size);
finish = fru->size;
lprintf(LOG_NOTICE, "Read FRU Area length %d too large, "
"Adjusting to %d",
offset + length, finish - offset);
+ length = finish - offset;
}
memset(&req, 0, sizeof(req));
@@ -667,6 +672,7 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
}
}
+ size_left_in_buffer = length;
do {
tmp = fru->access ? off >> 1 : off;
msg_data[0] = id;
@@ -707,9 +713,18 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
}
tmp = fru->access ? rsp->data[0] << 1 : rsp->data[0];
+ if(rsp->data_len < 1
+ || tmp > rsp->data_len - 1
+ || tmp > size_left_in_buffer)
+ {
+ printf(" Not enough buffer size");
+ return -1;
+ }
+
memcpy(frubuf, rsp->data + 1, tmp);
off += tmp;
frubuf += tmp;
+ size_left_in_buffer -= tmp;
/* sometimes the size returned in the Info command
* is too large. return 0 so higher level function
* still attempts to parse what was returned */
@@ -742,7 +757,9 @@ read_fru_area_section(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
uint32_t offset, uint32_t length, uint8_t *frubuf)
{
static uint32_t fru_data_rqst_size = 20;
- uint32_t off = offset, tmp, finish;
+ uint32_t off = offset;
+ uint32_t tmp, finish;
+ uint32_t size_left_in_buffer;
struct ipmi_rs * rsp;
struct ipmi_rq req;
uint8_t msg_data[4];
@@ -755,10 +772,12 @@ read_fru_area_section(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
finish = offset + length;
if (finish > fru->size) {
+ memset(frubuf + fru->size, 0, length - fru->size);
finish = fru->size;
lprintf(LOG_NOTICE, "Read FRU Area length %d too large, "
"Adjusting to %d",
offset + length, finish - offset);
+ length = finish - offset;
}
memset(&req, 0, sizeof(req));
@@ -773,6 +792,8 @@ read_fru_area_section(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
if (fru->access && fru_data_rqst_size > 16)
#endif
fru_data_rqst_size = 16;
+
+ size_left_in_buffer = length;
do {
tmp = fru->access ? off >> 1 : off;
msg_data[0] = id;
@@ -804,8 +825,16 @@ read_fru_area_section(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
}
tmp = fru->access ? rsp->data[0] << 1 : rsp->data[0];
+ if(rsp->data_len < 1
+ || tmp > rsp->data_len - 1
+ || tmp > size_left_in_buffer)
+ {
+ printf(" Not enough buffer size");
+ return -1;
+ }
memcpy((frubuf + off)-offset, rsp->data + 1, tmp);
off += tmp;
+ size_left_in_buffer -= tmp;
/* sometimes the size returned in the Info command
* is too large. return 0 so higher level function
@@ -3033,7 +3062,7 @@ ipmi_fru_print(struct ipmi_intf * intf, struct sdr_record_fru_locator * fru)
return 0;
memset(desc, 0, sizeof(desc));
- memcpy(desc, fru->id_string, fru->id_code & 0x01f);
+ memcpy(desc, fru->id_string, __min(fru->id_code & 0x01f, sizeof(desc)));
desc[fru->id_code & 0x01f] = 0;
printf("FRU Device Description : %s (ID %d)\n", desc, fru->device_id);
diff --git a/lib/ipmi_lanp.c b/lib/ipmi_lanp.c
index 65d881b..022c7f1 100644
--- a/lib/ipmi_lanp.c
+++ b/lib/ipmi_lanp.c
@@ -1809,7 +1809,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert,
if (p == NULL) {
return (-1);
}
- memcpy(data, p->data, p->data_len);
+ memcpy(data, p->data, __min(p->data_len, sizeof(data)));
/* set new ipaddr */
memcpy(data+3, temp, 4);
printf("Setting LAN Alert %d IP Address to %d.%d.%d.%d\n", alert,
@@ -1824,7 +1824,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert,
if (p == NULL) {
return (-1);
}
- memcpy(data, p->data, p->data_len);
+ memcpy(data, p->data, __min(p->data_len, sizeof(data)));
/* set new macaddr */
memcpy(data+7, temp, 6);
printf("Setting LAN Alert %d MAC Address to "
@@ -1838,7 +1838,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert,
if (p == NULL) {
return (-1);
}
- memcpy(data, p->data, p->data_len);
+ memcpy(data, p->data, __min(p->data_len, sizeof(data)));
if (strncasecmp(argv[1], "def", 3) == 0 ||
strncasecmp(argv[1], "default", 7) == 0) {
@@ -1864,7 +1864,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert,
if (p == NULL) {
return (-1);
}
- memcpy(data, p->data, p->data_len);
+ memcpy(data, p->data, __min(p->data_len, sizeof(data)));
if (strncasecmp(argv[1], "on", 2) == 0 ||
strncasecmp(argv[1], "yes", 3) == 0) {
@@ -1889,7 +1889,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert,
if (p == NULL) {
return (-1);
}
- memcpy(data, p->data, p->data_len);
+ memcpy(data, p->data, __min(p->data_len, sizeof(data)));
if (strncasecmp(argv[1], "pet", 3) == 0) {
printf("Setting LAN Alert %d destination to PET Trap\n", alert);
@@ -1917,7 +1917,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert,
if (p == NULL) {
return (-1);
}
- memcpy(data, p->data, p->data_len);
+ memcpy(data, p->data, __min(p->data_len, sizeof(data)));
if (str2uchar(argv[1], &data[2]) != 0) {
lprintf(LOG_ERR, "Invalid time: %s", argv[1]);
@@ -1933,7 +1933,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert,
if (p == NULL) {
return (-1);
}
- memcpy(data, p->data, p->data_len);
+ memcpy(data, p->data, __min(p->data_len, sizeof(data)));
if (str2uchar(argv[1], &data[3]) != 0) {
lprintf(LOG_ERR, "Invalid retry: %s", argv[1]);
diff --git a/lib/ipmi_sdr.c b/lib/ipmi_sdr.c
index fd2c02d..01d81f7 100644
--- a/lib/ipmi_sdr.c
+++ b/lib/ipmi_sdr.c
@@ -2086,7 +2086,7 @@ ipmi_sdr_print_sensor_eventonly(struct ipmi_intf *intf,
return -1;
memset(desc, 0, sizeof (desc));
- snprintf(desc, (sensor->id_code & 0x1f) + 1, "%s", sensor->id_string);
+ snprintf(desc, sizeof(desc), "%.*s", (sensor->id_code & 0x1f) + 1, sensor->id_string);
if (verbose) {
printf("Sensor ID : %s (0x%x)\n",
@@ -2137,7 +2137,7 @@ ipmi_sdr_print_sensor_mc_locator(struct ipmi_intf *intf,
return -1;
memset(desc, 0, sizeof (desc));
- snprintf(desc, (mc->id_code & 0x1f) + 1, "%s", mc->id_string);
+ snprintf(desc, sizeof(desc), "%.*s", (mc->id_code & 0x1f) + 1, mc->id_string);
if (verbose == 0) {
if (csv_output)
@@ -2230,7 +2230,7 @@ ipmi_sdr_print_sensor_generic_locator(struct ipmi_intf *intf,
char desc[17];
memset(desc, 0, sizeof (desc));
- snprintf(desc, (dev->id_code & 0x1f) + 1, "%s", dev->id_string);
+ snprintf(desc, sizeof(desc), "%.*s", (dev->id_code & 0x1f) + 1, dev->id_string);
if (!verbose) {
if (csv_output)
@@ -2287,7 +2287,7 @@ ipmi_sdr_print_sensor_fru_locator(struct ipmi_intf *intf,
char desc[17];
memset(desc, 0, sizeof (desc));
- snprintf(desc, (fru->id_code & 0x1f) + 1, "%s", fru->id_string);
+ snprintf(desc, sizeof(desc), "%.*s", (fru->id_code & 0x1f) + 1, fru->id_string);
if (!verbose) {
if (csv_output)
@@ -2491,35 +2491,43 @@ ipmi_sdr_print_name_from_rawentry(struct ipmi_intf *intf, uint16_t id,
int rc =0;
char desc[17];
+ const char *id_string;
+ uint8_t id_code;
memset(desc, ' ', sizeof (desc));
switch ( type) {
case SDR_RECORD_TYPE_FULL_SENSOR:
record.full = (struct sdr_record_full_sensor *) raw;
- snprintf(desc, (record.full->id_code & 0x1f) +1, "%s",
- (const char *)record.full->id_string);
+ id_code = record.full->id_code;
+ id_string = record.full->id_string;
break;
+
case SDR_RECORD_TYPE_COMPACT_SENSOR:
record.compact = (struct sdr_record_compact_sensor *) raw ;
- snprintf(desc, (record.compact->id_code & 0x1f) +1, "%s",
- (const char *)record.compact->id_string);
+ id_code = record.compact->id_code;
+ id_string = record.compact->id_string;
break;
+
case SDR_RECORD_TYPE_EVENTONLY_SENSOR:
record.eventonly = (struct sdr_record_eventonly_sensor *) raw ;
- snprintf(desc, (record.eventonly->id_code & 0x1f) +1, "%s",
- (const char *)record.eventonly->id_string);
- break;
+ id_code = record.eventonly->id_code;
+ id_string = record.eventonly->id_string;
+ break;
+
case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR:
record.mcloc = (struct sdr_record_mc_locator *) raw ;
- snprintf(desc, (record.mcloc->id_code & 0x1f) +1, "%s",
- (const char *)record.mcloc->id_string);
+ id_code = record.mcloc->id_code;
+ id_string = record.mcloc->id_string;
break;
+
default:
rc = -1;
- break;
- }
+ }
+ if (!rc) {
+ snprintf(desc, sizeof(desc), "%.*s", (id_code & 0x1f) + 1, id_string);
+ }
- lprintf(LOG_INFO, "ID: 0x%04x , NAME: %-16s", id, desc);
+ lprintf(LOG_INFO, "ID: 0x%04x , NAME: %-16s", id, desc);
return rc;
}
diff --git a/lib/ipmi_session.c b/lib/ipmi_session.c
index 141f0f4..b9af1fd 100644
--- a/lib/ipmi_session.c
+++ b/lib/ipmi_session.c
@@ -309,8 +309,10 @@ ipmi_get_session_info(struct ipmi_intf * intf,
}
else
{
- memcpy(&session_info, rsp->data, rsp->data_len);
- print_session_info(&session_info, rsp->data_len);
+ memcpy(&session_info, rsp->data,
+ __min(rsp->data_len, sizeof(session_info)));
+ print_session_info(&session_info,
+ __min(rsp->data_len, sizeof(session_info)));
}
break;
@@ -341,8 +343,10 @@ ipmi_get_session_info(struct ipmi_intf * intf,
break;
}
- memcpy(&session_info, rsp->data, rsp->data_len);
- print_session_info(&session_info, rsp->data_len);
+ memcpy(&session_info, rsp->data,
+ __min(rsp->data_len, sizeof(session_info)));
+ print_session_info(&session_info,
+ __min(rsp->data_len, sizeof(session_info)));
} while (i <= session_info.session_slot_count);
break;
--
2.20.1

View File

@ -0,0 +1,420 @@
From 87a898756a7bd54898c1f6d2a5441efb1f810b67 Mon Sep 17 00:00:00 2001
From: qctbmc <qct.bmc@gmail.com>
Date: Tue, 10 Jul 2018 11:21:55 +0800
Subject: [PATCH] oem: Add basic support for Quanta
---
include/ipmitool/Makefile.am | 2 +-
include/ipmitool/ipmi_quantaoem.h | 55 +++++++++
lib/Makefile.am | 2 +-
lib/ipmi_main.c | 1 +
lib/ipmi_oem.c | 14 +++
lib/ipmi_quantaoem.c | 184 ++++++++++++++++++++++++++++++
lib/ipmi_sel.c | 21 +++-
src/ipmitool.c | 1 +
8 files changed, 274 insertions(+), 6 deletions(-)
create mode 100644 include/ipmitool/ipmi_quantaoem.h
create mode 100644 lib/ipmi_quantaoem.c
diff --git a/include/ipmitool/Makefile.am b/include/ipmitool/Makefile.am
index 9093a56..8bc584a 100644
--- a/include/ipmitool/Makefile.am
+++ b/include/ipmitool/Makefile.am
@@ -39,4 +39,4 @@ noinst_HEADERS = log.h bswap.h hpm2.h helper.h ipmi.h ipmi_cc.h ipmi_intf.h \
ipmi_fwum.h ipmi_main.h ipmi_tsol.h ipmi_firewall.h \
ipmi_kontronoem.h ipmi_ekanalyzer.h ipmi_gendev.h ipmi_ime.h \
ipmi_delloem.h ipmi_dcmi.h ipmi_vita.h ipmi_sel_supermicro.h \
- ipmi_cfgp.h ipmi_lanp6.h
+ ipmi_cfgp.h ipmi_lanp6.h ipmi_quantaoem.h
diff --git a/include/ipmitool/ipmi_quantaoem.h b/include/ipmitool/ipmi_quantaoem.h
new file mode 100644
index 0000000..544f510
--- /dev/null
+++ b/include/ipmitool/ipmi_quantaoem.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2018 Quanta Computer Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Quanta Computer Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * Quanta Computer Inc. AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * Quanta Computer Inc. OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IPMI_QUANTAOEM_H
+#define IPMI_QUANTAOEM_H
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_sdr.h>
+
+#define OEM_QCT_NETFN 0x36
+#define OEM_QCT_GET_INFO 0x65
+
+typedef enum
+{
+ OEM_QCT_PLATFORM_UNKNOWN = 0,
+ OEM_QCT_PLATFORM_GRANTLEY,
+ OEM_QCT_PLATFORM_PURLEY
+} qct_platform_t;
+
+qct_platform_t oem_qct_get_platform_id(struct ipmi_intf *intf);
+char *oem_qct_get_evt_desc(struct ipmi_intf *intf, struct sel_event_record *rec);
+
+#endif /*IPMI_QUANTAOEM_H*/
diff --git a/lib/Makefile.am b/lib/Makefile.am
index cc69a8f..e7568f3 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -41,7 +41,7 @@ libipmitool_la_SOURCES = helper.c ipmi_sdr.c ipmi_sel.c ipmi_sol.c ipmi_pef.c \
ipmi_main.c ipmi_tsol.c ipmi_firewall.c ipmi_kontronoem.c \
ipmi_hpmfwupg.c ipmi_sdradd.c ipmi_ekanalyzer.c ipmi_gendev.c \
ipmi_ime.c ipmi_delloem.c ipmi_dcmi.c hpm2.c ipmi_vita.c \
- ipmi_lanp6.c ipmi_cfgp.c \
+ ipmi_lanp6.c ipmi_cfgp.c ipmi_quantaoem.c \
../src/plugins/lan/md5.c ../src/plugins/lan/md5.h
libipmitool_la_LDFLAGS = -export-dynamic
diff --git a/lib/ipmi_main.c b/lib/ipmi_main.c
index 6aee102..9d4a148 100644
--- a/lib/ipmi_main.c
+++ b/lib/ipmi_main.c
@@ -75,6 +75,7 @@
#include <ipmitool/ipmi_picmg.h>
#include <ipmitool/ipmi_kontronoem.h>
#include <ipmitool/ipmi_vita.h>
+#include <ipmitool/ipmi_quantaoem.h>
#ifdef HAVE_CONFIG_H
# include <config.h>
diff --git a/lib/ipmi_oem.c b/lib/ipmi_oem.c
index 96db2ea..86fd803 100644
--- a/lib/ipmi_oem.c
+++ b/lib/ipmi_oem.c
@@ -39,6 +39,7 @@
static int ipmi_oem_supermicro(struct ipmi_intf * intf);
static int ipmi_oem_ibm(struct ipmi_intf * intf);
+static int ipmi_oem_quanta(struct ipmi_intf * intf);
static struct ipmi_oem_handle ipmi_oem_list[] = {
{
@@ -71,6 +72,11 @@ static struct ipmi_oem_handle ipmi_oem_list[] = {
.name = "kontron",
.desc = "Kontron OEM big buffer support"
},
+ {
+ .name = "quanta",
+ .desc = "Quanta IPMIv1.5 BMC with OEM LAN authentication support",
+ .setup = ipmi_oem_quanta,
+ },
{ 0 }
};
@@ -93,6 +99,14 @@ ipmi_oem_ibm(struct ipmi_intf * intf)
return ipmi_sel_oem_init((const char *)filename);
}
+/* Quanta IPMIv2 BMCs use OEM authtype */
+static int
+ipmi_oem_quanta(struct ipmi_intf * intf)
+{
+ ipmi_intf_session_set_authtype(intf, IPMI_SESSION_AUTHTYPE_OEM);
+ return 0;
+}
+
/* ipmi_oem_print - print list of OEM handles
*/
void
diff --git a/lib/ipmi_quantaoem.c b/lib/ipmi_quantaoem.c
new file mode 100644
index 0000000..7b4c5c6
--- /dev/null
+++ b/lib/ipmi_quantaoem.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2018 Quanta Computer Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Quanta Computer Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * Quanta Computer Inc. AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * Quanta Computer Inc. OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+#define _XOPEN_SOURCE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <time.h>
+#include <unistd.h>
+#include <signal.h>
+#include <ctype.h>
+#include <sys/time.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <sys/select.h>
+#include <termios.h>
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_mc.h>
+#include <ipmitool/ipmi_intf.h>
+#include <ipmitool/helper.h>
+#include <ipmitool/log.h>
+#include <ipmitool/ipmi_sel.h>
+#include <ipmitool/ipmi_sdr.h>
+#include <ipmitool/ipmi_strings.h>
+#include <ipmitool/ipmi_channel.h>
+#include <ipmitool/ipmi_quantaoem.h>
+#include <ipmitool/ipmi_raw.h>
+
+/* Max Size of the description String to be displyed for the Each sel entry */
+#define SIZE_OF_DESC 128
+
+#define CPU_SHIFT 6
+#define CPU_MASK 0X03
+#define CPU_NUM(x) (((x) >> CPU_SHIFT) & CPU_MASK)
+
+#define CHANNEL_BASE 0x41
+#define CHANNEL_SHIFT 3
+#define CHANNEL_MASK 0x07
+#define CHANNEL_OFFSET(x) (((x) >> CHANNEL_SHIFT) & CHANNEL_MASK)
+#define CHANNEL_NUM(x) (CHANNEL_BASE + CHANNEL_OFFSET(x))
+
+#define DIMM_MASK 0x07
+#define DIMM_NUM(x) ((x) & DIMM_MASK)
+
+#define GET_PLATFORM_ID_DATA_SIZE 4
+
+// Magic code to check if it's valid command
+#define QCT_MAGIC_1 0x4C
+#define QCT_MAGIC_2 0x1C
+#define QCT_MAGIC_3 0x00
+#define QCT_MAGIC_4 0x02
+
+qct_platform_t
+oem_qct_get_platform_id(struct ipmi_intf *intf)
+{
+ /* Execute a Get platform ID command to determine the board */
+ struct ipmi_rs *rsp;
+ struct ipmi_rq req;
+ qct_platform_t platform_id;
+ uint8_t msg_data[GET_PLATFORM_ID_DATA_SIZE];
+
+ /* Ask for IPMI v2 data as well */
+ msg_data[0] = QCT_MAGIC_1;
+ msg_data[1] = QCT_MAGIC_2;
+ msg_data[2] = QCT_MAGIC_3;
+ msg_data[3] = QCT_MAGIC_4;
+
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = OEM_QCT_NETFN;
+ req.msg.cmd = OEM_QCT_GET_INFO;
+ req.msg.data = msg_data;
+ req.msg.data_len = sizeof(msg_data);
+
+ rsp = intf->sendrecv(intf, &req);
+ if (rsp == NULL) {
+ lprintf(LOG_ERR, "Get Platform ID command failed");
+ return 0;
+ }
+ if (rsp->ccode) {
+ lprintf(LOG_ERR, "Get Platform ID command failed: %#x %s",
+ rsp->ccode, val2str(rsp->ccode, completion_code_vals));
+ return 0;
+ }
+ platform_id = rsp->data[0];
+ lprintf(LOG_DEBUG,"Platform ID: %hhx", rsp->data[0]);
+ return platform_id;
+}
+
+char *
+oem_qct_get_evt_desc(struct ipmi_intf *intf, struct sel_event_record *rec)
+{
+ struct ipmi_rs *rsp;
+ struct ipmi_rq req;
+ char *desc = NULL;
+ int data;
+ int sensor_type;
+ qct_platform_t platform_id;
+
+ /* Get the OEM event Bytes of the SEL Records byte 15 to data */
+ data = rec->sel_type.standard_type.event_data[2];
+ /* Check for the Standard Event type == 0x6F */
+ if (rec->sel_type.standard_type.event_type != 0x6F) {
+ goto out;
+ }
+ /* Allocate mem for te Description string */
+ desc = malloc(SIZE_OF_DESC);
+ if (desc == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ goto out;
+ }
+ memset(desc, 0, SIZE_OF_DESC);
+ sensor_type = rec->sel_type.standard_type.sensor_type;
+ switch (sensor_type) {
+ case SENSOR_TYPE_MEMORY:
+ memset(&req, 0, sizeof (req));
+ req.msg.netfn = IPMI_NETFN_APP;
+ req.msg.lun = 0;
+ req.msg.cmd = BMC_GET_DEVICE_ID;
+ req.msg.data = NULL;
+ req.msg.data_len = 0;
+
+ rsp = intf->sendrecv(intf, &req);
+ if (rsp == NULL) {
+ lprintf(LOG_ERR, " Error getting system info");
+ goto out;
+ } else if (rsp->ccode) {
+ lprintf(LOG_ERR, " Error getting system info: %s",
+ val2str(rsp->ccode, completion_code_vals));
+ goto out;
+ }
+ /* check the platform type */
+ platform_id = oem_qct_get_platform_id(intf);
+ if (OEM_QCT_PLATFORM_PURLEY == platform_id) {
+ snprintf(desc, SIZE_OF_DESC, "CPU%d_%c%d",
+ CPU_NUM(data),
+ CHANNEL_NUM(data),
+ DIMM_NUM(data));
+ }
+ break;
+ default:
+ goto out;
+ }
+ return desc;
+out:
+ if (desc) {
+ free(desc);
+ desc = NULL;
+ }
+ return desc;
+}
diff --git a/lib/ipmi_sel.c b/lib/ipmi_sel.c
index 8b0395e..a54fefd 100644
--- a/lib/ipmi_sel.c
+++ b/lib/ipmi_sel.c
@@ -50,6 +50,7 @@
#include <ipmitool/ipmi_fru.h>
#include <ipmitool/ipmi_sensor.h>
#include <ipmitool/ipmi_strings.h>
+#include <ipmitool/ipmi_quantaoem.h>
extern int verbose;
static int sel_extended = 0;
@@ -1244,6 +1245,9 @@ ipmi_get_oem_desc(struct ipmi_intf * intf, struct sel_event_record * rec)
case IPMI_OEM_SUPERMICRO_47488:
desc = get_supermicro_evt_desc(intf, rec);
break;
+ case IPMI_OEM_QUANTA:
+ desc = oem_qct_get_evt_desc(intf, rec);
+ break;
case IPMI_OEM_UNKNOWN:
default:
break;
@@ -1349,6 +1353,9 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char
sfx = ipmi_get_oem_desc(intf, rec);
break;
/* add your oem sensor assignation here */
+ case IPMI_OEM_QUANTA:
+ sfx = ipmi_get_oem_desc(intf, rec);
+ break;
default:
lprintf(LOG_DEBUG, "oem sensor type %x using standard type supplied description",
rec->sel_type.standard_type.sensor_type );
@@ -1359,9 +1366,12 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char
case IPMI_OEM_SUPERMICRO:
case IPMI_OEM_SUPERMICRO_47488:
sfx = ipmi_get_oem_desc(intf, rec);
- break;
+ break;
+ case IPMI_OEM_QUANTA:
+ sfx = ipmi_get_oem_desc(intf, rec);
+ break;
default:
- break;
+ break;
}
}
/*
@@ -1986,9 +1996,12 @@ ipmi_sel_print_std_entry(struct ipmi_intf * intf, struct sel_event_record * evt)
case IPMI_OEM_SUPERMICRO:
case IPMI_OEM_SUPERMICRO_47488:
print_sensor = 0;
- break;
+ break;
+ case IPMI_OEM_QUANTA:
+ print_sensor = 0;
+ break;
default:
- break;
+ break;
}
/*
* Sensor-Specific Discrete
diff --git a/src/ipmitool.c b/src/ipmitool.c
index 5e19c6e..ec0b741 100644
--- a/src/ipmitool.c
+++ b/src/ipmitool.c
@@ -66,6 +66,7 @@
#include <ipmitool/ipmi_ime.h>
#include <ipmitool/ipmi_dcmi.h>
#include <ipmitool/ipmi_vita.h>
+#include <ipmitool/ipmi_quantaoem.h>
#ifdef HAVE_CONFIG_H
# include <config.h>
--
2.20.1

View File

@ -0,0 +1,33 @@
From a365e624fff752bfe79438f6c177399492ccfdde Mon Sep 17 00:00:00 2001
From: Vaclav Dolezal <vdolezal@redhat.com>
Date: Fri, 1 Mar 2019 14:46:12 +0100
Subject: [PATCH] Fix "ipmitool pef {status,info}" not printing final newline
Signed-off-by: Vaclav Dolezal <vdolezal@redhat.com>
---
lib/ipmi_pef.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/lib/ipmi_pef.c b/lib/ipmi_pef.c
index bbf25f2..4be749e 100644
--- a/lib/ipmi_pef.c
+++ b/lib/ipmi_pef.c
@@ -1183,6 +1183,7 @@ ipmi_pef2_get_info(struct ipmi_intf *intf)
ipmi_pef_print_guid(guid_ptr);
}
ipmi_pef_print_flags(&pef_b2s_actions, P_SUPP, pcap.actions);
+ putchar('\n');
return 0;
}
@@ -1242,6 +1243,7 @@ ipmi_pef2_get_status(struct ipmi_intf *intf)
return (-1);
}
ipmi_pef_print_flags(&pef_b2s_actions, P_ACTV, rsp->data[1]);
+ putchar('\n');
return 0;
}
--
2.25.4

View File

@ -0,0 +1,38 @@
From 9d72def87ecc384d0a46525c766e755068fefe54 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?V=C3=A1clav=20Dole=C5=BEal?= <vdolezal@redhat.com>
Date: Thu, 28 May 2020 13:32:31 +0200
Subject: [PATCH] lanplus: don't retry pre-session Get cipher suites
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Some BMCs are ignoring it, causing needless delay.
Signed-off-by: Václav Doležal <vdolezal@redhat.com>
---
src/plugins/lanplus/lanplus.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/plugins/lanplus/lanplus.c b/src/plugins/lanplus/lanplus.c
index 3087348..c442c0e 100644
--- a/src/plugins/lanplus/lanplus.c
+++ b/src/plugins/lanplus/lanplus.c
@@ -3459,9 +3459,13 @@ ipmi_find_best_cipher_suite(struct ipmi_intf *intf)
};
const size_t nr_preferred = ARRAY_SIZE(cipher_order_preferred);
size_t ipref, i;
+ int rc;
+ int retry_old = intf->ssn_params.retry;
- if (ipmi_get_channel_cipher_suites(intf, "ipmi", IPMI_LAN_CHANNEL_E,
- suites, &nr_suites) < 0)
+ ipmi_intf_session_set_retry(intf, 1);
+ rc = ipmi_get_channel_cipher_suites(intf, "ipmi", IPMI_LAN_CHANNEL_E, suites, &nr_suites);
+ ipmi_intf_session_set_retry(intf, retry_old);
+ if (rc < 0)
{
/* default legacy behavior - cipher suite 3 if none is requested */
return IPMI_LANPLUS_CIPHER_SUITE_3;
--
2.25.4

View File

@ -0,0 +1,65 @@
From 646160e2175f9e0ba33e4f2bda12d84555e9c30e Mon Sep 17 00:00:00 2001
From: Alexander Amelkin <alexander@amelkin.msk.ru>
Date: Thu, 29 Nov 2018 13:10:53 +0300
Subject: [PATCH] lanplus: Cleanup. Refix 6dec83ff, fix be2c0c4b
This is a cleanup commit.
Commit 6dec83ff removed assignment of `rsp` pointer
in SOL-processing block of ipmi_lan_poll_single(),
but left the check for the pointer validity in place.
Although that has effectively fixed the bug of potentially
accessing the null `rsp` pointer in the `else` block introduced
with be2c0c4b, the resulting if/else looked suspicious and left
and impression that a NULL pointer could still be accessed.
This commit removes the check for `rsp` from the `if`
as it is checked at the start of the function where `rsp`
is initialized (and that is the only place where it is ever changed).
Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
(cherry picked from commit 64727f59c4a1412fdb73e092fb838ae66e2aad1a)
lanplus: Fix segfault for truncated dcmi response
On occasion a dcmi power reading will return error C6, and a
truncated response payload. As the decrypted payload is shorter
than the expected length, lanplus_decrypt_aes_cbc_128() adjusts
the payload_size downward by one byte. In ipmi_lan_poll_single()
the calculation to determine if the payload size has increased
erroniously sets extra_data_length to -1, with a subsequent
segv when calling a memmove to shift response data.
The fix is to check for a positive value in the extra_data_length.
Resolves ipmitool/ipmitool#72
(cherry picked from commit 9ec2232321a7bca7e1fb8f939d071f12c8dfa7fd)
---
src/plugins/lanplus/lanplus.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/plugins/lanplus/lanplus.c b/src/plugins/lanplus/lanplus.c
index c442c0e..ef132f6 100644
--- a/src/plugins/lanplus/lanplus.c
+++ b/src/plugins/lanplus/lanplus.c
@@ -814,7 +814,7 @@ ipmi_lan_poll_single(struct ipmi_intf * intf)
* rsp->data_len becomes the length of that data
*/
extra_data_length = payload_size - (offset - payload_start) - 1;
- if (extra_data_length) {
+ if (extra_data_length > 0) {
rsp->data_len = extra_data_length;
memmove(rsp->data, rsp->data + offset, extra_data_length);
} else {
@@ -868,7 +868,7 @@ ipmi_lan_poll_single(struct ipmi_intf * intf)
}
read_sol_packet(rsp, &offset);
extra_data_length = payload_size - (offset - payload_start);
- if (rsp && extra_data_length) {
+ if (extra_data_length > 0) {
rsp->data_len = extra_data_length;
memmove(rsp->data, rsp->data + offset, extra_data_length);
} else {
--
2.26.3

View File

@ -0,0 +1,33 @@
From f222df3081d965051be76b85ea52b4aff222edf1 Mon Sep 17 00:00:00 2001
From: "William A. Kennington III" <wak@google.com>
Date: Fri, 15 Jun 2018 14:47:12 -0700
Subject: [PATCH] plugins/open: Fix for interrupted select
The select syscall can be interrupted for signals like SIGPROF. The IPMI
command sent will still be outstanding but the send_command will return
an error. When the next command is sent it will get the completion for
the previous command and has the tendency to break state of end users.
Signed-off-by: William A. Kennington III <wak@google.com>
---
src/plugins/open/open.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/plugins/open/open.c b/src/plugins/open/open.c
index 5beeac7..59b736d 100644
--- a/src/plugins/open/open.c
+++ b/src/plugins/open/open.c
@@ -335,7 +335,9 @@ ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
FD_SET(intf->fd, &rset);
read_timeout.tv_sec = IPMI_OPENIPMI_READ_TIMEOUT;
read_timeout.tv_usec = 0;
- retval = select(intf->fd+1, &rset, NULL, NULL, &read_timeout);
+ 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 != NULL) {
--
2.40.1

View File

@ -0,0 +1,98 @@
diff -up ipmitool-1.8.18/src/plugins/open/open.c.checking-received ipmitool-1.8.18/src/plugins/open/open.c
--- ipmitool-1.8.18/src/plugins/open/open.c.checking-received 2023-07-25 17:14:22.112985375 +0200
+++ ipmitool-1.8.18/src/plugins/open/open.c 2023-07-25 17:14:22.115985324 +0200
@@ -336,48 +336,61 @@ ipmi_openipmi_send_cmd(struct ipmi_intf
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 != NULL) {
- free(data);
+ 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 != NULL) {
+ free(data);
data = NULL;
- }
- return NULL;
- } else if (retval == 0) {
- lprintf(LOG_ERR, "No data available");
- if (data != NULL) {
- free(data);
- data = NULL;
- }
- return NULL;
- }
- if (FD_ISSET(intf->fd, &rset) == 0) {
- lprintf(LOG_ERR, "No data available");
- if (data != NULL) {
- free(data);
+ }
+ return NULL;
+ } else if (retval == 0) {
+ lprintf(LOG_ERR, "No data available");
+ if (data != NULL) {
+ 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 != NULL) {
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 != NULL) {
+ 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:");

View File

@ -0,0 +1,36 @@
Description: Add IANA ID for NVIDIA hardware
Add the NVIDIA IANA ID to the hardcoded list used in ipmitool <= 1.8.18.
After upstream commit "9d41136 ID:491 - Fetch vendor IDs from IANA", ipmitool
generates a list of vendor IDs dynamically at build time, so we can drop this
patch in future releases.
Author: dann frazier <dannf@debian.org>
Origin: backport
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=903616
Forwarded: not-needed
Last-Update: 2018-07-11
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
Index: ipmitool-1.8.18/include/ipmitool/ipmi.h
===================================================================
--- ipmitool-1.8.18.orig/include/ipmitool/ipmi.h
+++ ipmitool-1.8.18/include/ipmitool/ipmi.h
@@ -279,6 +279,7 @@ typedef enum IPMI_OEM {
/* 4769 for [IBM Corporation] */
IPMI_OEM_IBM_4769 = 4769,
IPMI_OEM_MAGNUM = 5593,
+ IPMI_OEM_NVIDIA = 5703,
IPMI_OEM_TYAN = 6653,
IPMI_OEM_QUANTA = 7244,
IPMI_OEM_NEWISYS = 9237,
Index: ipmitool-1.8.18/lib/ipmi_strings.c
===================================================================
--- ipmitool-1.8.18.orig/lib/ipmi_strings.c
+++ ipmitool-1.8.18/lib/ipmi_strings.c
@@ -96,6 +96,7 @@ const struct valstr ipmi_oem_info[] = {
{ IPMI_OEM_IBM_4769, "IBM Corporation" },
{ IPMI_OEM_IBM_20301, "IBM eServer X" },
{ IPMI_OEM_ADLINK_24339, "ADLINK Technology Inc." },
+ { IPMI_OEM_NVIDIA, "NVIDIA Corporation" },
{ 0xffff , NULL },
};

View File

@ -0,0 +1,232 @@
From 3e0ecc5edcccc85654784d0888dbeb2f116204e0 Mon Sep 17 00:00:00 2001
From: Patrick Venture <venture@google.com>
Date: Thu, 22 Nov 2018 15:40:24 -0800
Subject: [PATCH] move static objects to source file
Move static objects declared in headers to the source files where
they're used.
Partially resolves ipmitool/ipmitool#13
Signed-off-by: Patrick Venture <venture@google.com>
---
include/ipmitool/ipmi_sdr.h | 43 -----------
lib/ipmi_sdr.c | 146 ++++++++++++++++++++++++++++++++++++
2 files changed, 146 insertions(+), 43 deletions(-)
diff --git a/include/ipmitool/ipmi_sdr.h b/include/ipmitool/ipmi_sdr.h
index 9001e59..5e6afd3 100644
--- a/include/ipmitool/ipmi_sdr.h
+++ b/include/ipmitool/ipmi_sdr.h
@@ -773,50 +773,7 @@ struct sdr_record_list {
#pragma pack(0)
#endif
-
-/* unit description codes (IPMI v1.5 section 37.16) */
-#define UNIT_MAX 0x90
-static const char *unit_desc[] __attribute__ ((unused)) = {
-"unspecified",
- "degrees C", "degrees F", "degrees K",
- "Volts", "Amps", "Watts", "Joules",
- "Coulombs", "VA", "Nits",
- "lumen", "lux", "Candela",
- "kPa", "PSI", "Newton",
- "CFM", "RPM", "Hz",
- "microsecond", "millisecond", "second", "minute", "hour",
- "day", "week", "mil", "inches", "feet", "cu in", "cu feet",
- "mm", "cm", "m", "cu cm", "cu m", "liters", "fluid ounce",
- "radians", "steradians", "revolutions", "cycles",
- "gravities", "ounce", "pound", "ft-lb", "oz-in", "gauss",
- "gilberts", "henry", "millihenry", "farad", "microfarad",
- "ohms", "siemens", "mole", "becquerel", "PPM", "reserved",
- "Decibels", "DbA", "DbC", "gray", "sievert",
- "color temp deg K", "bit", "kilobit", "megabit", "gigabit",
- "byte", "kilobyte", "megabyte", "gigabyte", "word", "dword",
- "qword", "line", "hit", "miss", "retry", "reset",
- "overflow", "underrun", "collision", "packets", "messages",
- "characters", "error", "correctable error", "uncorrectable error",};
-
-/* sensor type codes (IPMI v1.5 table 36.3)
- / Updated to v2.0 Table 42-3, Sensor Type Codes */
#define SENSOR_TYPE_MAX 0x2C
-static const char *sensor_type_desc[] __attribute__ ((unused)) = {
-"reserved",
- "Temperature", "Voltage", "Current", "Fan",
- "Physical Security", "Platform Security", "Processor",
- "Power Supply", "Power Unit", "Cooling Device", "Other",
- "Memory", "Drive Slot / Bay", "POST Memory Resize",
- "System Firmwares", "Event Logging Disabled", "Watchdog1",
- "System Event", "Critical Interrupt", "Button",
- "Module / Board", "Microcontroller", "Add-in Card",
- "Chassis", "Chip Set", "Other FRU", "Cable / Interconnect",
- "Terminator", "System Boot Initiated", "Boot Error",
- "OS Boot", "OS Critical Stop", "Slot / Connector",
- "System ACPI Power State", "Watchdog2", "Platform Alert",
- "Entity Presence", "Monitor ASIC", "LAN",
- "Management Subsys Health", "Battery", "Session Audit",
- "Version Change", "FRU State" };
struct sensor_reading {
char s_id[33]; /* name of the sensor */
diff --git a/lib/ipmi_sdr.c b/lib/ipmi_sdr.c
index d51c174..eb40b36 100644
--- a/lib/ipmi_sdr.c
+++ b/lib/ipmi_sdr.c
@@ -68,6 +68,152 @@ static struct sdr_record_list *sdr_list_head = NULL;
static struct sdr_record_list *sdr_list_tail = NULL;
static struct ipmi_sdr_iterator *sdr_list_itr = NULL;
+/* unit description codes (IPMI v1.5 section 37.16) */
+#define UNIT_MAX 0x90
+static const char *unit_desc[] = {
+ "unspecified",
+ "degrees C",
+ "degrees F",
+ "degrees K",
+ "Volts",
+ "Amps",
+ "Watts",
+ "Joules",
+ "Coulombs",
+ "VA",
+ "Nits",
+ "lumen",
+ "lux",
+ "Candela",
+ "kPa",
+ "PSI",
+ "Newton",
+ "CFM",
+ "RPM",
+ "Hz",
+ "microsecond",
+ "millisecond",
+ "second",
+ "minute",
+ "hour",
+ "day",
+ "week",
+ "mil",
+ "inches",
+ "feet",
+ "cu in",
+ "cu feet",
+ "mm",
+ "cm",
+ "m",
+ "cu cm",
+ "cu m",
+ "liters",
+ "fluid ounce",
+ "radians",
+ "steradians",
+ "revolutions",
+ "cycles",
+ "gravities",
+ "ounce",
+ "pound",
+ "ft-lb",
+ "oz-in",
+ "gauss",
+ "gilberts",
+ "henry",
+ "millihenry",
+ "farad",
+ "microfarad",
+ "ohms",
+ "siemens",
+ "mole",
+ "becquerel",
+ "PPM",
+ "reserved",
+ "Decibels",
+ "DbA",
+ "DbC",
+ "gray",
+ "sievert",
+ "color temp deg K",
+ "bit",
+ "kilobit",
+ "megabit",
+ "gigabit",
+ "byte",
+ "kilobyte",
+ "megabyte",
+ "gigabyte",
+ "word",
+ "dword",
+ "qword",
+ "line",
+ "hit",
+ "miss",
+ "retry",
+ "reset",
+ "overflow",
+ "underrun",
+ "collision",
+ "packets",
+ "messages",
+ "characters",
+ "error",
+ "correctable error",
+ "uncorrectable error"
+};
+
+/* sensor type codes (IPMI v1.5 table 36.3)
+ / Updated to v2.0 Table 42-3, Sensor Type Codes */
+static const char *sensor_type_desc[] = {
+ "reserved",
+ "Temperature",
+ "Voltage",
+ "Current",
+ "Fan",
+ "Physical Security",
+ "Platform Security",
+ "Processor",
+ "Power Supply",
+ "Power Unit",
+ "Cooling Device",
+ "Other",
+ "Memory",
+ "Drive Slot / Bay",
+ "POST Memory Resize",
+ "System Firmwares",
+ "Event Logging Disabled",
+ "Watchdog1",
+ "System Event",
+ "Critical Interrupt",
+ "Button",
+ "Module / Board",
+ "Microcontroller",
+ "Add-in Card",
+ "Chassis",
+ "Chip Set",
+ "Other FRU",
+ "Cable / Interconnect",
+ "Terminator",
+ "System Boot Initiated",
+ "Boot Error",
+ "OS Boot",
+ "OS Critical Stop",
+ "Slot / Connector",
+ "System ACPI Power State",
+ "Watchdog2",
+ "Platform Alert",
+ "Entity Presence",
+ "Monitor ASIC",
+ "LAN",
+ "Management Subsys Health",
+ "Battery",
+ "Session Audit",
+ "Version Change",
+ "FRU State"
+};
+
void printf_sdr_usage();
/* From src/plugins/ipmi_intf.c: */
--
2.40.1

View File

@ -0,0 +1,201 @@
From 12e2f5da63fcfdb544f87ec492e5b1bc4f89868c Mon Sep 17 00:00:00 2001
From: Alexander Amelkin <alexander@amelkin.msk.ru>
Date: Fri, 19 Apr 2019 15:07:25 +0300
Subject: [PATCH] sdr: Fix segfault on invalid unit types
The program would crash if the BMC returned an out of range (>90)
unit type for a full sensor record. This commit adds a range check
and also add support for IPMI 2.0 additional unit types 91 and 92
("fatal error" and "grams").
Resolves ipmitool/ipmitool#118
Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
---
include/ipmitool/ipmi_sdr.h | 32 ++++++++++++++---
lib/ipmi_sdr.c | 72 +++++++++++++++++++++++++------------
2 files changed, 78 insertions(+), 26 deletions(-)
diff --git a/include/ipmitool/ipmi_sdr.h b/include/ipmitool/ipmi_sdr.h
index 5e6afd3..9f783c4 100644
--- a/include/ipmitool/ipmi_sdr.h
+++ b/include/ipmitool/ipmi_sdr.h
@@ -37,6 +37,7 @@
# include <config.h>
#endif
+#include <stdbool.h>
#include <inttypes.h>
#include <math.h>
#include <ipmitool/bswap.h>
@@ -381,6 +382,29 @@ struct sdr_record_common_sensor {
struct sdr_record_mask mask;
+/* IPMI 2.0, Table 43-1, byte 21[7:6] Analog (numeric) Data Format */
+#define SDR_UNIT_FMT_UNSIGNED 0 /* unsigned */
+#define SDR_UNIT_FMT_1S_COMPL 1 /* 1's complement (signed) */
+#define SDR_UNIT_FMT_2S_COMPL 2 /* 2's complement (signed) */
+#define SDR_UNIT_FMT_NA 3 /* does not return analog (numeric) reading */
+/* IPMI 2.0, Table 43-1, byte 21[5:3] Rate */
+#define SDR_UNIT_RATE_NONE 0 /* none */
+#define SDR_UNIT_RATE_MICROSEC 1 /* per us */
+#define SDR_UNIT_RATE_MILLISEC 2 /* per ms */
+#define SDR_UNIT_RATE_SEC 3 /* per s */
+#define SDR_UNIT_RATE_MIN 4 /* per min */
+#define SDR_UNIT_RATE_HR 5 /* per hour */
+#define SDR_UNIT_RATE_DAY 6 /* per day */
+#define SDR_UNIT_RATE_RSVD 7 /* reserved */
+/* IPMI 2.0, Table 43-1, byte 21[2:1] Modifier Unit */
+#define SDR_UNIT_MOD_NONE 0 /* none */
+#define SDR_UNIT_MOD_DIV 1 /* Basic Unit / Modifier Unit */
+#define SDR_UNIT_MOD_MUL 2 /* Basic Unit * Mofifier Unit */
+#define SDR_UNIT_MOD_RSVD 3 /* Reserved */
+/* IPMI 2.0, Table 43-1, byte 21[0] Percentage */
+#define SDR_UNIT_PCT_NO 0
+#define SDR_UNIT_PCT_YES 1
+
struct {
#if WORDS_BIGENDIAN
uint8_t analog:2;
@@ -394,8 +418,8 @@ struct sdr_record_common_sensor {
uint8_t analog:2;
#endif
struct {
- uint8_t base;
- uint8_t modifier;
+ uint8_t base; /* Base unit type code per IPMI 2.0 Table 43-15 */
+ uint8_t modifier; /* Modifier unit type code per Table 43-15 */
} ATTRIBUTE_PACKING type;
} ATTRIBUTE_PACKING unit;
} ATTRIBUTE_PACKING;
@@ -833,8 +857,8 @@ void ipmi_sdr_print_sensor_hysteresis(struct sdr_record_common_sensor *sensor,
struct sdr_record_full_sensor *full,
uint8_t hysteresis_value,
const char *hdrstr);
-const char *ipmi_sdr_get_unit_string(uint8_t pct, uint8_t type,
- uint8_t base, uint8_t modifier);
+const char *ipmi_sdr_get_unit_string(bool pct, uint8_t type,
+ uint8_t base, uint8_t modifier);
struct sensor_reading *
ipmi_sdr_read_sensor_value(struct ipmi_intf *intf,
struct sdr_record_common_sensor *sensor,
diff --git a/lib/ipmi_sdr.c b/lib/ipmi_sdr.c
index eb40b36..b43765a 100644
--- a/lib/ipmi_sdr.c
+++ b/lib/ipmi_sdr.c
@@ -68,8 +68,9 @@ static struct sdr_record_list *sdr_list_head = NULL;
static struct sdr_record_list *sdr_list_tail = NULL;
static struct ipmi_sdr_iterator *sdr_list_itr = NULL;
-/* unit description codes (IPMI v1.5 section 37.16) */
-#define UNIT_MAX 0x90
+/* IPMI 2.0 Table 43-15, Sensor Unit Type Codes */
+#define UNIT_TYPE_MAX 92 /* This is the ID of "grams" */
+#define UNIT_TYPE_LONGEST_NAME 19 /* This is the length of "color temp deg K" */
static const char *unit_desc[] = {
"unspecified",
"degrees C",
@@ -161,7 +162,9 @@ static const char *unit_desc[] = {
"characters",
"error",
"correctable error",
- "uncorrectable error"
+ "uncorrectable error",
+ "fatal error",
+ "grams"
};
/* sensor type codes (IPMI v1.5 table 36.3)
@@ -220,35 +223,60 @@ void printf_sdr_usage();
uint16_t
ipmi_intf_get_max_response_data_size(struct ipmi_intf * intf);
-/* ipmi_sdr_get_unit_string - return units for base/modifier
+/** ipmi_sdr_get_unit_string - return units for base/modifier
*
- * @pct: units are a percentage
- * @type: unit type
- * @base: base
- * @modifier: modifier
+ * @param[in] pct Indicates that units are a percentage
+ * @param[in] relation Modifier unit to base unit relation
+ * (SDR_UNIT_MOD_NONE, SDR_UNIT_MOD_MUL,
+ * or SDR_UNIT_MOD_DIV)
+ * @param[in] base The base unit type id
+ * @param[in] modifier The modifier unit type id
*
- * returns pointer to static string
+ * @returns a pointer to static string
*/
const char *
-ipmi_sdr_get_unit_string(uint8_t pct, uint8_t type, uint8_t base, uint8_t modifier)
+ipmi_sdr_get_unit_string(bool pct, uint8_t relation,
+ uint8_t base, uint8_t modifier)
{
- static char unitstr[16];
+ /*
+ * Twice as long as the longest possible unit name, plus
+ * four characters for '%' and relation (either ' * ' or '/'),
+ * plus the terminating null-byte.
+ */
+ static char unitstr[2 * UNIT_TYPE_LONGEST_NAME + 4 + 1];
+
/*
* By default, if units are supposed to be percent, we will pre-pend
* the percent string to the textual representation of the units.
*/
- char *pctstr = pct ? "% " : "";
- memset(unitstr, 0, sizeof (unitstr));
- switch (type) {
- case 2:
- snprintf(unitstr, sizeof (unitstr), "%s%s * %s",
- pctstr, unit_desc[base], unit_desc[modifier]);
+ const char *pctstr = pct ? "% " : "";
+ const char *basestr;
+ const char *modstr;
+
+ if (base <= UNIT_TYPE_MAX) {
+ basestr = unit_desc[base];
+ }
+ else {
+ basestr = "invalid";
+ }
+
+ if (modifier <= UNIT_TYPE_MAX) {
+ modstr = unit_desc[modifier];
+ }
+ else {
+ modstr = "invalid";
+ }
+
+ switch (relation) {
+ case SDR_UNIT_MOD_MUL:
+ snprintf(unitstr, sizeof (unitstr), "%s%s * %s",
+ pctstr, basestr, modstr);
break;
- case 1:
+ case SDR_UNIT_MOD_DIV:
snprintf(unitstr, sizeof (unitstr), "%s%s/%s",
- pctstr, unit_desc[base], unit_desc[modifier]);
+ pctstr, basestr, modstr);
break;
- case 0:
+ case SDR_UNIT_MOD_NONE:
default:
/*
* Display the text "percent" only when the Base unit is
@@ -257,8 +285,8 @@ ipmi_sdr_get_unit_string(uint8_t pct, uint8_t type, uint8_t base, uint8_t modifi
if (base == 0 && pct) {
snprintf(unitstr, sizeof(unitstr), "percent");
} else {
- snprintf(unitstr, sizeof (unitstr), "%s%s",
- pctstr, unit_desc[base]);
+ snprintf(unitstr, sizeof (unitstr), "%s%s",
+ pctstr, basestr);
}
break;
}
--
2.40.1

View File

@ -1,7 +1,7 @@
Name: ipmitool
Summary: Utility for IPMI control
Version: 1.8.18
Release: 10%{?dist}
Release: 19%{?dist}
License: BSD
URL: http://ipmitool.sourceforge.net/
Source0: http://downloads.sourceforge.net/project/%{name}/%{name}/%{version}/%{name}-%{version}.tar.bz2
@ -20,6 +20,17 @@ Patch4: 0004-slowswid.patch
Patch5: 0005-sensor-id-length.patch
Patch6: 0006-enable-usb.patch
Patch7: 0007-check-input.patch
Patch8: 0008-use-best-cipher.patch
Patch9: 0009-CVE-2020-5208.patch
Patch10: 0010-quanta-oem-support.patch
Patch11: 0011-pef-missing-newline.patch
Patch12: 0012-lanplus-cipher-retry.patch
Patch13: 0013-lanplus-Cleanup.-Refix-6dec83ff-fix-be2c0c4b.patch
Patch20: 0020-plugins-open-Fix-for-interrupted-select.patch
Patch21: 0021-open-checking-received-msg-id-against-expectation.patch
Patch22: 0022-nvidia-iana.patch
Patch23: 0023-move-static-objects-to-source-file.patch
Patch24: 0024-sdr-Fix-segfault-on-invalid-unit-types.patch
BuildRequires: openssl-devel readline-devel ncurses-devel
%{?systemd_requires}
@ -106,7 +117,9 @@ autoconf
automake --foreign
# end: release auto-tools
%configure --disable-dependency-tracking --enable-file-security --disable-intf-free
%configure \
CFLAGS="%{optflags} -fno-strict-aliasing" \
--disable-dependency-tracking --enable-file-security --disable-intf-free
make %{?_smp_mflags}
%install
@ -177,6 +190,44 @@ install -Dm 755 contrib/bmc-snmp-proxy %{buildroot}%{_libexecdir}/bmc-sn
%{_libexecdir}/bmc-snmp-proxy
%changelog
* Mon Jul 31 2023 Pavel Cahyna <pcahyna@redhat.com> - 1.8.18-19
- Backport upstream PR 120 to fix segfault on invalid unit types
Resolves: rhbz#2224578
- Add vendor ID for NVIDIA BMCs
Resolves: rhbz#2218358
- Add upstream ipmievd patch to check received msg id against expectation
Fixes problem where SEL response is not recognized correctly
when SEL request times out
Resolves: rhbz#2224569
* Mon Jul 19 2021 Pavel Cahyna <pcahyna@redhat.com> - 1.8.18-18
- Protect against negative values to memmove that caused
"ipmitool sol activate" to crash against an IBM DataPower appliance
(#1951480)
Cherry-picked from upstream PR#78.
* Wed Jun 03 2020 Václav Doležal <vdolezal@redhat.com> - 1.8.18-17
- Disable retry of pre-session "Get cipher suites" command as some
BMCs are ignoring it (#1831158)
* Thu Apr 30 2020 Václav Doležal <vdolezal@redhat.com> - 1.8.18-16
- Fix "ipmitool pef {status,info}" not printing final newline (#1840546)
* Thu Apr 30 2020 Václav Doležal <vdolezal@redhat.com> - 1.8.18-15
- Backport OEM support for Quanta (#1811941)
* Fri Feb 07 2020 Václav Doležal <vdolezal@redhat.com> - 1.8.18-14
- Fix memory leak (found by covscan)
* Fri Feb 07 2020 Václav Doležal <vdolezal@redhat.com> - 1.8.18-13
- Backport fix for CVE-2020-5208 (#1799039)
* Fri Nov 15 2019 Václav Doležal <vdolezal@redhat.com> - 1.8.18-12
- Disable -fstrict-aliasing (RPMDiff issue)
* Tue Oct 15 2019 Václav Doležal <vdolezal@redhat.com> - 1.8.18-11
- Choose the best cipher suite available when connecting over LAN (#1749360)
* Thu Feb 22 2018 Josef Ridky <jridky@redhat.com> - 1.8.18-10
- Spec clean up
- Add support to set kg key