diff options
author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2016-10-09 09:19:55 +0200 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2016-10-09 09:19:55 +0200 |
commit | 7ddeb3781f3d79ef1ae5a765a66f6cdd1ec113ef (patch) | |
tree | 3546836f27de4168559a62d8022626dfb101a133 /lib | |
parent | 5bac665e38a15e6725f9ec17c7f7e80a0506aa08 (diff) | |
parent | 82ac6c87ce0b0af2fb8de25d70442fec406bb742 (diff) |
Merge tag 'upstream/1.8.18'
Upstream version 1.8.18
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile.am | 1 | ||||
-rw-r--r-- | lib/Makefile.in | 6 | ||||
-rw-r--r-- | lib/dimm_spd.c | 22 | ||||
-rw-r--r-- | lib/helper.c | 183 | ||||
-rw-r--r-- | lib/ipmi_cfgp.c | 542 | ||||
-rw-r--r-- | lib/ipmi_channel.c | 3 | ||||
-rw-r--r-- | lib/ipmi_chassis.c | 2 | ||||
-rw-r--r-- | lib/ipmi_delloem.c | 87 | ||||
-rw-r--r-- | lib/ipmi_ekanalyzer.c | 29 | ||||
-rw-r--r-- | lib/ipmi_event.c | 42 | ||||
-rw-r--r-- | lib/ipmi_firewall.c | 10 | ||||
-rw-r--r-- | lib/ipmi_fru.c | 115 | ||||
-rw-r--r-- | lib/ipmi_hpmfwupg.c | 7 | ||||
-rw-r--r-- | lib/ipmi_lanp.c | 100 | ||||
-rw-r--r-- | lib/ipmi_lanp6.c | 1240 | ||||
-rw-r--r-- | lib/ipmi_main.c | 125 | ||||
-rw-r--r-- | lib/ipmi_mc.c | 109 | ||||
-rw-r--r-- | lib/ipmi_pef.c | 1237 | ||||
-rw-r--r-- | lib/ipmi_picmg.c | 10 | ||||
-rw-r--r-- | lib/ipmi_sdr.c | 148 | ||||
-rw-r--r-- | lib/ipmi_sel.c | 330 | ||||
-rw-r--r-- | lib/ipmi_sensor.c | 6 | ||||
-rw-r--r-- | lib/ipmi_session.c | 18 | ||||
-rw-r--r-- | lib/ipmi_sol.c | 10 | ||||
-rw-r--r-- | lib/ipmi_strings.c | 100 | ||||
-rw-r--r-- | lib/ipmi_sunoem.c | 2 |
26 files changed, 3533 insertions, 951 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index 359cb30..cc69a8f 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -41,6 +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 \ ../src/plugins/lan/md5.c ../src/plugins/lan/md5.h libipmitool_la_LDFLAGS = -export-dynamic diff --git a/lib/Makefile.in b/lib/Makefile.in index ccb468f..0e2b6b2 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -131,7 +131,8 @@ am_libipmitool_la_OBJECTS = helper.lo ipmi_sdr.lo ipmi_sel.lo \ ipmi_tsol.lo ipmi_firewall.lo ipmi_kontronoem.lo \ ipmi_hpmfwupg.lo ipmi_sdradd.lo ipmi_ekanalyzer.lo \ ipmi_gendev.lo ipmi_ime.lo ipmi_delloem.lo ipmi_dcmi.lo \ - hpm2.lo ipmi_vita.lo ../src/plugins/lan/md5.lo + hpm2.lo ipmi_vita.lo ipmi_lanp6.lo ipmi_cfgp.lo \ + ../src/plugins/lan/md5.lo libipmitool_la_OBJECTS = $(am_libipmitool_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -362,6 +363,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 \ ../src/plugins/lan/md5.c ../src/plugins/lan/md5.h libipmitool_la_LDFLAGS = -export-dynamic @@ -436,6 +438,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dimm_spd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/helper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hpm2.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_cfgp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_channel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_chassis.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_dcmi.Plo@am__quote@ @@ -451,6 +454,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_isol.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_kontronoem.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_lanp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_lanp6.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_main.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_mc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_oem.Plo@am__quote@ diff --git a/lib/dimm_spd.c b/lib/dimm_spd.c index 8b6927c..41e30db 100644 --- a/lib/dimm_spd.c +++ b/lib/dimm_spd.c @@ -1340,11 +1340,10 @@ ipmi_spd_print(uint8_t *spd_data, int len) printf(" Memory Type : %s\n", val2str(spd_data[2], spd_memtype_vals)); - + if (spd_data[2] == 0x0B) /* DDR3 SDRAM */ { int iPN; - char *pchPN = spd_data+128; int sdram_cap = 0; int pri_bus_width = 0; int sdram_width = 0; @@ -1353,7 +1352,7 @@ ipmi_spd_print(uint8_t *spd_data, int len) if (len < 148) return -1; /* we need first 91 bytes to do our thing */ - + sdram_cap = ldexp(256,(spd_data[4]&15)); pri_bus_width = ldexp(8,(spd_data[8]&7)); @@ -1366,7 +1365,7 @@ ipmi_spd_print(uint8_t *spd_data, int len) printf(" SDRAM Device Width : %d bits\n", sdram_width ); printf(" Number of Ranks : %d\n", ranks ); printf(" Memory size : %d MB\n", mem_size ); - + /* printf(" Memory Density : %s\n", val2str(spd_data[4]&15, ddr3_density_vals)); */ printf(" 1.5 V Nominal Op : %s\n", (((spd_data[6]&1) != 0) ? "No":"Yes" ) ); printf(" 1.35 V Nominal Op : %s\n", (((spd_data[6]&2) != 0) ? "No":"Yes" ) ); @@ -1417,16 +1416,15 @@ ipmi_spd_print(uint8_t *spd_data, int len) } - printf(" Manufacture Date : year %c%c week %c%c\n", + printf(" Manufacture Date : year %c%c week %c%c\n", '0'+(spd_data[120]>>4), '0'+(spd_data[120]&15), '0'+(spd_data[121]>>4), '0'+(spd_data[121]&15) ); - + printf(" Serial Number : %02x%02x%02x%02x\n", spd_data[122], spd_data[123], spd_data[124], spd_data[125]); - + printf(" Part Number : "); - for (iPN=0; iPN < 19; iPN++) - { - printf( "%c", *pchPN++ ); + for (iPN = 128; iPN < 146; iPN++) { + printf("%c", spd_data[iPN]); } printf("\n"); } else if (spd_data[2] == 0x0C) /* DDR4 SDRAM */ @@ -1552,7 +1550,7 @@ ipmi_spd_print(uint8_t *spd_data, int len) val2str(spd_data[8], spd_voltage_vals)); printf(" Error Detect/Cor : %s\n", val2str(spd_data[11], spd_config_vals)); - + /* handle jedec table bank continuation values */ printf(" Manufacturer : "); if (spd_data[64] != 0x7f) @@ -1603,7 +1601,7 @@ ipmi_spd_print(uint8_t *spd_data, int len) part[18] = 0; printf(" Part Number : %s\n", part); } - + printf(" Serial Number : %02x%02x%02x%02x\n", spd_data[95], spd_data[96], spd_data[97], spd_data[98]); } diff --git a/lib/helper.c b/lib/helper.c index 022a9c9..de91438 100644 --- a/lib/helper.c +++ b/lib/helper.c @@ -51,6 +51,7 @@ #include <fcntl.h> #include <errno.h> #include <assert.h> +#include <ctype.h> #if HAVE_CONFIG_H # include <config.h> @@ -79,22 +80,139 @@ uint16_t buf2short(uint8_t * buf) return (uint16_t)(buf[1] << 8 | buf[0]); } -const char * buf2str(uint8_t * buf, int len) +/* buf2str_extended - convert sequence of bytes to hexadecimal string with + * optional separator + * + * @param buf - data to convert + * @param len - size of data + * @param sep - optional separator (can be NULL) + * + * @returns buf representation in hex, possibly truncated to fit + * allocated static memory + */ +const char * +buf2str_extended(const uint8_t *buf, int len, const char *sep) { - static char str[2049]; + static char str[BUF2STR_MAXIMUM_OUTPUT_SIZE]; + char *cur; int i; + int sz; + int left; + int sep_len; - if (len <= 0 || len > 1024) - return NULL; + if (buf == NULL) { + snprintf(str, sizeof(str), "<NULL>"); + return (const char *)str; + } + cur = str; + left = sizeof(str); + if (sep) { + sep_len = strlen(sep); + } else { + sep_len = 0; + } + for (i = 0; i < len; i++) { + /* may return more than 2, depending on locale */ + sz = snprintf(cur, left, "%2.2x", buf[i]); + if (sz >= left) { + /* buffer overflow, truncate */ + break; + } + cur += sz; + left -= sz; + /* do not write separator after last byte */ + if (sep && i != (len - 1)) { + if (sep_len >= left) { + break; + } + strncpy(cur, sep, left - sz); + cur += sep_len; + left -= sep_len; + } + } + *cur = '\0'; - memset(str, 0, 2049); + return (const char *)str; +} - for (i=0; i<len; i++) - sprintf(str+i+i, "%2.2x", buf[i]); +const char * +buf2str(const uint8_t *buf, int len) +{ + return buf2str_extended(buf, len, NULL); +} - str[len*2] = '\0'; +/* ipmi_parse_hex - convert hexadecimal numbers to ascii string + * Input string must be composed of two-characer + * hexadecimal numbers. + * There is no separator between the numbers. Each number + * results in one byte of the converted string. + * + * Example: ipmi_parse_hex("50415353574F5244") + * returns 'PASSWORD' + * + * @param str: input string. It must contain only even number + * of '0'-'9','a'-'f' and 'A-F' characters. + * @param out: pointer to output data + * @param size: size of the output buffer + * @returns 0 for empty input string + * -1 for string with odd length + * -2 if out is NULL + * -3 if there is non-hexadecimal char in string + * >0 length of resulting binary data even if it is > size + */ +int +ipmi_parse_hex(const char *str, uint8_t *out, int size) +{ + const char *p; + uint8_t *q; + uint8_t d = 0; + uint8_t b = 0; + int shift = 4; + int len; + + len = strlen(str); + if (len == 0) { + return 0; + } - return (const char *)str; + if (len % 2 != 0) { + return -1; + } + + len /= 2; /* out bytes */ + if (out == NULL) { + return -2; + } + + for (p = str, q = out; *p; p++) { + if (!isxdigit(*p)) { + return -3; + } + + if (*p < 'A') { + /* it must be 0-9 */ + d = *p - '0'; + } else { + /* it's A-F or a-f */ + /* convert to lowercase and to 10-15 */ + d = (*p | 0x20) - 'a' + 10; + } + + if (q < (out + size)) { + /* there is space, store */ + b += d << shift; + if (shift) { + shift = 0; + } else { + shift = 4; + *q = b; + b = 0; + q++; + } + } + } + + return len; } void printbuf(const uint8_t * buf, int len, const char * desc) @@ -116,6 +234,53 @@ void printbuf(const uint8_t * buf, int len, const char * desc) fprintf(stderr, "\n"); } +/* str2mac - parse-out MAC address from given string and store it + * into buffer. + * + * @arg: string to be parsed. + * @buf: buffer of 6 to hold parsed MAC address. + * + * returns zero on success, (-1) on error and error message is printed-out. + */ +int +str2mac(const char *arg, uint8_t *buf) +{ + unsigned int m1 = 0; + unsigned int m2 = 0; + unsigned int m3 = 0; + unsigned int m4 = 0; + unsigned int m5 = 0; + unsigned int m6 = 0; + if (sscanf(arg, "%02x:%02x:%02x:%02x:%02x:%02x", + &m1, &m2, &m3, &m4, &m5, &m6) != 6) { + lprintf(LOG_ERR, "Invalid MAC address: %s", arg); + return -1; + } + if (m1 > UINT8_MAX || m2 > UINT8_MAX + || m3 > UINT8_MAX || m4 > UINT8_MAX + || m5 > UINT8_MAX || m6 > UINT8_MAX) { + lprintf(LOG_ERR, "Invalid MAC address: %s", arg); + return -1; + } + buf[0] = (uint8_t)m1; + buf[1] = (uint8_t)m2; + buf[2] = (uint8_t)m3; + buf[3] = (uint8_t)m4; + buf[4] = (uint8_t)m5; + buf[5] = (uint8_t)m6; + return 0; +} + +/* mac2str -- return MAC address as a string + * + * @buf: buffer of 6 to hold parsed MAC address. + */ +const char * +mac2str(const uint8_t *buf) +{ + return buf2str_extended(buf, 6, ":"); +} + const char * val2str(uint16_t val, const struct valstr *vs) { static char un_str[32]; diff --git a/lib/ipmi_cfgp.c b/lib/ipmi_cfgp.c new file mode 100644 index 0000000..b8af80d --- /dev/null +++ b/lib/ipmi_cfgp.c @@ -0,0 +1,542 @@ +/* + * Copyright (c) 2016 Pentair Technical Products. All right 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 Pentair Technical Products 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * PENTAIR TECHNICAL SOLUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <malloc.h> +#include <string.h> + +#include <ipmitool/helper.h> +#include <ipmitool/ipmi_cfgp.h> +#include <ipmitool/log.h> + +/* ipmi_cfgp_init initialize configuration parameter context + * @param ctx context to initialize + * @param set array of parameter descriptors + * @param count amount of descriptors supplied + * @param handler function to do real job on parameters from the set + * @param priv private data for the handler + */ +int +ipmi_cfgp_init(struct ipmi_cfgp_ctx *ctx, const struct ipmi_cfgp *set, + unsigned int count, const char *cmdname, + ipmi_cfgp_handler_t handler, void *priv) +{ + if (ctx == NULL || set == NULL || handler == NULL || !cmdname) { + return -1; + } + + memset(ctx, 0, sizeof(struct ipmi_cfgp_ctx)); + + ctx->set = set; + ctx->count = count; + ctx->cmdname = cmdname; + ctx->handler = handler; + ctx->priv = priv; + + return 0; +} + +/* ipmi_cfgp_uninit destroy data list attached to context + * @param ctx parameter context to clear + * @returns 0 -- list destroyed + * -1 -- ctx is NULL + */ +int +ipmi_cfgp_uninit(struct ipmi_cfgp_ctx *ctx) +{ + struct ipmi_cfgp_data *d; + + if (ctx == NULL) { + return -1; + } + + while (ctx->v) { + d = ctx->v; + ctx->v = d->next; + free(d); + d = NULL; + } + + return 0; +} + +/* lookup_cfgp -- find a parameter in a set*/ +static const struct ipmi_cfgp * +lookup_cfgp(const struct ipmi_cfgp_ctx *ctx, const char *name) +{ + const struct ipmi_cfgp *p; + int i; + + for (i = 0; i < ctx->count; i++) { + p = &ctx->set[i]; + + if (p->name && !strcasecmp(p->name, name)) { + return p; + } + } + + return NULL; +} + +/* ipmi_cfgp_parse_sel parse parameter selector + * (parameter ID, set selector, block selector) from cmdline. + * + * @param ctx configuration parameter context to use + * @param argc elements left in argv + * @param argv array of arguments + * @param sel where to store parsed selector + * + * @returns >=0 number of argv elements used + * <0 error + */ +int +ipmi_cfgp_parse_sel(struct ipmi_cfgp_ctx *ctx, + int argc, const char **argv, struct ipmi_cfgp_sel *sel) +{ + const struct ipmi_cfgp *p; + + if (ctx == NULL || argv == NULL || sel == NULL) { + return -1; + } + + sel->param = -1; + sel->set = -1; + sel->block = -1; + + if (argc == 0) { + /* no parameter specified, good for print, save */ + return 0; + } + + p = lookup_cfgp(ctx, argv[0]); + if (p == NULL) { + lprintf(LOG_ERR, "invalid parameter"); + return -1; + } + + sel->param = p - ctx->set; + sel->set = p->is_set ? -1 : 0; + sel->block = p->has_blocks ? -1 : 0; + + if (argc == 1 || !p->is_set) { + /* No set and block selector applicable or specified */ + return 1; + } + + if (str2int(argv[1], &sel->set) + || sel->set < 0 + || (sel->set == 0 && p->first_set)) { + lprintf(LOG_ERR, "invalid set selector"); + return -1; + } + + if (argc == 2 || !p->has_blocks) { + /* No block selector applicable or specified */ + return 2; + } + + if (str2int(argv[2], &sel->block) + || sel->block < 0 + || (sel->block == 0 && p->first_block)) { + lprintf(LOG_ERR, "invalid block selector"); + return -1; + } + + return 3; +} + +/* cfgp_add_data adds block of data to list in the configuration + * parameter context + * + * @param ctx context to add data to + * @param data parameter data + */ +static void +cfgp_add_data(struct ipmi_cfgp_ctx *ctx, struct ipmi_cfgp_data *data) +{ + struct ipmi_cfgp_data **pprev = &ctx->v; + + data->next = NULL; + + while (*pprev) { + pprev = &(*pprev)->next; + } + + *pprev = data; +} + +/* cfgp_usage prints format for configuration parameter + * + * @param p configuration parameter descriptor + * @param write 0 if no value is expected, !=0 otherwise + */ +static void +cfgp_usage(const struct ipmi_cfgp *p, int write) +{ + if (p->name == NULL) { + return; + } + + if (write && p->format == NULL) { + return; + } + + printf(" %s%s%s %s\n", + p->name, p->is_set ? " <set_sel>" : "", + p->has_blocks ? " <block_sel>" : "", + write ? p->format : ""); +} + +/* ipmi_cfgp_usage prints format for configuration parameter set + * + * @param set configuration parameter descriptor array + * @param count number of elements in set + * @param write 0 if no value is expected, !=0 otherwise + */ +void +ipmi_cfgp_usage(const struct ipmi_cfgp *set, int count, int write) +{ + const struct ipmi_cfgp *p; + int i; + + if (set == NULL) { + return; + } + + for (i = 0; i < count; i++) { + p = &set[i]; + + if (write && p->access == CFGP_RDONLY) { + continue; + } + + if (!write && p->access == CFGP_WRONLY) { + continue; + } + + cfgp_usage(p, write); + } +} + +/* ipmi_cfgp_parse_data parse parameter data from command line into context + * @param ctx context to add data + * @param sel parameter selector + * @param argc number of elements in argv + * @param argv array of unparsed arguments + * + * @returns 0 on success + * <0 on error + */ +int +ipmi_cfgp_parse_data(struct ipmi_cfgp_ctx *ctx, + const struct ipmi_cfgp_sel *sel, int argc, const char **argv) +{ + const struct ipmi_cfgp *p; + struct ipmi_cfgp_data *data; + struct ipmi_cfgp_action action; + + if (ctx == NULL || sel == NULL || argv == NULL) { + return -1; + } + + if (sel->param == -1 || sel->param >= ctx->count) { + lprintf(LOG_ERR, "invalid parameter, must be one of:"); + ipmi_cfgp_usage(ctx->set, ctx->count, 1); + return -1; + } + + if (sel->set == -1) { + lprintf(LOG_ERR, "set selector is not specified"); + return -1; + } + + if (sel->block == -1) { + lprintf(LOG_ERR, "block selector is not specified"); + return -1; + } + + p = &ctx->set[sel->param]; + + if (p->size == 0) { + return -1; + } + + data = malloc(sizeof(struct ipmi_cfgp_data) + p->size); + if (data == NULL) { + return -1; + } + + memset(data, 0, sizeof(struct ipmi_cfgp_data) + p->size); + + action.type = CFGP_PARSE; + action.set = sel->set; + action.block = sel->block; + action.argc = argc; + action.argv = argv; + action.file = NULL; + + if (ctx->handler(ctx->priv, p, &action, data->data) != 0) { + ipmi_cfgp_usage(p, 1, 1); + free(data); + data = NULL; + return -1; + } + + data->sel = *sel; + + cfgp_add_data(ctx, data); + return 0; +} + +/* cfgp_get_param -- get parameter data from MC into data list within context + * + * @param ctx context + * @param p parameter descriptor + * @param set parameter set selector, can be -1 to scan all set selectors + * @param block parameter block selector, can be -1 to get all blocks + * @param quiet set to non-zero to continue on errors + * (required for -1 to work) + * @returns 0 on success, non-zero otherwise + */ +static int +cfgp_get_param(struct ipmi_cfgp_ctx *ctx, const struct ipmi_cfgp *p, + int set, int block, int quiet) +{ + struct ipmi_cfgp_data *data; + struct ipmi_cfgp_action action; + int cset; + int cblock; + int ret; + + if (p->size == 0) { + return -1; + } + + action.type = CFGP_GET; + action.argc = 0; + action.argv = NULL; + action.file = NULL; + + if (set == -1 && !p->is_set) { + set = 0; + } + + if (block == -1 && !p->has_blocks) { + block = 0; + } + + if (set == -1) { + cset = p->first_set; + } else { + cset = set; + } + + action.quiet = quiet; + + do { + if (block == -1) { + cblock = p->first_block; + } else { + cblock = block; + } + + do { + data = malloc(sizeof(struct ipmi_cfgp_data) + p->size); + if (data == NULL) { + return -1; + } + + memset(data, 0, sizeof(struct ipmi_cfgp_data) + p->size); + + action.set = cset; + action.block = cblock; + + ret = ctx->handler(ctx->priv, p, &action, data->data); + if (ret != 0) { + free(data); + data = NULL; + + if (!action.quiet) { + return ret; + } + break; + } + + data->sel.param = p - ctx->set; + data->sel.set = cset; + data->sel.block = cblock; + + cfgp_add_data(ctx, data); + + cblock++; + action.quiet = 1; + } while (block == -1); + + if (ret != 0 && cblock == p->first_block) { + break; + } + + cset++; + } while (set == -1); + + return 0; +} + +/* ipmi_cfgp_get -- get parameters data from MC into data list within context + * + * @param ctx context + * @param sel parameter selector + * @returns 0 on success, non-zero otherwise + */ +int +ipmi_cfgp_get(struct ipmi_cfgp_ctx *ctx, const struct ipmi_cfgp_sel *sel) +{ + int i; + int ret; + + if (ctx == NULL || sel == NULL) { + return -1; + } + + if (sel->param != -1) { + if (sel->param >= ctx->count) { + return -1; + } + + ret = cfgp_get_param(ctx, &ctx->set[sel->param], + sel->set, sel->block, 0); + if (ret) { + return -1; + } + return 0; + } + + for (i = 0; i < ctx->count; i++) { + if (ctx->set[i].access == CFGP_WRONLY) { + continue; + } + + if (cfgp_get_param(ctx, &ctx->set[i], sel->set, sel->block, 1)) { + return -1; + } + } + + return 0; +} + +static int +cfgp_do_action(struct ipmi_cfgp_ctx *ctx, int action_type, + const struct ipmi_cfgp_sel *sel, FILE *file, int filter) +{ + const struct ipmi_cfgp *p; + struct ipmi_cfgp_data *data; + struct ipmi_cfgp_action action; + int ret; + + if (ctx == NULL || sel == NULL) { + return -1; + } + + action.type = action_type; + action.argc = 0; + action.argv = NULL; + action.file = file; + + for (data = ctx->v; data != NULL; data = data->next) { + if (sel->param != -1 && sel->param != data->sel.param) { + continue; + } + if (sel->set != -1 && sel->set != data->sel.set) { + continue; + } + if (sel->block != -1 && sel->block != data->sel.block) { + continue; + } + if (ctx->set[data->sel.param].access == filter) { + continue; + } + + p = &ctx->set[data->sel.param]; + + action.set = data->sel.set; + action.block = data->sel.block; + + if (action_type == CFGP_SAVE) { + fprintf(file, "%s %s ", ctx->cmdname, p->name); + if (p->is_set) { + fprintf(file, "%d ", data->sel.set); + } + if (p->has_blocks) { + fprintf(file, "%d ", data->sel.block); + } + } + + ret = ctx->handler(ctx->priv, p, &action, data->data); + + if (action_type == CFGP_SAVE) { + fputc('\n', file); + } + + if (ret != 0) { + return -1; + } + } + + return 0; +} + +int +ipmi_cfgp_set(struct ipmi_cfgp_ctx *ctx, const struct ipmi_cfgp_sel *sel) +{ + return cfgp_do_action(ctx, CFGP_SET, sel, NULL, CFGP_RDONLY); +} + +int +ipmi_cfgp_save(struct ipmi_cfgp_ctx *ctx, + const struct ipmi_cfgp_sel *sel, FILE *file) +{ + if (file == NULL) { + return -1; + } + + return cfgp_do_action(ctx, CFGP_SAVE, sel, file, CFGP_RDONLY); +} + +int +ipmi_cfgp_print(struct ipmi_cfgp_ctx *ctx, + const struct ipmi_cfgp_sel *sel, FILE *file) +{ + if (file == NULL) { + return -1; + } + + return cfgp_do_action(ctx, CFGP_PRINT, sel, file, CFGP_RESERVED); +} diff --git a/lib/ipmi_channel.c b/lib/ipmi_channel.c index 5171644..fab2e54 100644 --- a/lib/ipmi_channel.c +++ b/lib/ipmi_channel.c @@ -734,7 +734,8 @@ ipmi_get_user_access(struct ipmi_intf *intf, uint8_t channel, uint8_t user_id) (user_access.ipmi_messaging) ? "en" : "dis"); printf("Privilege Level : %s\n", val2str(user_access.privilege_limit, ipmi_privlvl_vals)); - + printf("Enable Status : %s\n", + val2str(user_access.enable_status, ipmi_user_enable_status_vals)); curr_uid ++; } while (!user_id && curr_uid <= max_uid); diff --git a/lib/ipmi_chassis.c b/lib/ipmi_chassis.c index fb7c27d..7b5c2a8 100644 --- a/lib/ipmi_chassis.c +++ b/lib/ipmi_chassis.c @@ -1381,7 +1381,7 @@ ipmi_chassis_main(struct ipmi_intf * intf, int argc, char ** argv) } } else { - lprintf(LOG_ERR, "Invalid Chassis command: %s", argv[0]); + lprintf(LOG_ERR, "Invalid chassis command: %s", argv[0]); return -1; } diff --git a/lib/ipmi_delloem.c b/lib/ipmi_delloem.c index 9bb0885..bc78c1d 100644 --- a/lib/ipmi_delloem.c +++ b/lib/ipmi_delloem.c @@ -1652,11 +1652,7 @@ ipmi_macinfo_drac_idrac_virtual_mac(struct ipmi_intf* intf,uint8_t NicNum) printf("\niDRAC6 MAC Address "); } - for (j = 0; j < 5; j++) { - printf("%02x:", VirtualMacAddress[j]); - } - printf("%02x", VirtualMacAddress[j]); - printf("\n"); + printf("%s\n", mac2str(VirtualMacAddress)); return 0; } /* @@ -1724,11 +1720,7 @@ ipmi_macinfo_drac_idrac_mac(struct ipmi_intf* intf,uint8_t NicNum) printf("\niDRAC6 MAC Address "); } - for (j = 0; j < 5; j++) { - printf("%02x:", iDRAC6MacAddressByte[j]); - } - printf("%02x", iDRAC6MacAddressByte[j]); - printf("\n"); + printf("%s\n", mac2str(iDRAC6MacAddressByte)); return 0; } /* @@ -1786,13 +1778,8 @@ ipmi_macinfo_10g(struct ipmi_intf* intf, uint8_t NicNum) for (i = 0; i < Total_No_NICs; i++) { if ((0xff == NicNum) || (i == NicNum)) { printf("\n%d",i); - printf("\t\t"); - for (j = 0 ; j < 5; j++) { - printf("%02x:", - EmbeddedNICMacAddress_10G.MacAddress[i].MacAddressByte[j]); - } - printf("%02x", - EmbeddedNICMacAddress_10G.MacAddress[i].MacAddressByte[j]); + printf("\t\t%s", + mac2str(EmbeddedNICMacAddress_10G.MacAddress[i].MacAddressByte)); } } printf("\n"); @@ -1889,13 +1876,7 @@ ipmi_macinfo_11g(struct ipmi_intf* intf, uint8_t NicNum) if ((0xff==NicNum) || (NicNum == EmbeddedNICMacAddress.LOMMacAddress[i].NICNumber)) { printf("\n%d",EmbeddedNICMacAddress.LOMMacAddress[i].NICNumber); - printf("\t\t"); - for (j = 0; j < 5; j++) { - printf("%02x:", - EmbeddedNICMacAddress.LOMMacAddress[i].MacAddressByte[j]); - } - printf("%02x", - EmbeddedNICMacAddress.LOMMacAddress[i].MacAddressByte[j]); + printf("\t\t%s", mac2str(EmbeddedNICMacAddress.LOMMacAddress[i].MacAddressByte)); if (LOM_ETHERNET_ENABLED == EmbeddedNICMacAddress.LOMMacAddress[i].EthernetStatus) { @@ -3061,9 +3042,9 @@ ipmi_get_power_headroom_command(struct ipmi_intf * intf,uint8_t unit) if (unit == btuphr) { peakpowerheadroombtuphr = watt_to_btuphr_conversion(powerheadroom.peakheadroom); instantpowerhearoom = watt_to_btuphr_conversion(powerheadroom.instheadroom); - printf("System Instantaneous Headroom : %lld BTU/hr\n", + printf("System Instantaneous Headroom : %" PRId64 " BTU/hr\n", instantpowerhearoom); - printf("System Peak Headroom : %lld BTU/hr\n", + printf("System Peak Headroom : %" PRId64 " BTU/hr\n", peakpowerheadroombtuphr); } else { printf("System Instantaneous Headroom : %d W\n", @@ -3452,63 +3433,63 @@ ipmi_print_power_consmpt_history(struct ipmi_intf * intf, int unit) if (unit == btuphr) { printf("Average Power Consumption "); tempbtuphrconv = watt_to_btuphr_conversion(avgpower.lastminutepower); - printf("%4lld BTU/hr ", tempbtuphrconv); + printf("%4" PRId64 " BTU/hr ", tempbtuphrconv); tempbtuphrconv = watt_to_btuphr_conversion(avgpower.lasthourpower); - printf("%4lld BTU/hr ", tempbtuphrconv); + printf("%4" PRId64 " BTU/hr ", tempbtuphrconv); tempbtuphrconv = watt_to_btuphr_conversion(avgpower.lastdaypower); - printf("%4lld BTU/hr ", tempbtuphrconv); + printf("%4" PRId64 " BTU/hr ", tempbtuphrconv); tempbtuphrconv = watt_to_btuphr_conversion(avgpower.lastweakpower); - printf("%4lld BTU/hr\n", tempbtuphrconv); + printf("%4" PRId64 " BTU/hr\n", tempbtuphrconv); printf("Max Power Consumption "); tempbtuphrconv = watt_to_btuphr_conversion(stPeakpower.lastminutepower); - printf("%4lld BTU/hr ", tempbtuphrconv); + printf("%4" PRId64 " BTU/hr ", tempbtuphrconv); tempbtuphrconv = watt_to_btuphr_conversion(stPeakpower.lasthourpower); - printf("%4lld BTU/hr ", tempbtuphrconv); + printf("%4" PRId64 " BTU/hr ", tempbtuphrconv); tempbtuphrconv = watt_to_btuphr_conversion(stPeakpower.lastdaypower); - printf("%4lld BTU/hr ", tempbtuphrconv); + printf("%4" PRId64 " BTU/hr ", tempbtuphrconv); tempbtuphrconv = watt_to_btuphr_conversion(stPeakpower.lastweakpower); - printf("%4lld BTU/hr\n", tempbtuphrconv); + printf("%4" PRId64 " BTU/hr\n", tempbtuphrconv); printf("Min Power Consumption "); tempbtuphrconv = watt_to_btuphr_conversion(stMinpower.lastminutepower); - printf("%4lld BTU/hr ", tempbtuphrconv); + printf("%4" PRId64 " BTU/hr ", tempbtuphrconv); tempbtuphrconv = watt_to_btuphr_conversion(stMinpower.lasthourpower); - printf("%4lld BTU/hr ", tempbtuphrconv); + printf("%4" PRId64 " BTU/hr ", tempbtuphrconv); tempbtuphrconv = watt_to_btuphr_conversion(stMinpower.lastdaypower); - printf("%4lld BTU/hr ", tempbtuphrconv); + printf("%4" PRId64 " BTU/hr ", tempbtuphrconv); tempbtuphrconv = watt_to_btuphr_conversion(stMinpower.lastweakpower); - printf("%4lld BTU/hr\n\n", tempbtuphrconv); + printf("%4" PRId64 " BTU/hr\n\n", tempbtuphrconv); } else { printf("Average Power Consumption "); tempbtuphrconv = (avgpower.lastminutepower); - printf("%4lld W ", tempbtuphrconv); + printf("%4" PRId64 " W ", tempbtuphrconv); tempbtuphrconv = (avgpower.lasthourpower); - printf("%4lld W ", tempbtuphrconv); + printf("%4" PRId64 " W ", tempbtuphrconv); tempbtuphrconv = (avgpower.lastdaypower); - printf("%4lld W ", tempbtuphrconv); + printf("%4" PRId64 " W ", tempbtuphrconv); tempbtuphrconv=(avgpower.lastweakpower); - printf("%4lld W \n", tempbtuphrconv); + printf("%4" PRId64 " W \n", tempbtuphrconv); printf("Max Power Consumption "); tempbtuphrconv = (stPeakpower.lastminutepower); - printf("%4lld W ", tempbtuphrconv); + printf("%4" PRId64 " W ", tempbtuphrconv); tempbtuphrconv = (stPeakpower.lasthourpower); - printf("%4lld W ", tempbtuphrconv); + printf("%4" PRId64 " W ", tempbtuphrconv); tempbtuphrconv = (stPeakpower.lastdaypower); - printf("%4lld W ", tempbtuphrconv); + printf("%4" PRId64 " W ", tempbtuphrconv); tempbtuphrconv = (stPeakpower.lastweakpower); - printf("%4lld W \n", tempbtuphrconv); + printf("%4" PRId64 " W \n", tempbtuphrconv); printf("Min Power Consumption "); tempbtuphrconv = (stMinpower.lastminutepower); - printf("%4lld W ", tempbtuphrconv); + printf("%4" PRId64 " W ", tempbtuphrconv); tempbtuphrconv = (stMinpower.lasthourpower); - printf("%4lld W ", tempbtuphrconv); + printf("%4" PRId64 " W ", tempbtuphrconv); tempbtuphrconv = (stMinpower.lastdaypower); - printf("%4lld W ", tempbtuphrconv); + printf("%4" PRId64 " W ", tempbtuphrconv); tempbtuphrconv = (stMinpower.lastweakpower); - printf("%4lld W \n\n", tempbtuphrconv); + printf("%4" PRId64 " W \n\n", tempbtuphrconv); } lastminutepeakpower = stPeakpower.lastminutepowertime; @@ -3612,11 +3593,11 @@ ipmi_print_power_cap(struct ipmi_intf * intf,uint8_t unit) if (rc == 0) { if (unit == btuphr) { tempbtuphrconv = watt_to_btuphr_conversion(ipmipowercap.MaximumPowerConsmp); - printf("Maximum power: %lld BTU/hr\n", tempbtuphrconv); + printf("Maximum power: %" PRId64 " BTU/hr\n", tempbtuphrconv); tempbtuphrconv = watt_to_btuphr_conversion(ipmipowercap.MinimumPowerConsmp); - printf("Minimum power: %lld BTU/hr\n", tempbtuphrconv); + printf("Minimum power: %" PRId64 " BTU/hr\n", tempbtuphrconv); tempbtuphrconv = watt_to_btuphr_conversion(ipmipowercap.PowerCap); - printf("Power cap : %lld BTU/hr\n", tempbtuphrconv); + printf("Power cap : %" PRId64 " BTU/hr\n", tempbtuphrconv); } else { printf("Maximum power: %d Watt\n", ipmipowercap.MaximumPowerConsmp); printf("Minimum power: %d Watt\n", ipmipowercap.MinimumPowerConsmp); diff --git a/lib/ipmi_ekanalyzer.c b/lib/ipmi_ekanalyzer.c index d6ce4c7..7a6c63d 100644 --- a/lib/ipmi_ekanalyzer.c +++ b/lib/ipmi_ekanalyzer.c @@ -602,10 +602,13 @@ ipmi_ekanalyzer_main(struct ipmi_intf *intf, int argc, char **argv) */ filename_size = strlen(argv[index]) - SIZE_OF_FILE_TYPE + 1; if (filename_size > 0) { - /* TODO - check malloc() retval */ filename[i] = malloc( filename_size ); if (filename[i] != NULL) { strcpy(filename[i], &argv[index][SIZE_OF_FILE_TYPE]); + } else { + lprintf(LOG_ERR, "ipmitool: malloc failure"); + rc = ERROR_STATUS; + break; } } rc = OK_STATUS; @@ -2205,6 +2208,9 @@ ipmi_ek_create_amc_p2p_record(struct ipmi_ek_multi_header *record, int index_oem = 0; amc_record->oem_guid = malloc(amc_record->guid_count * \ sizeof(struct fru_picmgext_guid)); + if (amc_record->oem_guid == NULL) { + return ERROR_STATUS; + } for (index_oem = 0; index_oem < amc_record->guid_count; index_oem++) { memcpy(&amc_record->oem_guid[index_oem].guid, @@ -2232,6 +2238,9 @@ ipmi_ek_create_amc_p2p_record(struct ipmi_ek_multi_header *record, int ch_index = 0; amc_record->ch_desc = malloc((amc_record->ch_count) * \ sizeof(struct fru_picmgext_amc_channel_desc_record)); + if (amc_record->ch_desc == NULL) { + return ERROR_STATUS; + } for (ch_index = 0; ch_index < amc_record->ch_count; ch_index++) { unsigned int data; @@ -2255,6 +2264,9 @@ ipmi_ek_create_amc_p2p_record(struct ipmi_ek_multi_header *record, int i=0; amc_record->link_desc = malloc(amc_record->link_desc_count * \ sizeof(struct fru_picmgext_amc_link_desc_record)); + if (amc_record->link_desc == NULL) { + return ERROR_STATUS; + } for (i = 0; i< amc_record->link_desc_count; i++) { unsigned int data[2]; struct fru_picmgext_amc_link_desc_record *src, *dst; @@ -2767,7 +2779,6 @@ ipmi_ek_display_board_info_area(FILE *input_file, char *board_type, lprintf(LOG_ERR, "ipmitool: malloc failure"); return (size_t)(-1); } - ret = fread(additional_data, size_board, 1, input_file); if ((ret != 1) || ferror(input_file)) { lprintf(LOG_ERR, "Invalid Additional Data!"); @@ -3363,7 +3374,7 @@ ipmi_ek_display_board_p2p_record(struct ipmi_ek_multi_header *record) printf("\n"); offset += sizeof(struct fru_picmgext_guid); } - for (offset; + for (offset = offset; offset < record->header.len; offset += sizeof(struct fru_picmgext_link_desc)) { /* to solve little endian/big endian problem */ @@ -3522,7 +3533,7 @@ ipmi_ek_display_radial_ipmb0_record(struct ipmi_ek_multi_header *record) if (record->data[offset] < 1) { return; } - for (offset; offset < record->header.len;) { + for (offset = offset; offset < record->header.len;) { unsigned char entry_count = 0; printf(" IPMB-0 Hub Descriptor\n"); printf("\tHardware Address: 0x%02x\n", @@ -4046,14 +4057,18 @@ ipmi_ekanalyzer_fru_file2structure(char *filename, fseek(input_file, multi_offset, SEEK_SET); while (!feof(input_file)) { - /* TODO - check malloc() */ *list_record = malloc(sizeof(struct ipmi_ek_multi_header)); + if (*list_record == NULL) { + lprintf(LOG_ERR, "ipmitool: malloc failure"); + return ERROR_STATUS; + } ret = fread(&(*list_record)->header, START_DATA_OFFSET, 1, input_file); if ((ret != 1) || ferror(input_file)) { - /* TODO - no free?! */ - lprintf(LOG_ERR, "Invalid Header!"); + free(*list_record); + *list_record = NULL; fclose(input_file); + lprintf(LOG_ERR, "Invalid Header!"); return ERROR_STATUS; } if ((*list_record)->header.len == 0) { diff --git a/lib/ipmi_event.c b/lib/ipmi_event.c index 16fc80d..bc32ae8 100644 --- a/lib/ipmi_event.c +++ b/lib/ipmi_event.c @@ -207,18 +207,20 @@ ipmi_send_platform_event_num(struct ipmi_intf * intf, int num) } static int -ipmi_event_find_offset(uint8_t code, - struct ipmi_event_sensor_types * evt, - char * desc) +ipmi_event_find_offset(struct ipmi_intf *intf, uint8_t sensor_type, uint8_t event_type, char *desc) { - if (desc == NULL || code == 0) + const struct ipmi_event_sensor_types *evt; + + if (desc == NULL || sensor_type == 0 || event_type == 0) { return 0x00; + } - while (evt->type) { - if (evt->code == code && evt->desc != NULL && - strncasecmp(desc, evt->desc, __maxlen(desc, evt->desc)) == 0) + for (evt = ipmi_get_first_event_sensor_type(intf, sensor_type, event_type); + evt != NULL; evt = ipmi_get_next_event_sensor_type(evt)) { + if (evt->desc != NULL && + strncasecmp(desc, evt->desc, __maxlen(desc, evt->desc)) == 0) { return evt->offset; - evt++; + } } lprintf(LOG_WARN, "Unable to find matching event offset for '%s'", desc); @@ -226,11 +228,11 @@ ipmi_event_find_offset(uint8_t code, } static void -print_sensor_states(uint8_t sensor_type, uint8_t event_type) +print_sensor_states(struct ipmi_intf *intf, uint8_t sensor_type, uint8_t event_type) { - ipmi_sdr_print_discrete_state_mini( + ipmi_sdr_print_discrete_state_mini(intf, "Sensor States: \n ", "\n ", sensor_type, - event_type, 0xff, 0xff); + event_type, 0xff, 0xff); printf("\n"); } @@ -400,7 +402,7 @@ ipmi_event_fromsensor(struct ipmi_intf * intf, char * id, char * state, char * e * print list of available states for this sensor */ if (state == NULL || strncasecmp(state, "list", 4) == 0) { - print_sensor_states(emsg.sensor_type, emsg.event_type); + print_sensor_states(intf, emsg.sensor_type, emsg.event_type); printf("Sensor State Shortcuts:\n"); for (x = 0; x < sizeof(digi_on)/sizeof(*digi_on); x++) { printf(" %-9s %-9s\n", digi_on[x], digi_off[x]); @@ -422,8 +424,8 @@ ipmi_event_fromsensor(struct ipmi_intf * intf, char * id, char * state, char * e } } if (off == 0) { - off = ipmi_event_find_offset( - emsg.event_type, generic_event_types, state); + off = ipmi_event_find_offset(intf, + emsg.sensor_type, emsg.event_type, state); if (off < 0) return -1; emsg.event_data[0] = off; @@ -440,11 +442,11 @@ ipmi_event_fromsensor(struct ipmi_intf * intf, char * id, char * state, char * e * print list of available states for this sensor */ if (state == NULL || strncasecmp(state, "list", 4) == 0) { - print_sensor_states(emsg.sensor_type, emsg.event_type); + print_sensor_states(intf, emsg.sensor_type, emsg.event_type); return 0; } - off = ipmi_event_find_offset( - emsg.event_type, generic_event_types, state); + off = ipmi_event_find_offset(intf, + emsg.sensor_type, emsg.event_type, state); if (off < 0) return -1; emsg.event_data[0] = off; @@ -460,11 +462,11 @@ ipmi_event_fromsensor(struct ipmi_intf * intf, char * id, char * state, char * e * print list of available states for this sensor */ if (state == NULL || strncasecmp(state, "list", 4) == 0) { - print_sensor_states(emsg.sensor_type, emsg.event_type); + print_sensor_states(intf, emsg.sensor_type, emsg.event_type); return 0; } - off = ipmi_event_find_offset( - emsg.sensor_type, sensor_specific_types, state); + off = ipmi_event_find_offset(intf, + emsg.sensor_type, emsg.event_type, state); if (off < 0) return -1; emsg.event_data[0] = off; diff --git a/lib/ipmi_firewall.c b/lib/ipmi_firewall.c index c3f51ad..26bfd30 100644 --- a/lib/ipmi_firewall.c +++ b/lib/ipmi_firewall.c @@ -899,7 +899,7 @@ static int ipmi_firewall_info(struct ipmi_intf * intf, int argc, char ** argv) { int ret = 0; - struct ipmi_function_params p = {0xe, -1, -1, -1, -1}; + struct ipmi_function_params p = {0xe, -1, -1, -1, -1, 0}; struct bmc_fn_support * bmc_fn_support; unsigned int l, n, c; @@ -1012,7 +1012,7 @@ ipmi_firewall_info(struct ipmi_intf * intf, int argc, char ** argv) static int ipmi_firewall_enable_disable(struct ipmi_intf * intf, int enable, int argc, char ** argv) { - struct ipmi_function_params p = {0xe, -1, -1, -1, -1}; + struct ipmi_function_params p = {0xe, -1, -1, -1, -1, 0}; struct bmc_fn_support * bmc_fn_support; int ret; unsigned int l, n, c; @@ -1103,7 +1103,7 @@ ipmi_firewall_enable_disable(struct ipmi_intf * intf, int enable, int argc, char static int ipmi_firewall_reset(struct ipmi_intf * intf, int argc, char ** argv) { - struct ipmi_function_params p = {0xe, -1, -1, -1, -1}; + struct ipmi_function_params p = {0xe, -1, -1, -1, -1, 0}; struct bmc_fn_support * bmc_fn_support; int ret; unsigned int l, n, c; @@ -1135,8 +1135,8 @@ ipmi_firewall_reset(struct ipmi_intf * intf, int argc, char ** argv) for (l=0; l<MAX_LUN; l++) { p.lun = l; - for (n=0; n<MAX_NETFN; n+=2) { - p.netfn = n; + for (n=0; n<MAX_NETFN_PAIR; n++) { + p.netfn = n*2; for (c=0; c<MAX_COMMAND; c++) { p.command = c; printf("reset lun %d, netfn %d, command %d, subfn\n", l, n, c); diff --git a/lib/ipmi_fru.c b/lib/ipmi_fru.c index 5c94b08..cf00eff 100644 --- a/lib/ipmi_fru.c +++ b/lib/ipmi_fru.c @@ -50,6 +50,13 @@ #define FRU_MULTIREC_CHUNK_SIZE (255 + sizeof(struct fru_multirec_header)) +static const char *section_id[4] = { + "Internal Use Section", + "Chassis Section", + "Board Section", + "Product Section" +}; + /* From lib/dimm_spd.c: */ int ipmi_spd_print_fru(struct ipmi_intf * intf, uint8_t id); @@ -677,9 +684,9 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id, break; } if (rsp->ccode > 0) { - /* if we get C8h or CAh completion code then we requested too + /* if we get C7h or C8h or CAh return code then we requested too * many bytes at once so try again with smaller size */ - if ((rsp->ccode == 0xc8 || rsp->ccode == 0xca) + if ((rsp->ccode == 0xc7 || rsp->ccode == 0xc8 || rsp->ccode == 0xca) && fru->max_read_size > 8) { if (fru->max_read_size > 32) { /* subtract read length more aggressively */ @@ -2281,8 +2288,7 @@ static void ipmi_fru_picmg_ext_print(uint8_t * fru_data, int off, int length) printf(" Link Type Extension: 0x%02x - ", d->ext); if (d->type == FRU_PICMGEXT_LINK_TYPE_BASE) { - switch (d->ext) - { + switch (d->ext) { case 0: printf("10/100/1000BASE-T Link (four-pair)\n"); break; @@ -2290,76 +2296,93 @@ static void ipmi_fru_picmg_ext_print(uint8_t * fru_data, int off, int length) printf("ShMC Cross-connect (two-pair)\n"); break; default: - printf("Unknwon\n"); + printf("Unknown\n"); break; } } else if (d->type == FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET) { - switch (d->ext) - { + switch (d->ext) { case 0: - printf("Fixed 1000Base-BX\n"); + printf("1000Base-BX\n"); break; case 1: - printf("Fixed 10GBASE-BX4 [XAUI]\n"); + printf("10GBase-BX4 [XAUI]\n"); break; case 2: printf("FC-PI\n"); break; + case 3: + printf("1000Base-KX\n"); + break; + case 4: + printf("10GBase-KX4\n"); + break; + default: + printf("Unknown\n"); + break; + } + } else if (d->type == FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET_10GBD) { + switch (d->ext) { + case 0: + printf("10GBase-KR\n"); + break; + case 1: + printf("40GBase-KR4\n"); + break; default: - printf("Unknwon\n"); + printf("Unknown\n"); break; } } else if (d->type == FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND) { - printf("Unknwon\n"); + printf("Unknown\n"); } else if (d->type == FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR) { - printf("Unknwon\n"); + printf("Unknown\n"); } else if (d->type == FRU_PICMGEXT_LINK_TYPE_PCIE) { - printf("Unknwon\n"); + printf("Unknown\n"); } else { - printf("Unknwon\n"); + printf("Unknown\n"); } printf(" Link Type: 0x%02x - ", d->type); - if (d->type == 0 || d->type == 0xff) { - printf("Reserved\n"); - } - else if (d->type >= 0x06 && d->type <= 0xef) { - printf("Reserved\n"); - } - else if (d->type >= 0xf0 && d->type <= 0xfe) { - printf("OEM GUID Definition\n"); - } - else { - switch (d->type) - { - case FRU_PICMGEXT_LINK_TYPE_BASE: - printf("PICMG 3.0 Base Interface 10/100/1000\n"); - break; - case FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET: - printf("PICMG 3.1 Ethernet Fabric Interface\n"); - break; - case FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND: - printf("PICMG 3.2 Infiniband Fabric Interface\n"); - break; - case FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR: - printf("PICMG 3.3 Star Fabric Interface\n"); - break; - case FRU_PICMGEXT_LINK_TYPE_PCIE: - printf("PICMG 3.4 PCI Express Fabric Interface\n"); - break; - default: + switch (d->type) { + case FRU_PICMGEXT_LINK_TYPE_BASE: + printf("PICMG 3.0 Base Interface 10/100/1000\n"); + break; + case FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET: + printf("PICMG 3.1 Ethernet Fabric Interface\n"); + printf(" Base signaling Link Class\n"); + break; + case FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND: + printf("PICMG 3.2 Infiniband Fabric Interface\n"); + break; + case FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR: + printf("PICMG 3.3 Star Fabric Interface\n"); + break; + case FRU_PICMGEXT_LINK_TYPE_PCIE: + printf("PICMG 3.4 PCI Express Fabric Interface\n"); + break; + case FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET_10GBD: + printf("PICMG 3.1 Ethernet Fabric Interface\n"); + printf(" 10.3125Gbd signaling Link Class\n"); + break; + default: + if (d->type == 0 || d->type == 0xff) { + printf("Reserved\n"); + } else if (d->type >= 0x06 && d->type <= 0xef) { + printf("Reserved\n"); + } else if (d->type >= 0xf0 && d->type <= 0xfe) { + printf("OEM GUID Definition\n"); + } else { printf("Invalid\n"); - break; - } + } + break; } printf(" Link Designator: \n"); printf(" Port Flag: 0x%02x\n", d->desig_port); printf(" Interface: 0x%02x - ", d->desig_if); - switch (d->desig_if) - { + switch (d->desig_if) { case FRU_PICMGEXT_DESIGN_IF_BASE: printf("Base Interface\n"); break; diff --git a/lib/ipmi_hpmfwupg.c b/lib/ipmi_hpmfwupg.c index 9cbd4ff..bbcffc0 100644 --- a/lib/ipmi_hpmfwupg.c +++ b/lib/ipmi_hpmfwupg.c @@ -1399,7 +1399,12 @@ HpmfwupgGetBufferFromFile(char *imageFilename, return HPMFWUPG_ERROR; } /* Get the raw data in file */ - fseek(pImageFile, 0, SEEK_END); + ret = fseek(pImageFile, 0, SEEK_END); + if (ret != 0) { + lprintf(LOG_ERR, "Failed to seek in the image file '%s'", + imageFilename); + return HPMFWUPG_ERROR; + } pFwupgCtx->imageSize = ftell(pImageFile); pFwupgCtx->pImageData = malloc(sizeof(unsigned char)*pFwupgCtx->imageSize); if (pFwupgCtx->pImageData == NULL) { diff --git a/lib/ipmi_lanp.c b/lib/ipmi_lanp.c index ecd313a..65d881b 100644 --- a/lib/ipmi_lanp.c +++ b/lib/ipmi_lanp.c @@ -104,7 +104,7 @@ is_lan_channel(struct ipmi_intf * intf, uint8_t chan) * @intf: ipmi interface handle * @start: channel number to start searching from */ -static uint8_t +uint8_t find_lan_channel(struct ipmi_intf * intf, uint8_t start) { uint8_t chan = 0; @@ -704,8 +704,7 @@ ipmi_lan_print(struct ipmi_intf * intf, uint8_t chan) if (p == NULL) return -1; if (p->data != NULL) - printf("%-24s: %02x:%02x:%02x:%02x:%02x:%02x\n", p->desc, - p->data[0], p->data[1], p->data[2], p->data[3], p->data[4], p->data[5]); + printf("%-24s: %s\n", p->desc, mac2str(p->data)); p = get_lan_param(intf, chan, IPMI_LANP_SNMP_STRING); if (p == NULL) @@ -744,8 +743,7 @@ ipmi_lan_print(struct ipmi_intf * intf, uint8_t chan) if (p == NULL) return -1; if (p->data != NULL) - printf("%-24s: %02x:%02x:%02x:%02x:%02x:%02x\n", p->desc, - p->data[0], p->data[1], p->data[2], p->data[3], p->data[4], p->data[5]); + printf("%-24s: %s\n", p->desc, mac2str(p->data)); p = get_lan_param(intf, chan, IPMI_LANP_BAK_GATEWAY_IP); if (p == NULL) @@ -758,8 +756,7 @@ ipmi_lan_print(struct ipmi_intf * intf, uint8_t chan) if (p == NULL) return -1; if (p->data != NULL) - printf("%-24s: %02x:%02x:%02x:%02x:%02x:%02x\n", p->desc, - p->data[0], p->data[1], p->data[2], p->data[3], p->data[4], p->data[5]); + printf("%-24s: %s\n", p->desc, mac2str(p->data)); p = get_lan_param(intf, chan, IPMI_LANP_VLAN_ID); if (p != NULL && p->data != NULL) { @@ -1103,42 +1100,6 @@ ipmi_set_user_access(struct ipmi_intf *intf, uint8_t channel, uint8_t user_id) } } -/* get_cmdline_macaddr - parse-out MAC address from given string and store it - * into buffer. - * - * @arg: string to be parsed. - * @buf: buffer of 6 to hold parsed MAC address. - * - * returns zero on success, (-1) on error and error message is printed-out. - */ -static int -get_cmdline_macaddr(char *arg, uint8_t *buf) -{ - uint32_t m1 = 0; - uint32_t m2 = 0; - uint32_t m3 = 0; - uint32_t m4 = 0; - uint32_t m5 = 0; - uint32_t m6 = 0; - if (sscanf(arg, "%02x:%02x:%02x:%02x:%02x:%02x", - &m1, &m2, &m3, &m4, &m5, &m6) != 6) { - lprintf(LOG_ERR, "Invalid MAC address: %s", arg); - return -1; - } - if (m1 > UINT8_MAX || m2 > UINT8_MAX - || m3 > UINT8_MAX || m4 > UINT8_MAX - || m5 > UINT8_MAX || m6 > UINT8_MAX) { - lprintf(LOG_ERR, "Invalid MAC address: %s", arg); - return -1; - } - buf[0] = (uint8_t)m1; - buf[1] = (uint8_t)m2; - buf[2] = (uint8_t)m3; - buf[3] = (uint8_t)m4; - buf[4] = (uint8_t)m5; - buf[5] = (uint8_t)m6; - return 0; -} static int @@ -1243,12 +1204,27 @@ get_cmdline_ipaddr(char * arg, uint8_t * buf) static int ipmi_lan_set_vlan_id(struct ipmi_intf *intf, uint8_t chan, char *string) { + struct lan_param *p; uint8_t data[2]; int rc; if (string == NULL) { - data[0] = 0; - data[1] = 0; + lprintf(LOG_DEBUG, "Get current VLAN ID from BMC."); + p = get_lan_param(intf, chan, IPMI_LANP_VLAN_ID); + if (p != NULL && p->data != NULL && p->data_len > 1) { + int id = ((p->data[1] & 0x0f) << 8) + p->data[0]; + if (id < 1 || id > 4094) { + lprintf(LOG_ERR, + "Retrieved VLAN ID %i is out of range <1..4094>.", + id); + return (-1); + } + data[0] = p->data[0]; + data[1] = p->data[1] & 0x0F; + } else { + data[0] = 0; + data[1] = 0; + } } else { int id = 0; @@ -1540,11 +1516,11 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) print_lan_set_usage(); return -1; } - rc = get_cmdline_macaddr(argv[2], data); + rc = str2mac(argv[2], data); if (rc == 0) { - printf("Setting LAN %s to %02x:%02x:%02x:%02x:%02x:%02x\n", - ipmi_lan_params[IPMI_LANP_MAC_ADDR].desc, - data[0], data[1], data[2], data[3], data[4], data[5]); + printf("Setting LAN %s to %s\n", + ipmi_lan_params[IPMI_LANP_MAC_ADDR].desc, + mac2str(data)); rc = set_lan_param(intf, chan, IPMI_LANP_MAC_ADDR, data, 6); } } @@ -1566,10 +1542,10 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) rc = set_lan_param(intf, chan, IPMI_LANP_DEF_GATEWAY_IP, data, 4); } else if ((strncmp(argv[2], "macaddr", 7) == 0) && - (get_cmdline_macaddr(argv[3], data) == 0)) { - printf("Setting LAN %s to %02x:%02x:%02x:%02x:%02x:%02x\n", - ipmi_lan_params[IPMI_LANP_DEF_GATEWAY_MAC].desc, - data[0], data[1], data[2], data[3], data[4], data[5]); + (str2mac(argv[3], data) == 0)) { + printf("Setting LAN %s to %s\n", + ipmi_lan_params[IPMI_LANP_DEF_GATEWAY_MAC].desc, + mac2str(data)); rc = set_lan_param(intf, chan, IPMI_LANP_DEF_GATEWAY_MAC, data, 6); } else { @@ -1595,10 +1571,10 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) rc = set_lan_param(intf, chan, IPMI_LANP_BAK_GATEWAY_IP, data, 4); } else if ((strncmp(argv[2], "macaddr", 7) == 0) && - (get_cmdline_macaddr(argv[3], data) == 0)) { - printf("Setting LAN %s to %02x:%02x:%02x:%02x:%02x:%02x\n", - ipmi_lan_params[IPMI_LANP_BAK_GATEWAY_MAC].desc, - data[0], data[1], data[2], data[3], data[4], data[5]); + (str2mac(argv[3], data) == 0)) { + printf("Setting LAN %s to %s\n", + ipmi_lan_params[IPMI_LANP_BAK_GATEWAY_MAC].desc, + mac2str(data)); rc = set_lan_param(intf, chan, IPMI_LANP_BAK_GATEWAY_MAC, data, 6); } else { @@ -1776,9 +1752,8 @@ ipmi_lan_alert_print(struct ipmi_intf * intf, uint8_t channel, uint8_t alert) printf("%-24s: %d.%d.%d.%d\n", "Alert IP Address", paddr[3], paddr[4], paddr[5], paddr[6]); - printf("%-24s: %02x:%02x:%02x:%02x:%02x:%02x\n", "Alert MAC Address", - paddr[7], paddr[8], paddr[9], - paddr[10], paddr[11], paddr[12]); + printf("%-24s: %s\n", "Alert MAC Address", + mac2str(&paddr[7])); printf("\n"); return 0; @@ -1843,7 +1818,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert, } /* alert destination mac address */ else if (strncasecmp(argv[0], "macaddr", 7) == 0 && - (get_cmdline_macaddr(argv[1], temp) == 0)) { + (str2mac(argv[1], temp) == 0)) { /* get current parameter */ p = get_lan_param_select(intf, chan, IPMI_LANP_DEST_ADDR, alert); if (p == NULL) { @@ -1853,8 +1828,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert, /* set new macaddr */ memcpy(data+7, temp, 6); printf("Setting LAN Alert %d MAC Address to " - "%02x:%02x:%02x:%02x:%02x:%02x\n", alert, - data[7], data[8], data[9], data[10], data[11], data[12]); + "%s\n", alert, mac2str(&data[7])); rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_ADDR, data, p->data_len); } /* alert destination gateway selector */ diff --git a/lib/ipmi_lanp6.c b/lib/ipmi_lanp6.c new file mode 100644 index 0000000..bbffb89 --- /dev/null +++ b/lib/ipmi_lanp6.c @@ -0,0 +1,1240 @@ +/* + * Copyright (c) 2016 Pentair Technical Products. All right 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 Pentair Technical Products 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * PENTAIR TECHNICAL SOLUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <ipmitool/helper.h> +#include <ipmitool/ipmi_cc.h> +#include <ipmitool/ipmi_cfgp.h> +#include <ipmitool/ipmi_lanp.h> +#include <ipmitool/ipmi_lanp6.h> +#include <ipmitool/log.h> + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <arpa/inet.h> + +/* + * LAN6 command values. + */ +enum { + LANP_CMD_SAVE, + LANP_CMD_SET, + LANP_CMD_PRINT, + LANP_CMD_LOCK, + LANP_CMD_COMMIT, + LANP_CMD_DISCARD, + LANP_CMD_HELP, + LANP_CMD_ANY = 0xFF +}; + +/* + * Generic LAN configuration parameters. + */ +const struct ipmi_lanp generic_lanp6[] = { + { 0, "Set In Progress", 1 }, + { 50, "IPv6/IPv4 Support", 1 }, + { 51, "IPv6/IPv4 Addressing Enables", 1 }, + { 52, "IPv6 Header Traffic Class", 1 }, + { 53, "IPv6 Header Static Hop Limit", 1 }, + { 54, "IPv6 Header Flow Label", 3 }, + { 55, "IPv6 Status", 3 }, + { 56, "IPv6 Static Address", 20 }, + { 57, "IPv6 DHCPv6 Static DUID Storage Length", 1 }, + { 58, "IPv6 DHCPv6 Static DUID", 18 }, + { 59, "IPv6 Dynamic Address", 20 }, + { 60, "IPv6 DHCPv6 Dynamic DUID Storage Length", 1 }, + { 61, "IPv6 DHCPv6 Dynamic DUID", 18 }, + { 62, "IPv6 DHCPv6 Timing Configuration Support", 1 }, + { 63, "IPv6 DHCPv6 Timing Configuration", 18 }, + { 64, "IPv6 Router Address Configuration Control", 1 }, + { 65, "IPv6 Static Router 1 IP Address", 16 }, + { 66, "IPv6 Static Router 1 MAC Address", 6 }, + { 67, "IPv6 Static Router 1 Prefix Length", 1 }, + { 68, "IPv6 Static Router 1 Prefix Value", 16 }, + { 69, "IPv6 Static Router 2 IP Address", 16 }, + { 70, "IPv6 Static Router 2 MAC Address", 6 }, + { 71, "IPv6 Static Router 2 Prefix Length", 1 }, + { 72, "IPv6 Static Router 2 Prefix Value", 16 }, + { 73, "IPv6 Number of Dynamic Router Info Sets", 1 }, + { 74, "IPv6 Dynamic Router Info IP Address", 17 }, + { 75, "IPv6 Dynamic Router Info MAC Address", 7 }, + { 76, "IPv6 Dynamic Router Info Prefix Length", 2 }, + { 77, "IPv6 Dynamic Router Info Prefix Value", 17 }, + { 78, "IPv6 Dynamic Router Received Hop Limit", 1 }, + { 79, "IPv6 ND/SLAAC Timing Configuration Support", 1 }, + { 80, "IPv6 ND/SLAAC Timing Configuration", 18 }, + { 0, NULL, 0 } +}; + +/* + * Set/Get LAN Configuration Parameters + * command-specific completion codes. + */ +const struct valstr lanp_cc_vals[] = { + { 0x80, "Parameter not supported" }, + { 0x81, "Set already in progress" }, + { 0x82, "Parameter is read-only" }, + { 0x83, "Write-only parameter" }, + { 0x00, NULL } +}; + +/* + * IPv6/IPv4 Addressing Enables. + */ +const struct valstr ip6_enable_vals[] = { + { 0, "ipv4" }, + { 1, "ipv6" }, + { 2, "both" }, + { 0xFF, NULL } +}; + +/* + * Enable/Disable a static address. + */ +const struct valstr ip6_addr_enable_vals[] = { + { 0x00, "disable" }, + { 0x80, "enable" }, + { 0xFF, NULL } +}; + +/* + * IPv6 address source values. + */ +const struct valstr ip6_addr_sources[] = { + { 0, "static" }, + { 1, "SLAAC" }, + { 2, "DHCPv6" }, + { 0, NULL } +}; + +/* + * IPv6 address status values. + */ +const struct valstr ip6_addr_statuses[] = { + { 0, "active" }, + { 1, "disabled" }, + { 2, "pending" }, + { 3, "failed" }, + { 4, "deprecated" }, + { 5, "invalid" }, + { 0xFF, NULL } +}; + +/* + * DHCPv6 DUID type values. + */ +const struct valstr ip6_duid_types[] = { + { 0, "unknown" }, + { 1, "DUID-LLT" }, + { 2, "DUID-EN" }, + { 3, "DUID-LL" }, + { 0xFF, NULL } +}; + +/* + * Timing Configuration support values. + */ +const struct valstr ip6_cfg_sup_vals[] = { + { 0, "not supported" }, + { 1, "global" }, + { 2, "per interface" }, + { 0xFF, NULL } +}; + +/* + * Router Address Configuration Control values. + */ +const struct valstr ip6_rtr_configs[] = { + { 1, "static" }, + { 2, "dynamic" }, + { 3, "both" }, + { 0xFF, NULL } +}; + + +const struct valstr ip6_command_vals[] = { + { LANP_CMD_SET, "set" }, + { LANP_CMD_SAVE, "save" }, + { LANP_CMD_PRINT, "print" }, + { LANP_CMD_LOCK, "lock" }, + { LANP_CMD_COMMIT, "commit" }, + { LANP_CMD_DISCARD, "discard" }, + { LANP_CMD_HELP, "help" }, + { LANP_CMD_ANY, NULL } +}; + +static const struct ipmi_cfgp lan_cfgp[] = { + { .name = "support", .format = NULL, .size = 1, + .access = CFGP_RDONLY, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_SUPPORT + }, + { .name = "enables", .format = "{ipv4|ipv6|both}", .size = 1, + .access = CFGP_RDWR, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_ENABLES + }, + { .name = "traffic_class", .format = "<value>", .size = 1, + .access = CFGP_RDWR, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_TRAFFIC_CLASS + }, + { .name = "static_hops", .format = "<value>", .size = 1, + .access = CFGP_RDWR, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_STATIC_HOPS + }, + { .name = "flow_label", .format = "<value>", .size = 3, + .access = CFGP_RDWR, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_FLOW_LABEL + }, + { .name = "status", .format = NULL, .size = 3, + .access = CFGP_RDONLY, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_STATUS + }, + { .name = "static_addr", + .format = "{enable|disable} <addr> <pfx_len>", .size = 20, + .access = CFGP_RDWR, + .is_set = 1, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_STATIC_ADDR + }, + { .name = "static_duid_stg", .format = NULL, .size = 1, + .access = CFGP_RDONLY, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_STATIC_DUID_STG + }, + { .name = "static_duid", .format = "<data>", .size = 18, + .access = CFGP_RDWR, + .is_set = 1, .first_set = 0, .has_blocks = 1, .first_block = 0, + .specific = IPMI_LANP_IP6_STATIC_DUID + }, + { .name = "dynamic_addr", .format = NULL, .size = 20, + .access = CFGP_RDONLY, + .is_set = 1, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_DYNAMIC_ADDR + }, + { .name = "dynamic_duid_stg", .format = NULL, .size = 1, + .access = CFGP_RDONLY, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_DYNAMIC_DUID_STG + }, + { .name = "dynamic_duid", .format = "<data>", .size = 18, + .access = CFGP_RDWR, + .is_set = 1, .first_set = 0, .has_blocks = 1, .first_block = 0, + .specific = IPMI_LANP_IP6_DYNAMIC_DUID + }, + { .name = "dhcp6_cfg_sup", .format = NULL, .size = 1, + .access = CFGP_RDONLY, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_DHCP6_CFG_SUP + }, + { .name = "dhcp6_cfg", .format = "<data> <data>", .size = 36, + .access = CFGP_RDWR, + .is_set = 1, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_DHCP6_CFG + }, + { .name = "rtr_cfg", .format = "{static|dynamic|both}", .size = 1, + .access = CFGP_RDWR, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_ROUTER_CFG + }, + { .name = "static_rtr", + .format = "<addr> <macaddr> <prefix> <prefix_len>", .size = 43, + .access = CFGP_RDWR, + .is_set = 1, .first_set = 1, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_STATIC_RTR1_ADDR + }, + { .name = "num_dynamic_rtrs", .format = NULL, .size = 1, + .access = CFGP_RDONLY, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_NUM_DYNAMIC_RTRS + }, + { .name = "dynamic_rtr", .format = NULL, .size = 43, + .access = CFGP_RDONLY, + .is_set = 1, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_DYNAMIC_RTR_ADDR + }, + { .name = "dynamic_hops", .format = NULL, .size = 1, + .access = CFGP_RDONLY, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_DYNAMIC_HOPS + }, + { .name = "ndslaac_cfg_sup", .format = NULL, .size = 1, + .access = CFGP_RDONLY, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_NDSLAAC_CFG_SUP + }, + { .name = "ndslaac_cfg", .format = "<data>", .size = 18, + .access = CFGP_RDWR, + .is_set = 1, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_NDSLAAC_CFG + } +}; + +/* + * Lookup LAN parameter descriptor by parameter selector. + */ +const struct ipmi_lanp * +lookup_lanp(int param) +{ + const struct ipmi_lanp *p = generic_lanp6; + + while (p->name) { + if (p->selector == param) { + return p; + } + + p++; + } + + return NULL; +} + +/* + * Print request error. + */ +static int +ipmi_lanp_err(const struct ipmi_rs *rsp, const struct ipmi_lanp *p, + const char *action, int quiet) +{ + const char *reason; + char cc_msg[10]; + int log_level = LOG_ERR; + int err; + + if (rsp == NULL) { + reason = "No response"; + err = -1; + } else { + err = rsp->ccode; + if (quiet == 1 + && (rsp->ccode == 0x80 + || rsp->ccode == IPMI_CC_PARAM_OUT_OF_RANGE + || rsp->ccode == IPMI_CC_INV_DATA_FIELD_IN_REQ)) { + /* be quiet */ + return err; + } + + if (rsp->ccode >= 0xC0) { + /* browse for generic completion codes */ + reason = val2str(rsp->ccode, completion_code_vals); + } else { + /* browse for command-specific completion codes first */ + reason = val2str(rsp->ccode, lanp_cc_vals); + } + + if (reason == NULL) { + /* print completion code value */ + snprintf(cc_msg, sizeof(cc_msg), "CC=%02x", rsp->ccode); + reason = cc_msg; + } + + if (rsp->ccode == IPMI_CC_OK) { + log_level = LOG_DEBUG; + } + } + + lprintf(log_level, "Failed to %s %s: %s", action, p->name, reason); + return err; +} + +/* + * Get dynamic OEM LAN configuration parameter from BMC. + * Dynamic in this context is when the base for OEM LAN parameters + * is not known apriori. + */ +int +ipmi_get_dynamic_oem_lanp(void *priv, const struct ipmi_lanp *param, + int oem_base, int set_selector, int block_selector, + void *data, int quiet) +{ + struct ipmi_lanp_priv *lp = priv; + struct ipmi_rs *rsp; + struct ipmi_rq req; + uint8_t req_data[4]; + int length; + + if (!priv || !param || !data) { + return -1; + } + req_data[0] = lp->channel; + req_data[1] = param->selector + oem_base; + req_data[2] = set_selector; + req_data[3] = block_selector; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_TRANSPORT; + req.msg.cmd = 2; + req.msg.data = req_data; + req.msg.data_len = 4; + + lprintf(LOG_INFO, "Getting parameter '%s' set %d block %d", + param->name, set_selector, block_selector); + + rsp = lp->intf->sendrecv(lp->intf, &req); + if (rsp == NULL || rsp->ccode) { + return ipmi_lanp_err(rsp, param, "get", quiet); + } + + memset(data, 0, param->size); + + if (rsp->data_len - 1 < param->size) { + length = rsp->data_len - 1; + } else { + length = param->size; + } + + if (length) { + memcpy(data, rsp->data + 1, length); + } + + return 0; +} + +/* + * Get generic LAN configuration parameter. + */ +int +ipmi_get_lanp(void *priv, int param_selector, int set_selector, + int block_selector, void *data, int quiet) +{ + return ipmi_get_dynamic_oem_lanp(priv, lookup_lanp(param_selector), 0, + set_selector, block_selector, data, quiet); +} + +/* + * Set dynamic OEM LAN configuration parameter to BMC. + * Dynamic in this context is when the base for OEM LAN parameters + * is not known apriori. + */ +int +ipmi_set_dynamic_oem_lanp(void *priv, const struct ipmi_lanp *param, + int base, const void *data) +{ + struct ipmi_lanp_priv *lp = priv; + struct ipmi_rs *rsp; + struct ipmi_rq req; + uint8_t req_data[32]; + + if (!priv || !param || !data) { + return -1; + } + /* fill the first two bytes */ + req_data[0] = lp->channel; + req_data[1] = param->selector + base; + + /* fill the rest data */ + memcpy(&req_data[2], data, param->size); + + /* fill request */ + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_TRANSPORT; + req.msg.cmd = 1; + req.msg.data = req_data; + req.msg.data_len = param->size + 2; + + lprintf(LOG_INFO, "Setting parameter '%s'", param->name); + + rsp = lp->intf->sendrecv(lp->intf, &req); + if (rsp == NULL || rsp->ccode) { + return ipmi_lanp_err(rsp, param, "set", 0); + } + + return 0; +} + +/* + * Set generic LAN configuration parameter. + */ +int +ipmi_set_lanp(void *priv, int param_selector, const void *data) +{ + return ipmi_set_dynamic_oem_lanp(priv, lookup_lanp(param_selector), + 0, data); +} + +static int +lanp_parse_cfgp(const struct ipmi_cfgp *p, int set, int block, + int argc, const char *argv[], unsigned char *data) +{ + unsigned int v; + + if (argc == 0) { + return -1; + } + + switch(p->specific) { + case IPMI_LANP_IP6_ENABLES: + data[0] = str2val(argv[0], ip6_enable_vals); + if (data[0] == 0xFF) { + lprintf(LOG_ERR, "invalid value"); + return -1; + } + break; + + case IPMI_LANP_IP6_FLOW_LABEL: + if (str2uint(argv[0], &v)) { + lprintf(LOG_ERR, "invalid value"); + return -1; + } + + data[0] = (v >> 16) & 0x0F; + data[1] = (v >> 8) & 0xFF; + data[2] = v & 0xFF; + break; + + case IPMI_LANP_IP6_STATUS: + if (argc < 3) { + return -1; + } + + if (str2uchar(argv[0], &data[0]) + || str2uchar(argv[1], &data[1]) + || str2uchar(argv[2], &data[2])) { + lprintf(LOG_ERR, "invalid value"); + return -1; + } + break; + + case IPMI_LANP_IP6_STATIC_ADDR: + case IPMI_LANP_IP6_DYNAMIC_ADDR: + if (argc < 3) { + return -1; + } + + data[0] = set; + if (p->specific == IPMI_LANP_IP6_STATIC_ADDR) { + data[1] = str2val(argv[0], ip6_addr_enable_vals); + } else { + data[1] = str2val(argv[0], ip6_addr_sources); + } + if (data[1] == 0xFF) { + lprintf(LOG_ERR, "invalid value"); + return -1; + } + + if (inet_pton(AF_INET6, argv[1], &data[2]) != 1) { + lprintf(LOG_ERR, "invalid value"); + return -1; + } + + if (str2uchar(argv[2], &data[18])) { + lprintf(LOG_ERR, "invalid value"); + return -1; + } + + if (argc >= 4) { + data[19] = str2val(argv[3], ip6_addr_statuses); + } + break; + + case IPMI_LANP_IP6_STATIC_DUID: + case IPMI_LANP_IP6_DYNAMIC_DUID: + case IPMI_LANP_IP6_NDSLAAC_CFG: + data[0] = set; + data[1] = block; + if (ipmi_parse_hex(argv[0], &data[2], 16) < 0) { + lprintf(LOG_ERR, "invalid value"); + return -1; + } + break; + + case IPMI_LANP_IP6_DHCP6_CFG: + data[0] = set; + data[1] = 0; + data[18] = set; + data[19] = 1; + + if (ipmi_parse_hex(argv[0], &data[2], 16) < 0 + || (argc > 1 && + ipmi_parse_hex(argv[1], &data[20], 6) < 0)) { + lprintf(LOG_ERR, "invalid value"); + return -1; + } + break; + + case IPMI_LANP_IP6_ROUTER_CFG: + data[0] = str2val(argv[0], ip6_rtr_configs); + if (data[0] == 0xFF) { + lprintf(LOG_ERR, "invalid value"); + return -1; + } + break; + + case IPMI_LANP_IP6_STATIC_RTR1_ADDR: + if (set > 2) { + lprintf(LOG_ERR, "invalid value"); + return -1; + } + + case IPMI_LANP_IP6_DYNAMIC_RTR_ADDR: + if (argc < 4) { + return -1; + } + + /* + * Data is stored in the following way: + * 0: <set> <addr1>...<addr16> + * 17: <set> <mac1>...<mac6> + * 24: <set> <pfxlen> + * 26: <set> <pfx1>...<pfx16> + */ + data[0] = data[17] = data[24] = data[26] = set; + + if (inet_pton(AF_INET6, argv[0], &data[1]) != 1 + || str2mac(argv[1], &data[18]) + || inet_pton(AF_INET6, argv[2], &data[27]) != 1 + || str2uchar(argv[3], &data[25])) { + lprintf(LOG_ERR, "invalid value"); + return -1; + } + break; + + default: + if (str2uchar(argv[0], &data[0])) { + lprintf(LOG_ERR, "invalid value"); + return -1; + } + } + + return 0; +} + +static int +lanp_set_cfgp(void *priv, const struct ipmi_cfgp *p, const unsigned char *data) +{ + int ret; + int param = p->specific; + int off = 0; + + switch(param) { + case IPMI_LANP_IP6_DHCP6_CFG: + ret = ipmi_set_lanp(priv, param, &data[0]); + if (ret == 0) { + ret = ipmi_set_lanp(priv, param, &data[18]); + } + break; + + case IPMI_LANP_IP6_STATIC_RTR1_ADDR: + if (data[0] == 2) { + param = IPMI_LANP_IP6_STATIC_RTR2_ADDR; + } + off = 1; + + case IPMI_LANP_IP6_DYNAMIC_RTR_ADDR: + ret = ipmi_set_lanp(priv, param, &data[0 + off]); + if (ret == 0) { + ret = ipmi_set_lanp(priv, param + 1, &data[17 + off]); + } + if (ret == 0) { + ret = ipmi_set_lanp(priv, param + 2, &data[24 + off]); + } + if (ret == 0) { + ret = ipmi_set_lanp(priv, param + 3, &data[26 + off]); + } + break; + + + default: + ret = ipmi_set_lanp(priv, param, data); + } + + return ret; +} + +static int +lanp_get_cfgp(void *priv, const struct ipmi_cfgp *p, + int set, int block, unsigned char *data, int quiet) +{ + int ret; + int param = p->specific; + int off = 0; + + switch(param) { + case IPMI_LANP_IP6_DHCP6_CFG: + ret = ipmi_get_lanp(priv, param, set, 0, &data[0], quiet); + if (ret == 0) { + ret = ipmi_get_lanp(priv, param, set, + 1, &data[18], quiet); + } + break; + + case IPMI_LANP_IP6_STATIC_RTR1_ADDR: + if (set > 2) { + return -1; + } + + if (set == 2) { + param = IPMI_LANP_IP6_STATIC_RTR2_ADDR; + } + set = 0; + off = 1; + data[0] = data[17] = data[24] = data[26] = set; + + case IPMI_LANP_IP6_DYNAMIC_RTR_ADDR: + ret = ipmi_get_lanp(priv, param, set, block, + &data[0 + off], quiet); + if (ret == 0) { + ret = ipmi_get_lanp(priv, param + 1, set, block, + &data[17 + off], 0); + } + if (ret == 0) { + ret = ipmi_get_lanp(priv, param + 2, set, block, + &data[24 + off], 0); + } + if (ret == 0) { + ret = ipmi_get_lanp(priv, param + 3, set, block, + &data[26 + off], 0); + } + break; + + default: + ret = ipmi_get_lanp(priv, param, set, block, data, quiet); + } + + return ret; +} + +static int +lanp_save_cfgp(const struct ipmi_cfgp *p, const unsigned char *data, FILE *file) +{ + char addr[INET6_ADDRSTRLEN]; + char pfx[INET6_ADDRSTRLEN]; + const char *src; + + switch(p->specific) { + case IPMI_LANP_IP6_ENABLES: + fputs(val2str(data[0], ip6_enable_vals), file); + break; + + case IPMI_LANP_IP6_FLOW_LABEL: + fprintf(file, "0x%xd", (data[0] << 16 ) | (data[1] << 8) | data[2]); + break; + + case IPMI_LANP_IP6_STATUS: + fprintf(file, "%d %d %d", data[0], data[1], data[2]); + break; + + case IPMI_LANP_IP6_STATIC_ADDR: + case IPMI_LANP_IP6_DYNAMIC_ADDR: + if (p->specific == IPMI_LANP_IP6_STATIC_ADDR) { + src = val2str(data[1], ip6_addr_enable_vals); + } else { + src = val2str(data[1], ip6_addr_sources); + } + + fprintf(file, "%s %s %d %s", src, + inet_ntop(AF_INET6, &data[2], addr, sizeof(addr)), + data[18], val2str(data[19], ip6_addr_statuses)); + break; + + case IPMI_LANP_IP6_STATIC_DUID: + case IPMI_LANP_IP6_DYNAMIC_DUID: + case IPMI_LANP_IP6_NDSLAAC_CFG: + fprintf(file, "%s", buf2str(&data[2], 16)); + break; + + case IPMI_LANP_IP6_DHCP6_CFG: + fprintf(file, "%s", buf2str(&data[2], 16)); + fprintf(file, " %s", buf2str(&data[20], 6)); + break; + + case IPMI_LANP_IP6_ROUTER_CFG: + fputs(val2str(data[0], ip6_rtr_configs), file); + break; + + case IPMI_LANP_IP6_STATIC_RTR1_ADDR: + case IPMI_LANP_IP6_DYNAMIC_RTR_ADDR: + fprintf(file, "%s %s %s %d", + inet_ntop(AF_INET6, &data[1], addr, sizeof(addr)), + mac2str(&data[18]), + inet_ntop(AF_INET6, &data[27], pfx, sizeof(pfx)), data[25]); + break; + + default: + fprintf(file, "%d", data[0]); + } + + return 0; +} + + +static int +lanp_print_cfgp(const struct ipmi_cfgp *p, + int set, int block, const unsigned char *data, FILE *file) +{ + char addr[INET6_ADDRSTRLEN]; + char pfx[INET6_ADDRSTRLEN]; + const char *pname; + const struct ipmi_lanp *lanp = lookup_lanp(p->specific); + + if (!lanp || !p || !file || !data || !lanp->name) { + return -1; + } + pname = lanp->name; + + switch(p->specific) { + case IPMI_LANP_IP6_SUPPORT: + fprintf(file, "%s:\n" + " IPv6 only: %s\n" + " IPv4 and IPv6: %s\n" + " IPv6 Destination Addresses for LAN alerting: %s\n", + pname, + data[0] & 1 ? "yes" : "no", + data[0] & 2 ? "yes" : "no", + data[0] & 4 ? "yes" : "no"); + break; + + case IPMI_LANP_IP6_ENABLES: + fprintf(file, "%s: %s\n", + pname, val2str(data[0], ip6_enable_vals)); + break; + + case IPMI_LANP_IP6_FLOW_LABEL: + fprintf(file, "%s: %d\n", + pname, (data[0] << 16 ) | (data[1] << 8) | data[2]); + break; + + case IPMI_LANP_IP6_STATUS: + fprintf(file, "%s:\n" + " Static address max: %d\n" + " Dynamic address max: %d\n" + " DHCPv6 support: %s\n" + " SLAAC support: %s\n", + pname, + data[0], data[1], + (data[2] & 1) ? "yes" : "no", + (data[2] & 2) ? "yes" : "no"); + break; + + case IPMI_LANP_IP6_STATIC_ADDR: + fprintf(file, "%s %d:\n" + " Enabled: %s\n" + " Address: %s/%d\n" + " Status: %s\n", + pname, set, + (data[1] & 0x80) ? "yes" : "no", + inet_ntop(AF_INET6, &data[2], addr, sizeof(addr)), + data[18], val2str(data[19] & 0xF, ip6_addr_statuses)); + break; + + case IPMI_LANP_IP6_DYNAMIC_ADDR: + fprintf(file, "%s %d:\n" + " Source/Type: %s\n" + " Address: %s/%d\n" + " Status: %s\n", + pname, set, + val2str(data[1] & 0xF, ip6_addr_sources), + inet_ntop(AF_INET6, &data[2], addr, sizeof(addr)), + data[18], val2str(data[19] & 0xF, ip6_addr_statuses)); + break; + + case IPMI_LANP_IP6_STATIC_DUID: + case IPMI_LANP_IP6_DYNAMIC_DUID: + if (block == 0) { + fprintf(file, "%s %d:\n" + " Length: %d\n" + " Type: %s\n", + pname, set, data[2], + val2str((data[3] << 8) + data[4], ip6_duid_types)); + } + fprintf(file, " %s\n", buf2str(&data[2], 16)); + break; + + case IPMI_LANP_IP6_DHCP6_CFG_SUP: + case IPMI_LANP_IP6_NDSLAAC_CFG_SUP: + fprintf(file, "%s: %s\n", + pname, val2str(data[0], ip6_cfg_sup_vals)); + break; + + case IPMI_LANP_IP6_DHCP6_CFG: + fprintf(file, "%s %d:\n", pname, set); + + fprintf(file, + " SOL_MAX_DELAY: %d\n" + " SOL_TIMEOUT: %d\n" + " SOL_MAX_RT: %d\n" + " REQ_TIMEOUT: %d\n" + " REQ_MAX_RT: %d\n" + " REQ_MAX_RC: %d\n" + " CNF_MAX_DELAY: %d\n" + " CNF_TIMEOUT: %d\n" + " CNF_MAX_RT: %d\n" + " CNF_MAX_RD: %d\n" + " REN_TIMEOUT: %d\n" + " REN_MAX_RT: %d\n" + " REB_TIMEOUT: %d\n" + " REB_MAX_RT: %d\n" + " INF_MAX_DELAY: %d\n" + " INF_TIMEOUT: %d\n" + " INF_MAX_RT: %d\n" + " REL_TIMEOUT: %d\n" + " REL_MAX_RC: %d\n" + " DEC_TIMEOUT: %d\n" + " DEC_MAX_RC: %d\n" + " HOP_COUNT_LIMIT: %d\n", + data[2], data[3], data[4], data[5], + data[6], data[7], data[8], data[9], + data[10], data[11], data[12], data[13], + data[14], data[15], data[16], data[17], + data[20], data[21], data[22], data[23], + data[24], data[25]); + break; + + case IPMI_LANP_IP6_ROUTER_CFG: + fprintf(file, "%s:\n" + " Enable static router address: %s\n" + " Enable dynamic router address: %s\n", + pname, + (data[0] & 1) ? "yes" : "no", + (data[0] & 2) ? "yes" : "no"); + break; + + case IPMI_LANP_IP6_STATIC_RTR1_ADDR: + case IPMI_LANP_IP6_DYNAMIC_RTR_ADDR: + if (p->specific == IPMI_LANP_IP6_STATIC_RTR1_ADDR) { + pname = "IPv6 Static Router"; + } else { + pname = "IPv6 Dynamic Router"; + } + + fprintf(file, "%s %d:\n" + " Address: %s\n" + " MAC: %s\n" + " Prefix: %s/%d\n", + pname, set, + inet_ntop(AF_INET6, &data[1], addr, sizeof(addr)), + mac2str(&data[18]), + inet_ntop(AF_INET6, &data[27], pfx, sizeof(pfx)), data[25]); + break; + + case IPMI_LANP_IP6_NDSLAAC_CFG: + fprintf(file, "%s %d:\n" + " MAX_RTR_SOLICITATION_DELAY: %d\n" + " RTR_SOLICITATION_INTERVAL: %d\n" + " MAX_RTR_SOLICITATIONS: %d\n" + " DupAddrDetectTransmits: %d\n" + " MAX_MULTICAST_SOLICIT: %d\n" + " MAX_UNICAST_SOLICIT: %d\n" + " MAX_ANYCAST_DELAY_TIME: %d\n" + " MAX_NEIGHBOR_ADVERTISEMENT: %d\n" + " REACHABLE_TIME: %d\n" + " RETRANS_TIMER: %d\n" + " DELAY_FIRST_PROBE_TIME: %d\n" + " MAX_RANDOM_FACTOR: %d\n" + " MIN_RANDOM_FACTOR: %d\n", + pname, set, + data[2], data[3], data[4], data[5], + data[6], data[7], data[8], data[9], + data[10], data[11], data[12], data[13], + data[14]); + break; + + default: + fprintf(file, "%s: %d\n", pname, data[0]); + } + + return 0; +} + +static int +lanp_ip6_cfgp(void *priv, const struct ipmi_cfgp *p, + const struct ipmi_cfgp_action *action, unsigned char *data) +{ + switch (action->type) { + case CFGP_PARSE: + return lanp_parse_cfgp(p, action->set, action->block, + action->argc, action->argv, data); + + case CFGP_GET: + return lanp_get_cfgp(priv, p, action->set, action->block, + data, action->quiet); + + case CFGP_SET: + return lanp_set_cfgp(priv, p, data); + + case CFGP_SAVE: + return lanp_save_cfgp(p, data, action->file); + + case CFGP_PRINT: + return lanp_print_cfgp(p, action->set, action->block, + data, action->file); + + default: + return -1; + } + + return 0; +} + +static void lanp_print_usage(int cmd) +{ + if (cmd == LANP_CMD_ANY || cmd == LANP_CMD_HELP) { + printf(" help [command]\n"); + } + if (cmd == LANP_CMD_ANY || cmd == LANP_CMD_SAVE) { + printf(" save <channel> [<parameter> [<set_sel> [<block_sel>]]]\n"); + } + if (cmd == LANP_CMD_ANY || cmd == LANP_CMD_SET) { + printf(" set <channel> [nolock] <parameter> [<set_sel> [<block_sel>]] <values...>\n"); + } + if (cmd == LANP_CMD_ANY || cmd == LANP_CMD_PRINT) { + printf(" print <channel> [<parameter> [<set_sel> [<block_sel>]]]\n"); + } + if (cmd == LANP_CMD_ANY || cmd == LANP_CMD_LOCK) { + printf(" lock <channel>\n"); + } + if (cmd == LANP_CMD_ANY || cmd == LANP_CMD_COMMIT) { + printf(" commit <channel>\n"); + } + if (cmd == LANP_CMD_ANY || cmd == LANP_CMD_DISCARD) { + printf(" discard <channel>\n"); + } + if (cmd == LANP_CMD_SAVE + || cmd == LANP_CMD_PRINT + || cmd == LANP_CMD_SET) { + printf("\n available parameters:\n"); + /* 'save' shall use 'write' filter, since it outputs a block + * of 'set's */ + ipmi_cfgp_usage(lan_cfgp, + sizeof(lan_cfgp)/sizeof(lan_cfgp[0]), + cmd != LANP_CMD_PRINT); + } +} + +static int +lanp_lock(struct ipmi_lanp_priv *lp) +{ + unsigned char byte = 1; + + return ipmi_set_lanp(lp, 0, &byte); +} + +static int +lanp_discard(struct ipmi_lanp_priv *lp) +{ + unsigned char byte = 0; + + return ipmi_set_lanp(lp, 0, &byte); +} + +static int +lanp_commit(struct ipmi_lanp_priv *lp) +{ + unsigned char byte = 2; + int ret; + + ret = ipmi_set_lanp(lp, 0, &byte); + if (ret == 0) { + ret = lanp_discard(lp); + } + + return ret; +} + +int +ipmi_lan6_main(struct ipmi_intf *intf, int argc, char **argv) +{ + struct ipmi_cfgp_ctx ctx; + struct ipmi_cfgp_sel sel; + struct ipmi_lanp_priv lp; + int cmd; + int chan; + int nolock = 0; + int ret; + + if (argc == 0) { + lanp_print_usage(LANP_CMD_ANY); + return 0; + } + + cmd = str2val(argv[0], ip6_command_vals); + if (cmd == LANP_CMD_ANY) { + lanp_print_usage(cmd); + return -1; + } + + if (cmd == LANP_CMD_HELP) { + if (argc == 1) { + cmd = LANP_CMD_ANY; + } else { + cmd = str2val(argv[1], ip6_command_vals); + } + + lanp_print_usage(cmd); + return 0; + } + + /* + * the rest commands expect channel number + * with the exception of 'get' and 'print' + */ + if (argc == 1) { + if (cmd == LANP_CMD_SAVE || cmd == LANP_CMD_PRINT) { + chan = find_lan_channel(intf, 1); + if (chan == 0) { + lprintf(LOG_ERR, "No LAN channel found"); + return -1; + } + } else { + lanp_print_usage(cmd); + return -1; + } + + argc -= 1; + argv += 1; + } else { + if (str2int(argv[1], &chan) != 0) { + lprintf(LOG_ERR, "Invalid channel: %s", argv[1]); + return -1; + } + + argc -= 2; + argv += 2; + + if (cmd == LANP_CMD_SET) { + if (argc && !strcasecmp(argv[0], "nolock")) { + nolock = 1; + + argc -= 1; + argv += 1; + } + } + + } + + lp.intf = intf; + lp.channel = chan; + + /* + * lock/commit/discard commands do not require parsing + * of parameter selection + */ + + switch (cmd) { + case LANP_CMD_LOCK: + lprintf(LOG_NOTICE, "Lock parameter(s)..."); + return lanp_lock(&lp); + + case LANP_CMD_COMMIT: + lprintf(LOG_NOTICE, "Commit parameter(s)..."); + return lanp_commit(&lp); + + case LANP_CMD_DISCARD: + lprintf(LOG_NOTICE, "Discard parameter(s)..."); + return lanp_discard(&lp); + } + + /* + * initialize configuration context and parse parameter selection + */ + + ipmi_cfgp_init(&ctx, lan_cfgp, + sizeof(lan_cfgp)/sizeof(lan_cfgp[0]), "lan6 set nolock", + lanp_ip6_cfgp, &lp); + + ret = ipmi_cfgp_parse_sel(&ctx, argc, (const char **)argv, &sel); + if (ret == -1) { + lanp_print_usage(cmd); + ipmi_cfgp_uninit(&ctx); + return -1; + } + + argc -= ret; + argv += ret; + + /* + * handle the rest commands + */ + + switch (cmd) { + case LANP_CMD_SAVE: + case LANP_CMD_PRINT: + lprintf(LOG_NOTICE, "Getting parameter(s)..."); + + ret = ipmi_cfgp_get(&ctx, &sel); + if (ret != 0) { + break; + } + + if (cmd == LANP_CMD_SAVE) { + static char cmd[20]; + FILE *out = stdout; + snprintf(cmd, sizeof(cmd) - 1, "lan6 set %d nolock", + lp.channel); + cmd[sizeof(cmd) - 1] = '\0'; + ctx.cmdname = cmd; + fprintf(out, "lan6 lock %d\n", lp.channel); + ret = ipmi_cfgp_save(&ctx, &sel, out); + fprintf(out, "lan6 commit %d\nlan6 discard %d\nexit\n", + lp.channel, lp.channel); + } else { + ret = ipmi_cfgp_print(&ctx, &sel, stdout); + } + break; + + case LANP_CMD_SET: + ret = ipmi_cfgp_parse_data(&ctx, &sel, argc, + (const char **)argv); + if (ret != 0) { + break; + } + + lprintf(LOG_NOTICE, "Setting parameter(s)..."); + + if (!nolock) { + ret = lanp_lock(&lp); + if (ret != 0) { + break; + } + } + + ret = ipmi_cfgp_set(&ctx, &sel); + if (!nolock) { + if (ret == 0) { + ret = lanp_commit(&lp); + } else { + lanp_discard(&lp); + } + } + break; + } + + /* + * free allocated memory + */ + ipmi_cfgp_uninit(&ctx); + + return ret; +} diff --git a/lib/ipmi_main.c b/lib/ipmi_main.c index e6f96f6..811c80b 100644 --- a/lib/ipmi_main.c +++ b/lib/ipmi_main.c @@ -291,69 +291,6 @@ void ipmi_catch_sigint() exit(-1); } -/* ipmi_parse_hex - convert hexadecimal numbers to ascii string - * Input string must be composed of two-characer hexadecimal numbers. - * There is no separator between the numbers. Each number results in one character - * of the converted string. - * - * Example: ipmi_parse_hex("50415353574F5244") returns 'PASSWORD' - * - * @param str: input string. It must contain only even number of '0'-'9','a'-'f' and 'A-F' characters. - * @returns converted ascii string - * @returns NULL on error - */ -static unsigned char * -ipmi_parse_hex(const char *str) -{ - const char * p; - unsigned char * out, *q; - unsigned char b = 0; - int shift = 4; - - if (strlen(str) == 0) - return NULL; - - if (strlen(str) % 2 != 0) { - lprintf(LOG_ERR, "Number of hex_kg characters is not even"); - return NULL; - } - - if (strlen(str) > (IPMI_KG_BUFFER_SIZE-1)*2) { - lprintf(LOG_ERR, "Kg key is too long"); - return NULL; - } - - out = calloc(IPMI_KG_BUFFER_SIZE, sizeof(unsigned char)); - if (out == NULL) { - lprintf(LOG_ERR, "malloc failure"); - return NULL; - } - - for (p = str, q = out; *p; p++) { - if (!isxdigit(*p)) { - lprintf(LOG_ERR, "Kg_hex is not hexadecimal number"); - free(out); - out = NULL; - return NULL; - } - - if (*p < 'A') /* it must be 0-9 */ - b = *p - '0'; - else /* it's A-F or a-f */ - b = (*p | 0x20) - 'a' + 10; /* convert to lowercase and to 10-15 */ - - *q = *q + (b << shift); - if (shift) - shift = 0; - else { - shift = 4; - q++; - } - } - - return out; -} - static uint8_t ipmi_acquire_ipmb_address(struct ipmi_intf * intf) { @@ -406,7 +343,7 @@ ipmi_main(int argc, char ** argv, char * progname = NULL; char * oemtype = NULL; char * sdrcache = NULL; - unsigned char * kgkey = NULL; + uint8_t kgkey[IPMI_KG_BUFFER_SIZE]; char * seloem = NULL; int port = 0; int devnum = 0; @@ -421,6 +358,7 @@ ipmi_main(int argc, char ** argv, progname = strrchr(argv[0], '/'); progname = ((progname == NULL) ? argv[0] : progname+1); signal(SIGINT, ipmi_catch_sigint); + memset(kgkey, 0, sizeof(kgkey)); while ((argflag = getopt(argc, (char **)argv, OPTION_STRING)) != -1) { @@ -547,38 +485,30 @@ ipmi_main(int argc, char ** argv, } break; case 'k': - if (kgkey) { - free(kgkey); - kgkey = NULL; - } - kgkey = strdup(optarg); - if (kgkey == NULL) { - lprintf(LOG_ERR, "%s: malloc failure", progname); - goto out_free; - } + memset(kgkey, 0, sizeof(kgkey)); + strncpy((char *)kgkey, optarg, sizeof(kgkey) - 1); break; case 'K': if ((tmp_env = getenv("IPMI_KGKEY"))) { - if (kgkey) { - free(kgkey); - kgkey = NULL; - } - kgkey = strdup(tmp_env); - if (kgkey == NULL) { - lprintf(LOG_ERR, "%s: malloc failure", progname); - goto out_free; - } + memset(kgkey, 0, sizeof(kgkey)); + strncpy((char *)kgkey, tmp_env, + sizeof(kgkey) - 1); } else { lprintf(LOG_WARN, "Unable to read kgkey from environment"); } break; case 'y': - if (kgkey) { - free(kgkey); - kgkey = NULL; - } - kgkey = ipmi_parse_hex(optarg); - if (kgkey == NULL) { + memset(kgkey, 0, sizeof(kgkey)); + + rc = ipmi_parse_hex(optarg, kgkey, sizeof(kgkey) - 1); + if (rc == -1) { + lprintf(LOG_ERR, "Number of Kg key characters is not even"); + goto out_free; + } else if (rc == -3) { + lprintf(LOG_ERR, "Kg key is not hexadecimal number"); + goto out_free; + } else if (rc > (IPMI_KG_BUFFER_SIZE-1)) { + lprintf(LOG_ERR, "Kg key is too long"); goto out_free; } break; @@ -589,16 +519,10 @@ ipmi_main(int argc, char ** argv, tmp_pass = getpass("Key: "); #endif if (tmp_pass != NULL) { - if (kgkey) { - free(kgkey); - kgkey = NULL; - } - kgkey = strdup(tmp_pass); + memset(kgkey, 0, sizeof(kgkey)); + strncpy((char *)kgkey, tmp_pass, + sizeof(kgkey) - 1); tmp_pass = NULL; - if (kgkey == NULL) { - lprintf(LOG_ERR, "%s: malloc failure", progname); - goto out_free; - } } break; case 'U': @@ -928,8 +852,7 @@ ipmi_main(int argc, char ** argv, ipmi_intf_session_set_username(ipmi_main_intf, username); if (password != NULL) ipmi_intf_session_set_password(ipmi_main_intf, password); - if (kgkey != NULL) - ipmi_intf_session_set_kgkey(ipmi_main_intf, kgkey); + ipmi_intf_session_set_kgkey(ipmi_main_intf, kgkey); if (port > 0) ipmi_intf_session_set_port(ipmi_main_intf, port); if (authtype >= 0) @@ -1123,10 +1046,6 @@ ipmi_main(int argc, char ** argv, free(seloem); seloem = NULL; } - if (kgkey != NULL) { - free(kgkey); - kgkey = NULL; - } if (sdrcache != NULL) { free(sdrcache); sdrcache = NULL; diff --git a/lib/ipmi_mc.c b/lib/ipmi_mc.c index 5b4a080..4580bfb 100644 --- a/lib/ipmi_mc.c +++ b/lib/ipmi_mc.c @@ -462,78 +462,79 @@ ipmi_mc_get_deviceid(struct ipmi_intf * intf) return 0; } -/* Structure follow the IPMI V.2 Rev 1.0 - * See Table 20-10 */ -#ifdef HAVE_PRAGMA_PACK -#pragma pack(1) -#endif - -struct ipmi_guid { - uint32_t time_low; /* timestamp low field */ - uint16_t time_mid; /* timestamp middle field */ - uint16_t time_hi_and_version; /* timestamp high field and version number */ - uint8_t clock_seq_hi_variant;/* clock sequence high field and variant */ - uint8_t clock_seq_low; /* clock sequence low field */ - uint8_t node[6]; /* node */ -} ATTRIBUTE_PACKING; -#ifdef HAVE_PRAGMA_PACK -#pragma pack(0) -#endif - -/* ipmi_mc_get_guid - print this MC GUID +/* _ipmi_mc_get_guid - Gets BMCs GUID according to (22.14) * * @intf: ipmi interface + * @guid: pointer where to store BMC GUID * - * returns 0 on success - * returns -1 on error + * returns - negative number means error, positive is a ccode. */ -static int -ipmi_mc_get_guid(struct ipmi_intf * intf) +int +_ipmi_mc_get_guid(struct ipmi_intf *intf, struct ipmi_guid_t *guid) { - struct ipmi_rs * rsp; + struct ipmi_rs *rsp; struct ipmi_rq req; - struct ipmi_guid guid; + if (guid == NULL) { + return (-3); + } + memset(guid, 0, sizeof(struct ipmi_guid_t)); memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; req.msg.cmd = BMC_GET_GUID; rsp = intf->sendrecv(intf, &req); if (rsp == NULL) { - lprintf(LOG_ERR, "Get GUID command failed"); - return -1; - } - if (rsp->ccode > 0) { - lprintf(LOG_ERR, "Get GUID command failed: %s", - val2str(rsp->ccode, completion_code_vals)); - return -1; - } - - if (rsp->data_len == sizeof(struct ipmi_guid)) { - char tbuf[40]; - time_t s; - memset(tbuf, 0, 40); - memset(&guid, 0, sizeof(struct ipmi_guid)); - memcpy(&guid, rsp->data, rsp->data_len); - - /* Kipp - changed order of last field (node) to follow specification */ - printf("System GUID : %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x\n", - guid.time_low, guid.time_mid, guid.time_hi_and_version, - guid.clock_seq_hi_variant << 8 | guid.clock_seq_low, - guid.node[0], guid.node[1], guid.node[2], - guid.node[3], guid.node[4], guid.node[5]); - - s = (time_t)guid.time_low; /* Kipp - removed the BSWAP_32, it was not needed here */ - strftime(tbuf, sizeof(tbuf), "%m/%d/%Y %H:%M:%S", localtime(&s)); - printf("Timestamp : %s\n", tbuf); - } - else { - lprintf(LOG_ERR, "Invalid GUID length %d", rsp->data_len); + return (-1); + } else if (rsp->ccode > 0) { + return rsp->ccode; + } else if (rsp->data_len != 16 + || rsp->data_len != sizeof(struct ipmi_guid_t)) { + return (-2); } + memcpy(guid, &rsp->data[0], sizeof(struct ipmi_guid_t)); + return 0; +} +/* ipmi_mc_print_guid - print-out given BMC GUID + * + * @guid - struct with GUID. + * + * returns 0 + */ +static int +ipmi_mc_print_guid(struct ipmi_guid_t guid) +{ + char tbuf[40]; + time_t s; + memset(tbuf, 0, 40); + /* Kipp - changed order of last field (node) to follow specification */ + printf("System GUID : %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x\n", + guid.time_low, guid.time_mid, guid.time_hi_and_version, + guid.clock_seq_hi_variant << 8 | guid.clock_seq_low, + guid.node[0], guid.node[1], guid.node[2], + guid.node[3], guid.node[4], guid.node[5]); + + s = (time_t)guid.time_low; /* Kipp - removed the BSWAP_32, it was not needed here */ + strftime(tbuf, sizeof(tbuf), "%m/%d/%Y %H:%M:%S", localtime(&s)); + printf("Timestamp : %s\n", tbuf); return 0; } +/* ipmi_mc_get_guid - Gets and prints-out System GUID */ +int +ipmi_mc_get_guid(struct ipmi_intf *intf) +{ + struct ipmi_guid_t guid; + int rc; + rc = _ipmi_mc_get_guid(intf, &guid); + if (eval_ccode(rc) != 0) { + return (-1); + } + rc = ipmi_mc_print_guid(guid); + return rc; +} + /* ipmi_mc_get_selftest - returns and print selftest results * * @intf: ipmi interface diff --git a/lib/ipmi_pef.c b/lib/ipmi_pef.c index 22f29e4..bbf25f2 100644 --- a/lib/ipmi_pef.c +++ b/lib/ipmi_pef.c @@ -36,10 +36,13 @@ #include <ipmitool/bswap.h> #include <ipmitool/helper.h> -#include <ipmitool/log.h> #include <ipmitool/ipmi.h> +#include <ipmitool/ipmi_channel.h> #include <ipmitool/ipmi_intf.h> +#include <ipmitool/ipmi_mc.h> #include <ipmitool/ipmi_pef.h> +#include <ipmitool/ipmi_sel.h> +#include <ipmitool/log.h> extern int verbose; /* @@ -75,6 +78,8 @@ static const char * pef_flag_fmts[][3] = { }; static const char * listitem[] = {" | %s", ",%s", "%s"}; +static int ipmi_pef2_list_filters(struct ipmi_intf *); + const char * ipmi_pef_bit_desc(struct bit_desc_map * map, uint32_t value) { /* @@ -184,6 +189,31 @@ ipmi_pef_print_1xd(const char * text, uint32_t val) ipmi_pef_print_field(pef_fld_fmts[F_1XD], text, val); } +/* ipmi_pef_print_guid - print-out GUID. */ +static int +ipmi_pef_print_guid(uint8_t *guid) +{ + if (guid == NULL) { + return (-1); + } + + if (verbose) { + printf("%-*s : %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", + KYWD_LENGTH, "System GUID", + guid[0], guid[1], guid[2], guid[3], guid[4], + guid[5], guid[6], guid[7], guid[8], guid[9], + guid[10],guid[11], guid[12], guid[13], guid[14], + guid[15]); + } else { + printf(" | %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", + guid[0], guid[1], guid[2], guid[3], guid[4], + guid[5], guid[6], guid[7], guid[8], guid[9], + guid[10], guid[11], guid[12], guid[13], guid[14], + guid[15]); + } + return 0; +} + static struct ipmi_rs * ipmi_pef_msg_exchange(struct ipmi_intf * intf, struct ipmi_rq * req, char * txt) { /* @@ -204,58 +234,423 @@ ipmi_pef_msg_exchange(struct ipmi_intf * intf, struct ipmi_rq * req, char * txt) return(rsp); } -static uint8_t -ipmi_pef_get_policy_table(struct ipmi_intf * intf, - struct pef_cfgparm_policy_table_entry ** table) -{ /* - // get the PEF policy table: allocate space, fillin, and return its size - // NB: the caller must free the returned area (when returned size > 0) - */ - struct ipmi_rs * rsp; +/* _ipmi_get_pef_capabilities - Requests and returns result of (30.1) Get PEF + * Capabilities. + * + * @pcap - pointer where to store results. + * + * returns - negative number means error, positive is a ccode. + */ +int +_ipmi_get_pef_capabilities(struct ipmi_intf *intf, + struct pef_capabilities *pcap) +{ + struct ipmi_rs *rsp; + struct ipmi_rq req; + if (pcap == NULL) { + return (-3); + } + + memset(pcap, 0, sizeof(struct pef_capabilities)); + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_SE; + req.msg.cmd = IPMI_CMD_GET_PEF_CAPABILITIES; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + return (-1); + } else if (rsp->ccode != 0) { + return rsp->ccode; + } else if (rsp->data_len != 3) { + return (-2); + } + pcap->version = rsp->data[0]; + pcap->actions = rsp->data[1]; + pcap->event_filter_count = rsp->data[2]; + return 0; +} + +/* _ipmi_get_pef_filter_entry - Fetches one Entry from Event Filter Table + * identified by Filter ID. + * + * @filter_id - Filter ID of Entry in Event Filter Table. + * @filter_entry - Pointer where to copy Filter Entry data. + * + * returns - negative number means error, positive is a ccode. + */ +static int +_ipmi_get_pef_filter_entry(struct ipmi_intf *intf, uint8_t filter_id, + struct pef_cfgparm_filter_table_entry *filter_entry) +{ + struct ipmi_rs *rsp; + struct ipmi_rq req; + uint8_t data[3]; + uint8_t data_len = 3 * sizeof(uint8_t); + int dest_size; + if (filter_entry == NULL) { + return (-3); + } + + dest_size = (int)sizeof(struct pef_cfgparm_filter_table_entry); + memset(filter_entry, 0, dest_size); + memset(&data, 0, data_len); + data[0] = PEF_CFGPARM_ID_PEF_FILTER_TABLE_ENTRY; + data[1] = filter_id; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_SE; + req.msg.cmd = IPMI_CMD_GET_PEF_CONFIG_PARMS; + req.msg.data = (uint8_t *)&data; + req.msg.data_len = data_len; + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + return (-1); + } else if (rsp->ccode != 0) { + return rsp->ccode; + } else if (rsp->data_len != 22 || (rsp->data_len - 1) != dest_size) { + return (-2); + } + memcpy(filter_entry, &rsp->data[1], dest_size); + return 0; +} + +/* _ipmi_get_pef_filter_entry_cfg - Fetches configuration of one Entry from + * Event Filter Table identified by Filter ID. + * + * @filter_id - Filter ID of Entry in Event Filter Table. + * @filter_entry_cfg - Pointer where to copy Filter Entry configuration. + * + * returns - negative number means error, positive is a ccode. + */ +int +_ipmi_get_pef_filter_entry_cfg(struct ipmi_intf *intf, uint8_t filter_id, + struct pef_cfgparm_filter_table_data_1 *filter_cfg) +{ + struct ipmi_rs *rsp; + struct ipmi_rq req; + uint8_t data[3]; + uint8_t data_len = 3 * sizeof(uint8_t); + int dest_size; + if (filter_cfg == NULL) { + return (-3); + } + + dest_size = (int)sizeof(struct pef_cfgparm_filter_table_data_1); + memset(filter_cfg, 0, dest_size); + memset(&data, 0, data_len); + data[0] = PEF_CFGPARM_ID_PEF_FILTER_TABLE_DATA_1; + data[1] = filter_id; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_SE; + req.msg.cmd = IPMI_CMD_GET_PEF_CONFIG_PARMS; + req.msg.data = (uint8_t *)&data; + req.msg.data_len = data_len; + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + return (-1); + } else if (rsp->ccode != 0) { + return rsp->ccode; + } else if (rsp->data_len != 3 || (rsp->data_len - 1) != dest_size) { + return (-2); + } + memcpy(filter_cfg, &rsp->data[1], dest_size); + return 0; +} + +/* _ipmi_get_pef_policy_entry - Fetches one Entry from Alert Policy Table + * identified by Policy ID. + * + * @policy_id - Policy ID of Entry in Alert Policy Table. + * @policy_entry - Pointer where to copy Policy Entry data. + * + * returns - negative number means error, positive is a ccode. + */ +static int +_ipmi_get_pef_policy_entry(struct ipmi_intf *intf, uint8_t policy_id, + struct pef_cfgparm_policy_table_entry *policy_entry) +{ + struct ipmi_rs *rsp; + struct ipmi_rq req; + uint8_t data[3]; + uint8_t data_len = 3 * sizeof(uint8_t); + int dest_size; + if (policy_entry == NULL) { + return (-3); + } + + dest_size = (int)sizeof(struct pef_cfgparm_policy_table_entry); + memset(policy_entry, 0, dest_size); + memset(&data, 0, data_len); + data[0] = PEF_CFGPARM_ID_PEF_ALERT_POLICY_TABLE_ENTRY; + data[1] = policy_id & PEF_POLICY_TABLE_ID_MASK; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_SE; + req.msg.cmd = IPMI_CMD_GET_PEF_CONFIG_PARMS; + req.msg.data = (uint8_t *)&data; + req.msg.data_len = data_len; + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + return (-1); + } else if (rsp->ccode != 0) { + return rsp->ccode; + } else if (rsp->data_len != 5 || (rsp->data_len - 1) != dest_size) { + return (-2); + } + memcpy(policy_entry, &rsp->data[1], dest_size); + return 0; +} + +/* _ipmi_get_pef_filter_table_size - Fetch the Number of Event Filter Entries. + * If the number is 0, it means feature is not supported. + * + * @table_size - ptr to where to store number of entries. + * + * returns - negative number means error, positive is a ccode. + */ +static int +_ipmi_get_pef_filter_table_size(struct ipmi_intf *intf, uint8_t *table_size) +{ + struct ipmi_rs *rsp; struct ipmi_rq req; struct pef_cfgparm_selector psel; - struct pef_cfgparm_policy_table_entry * ptbl, * ptmp; - uint32_t i; - uint8_t tbl_size; + if (table_size == NULL) { + return (-3); + } + + *table_size = 0; + memset(&psel, 0, sizeof(psel)); + psel.id = PEF_CFGPARM_ID_PEF_FILTER_TABLE_SIZE; + memset(&req, 0, sizeof(req)); + + req.msg.netfn = IPMI_NETFN_SE; + req.msg.cmd = IPMI_CMD_GET_PEF_CONFIG_PARMS; + req.msg.data = (uint8_t *)&psel; + req.msg.data_len = sizeof(psel); + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + return (-1); + } else if (rsp->ccode != 0) { + return rsp->ccode; + } else if (rsp->data_len != 2) { + return (-2); + } + *table_size = rsp->data[1] & 0x7F; + return 0; +} + +/* _ipmi_get_pef_policy_table_size - Fetch the Number of Alert Policy Entries. If the + * number is 0, it means feature is not supported. + * + * @table_size - ptr to where to store number of entries. + * + * returns - negative number means error, positive is a ccode. + */ +static int +_ipmi_get_pef_policy_table_size(struct ipmi_intf *intf, uint8_t *table_size) +{ + struct ipmi_rs *rsp; + struct ipmi_rq req; + struct pef_cfgparm_selector psel; + + if (table_size == NULL) { + return (-3); + } + + *table_size = 0; memset(&psel, 0, sizeof(psel)); psel.id = PEF_CFGPARM_ID_PEF_ALERT_POLICY_TABLE_SIZE; memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_SE; req.msg.cmd = IPMI_CMD_GET_PEF_CONFIG_PARMS; req.msg.data = (uint8_t *)&psel; req.msg.data_len = sizeof(psel); - rsp = ipmi_pef_msg_exchange(intf, &req, "Alert policy table size"); - if (!rsp) - return(0); - tbl_size = (rsp->data[1] & PEF_POLICY_TABLE_SIZE_MASK); - i = (tbl_size * sizeof(struct pef_cfgparm_policy_table_entry)); - if (!i - || (ptbl = (struct pef_cfgparm_policy_table_entry *)malloc(i)) == NULL) - return(0); + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + return (-1); + } else if (rsp->ccode != 0) { + return rsp->ccode; + } else if (rsp->data_len != 2) { + return (-2); + } + *table_size = rsp->data[1] & 0x7F; + return 0; +} + +/* _ipmi_get_pef_system_guid - Fetches System GUID from PEF. This configuration + * parameter is optional. If data1 is 0x0, then this GUID is ignored by BMC. + * + * @system_guid - pointer where to store received data. + * + * returns - negative number means error, positive is a ccode. + */ +int +_ipmi_get_pef_system_guid(struct ipmi_intf *intf, + struct pef_cfgparm_system_guid *system_guid) +{ + struct ipmi_rs *rsp; + struct ipmi_rq req; + struct pef_cfgparm_selector psel; + if (system_guid == NULL) { + return (-3); + } + memset(system_guid, 0, sizeof(struct pef_cfgparm_system_guid)); memset(&psel, 0, sizeof(psel)); - psel.id = PEF_CFGPARM_ID_PEF_ALERT_POLICY_TABLE_ENTRY; - for (ptmp=ptbl, i=1; i<=tbl_size; i++) { - psel.set = (i & PEF_POLICY_TABLE_ID_MASK); - rsp = ipmi_pef_msg_exchange(intf, &req, "Alert policy table entry"); - if (!rsp - || i != (rsp->data[1] & PEF_POLICY_TABLE_ID_MASK)) { - lprintf(LOG_ERR, " **Error retrieving %s", - "Alert policy table entry"); - free(ptbl); - ptbl = NULL; - tbl_size = 0; - break; - } - memcpy(ptmp, &rsp->data[1], sizeof(*ptmp)); - ptmp++; + psel.id = PEF_CFGPARM_ID_SYSTEM_GUID; + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_SE; + req.msg.cmd = IPMI_CMD_GET_PEF_CONFIG_PARMS; + req.msg.data = (uint8_t *)&psel; + req.msg.data_len = sizeof(psel); + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + return (-1); + } else if (rsp->ccode != 0) { + return rsp->ccode; + } else if (rsp->data_len != 18 + || (rsp->data_len - 2) != sizeof(system_guid->guid)) { + return (-2); + } + system_guid->data1 = rsp->data[1] & 0x1; + memcpy(system_guid->guid, &rsp->data[2], sizeof(system_guid->guid)); + return 0; +} + +/* _ipmi_set_pef_filter_entry_cfg - Sets/updates configuration of Entry in Event + * Filter Table identified by Filter ID. + * + * @filter_id - ID of Entry in Event Filter Table to be updated + * @filter_cfg - Pointer to configuration data. + * + * returns - negative number means error, positive is a ccode. + */ +static int +_ipmi_set_pef_filter_entry_cfg(struct ipmi_intf *intf, uint8_t filter_id, + struct pef_cfgparm_filter_table_data_1 *filter_cfg) +{ + struct ipmi_rs *rsp; + struct ipmi_rq req; + uint8_t data[3]; + uint8_t data_len = 3 * sizeof(uint8_t); + if (filter_cfg == NULL) { + return (-3); } - *table = ptbl; - return(tbl_size); + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_SE; + req.msg.cmd = IPMI_CMD_SET_PEF_CONFIG_PARMS; + req.msg.data = (uint8_t *)&data; + req.msg.data_len = data_len; + + memset(&data, 0, data_len); + data[0] = PEF_CFGPARM_ID_PEF_FILTER_TABLE_DATA_1; + data[1] = filter_id; + data[2] = filter_cfg->cfg; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + return (-1); + } else if (rsp->ccode != 0) { + return rsp->ccode; + } + return 0; +} + +/* _ipmi_set_pef_policy_entry - Sets/updates Entry in Alert Policy Table identified by + * Policy ID. + * + * @policy_id - Policy ID of Entry in Alert Policy Table to be updated + * @policy_entry - Pointer to data. + * + * returns - negative number means error, positive is a ccode. + */ +static int +_ipmi_set_pef_policy_entry(struct ipmi_intf *intf, uint8_t policy_id, + struct pef_cfgparm_policy_table_entry *policy_entry) +{ + struct ipmi_rs *rsp; + struct ipmi_rq req; + struct pef_cfgparm_set_policy_table_entry payload; + if (policy_entry == NULL) { + return (-3); + } + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_SE; + req.msg.cmd = IPMI_CMD_SET_PEF_CONFIG_PARMS; + req.msg.data = (uint8_t *)&payload; + req.msg.data_len = sizeof(payload); + + memset(&payload, 0, sizeof(payload)); + payload.param_selector = PEF_CFGPARM_ID_PEF_ALERT_POLICY_TABLE_ENTRY; + payload.policy_id = policy_id & PEF_POLICY_TABLE_ID_MASK; + memcpy(&payload.entry, &policy_entry->entry, + sizeof(policy_entry->entry)); + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + return (-1); + } else if (rsp->ccode != 0) { + return rsp->ccode; + } + return 0; +} + +static void +ipmi_pef_print_oem_lan_dest(struct ipmi_intf *intf, uint8_t ch, uint8_t dest) +{ + char address[128]; + int len; + int rc; + int rlen; + int set; + uint8_t data[32]; + + if (ipmi_get_oem(intf) != IPMI_OEM_DELL) { + return; + } + /* Get # of IPV6 trap destinations */ + rc = ipmi_mc_getsysinfo(intf, IPMI_SYSINFO_DELL_IPV6_COUNT, 0x00, 0x00, 4, data); + if (rc != 0 || dest > data[0]) { + return; + } + ipmi_pef_print_str("Alert destination type", "xxx"); + ipmi_pef_print_str("PET Community", "xxx"); + ipmi_pef_print_dec("ACK timeout/retry (secs)", 0); + ipmi_pef_print_dec("Retries", 0); + + /* Get IPv6 destination string (may be in multiple sets) */ + memset(address, 0, sizeof(address)); + memset(data, 0, sizeof(data)); + rc = ipmi_mc_getsysinfo(intf, IPMI_SYSINFO_DELL_IPV6_DESTADDR, 0x00, dest, 19, data); + if (rc != 0) { + return; + } + /* Total length of IPv6 string */ + len = data[4]; + if ((rlen = len) > (IPMI_SYSINFO_SET0_SIZE-3)) { + /* First set has 11 bytes */ + rlen = IPMI_SYSINFO_SET0_SIZE - 3; + } + memcpy(address, data + 8, rlen); + for (set = 1; len > 11; set++) { + rc = ipmi_mc_getsysinfo(intf, IPMI_SYSINFO_DELL_IPV6_DESTADDR, set, dest, 19, data); + if ((rlen = len - 11) >= (IPMI_SYSINFO_SETN_SIZE - 2)) { + /* Remaining sets have 14 bytes */ + rlen = IPMI_SYSINFO_SETN_SIZE - 2; + } + memcpy(address + (set * 11), data + 3, rlen); + len -= rlen+3; + } + ipmi_pef_print_str("IPv6 Address", address); } +/* TODO - rewrite */ static void ipmi_pef_print_lan_dest(struct ipmi_intf * intf, uint8_t ch, uint8_t dest) { /* @@ -325,16 +720,13 @@ ipmi_pef_print_lan_dest(struct ipmi_intf * intf, uint8_t ch, uint8_t dest) pinfo->ip[0], pinfo->ip[1], pinfo->ip[2], pinfo->ip[3]); ipmi_pef_print_str("IP address", buf); - sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", - pinfo->mac[0], pinfo->mac[1], pinfo->mac[2], - pinfo->mac[3], pinfo->mac[4], pinfo->mac[5]); - ipmi_pef_print_str("MAC address", buf); + ipmi_pef_print_str("MAC address", mac2str(pinfo->mac)); } } static void -ipmi_pef_print_serial_dest_dial(struct ipmi_intf * intf, char * label, - struct pef_serial_cfgparm_selector * ssel) +ipmi_pef_print_serial_dest_dial(struct ipmi_intf *intf, char *label, + struct pef_serial_cfgparm_selector *ssel) { /* // print a dial string */ @@ -381,8 +773,8 @@ ipmi_pef_print_serial_dest_dial(struct ipmi_intf * intf, char * label, } static void -ipmi_pef_print_serial_dest_tap(struct ipmi_intf * intf, - struct pef_serial_cfgparm_selector * ssel) +ipmi_pef_print_serial_dest_tap(struct ipmi_intf *intf, + struct pef_serial_cfgparm_selector *ssel) { /* // print TAP destination info */ @@ -431,28 +823,21 @@ ipmi_pef_print_serial_dest_tap(struct ipmi_intf * intf, /* TODO : additional TAP settings? */ } +/* static void -ipmi_pef_print_serial_dest_ppp(struct ipmi_intf * intf, - struct pef_serial_cfgparm_selector * ssel) -{ /* - // print PPP destination info - */ - - /* TODO */ +ipmi_pef_print_serial_dest_ppp(struct ipmi_intf *intf, + struct pef_serial_cfgparm_selector *ssel) +{ } static void -ipmi_pef_print_serial_dest_callback(struct ipmi_intf * intf, - struct pef_serial_cfgparm_selector * ssel) -{ /* - // print callback destination info - */ - - /* TODO */ +ipmi_pef_print_serial_dest_callback(struct ipmi_intf *intf, + struct pef_serial_cfgparm_selector *ssel) } +*/ static void -ipmi_pef_print_serial_dest(struct ipmi_intf * intf, uint8_t ch, uint8_t dest) +ipmi_pef_print_serial_dest(struct ipmi_intf *intf, uint8_t ch, uint8_t dest) { /* // print Serial/PPP alert destination info */ @@ -479,6 +864,10 @@ ipmi_pef_print_serial_dest(struct ipmi_intf * intf, uint8_t ch, uint8_t dest) tbl_size = (rsp->data[1] & PEF_SERIAL_DEST_TABLE_SIZE_MASK); if (!dest || tbl_size == 0) /* Page alerting not supported */ return; + if (dest > tbl_size) { + ipmi_pef_print_oem_lan_dest(intf, ch, dest - tbl_size); + return; + } ssel.id = PEF_SERIAL_CFGPARM_ID_DESTINFO; ssel.set = dest; @@ -503,11 +892,11 @@ ipmi_pef_print_serial_dest(struct ipmi_intf * intf, uint8_t ch, uint8_t dest) ipmi_pef_print_serial_dest_tap(intf, &ssel); break; case PEF_SERIAL_DEST_TYPE_PPP: - ipmi_pef_print_serial_dest_ppp(intf, &ssel); + /* ipmi_pef_print_serial_dest_ppp(intf, &ssel); */ break; case PEF_SERIAL_DEST_TYPE_BASIC_CALLBACK: case PEF_SERIAL_DEST_TYPE_PPP_CALLBACK: - ipmi_pef_print_serial_dest_callback(intf, &ssel); + /* ipmi_pef_print_serial_dest_callback(intf, &ssel); */ break; } } @@ -529,7 +918,7 @@ ipmi_pef_print_event_info(struct pef_cfgparm_filter_table_entry * pef, char * bu static char * classes[] = {"Discrete", "Threshold", "OEM"}; uint16_t offmask; char * p; - int i; + unsigned int i; uint8_t t; ipmi_pef_print_str("Event severity", @@ -574,170 +963,234 @@ ipmi_pef_print_event_info(struct pef_cfgparm_filter_table_entry * pef, char * bu ipmi_pef_print_str("Event trigger(s)", buf); } +/* ipmi_pef_print_filter_entry - Print-out Entry of Event Filter Table. */ static void -ipmi_pef_print_entry(struct ipmi_rs * rsp, uint8_t id, - struct pef_cfgparm_filter_table_entry * pef) -{ /* - // print a PEF table entry - */ - uint8_t wrk, set; +ipmi_pef_print_filter_entry(struct pef_cfgparm_filter_table_entry *filter_entry) +{ char buf[128]; + uint8_t filter_enabled; + uint8_t set; - ipmi_pef_print_dec("PEF table entry", id); + ipmi_pef_print_dec("PEF Filter Table entry", filter_entry->data1); - wrk = !!(pef->entry.config & PEF_CONFIG_ENABLED); - sprintf(buf, "%sactive", (wrk ? "" : "in")); - if (pef->entry.config & PEF_CONFIG_PRECONFIGURED) - strcat(buf, ", pre-configured"); + filter_enabled = filter_entry->entry.config & PEF_CONFIG_ENABLED; + sprintf(buf, "%sabled", (filter_enabled ? "en" : "dis")); + switch (filter_entry->entry.config & 0x60) { + case 0x40: + strcat(buf, ", pre-configured"); + break; + case 0x00: + strcat(buf, ", configurable"); + break; + default: + /* Covers 0x60 and 0x20 which are reserved */ + strcat(buf, ", reserved"); + break; + } ipmi_pef_print_str("Status", buf); - if (wrk != 0) { - ipmi_pef_print_1xd("Version", rsp->data[0]); - ipmi_pef_print_str("Sensor type", - ipmi_pef_bit_desc(&pef_b2s_sensortypes, pef->entry.sensor_type)); + if (!filter_enabled) { + return; + } - if (pef->entry.sensor_number == PEF_SENSOR_NUMBER_MATCH_ANY) - ipmi_pef_print_str("Sensor number", "Any"); - else - ipmi_pef_print_dec("Sensor number", pef->entry.sensor_number); + ipmi_pef_print_str("Sensor type", + ipmi_pef_bit_desc(&pef_b2s_sensortypes, + filter_entry->entry.sensor_type)); - ipmi_pef_print_event_info(pef, buf); - ipmi_pef_print_str("Action", - ipmi_pef_bit_desc(&pef_b2s_actions, pef->entry.action)); + if (filter_entry->entry.sensor_number == PEF_SENSOR_NUMBER_MATCH_ANY) { + ipmi_pef_print_str("Sensor number", "Any"); + } else { + ipmi_pef_print_dec("Sensor number", + filter_entry->entry.sensor_number); + } - if (pef->entry.action & PEF_ACTION_ALERT) { - set = (pef->entry.policy_number & PEF_POLICY_NUMBER_MASK); - ipmi_pef_print_int("Policy set", set); - } + ipmi_pef_print_event_info(filter_entry, buf); + ipmi_pef_print_str("Action", + ipmi_pef_bit_desc(&pef_b2s_actions, + filter_entry->entry.action)); + + if (filter_entry->entry.action & PEF_ACTION_ALERT) { + set = (filter_entry->entry.policy_number & PEF_POLICY_NUMBER_MASK); + ipmi_pef_print_int("Policy set", set); } } -static void -ipmi_pef_list_entries(struct ipmi_intf * intf) -{ /* - // list all PEF table entries - */ - struct ipmi_rs * rsp; - struct ipmi_rq req; - struct pef_cfgparm_selector psel; - struct pef_cfgparm_filter_table_entry * pcfg; - uint32_t i; - uint8_t max_filters; +/* ipmi_pef2_filter_enable - Enable/Disable specific PEF Event Filter. + * + * @enable - enable(1) or disable(0) PEF Event Filter. + * @filter_id - Filter ID of Entry in Event Filter Table. + * + * returns - 0 on success, any other value means error. + */ +static int +ipmi_pef2_filter_enable(struct ipmi_intf *intf, uint8_t enable, uint8_t filter_id) +{ + struct pef_cfgparm_filter_table_data_1 filter_cfg; + int rc; + uint8_t filter_table_size; + + rc = _ipmi_get_pef_filter_table_size(intf, &filter_table_size); + if (eval_ccode(rc) != 0) { + return (-1); + } else if (filter_table_size == 0) { + lprintf(LOG_ERR, "PEF Filter isn't supported."); + return (-1); + } else if (filter_id > filter_table_size) { + lprintf(LOG_ERR, + "PEF Filter ID out of range. Valid range is (1..%d).", + filter_table_size); + return (-1); + } - memset(&req, 0, sizeof(req)); - req.msg.netfn = IPMI_NETFN_SE; - req.msg.cmd = IPMI_CMD_GET_PEF_CAPABILITIES; - rsp = ipmi_pef_msg_exchange(intf, &req, "PEF capabilities"); - if (!rsp - || (max_filters = ((struct pef_capabilities *)rsp->data)->tblsize) == 0) - return; /* sssh, not supported */ + memset(&filter_cfg, 0, sizeof(filter_cfg)); + rc = _ipmi_set_pef_filter_entry_cfg(intf, filter_id, &filter_cfg); + if (eval_ccode(rc) != 0) { + return (-1); + } - memset(&psel, 0, sizeof(psel)); - psel.id = PEF_CFGPARM_ID_PEF_FILTER_TABLE_ENTRY; - memset(&req, 0, sizeof(req)); - req.msg.netfn = IPMI_NETFN_SE; - req.msg.cmd = IPMI_CMD_GET_PEF_CONFIG_PARMS; - req.msg.data = (uint8_t *)&psel; - req.msg.data_len = sizeof(psel); - for (i=1; i<=max_filters; i++) { - if (i > 1) - printf("\n"); - psel.set = (i & PEF_FILTER_TABLE_ID_MASK); - rsp = ipmi_pef_msg_exchange(intf, &req, "PEF table entry"); - if (!rsp - || (psel.set != (rsp->data[1] & PEF_FILTER_TABLE_ID_MASK))) { - lprintf(LOG_ERR, " **Error retrieving %s", - "PEF table entry"); - continue; - } - pcfg = (struct pef_cfgparm_filter_table_entry *)&rsp->data[1]; - first_field = 1; - ipmi_pef_print_entry(rsp, psel.set, pcfg); + if (enable != 0) { + /* Enable */ + filter_cfg.cfg |= PEF_FILTER_ENABLED; + } else { + /* Disable */ + filter_cfg.cfg &= PEF_FILTER_DISABLED; } + rc = _ipmi_set_pef_filter_entry_cfg(intf, filter_id, &filter_cfg); + if (eval_ccode(rc) != 0) { + lprintf(LOG_ERR, "Failed to %s PEF Filter ID %d.", + enable ? "enable" : "disable", + filter_id); + return (-1); + } + printf("PEF Filter ID %" PRIu8 " is %s now.\n", filter_id, + enable ? "enabled" : "disabled"); + return rc; } -static void -ipmi_pef_list_policies(struct ipmi_intf * intf) -{ /* - // list PEF alert policies - */ - struct ipmi_rs * rsp; - struct ipmi_rq req; - struct pef_cfgparm_policy_table_entry * ptbl = NULL; - struct pef_cfgparm_policy_table_entry * ptmp = NULL; - uint32_t i; - uint8_t wrk, ch, medium, tbl_size; - - tbl_size = ipmi_pef_get_policy_table(intf, &ptbl); - if (!tbl_size) { - if (ptbl != NULL) { - free(ptbl); - ptbl = NULL; +void +ipmi_pef2_filter_help(void) +{ + lprintf(LOG_NOTICE, +"usage: pef filter help"); + lprintf(LOG_NOTICE, +" pef filter list"); + lprintf(LOG_NOTICE, +" pef filter enable <id = 1..n>"); + lprintf(LOG_NOTICE, +" pef filter disable <id = 1..n>"); + lprintf(LOG_NOTICE, +" pef filter create <id = 1..n> <params>"); + lprintf(LOG_NOTICE, +" pef filter delete <id = 1..n>"); +} + +/* ipmi_pef2_filter - Handle processing of "filter" CLI args. */ +int +ipmi_pef2_filter(struct ipmi_intf *intf, int argc, char **argv) +{ + int rc = 0; + + if (argc < 1) { + lprintf(LOG_ERR, "Not enough parameters given."); + ipmi_pef2_filter_help(); + rc = (-1); + } else if (!strncmp(argv[0], "help\0", 5)) { + ipmi_pef2_filter_help(); + rc = 0; + } else if (!strncmp(argv[0], "list\0", 5)) { + rc = ipmi_pef2_list_filters(intf); + } else if (!strncmp(argv[0], "enable\0", 7) + ||(!strncmp(argv[0], "disable\0", 8))) { + uint8_t enable; + uint8_t filter_id; + if (argc != 2) { + lprintf(LOG_ERR, "Not enough arguments given."); + ipmi_pef2_filter_help(); + return (-1); } - return; + if (str2uchar(argv[1], &filter_id) != 0) { + lprintf(LOG_ERR, "Invalid PEF Event Filter ID given: %s", argv[1]); + return (-1); + } else if (filter_id < 1) { + lprintf(LOG_ERR, "PEF Event Filter ID out of range. " + "Valid range is <1..255>."); + return (-1); + } + if (!strncmp(argv[0], "enable\0", 7)) { + enable = 1; + } else { + enable = 0; + } + rc = ipmi_pef2_filter_enable(intf, enable, filter_id); + } else if (!strncmp(argv[0], "create\0", 7)) { + lprintf(LOG_ERR, "Not implemented."); + rc = 1; + } else if (!strncmp(argv[0], "delete\0", 7)) { + lprintf(LOG_ERR, "Not implemented."); + rc = 1; + } else { + lprintf(LOG_ERR, "Invalid PEF Filter command: %s", argv[0]); + ipmi_pef2_filter_help(); + rc = 1; } - memset(&req, 0, sizeof(req)); - req.msg.netfn = IPMI_NETFN_APP; - req.msg.cmd = IPMI_CMD_GET_CHANNEL_INFO; - req.msg.data = &ch; - req.msg.data_len = sizeof(ch); - for (ptmp=ptbl, i=1; i<=tbl_size; i++, ptmp++) { - if ((ptmp->entry.policy & PEF_POLICY_ENABLED) == PEF_POLICY_ENABLED) { - if (i > 1) - printf("\n"); - first_field = 1; - ipmi_pef_print_dec("Alert policy table entry", - (ptmp->data1 & PEF_POLICY_TABLE_ID_MASK)); - ipmi_pef_print_dec("Policy set", - (ptmp->entry.policy & PEF_POLICY_ID_MASK) >> PEF_POLICY_ID_SHIFT); - ipmi_pef_print_str("Policy entry rule", - ipmi_pef_bit_desc(&pef_b2s_policies, (ptmp->entry.policy & PEF_POLICY_FLAGS_MASK))); - - if (ptmp->entry.alert_string_key & PEF_POLICY_EVENT_SPECIFIC) { - ipmi_pef_print_str("Event-specific", "true"); -// continue; - } - wrk = ptmp->entry.chan_dest; - - /* channel/description */ - ch = (wrk & PEF_POLICY_CHANNEL_MASK) >> PEF_POLICY_CHANNEL_SHIFT; - rsp = ipmi_pef_msg_exchange(intf, &req, "Channel info"); - if (!rsp || rsp->data[0] != ch) { - lprintf(LOG_ERR, " **Error retrieving %s", - "Channel info"); - continue; - } - medium = rsp->data[1]; - ipmi_pef_print_dec("Channel number", ch); - ipmi_pef_print_str("Channel medium", - ipmi_pef_bit_desc(&pef_b2s_ch_medium, medium)); - - /* destination/description */ - wrk &= PEF_POLICY_DESTINATION_MASK; - switch (medium) { - case PEF_CH_MEDIUM_TYPE_LAN: - ipmi_pef_print_lan_dest(intf, ch, wrk); - break; - case PEF_CH_MEDIUM_TYPE_SERIAL: - ipmi_pef_print_serial_dest(intf, ch, wrk); - break; - default: - ipmi_pef_print_dest(intf, ch, wrk); - break; - } + return rc; +} + +/* ipmi_pef2_get_info - Reports PEF capabilities + System GUID */ +static int +ipmi_pef2_get_info(struct ipmi_intf *intf) +{ + struct pef_capabilities pcap; + struct pef_cfgparm_system_guid psys_guid; + struct ipmi_guid_t guid; + int rc; + uint8_t *guid_ptr = NULL; + uint8_t policy_table_size; + + rc = _ipmi_get_pef_policy_table_size(intf, &policy_table_size); + if (eval_ccode(rc) != 0) { + lprintf(LOG_WARN, "Failed to get size of PEF Policy Table."); + policy_table_size = 0; + } + rc = _ipmi_get_pef_capabilities(intf, &pcap); + if (eval_ccode(rc) != 0) { + lprintf(LOG_ERR, "Failed to get PEF Capabilities."); + return (-1); + } + + ipmi_pef_print_1xd("Version", pcap.version); + ipmi_pef_print_dec("PEF Event Filter count", + pcap.event_filter_count); + ipmi_pef_print_dec("PEF Alert Policy Table size", + policy_table_size); + + rc = _ipmi_get_pef_system_guid(intf, &psys_guid); + if (rc != 0x80 && eval_ccode(rc) != 0) { + lprintf(LOG_ERR, "Failed to get PEF System GUID. %i", rc); + return (-1); + } else if (psys_guid.data1 == 0x1) { + /* IPMI_CMD_GET_SYSTEM_GUID */ + guid_ptr = &psys_guid.guid[0]; + } else { + rc = _ipmi_mc_get_guid(intf, &guid); + if (rc == 0) { + guid_ptr = (uint8_t *)&guid; } } - free(ptbl); - ptbl = NULL; + /* Got GUID? */ + if (guid_ptr) { + ipmi_pef_print_guid(guid_ptr); + } + ipmi_pef_print_flags(&pef_b2s_actions, P_SUPP, pcap.actions); + return 0; } -static void -ipmi_pef_get_status(struct ipmi_intf * intf) -{ /* - // report the PEF status - */ - struct ipmi_rs * rsp; +/* ipmi_pef2_get_status - TODO rewrite - report the PEF status */ +static int +ipmi_pef2_get_status(struct ipmi_intf *intf) +{ + struct ipmi_rs *rsp; struct ipmi_rq req; struct pef_cfgparm_selector psel; char tbuf[40]; @@ -751,7 +1204,7 @@ ipmi_pef_get_status(struct ipmi_intf * intf) if (!rsp) { lprintf(LOG_ERR, " **Error retrieving %s", "Last S/W processed ID"); - return; + return (-1); } memcpy(&timei, rsp->data, sizeof(timei)); #if WORDS_BIGENDIAN @@ -777,7 +1230,7 @@ ipmi_pef_get_status(struct ipmi_intf * intf) if (!rsp) { lprintf(LOG_ERR, " **Error retrieving %s", "PEF control"); - return; + return (-1); } ipmi_pef_print_flags(&pef_b2s_control, P_ABLE, rsp->data[1]); @@ -786,102 +1239,312 @@ ipmi_pef_get_status(struct ipmi_intf * intf) if (!rsp) { lprintf(LOG_ERR, " **Error retrieving %s", "PEF action"); - return; + return (-1); } ipmi_pef_print_flags(&pef_b2s_actions, P_ACTV, rsp->data[1]); + return 0; } -static void -ipmi_pef_get_info(struct ipmi_intf * intf) -{ /* - // report PEF capabilities + System GUID - */ - struct ipmi_rs * rsp; - struct ipmi_rq req; - struct pef_capabilities * pcap; - struct pef_cfgparm_selector psel; - struct pef_cfgparm_policy_table_entry * ptbl = NULL; - uint8_t * uid; - uint8_t actions, tbl_size; +/* ipmi_pef2_list_filters - List all entries in PEF Event Filter Table. */ +static int +ipmi_pef2_list_filters(struct ipmi_intf *intf) +{ + struct pef_capabilities pcap; + struct pef_cfgparm_filter_table_entry filter_entry; + int rc; + uint8_t i; + + rc = _ipmi_get_pef_capabilities(intf, &pcap); + if (eval_ccode(rc) != 0) { + return (-1); + } else if (pcap.event_filter_count == 0) { + lprintf(LOG_ERR, "PEF Event Filtering isn't supported."); + return (-1); + } - tbl_size = ipmi_pef_get_policy_table(intf, &ptbl); - if (ptbl != NULL) { - free(ptbl); - ptbl = NULL; + for (i = 1; i <= pcap.event_filter_count; i++) { + first_field = 1; + rc = _ipmi_get_pef_filter_entry(intf, i, &filter_entry); + if (eval_ccode(rc) != 0) { + lprintf(LOG_ERR, "Failed to get PEF Event Filter Entry %i.", + i); + continue; + } + ipmi_pef_print_filter_entry(&filter_entry); + printf("\n"); } + return 0; +} - memset(&req, 0, sizeof(req)); - req.msg.netfn = IPMI_NETFN_SE; - req.msg.cmd = IPMI_CMD_GET_PEF_CAPABILITIES; - rsp = ipmi_pef_msg_exchange(intf, &req, "PEF capabilities"); - if (!rsp) - return; - pcap = (struct pef_capabilities *)rsp->data; +/* ipmi_pef2_list_policies - List Entries in PEF Alert Policy Table. */ +static int +ipmi_pef2_list_policies(struct ipmi_intf *intf) +{ + struct channel_info_t channel_info; + struct pef_cfgparm_policy_table_entry entry; + int rc; + uint8_t dest; + uint8_t i; + uint8_t policy_table_size; + + rc = _ipmi_get_pef_policy_table_size(intf, &policy_table_size); + if (eval_ccode(rc) != 0) { + return (-1); + } else if (policy_table_size == 0) { + lprintf(LOG_ERR, "PEF Alert Policy isn't supported."); + return (-1); + } - ipmi_pef_print_1xd("Version", pcap->version); - ipmi_pef_print_dec("PEF table size", pcap->tblsize); - ipmi_pef_print_dec("Alert policy table size", tbl_size); - actions = pcap->actions; + for (i = 1; i <= policy_table_size; i++) { + first_field = 1; + rc = _ipmi_get_pef_policy_entry(intf, i, &entry); + if (eval_ccode(rc) != 0) { + continue; + } - memset(&psel, 0, sizeof(psel)); - psel.id = PEF_CFGPARM_ID_SYSTEM_GUID; - memset(&req, 0, sizeof(req)); - req.msg.netfn = IPMI_NETFN_SE; - req.msg.cmd = IPMI_CMD_GET_PEF_CONFIG_PARMS; - req.msg.data = (uint8_t *)&psel; - req.msg.data_len = sizeof(psel); - rsp = ipmi_pef_msg_exchange(intf, &req, "System GUID"); - uid = NULL; - if (rsp && (rsp->data[1] & PEF_SYSTEM_GUID_USED_IN_PET)) - uid = &rsp->data[2]; - else { - memset(&req, 0, sizeof(req)); - req.msg.netfn = IPMI_NETFN_APP; - req.msg.cmd = IPMI_CMD_GET_SYSTEM_GUID; - rsp = ipmi_pef_msg_exchange(intf, &req, "System GUID"); - if (rsp) - uid = &rsp->data[0]; - } - if (uid) { /* got GUID? */ - if (verbose) - printf(pef_fld_fmts[F_UID][0], KYWD_LENGTH, "System GUID", - uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7], - uid[8], uid[9], uid[10],uid[11],uid[12],uid[13],uid[14],uid[15]); - else - printf(pef_fld_fmts[F_UID][1], - uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7], - uid[8], uid[9], uid[10],uid[11],uid[12],uid[13],uid[14],uid[15]); + ipmi_pef_print_dec("Alert policy table entry", + (entry.data1 & PEF_POLICY_TABLE_ID_MASK)); + ipmi_pef_print_dec("Policy set", + (entry.entry.policy & PEF_POLICY_ID_MASK) >> PEF_POLICY_ID_SHIFT); + ipmi_pef_print_str("State", + entry.entry.policy & PEF_POLICY_ENABLED ? "enabled" : "disabled"); + ipmi_pef_print_str("Policy entry rule", + ipmi_pef_bit_desc(&pef_b2s_policies, + (entry.entry.policy & PEF_POLICY_FLAGS_MASK))); + + if (entry.entry.alert_string_key & PEF_POLICY_EVENT_SPECIFIC) { + ipmi_pef_print_str("Event-specific", "true"); + } + channel_info.channel = ((entry.entry.chan_dest & + PEF_POLICY_CHANNEL_MASK) >> + PEF_POLICY_CHANNEL_SHIFT); + rc = _ipmi_get_channel_info(intf, &channel_info); + if (eval_ccode(rc) != 0) { + continue; + } + ipmi_pef_print_dec("Channel number", channel_info.channel); + ipmi_pef_print_str("Channel medium", + ipmi_pef_bit_desc(&pef_b2s_ch_medium, + channel_info.medium)); + dest = entry.entry.chan_dest & PEF_POLICY_DESTINATION_MASK; + switch (channel_info.medium) { + case PEF_CH_MEDIUM_TYPE_LAN: + ipmi_pef_print_lan_dest(intf, channel_info.channel, + dest); + break; + case PEF_CH_MEDIUM_TYPE_SERIAL: + ipmi_pef_print_serial_dest(intf, channel_info.channel, + dest); + break; + default: + ipmi_pef_print_dest(intf, channel_info.channel, dest); + break; + } + printf("\n"); } - ipmi_pef_print_flags(&pef_b2s_actions, P_SUPP, actions); + return 0; } -int ipmi_pef_main(struct ipmi_intf * intf, int argc, char ** argv) -{ /* - // PEF subcommand handling - */ - int help = 0; - int rc = 0; - - if (!argc || !strncmp(argv[0], "info", 4)) - ipmi_pef_get_info(intf); - else if (!strncmp(argv[0], "help", 4)) - help = 1; - else if (!strncmp(argv[0], "status", 6)) - ipmi_pef_get_status(intf); - else if (!strncmp(argv[0], "policy", 6)) - ipmi_pef_list_policies(intf); - else if (!strncmp(argv[0], "list", 4)) - ipmi_pef_list_entries(intf); - else { - help = 1; - rc = -1; - lprintf(LOG_ERR, "Invalid PEF command: '%s'\n", argv[0]); +void +ipmi_pef2_policy_help(void) +{ + lprintf(LOG_NOTICE, +"usage: pef policy help"); + lprintf(LOG_NOTICE, +" pef policy list"); + lprintf(LOG_NOTICE, +" pef policy enable <id = 1..n>"); + lprintf(LOG_NOTICE, +" pef policy disable <id = 1..n>"); + lprintf(LOG_NOTICE, +" pef policy create <id = 1..n> <params>"); + lprintf(LOG_NOTICE, +" pef policy delete <id = 1..n>"); +} + +/* ipmi_pef2_policy_enable - Enable/Disable specific PEF policy + * + * @enable - enable(1) or disable(0) PEF Alert Policy + * @policy_id - Policy ID of Entry in Alert Policy Table. + * + * returns - 0 on success, any other value means error. + */ +static int +ipmi_pef2_policy_enable(struct ipmi_intf *intf, int enable, uint8_t policy_id) +{ + struct pef_cfgparm_policy_table_entry policy_entry; + int rc; + uint8_t policy_table_size; + + rc = _ipmi_get_pef_policy_table_size(intf, &policy_table_size); + if (eval_ccode(rc) != 0) { + return (-1); + } else if (policy_table_size == 0) { + lprintf(LOG_ERR, "PEF Policy isn't supported."); + return (-1); + } else if (policy_id > policy_table_size) { + lprintf(LOG_ERR, + "PEF Policy ID out of range. Valid range is (1..%d).", + policy_table_size); + return (-1); } - if (help) - lprintf(LOG_NOTICE, "PEF commands: info status policy list"); - else if (!verbose) - printf("\n"); + memset(&policy_entry, 0, sizeof(policy_entry)); + rc = _ipmi_get_pef_policy_entry(intf, policy_id, &policy_entry); + if (eval_ccode(rc) != 0) { + return (-1); + } + + if (enable != 0) { + /* Enable */ + policy_entry.entry.policy |= PEF_POLICY_ENABLED; + } else { + /* Disable */ + policy_entry.entry.policy &= PEF_POLICY_DISABLED; + } + rc = _ipmi_set_pef_policy_entry(intf, policy_id, &policy_entry); + if (eval_ccode(rc) != 0) { + lprintf(LOG_ERR, "Failed to %s PEF Policy ID %d.", + enable ? "enable" : "disable", + policy_id); + return (-1); + } + printf("PEF Policy ID %" PRIu8 " is %s now.\n", policy_id, + enable ? "enabled" : "disabled"); + return rc; +} + +/* ipmi_pef2_policy - Handle processing of "policy" CLI args. */ +int +ipmi_pef2_policy(struct ipmi_intf *intf, int argc, char **argv) +{ + int rc = 0; + + if (argc < 1) { + lprintf(LOG_ERR, "Not enough parameters given."); + ipmi_pef2_policy_help(); + rc = (-1); + } else if (!strncmp(argv[0], "help\0", 5)) { + ipmi_pef2_policy_help(); + rc = 0; + } else if (!strncmp(argv[0], "list\0", 5)) { + rc = ipmi_pef2_list_policies(intf); + } else if (!strncmp(argv[0], "enable\0", 7) + || !strncmp(argv[0], "disable\0", 8)) { + uint8_t enable; + uint8_t policy_id; + if (argc != 2) { + lprintf(LOG_ERR, "Not enough arguments given."); + ipmi_pef2_policy_help(); + return (-1); + } + if (str2uchar(argv[1], &policy_id) != 0) { + lprintf(LOG_ERR, "Invalid PEF Policy ID given: %s", argv[1]); + return (-1); + } else if (policy_id < 1 || policy_id > 127) { + lprintf(LOG_ERR, "PEF Policy ID out of range. Valid range is <1..127>."); + return (-1); + } + if (!strncmp(argv[0], "enable\0", 7)) { + enable = 1; + } else { + enable = 0; + } + rc = ipmi_pef2_policy_enable(intf, enable, policy_id); + } else if (!strncmp(argv[0], "create\0", 7)) { + lprintf(LOG_ERR, "Not implemented."); + rc = 1; + } else if (!strncmp(argv[0], "delete\0", 7)) { + lprintf(LOG_ERR, "Not implemented."); + rc = 1; + } else { + lprintf(LOG_ERR, "Invalid PEF Policy command: %s", argv[0]); + ipmi_pef2_policy_help(); + rc = 1; + } + return rc; +} + +/* ipmi_pef2_help - print-out help text. */ +void +ipmi_pef2_help(void) +{ + lprintf(LOG_NOTICE, +"usage: pef help"); + lprintf(LOG_NOTICE, +" pef capabilities"); + lprintf(LOG_NOTICE, +" pef event <params>"); + lprintf(LOG_NOTICE, +" pef filter list"); + lprintf(LOG_NOTICE, +" pef filter enable <id = 1..n>"); + lprintf(LOG_NOTICE, +" pef filter disable <id = 1..n>"); + lprintf(LOG_NOTICE, +" pef filter create <id = 1..n> <params>"); + lprintf(LOG_NOTICE, +" pef filter delete <id = 1..n>"); + lprintf(LOG_NOTICE, +" pef info"); + lprintf(LOG_NOTICE, +" pef policy list"); + lprintf(LOG_NOTICE, +" pef policy enable <id = 1..n>"); + lprintf(LOG_NOTICE, +" pef policy disable <id = 1..n>"); + lprintf(LOG_NOTICE, +" pef policy create <id = 1..n> <params>"); + lprintf(LOG_NOTICE, +" pef policy delete <id = 1..n>"); + lprintf(LOG_NOTICE, +" pef pet ack <params>"); + lprintf(LOG_NOTICE, +" pef status"); + lprintf(LOG_NOTICE, +" pef timer get"); + lprintf(LOG_NOTICE, +" pef timer set <0x00-0xFF>"); +} +int ipmi_pef_main(struct ipmi_intf *intf, int argc, char **argv) +{ + int rc = 0; + + if (argc < 1) { + lprintf(LOG_ERR, "Not enough parameters given."); + ipmi_pef2_help(); + rc = (-1); + } else if (!strncmp(argv[0], "help\0", 5)) { + ipmi_pef2_help(); + rc = 0; + } else if (!strncmp(argv[0], "capabilities\0", 13)) { + /* rc = ipmi_pef2_get_capabilities(intf); */ + lprintf(LOG_ERR, "Not implemented."); + rc = 1; + } else if (!strncmp(argv[0], "event\0", 6)) { + /* rc = ipmi_pef2_event(intf, (argc - 1), ++argv); */ + lprintf(LOG_ERR, "Not implemented."); + rc = 1; + } else if (!strncmp(argv[0], "filter\0", 7)) { + rc = ipmi_pef2_filter(intf, (argc - 1), ++argv); + } else if (!strncmp(argv[0], "info\0", 5)) { + rc = ipmi_pef2_get_info(intf); + } else if (!strncmp(argv[0], "pet\0", 4)) { + /* rc = ipmi_pef2_pet(intf, (argc - 1), ++argv); */ + lprintf(LOG_ERR, "Not implemented."); + rc = 1; + } else if (!strncmp(argv[0], "policy\0", 7)) { + rc = ipmi_pef2_policy(intf, (argc - 1), ++argv); + } else if (!strncmp(argv[0], "status\0", 7)) { + rc = ipmi_pef2_get_status(intf); + } else if (!strncmp(argv[0], "timer\0", 6)) { + /* rc = ipmi_pef2_timer(intf, (argc - 1), ++argv); */ + lprintf(LOG_ERR, "Not implemented."); + rc = 1; + } else { + lprintf(LOG_ERR, "Invalid PEF command: '%s'\n", argv[0]); + rc = (-1); + } return rc; } diff --git a/lib/ipmi_picmg.c b/lib/ipmi_picmg.c index 70f845d..c7d9c8e 100644 --- a/lib/ipmi_picmg.c +++ b/lib/ipmi_picmg.c @@ -2301,7 +2301,7 @@ uint8_t ipmi_picmg_ipmb_address(struct ipmi_intf *intf) { struct ipmi_rq req; struct ipmi_rs *rsp; - char msg_data; + uint8_t msg_data; if (!intf->picmg_avail) { return 0; @@ -2336,12 +2336,13 @@ picmg_discover(struct ipmi_intf *intf) { * PICMG Extension Version 2.0 (PICMG 3.0 Revision 1.0 ATCA) to * PICMG Extension Version 2.3 (PICMG 3.0 Revision 3.0 ATCA) * PICMG Extension Version 4.1 (PICMG 3.0 Revision 3.0 AMC) + * PICMG Extension Version 5.0 (MTCA.0 R1.0) */ /* First, check if PICMG extension is available and supported */ struct ipmi_rq req; struct ipmi_rs *rsp; - char msg_data; + uint8_t msg_data; uint8_t picmg_avail = 0; memset(&req, 0, sizeof(req)); @@ -2366,8 +2367,9 @@ picmg_discover(struct ipmi_intf *intf) { } else if (rsp->data[0] != 0) { lprintf(LOG_INFO,"Invalid Get PICMG Properties group extension %#x", rsp->data[0]); - } else if ((rsp->data[1] & 0x0F) != PICMG_ATCA_MAJOR_VERSION - && (rsp->data[1] & 0x0F) != PICMG_AMC_MAJOR_VERSION) { + } else if ((rsp->data[1] & 0x0F) != PICMG_EXTENSION_ATCA_MAJOR_VERSION + && (rsp->data[1] & 0x0F) != PICMG_EXTENSION_AMC0_MAJOR_VERSION + && (rsp->data[1] & 0x0F) != PICMG_EXTENSION_UTCA_MAJOR_VERSION) { lprintf(LOG_INFO,"Unknown PICMG Extension Version %d.%d", (rsp->data[1] & 0x0F), (rsp->data[1] >> 4)); } else { diff --git a/lib/ipmi_sdr.c b/lib/ipmi_sdr.c index e3122dc..2a9cbe3 100644 --- a/lib/ipmi_sdr.c +++ b/lib/ipmi_sdr.c @@ -689,32 +689,6 @@ ipmi_sdr_get_sensor_event_enable(struct ipmi_intf *intf, uint8_t sensor, return rsp; } -/* ipmi_sdr_get_sensor_type_desc - Get sensor type descriptor - * - * @type: ipmi sensor type - * - * returns - * string from sensor_type_desc - * or "reserved" - * or "OEM reserved" - */ -const char * -ipmi_sdr_get_sensor_type_desc(const uint8_t type) -{ - static char desc[32]; - memset(desc, 0, 32); - if (type <= SENSOR_TYPE_MAX) - return sensor_type_desc[type]; - if (type < 0xc0) - snprintf(desc, 32, "reserved #%02x", type); - else - { - snprintf(desc, 32, oemval2str(sdriana,type,ipmi_oem_sdr_type_vals), - type); - } - return desc; -} - /* ipmi_sdr_get_thresh_status - threshold status indicator * * @rsp: response from Get Sensor Reading comand @@ -1014,21 +988,21 @@ ipmi_sdr_print_sensor_event_status(struct ipmi_intf *intf, switch (numeric_fmt) { case DISCRETE_SENSOR: if (rsp->data_len == 2) { - ipmi_sdr_print_discrete_state("Assertion Events", + ipmi_sdr_print_discrete_state(intf, "Assertion Events", sensor_type, event_type, rsp->data[1], 0); } else if (rsp->data_len > 2) { - ipmi_sdr_print_discrete_state("Assertion Events", + ipmi_sdr_print_discrete_state(intf, "Assertion Events", sensor_type, event_type, rsp->data[1], rsp->data[2]); } if (rsp->data_len == 4) { - ipmi_sdr_print_discrete_state("Deassertion Events", + ipmi_sdr_print_discrete_state(intf, "Deassertion Events", sensor_type, event_type, rsp->data[3], 0); } else if (rsp->data_len > 4) { - ipmi_sdr_print_discrete_state("Deassertion Events", + ipmi_sdr_print_discrete_state(intf, "Deassertion Events", sensor_type, event_type, rsp->data[3], rsp->data[4]); @@ -1081,22 +1055,23 @@ ipmi_sdr_print_sensor_event_status(struct ipmi_intf *intf, } static int -ipmi_sdr_print_sensor_mask(struct sdr_record_mask *mask, - uint8_t sensor_type, - uint8_t event_type, int numeric_fmt) +ipmi_sdr_print_sensor_mask(struct ipmi_intf *intf, + struct sdr_record_mask *mask, + uint8_t sensor_type, + uint8_t event_type, int numeric_fmt) { /* iceblink - don't print some event status fields - CVS rev1.53 */ return 0; switch (numeric_fmt) { case DISCRETE_SENSOR: - ipmi_sdr_print_discrete_state("Assert Event Mask", sensor_type, + ipmi_sdr_print_discrete_state(intf, "Assert Event Mask", sensor_type, event_type, mask->type.discrete. assert_event & 0xff, (mask->type.discrete. assert_event & 0xff00) >> 8); - ipmi_sdr_print_discrete_state("Deassert Event Mask", + ipmi_sdr_print_discrete_state(intf, "Deassert Event Mask", sensor_type, event_type, mask->type.discrete. deassert_event & 0xff, @@ -1224,21 +1199,21 @@ ipmi_sdr_print_sensor_event_enable(struct ipmi_intf *intf, case DISCRETE_SENSOR: /* discrete */ if (rsp->data_len == 2) { - ipmi_sdr_print_discrete_state("Assertions Enabled", + ipmi_sdr_print_discrete_state(intf, "Assertions Enabled", sensor_type, event_type, rsp->data[1], 0); } else if (rsp->data_len > 2) { - ipmi_sdr_print_discrete_state("Assertions Enabled", + ipmi_sdr_print_discrete_state(intf, "Assertions Enabled", sensor_type, event_type, rsp->data[1], rsp->data[2]); } if (rsp->data_len == 4) { - ipmi_sdr_print_discrete_state("Deassertions Enabled", + ipmi_sdr_print_discrete_state(intf, "Deassertions Enabled", sensor_type, event_type, rsp->data[3], 0); } else if (rsp->data_len > 4) { - ipmi_sdr_print_discrete_state("Deassertions Enabled", + ipmi_sdr_print_discrete_state(intf, "Deassertions Enabled", sensor_type, event_type, rsp->data[3], rsp->data[4]); @@ -1381,8 +1356,9 @@ print_sensor_min_max(struct sdr_record_full_sensor *full) * returns void */ static void -print_csv_discrete(struct sdr_record_common_sensor *sensor, - const struct sensor_reading *sr) +print_csv_discrete(struct ipmi_intf *intf, + struct sdr_record_common_sensor *sensor, + const struct sensor_reading *sr) { if (!sr->s_reading_valid || sr->s_reading_unavailable) { printf("%02Xh,ns,%d.%d,No Reading", @@ -1400,7 +1376,7 @@ print_csv_discrete(struct sdr_record_common_sensor *sensor, printf("ok,%d.%d,", sensor->entity.id, sensor->entity.instance); - ipmi_sdr_print_discrete_state_mini(NULL, ", ", + ipmi_sdr_print_discrete_state_mini(intf, NULL, ", ", sensor->sensor.type, sensor->event_type, sr->s_data2, @@ -1430,7 +1406,7 @@ ipmi_sdr_read_sensor_value(struct ipmi_intf *intf, memset(&sr, 0, sizeof(sr)); switch (sdr_record_type) { - int idlen; + unsigned int idlen; case (SDR_RECORD_TYPE_FULL_SENSOR): sr.full = (struct sdr_record_full_sensor *)sensor; idlen = sr.full->id_code & 0x1f; @@ -1542,7 +1518,7 @@ ipmi_sdr_print_sensor_fc(struct ipmi_intf *intf, uint8_t sdr_record_type) { char sval[16]; - int i = 0; + unsigned int i = 0; uint8_t target, lun, channel; struct sensor_reading *sr; @@ -1567,7 +1543,7 @@ ipmi_sdr_print_sensor_fc(struct ipmi_intf *intf, printf("%s,", sr->s_id); if (!IS_THRESHOLD_SENSOR(sensor)) { /* Discrete/Non-Threshold */ - print_csv_discrete(sensor, sr); + print_csv_discrete(intf, sensor, sr); printf("\n"); } else { @@ -1581,7 +1557,7 @@ ipmi_sdr_print_sensor_fc(struct ipmi_intf *intf, printf("%s,%s", sr->s_a_units, ipmi_sdr_get_thresh_status(sr, "ns")); } else { /* Discrete/Threshold */ - print_csv_discrete(sensor, sr); + print_csv_discrete(intf, sensor, sr); } } else { printf(",,ns"); @@ -1589,10 +1565,9 @@ ipmi_sdr_print_sensor_fc(struct ipmi_intf *intf, if (verbose) { printf(",%d.%d,%s,%s,", - sensor->entity.id, sensor->entity.instance, - val2str(sensor->entity.id, entity_id_vals), - ipmi_sdr_get_sensor_type_desc(sensor->sensor. - type)); + sensor->entity.id, sensor->entity.instance, + val2str(sensor->entity.id, entity_id_vals), + ipmi_get_sensor_type(intf, sensor->sensor.type)); if (sr->full) { SENSOR_PRINT_CSV(sr->full, sr->full->analog_flag.nominal_read, @@ -1712,7 +1687,7 @@ ipmi_sdr_print_sensor_fc(struct ipmi_intf *intf, printf("%s %s", sr->s_a_str, sr->s_a_units); header = ", "; } - ipmi_sdr_print_discrete_state_mini(header, ", ", + ipmi_sdr_print_discrete_state_mini(intf, header, ", ", sensor->sensor.type, sensor->event_type, sr->s_data2, @@ -1740,7 +1715,7 @@ ipmi_sdr_print_sensor_fc(struct ipmi_intf *intf, if (!IS_THRESHOLD_SENSOR(sensor)) { /* Discrete */ printf(" Sensor Type (Discrete): %s (0x%02x)\n", - ipmi_sdr_get_sensor_type_desc(sensor->sensor.type), + ipmi_get_sensor_type(intf, sensor->sensor.type), sensor->sensor.type); lprintf(LOG_DEBUG, " Event Type Code : 0x%02x", sensor->event_type); @@ -1776,12 +1751,12 @@ ipmi_sdr_print_sensor_fc(struct ipmi_intf *intf, break; } - ipmi_sdr_print_discrete_state("States Asserted", + ipmi_sdr_print_discrete_state(intf, "States Asserted", sensor->sensor.type, sensor->event_type, sr->s_data2, sr->s_data3); - ipmi_sdr_print_sensor_mask(&sensor->mask, sensor->sensor.type, + ipmi_sdr_print_sensor_mask(intf, &sensor->mask, sensor->sensor.type, sensor->event_type, DISCRETE_SENSOR); ipmi_sdr_print_sensor_event_status(intf, sensor->keys.sensor_num, @@ -1804,7 +1779,7 @@ ipmi_sdr_print_sensor_fc(struct ipmi_intf *intf, return 0; /* done */ } printf(" Sensor Type (Threshold) : %s (0x%02x)\n", - ipmi_sdr_get_sensor_type_desc(sensor->sensor.type), + ipmi_get_sensor_type(intf, sensor->sensor.type), sensor->sensor.type); printf(" Sensor Reading : "); @@ -1945,7 +1920,7 @@ ipmi_sdr_print_sensor_fc(struct ipmi_intf *intf, printf("\n"); } - ipmi_sdr_print_sensor_mask(&sensor->mask, + ipmi_sdr_print_sensor_mask(intf, &sensor->mask, sensor->sensor.type, sensor->event_type, ANALOG_SENSOR); ipmi_sdr_print_sensor_event_status(intf, @@ -1988,46 +1963,43 @@ get_offset(uint8_t x) * no meaningful return value */ void -ipmi_sdr_print_discrete_state_mini(const char *header, const char *separator, +ipmi_sdr_print_discrete_state_mini(struct ipmi_intf *intf, + const char *header, const char *separator, uint8_t sensor_type, uint8_t event_type, uint8_t state1, uint8_t state2) { - uint8_t typ; - struct ipmi_event_sensor_types *evt; + const struct ipmi_event_sensor_types *evt; int pre = 0, c = 0; if (state1 == 0 && (state2 & 0x7f) == 0) return; - if (event_type == 0x6f) { - evt = sensor_specific_types; - typ = sensor_type; - } else { - evt = generic_event_types; - typ = event_type; - } - if (header) printf("%s", header); - for (; evt->type != NULL; evt++) { - if ((evt->code != typ) || - (evt->data != 0xFF)) + for (evt = ipmi_get_first_event_sensor_type(intf, sensor_type, event_type); + evt != NULL; evt = ipmi_get_next_event_sensor_type(evt)) { + if (evt->data != 0xFF) { continue; + } if (evt->offset > 7) { if ((1 << (evt->offset - 8)) & (state2 & 0x7f)) { - if (pre++ != 0) + if (pre++ != 0) { printf("%s", separator); - if (evt->desc) + } + if (evt->desc) { printf("%s", evt->desc); + } } } else { if ((1 << evt->offset) & state1) { - if (pre++ != 0) + if (pre++ != 0) { printf("%s", separator); - if (evt->desc) + } + if (evt->desc) { printf("%s", evt->desc); + } } } c++; @@ -2045,32 +2017,24 @@ ipmi_sdr_print_discrete_state_mini(const char *header, const char *separator, * no meaningful return value */ void -ipmi_sdr_print_discrete_state(const char *desc, +ipmi_sdr_print_discrete_state(struct ipmi_intf *intf, const char *desc, uint8_t sensor_type, uint8_t event_type, uint8_t state1, uint8_t state2) { - uint8_t typ; - struct ipmi_event_sensor_types *evt; + const struct ipmi_event_sensor_types *evt; int pre = 0, c = 0; if (state1 == 0 && (state2 & 0x7f) == 0) return; - if (event_type == 0x6f) { - evt = sensor_specific_types; - typ = sensor_type; - } else { - evt = generic_event_types; - typ = event_type; - } - - for (; evt->type != NULL; evt++) { - if ((evt->code != typ) || - (evt->data != 0xFF)) + for (evt = ipmi_get_first_event_sensor_type(intf, sensor_type, event_type); + evt != NULL; evt = ipmi_get_next_event_sensor_type(evt)) { + if (evt->data != 0xFF) { continue; + } if (pre == 0) { - printf(" %-21s : %s\n", desc, evt->type); + printf(" %-21s : %s\n", desc, ipmi_get_sensor_type(intf, sensor_type)); pre = 1; } @@ -2129,7 +2093,7 @@ ipmi_sdr_print_sensor_eventonly(struct ipmi_intf *intf, sensor->entity.id, sensor->entity.instance, val2str(sensor->entity.id, entity_id_vals)); printf("Sensor Type : %s (0x%02x)\n", - ipmi_sdr_get_sensor_type_desc(sensor->sensor_type), + ipmi_get_sensor_type(intf, sensor->sensor_type), sensor->sensor_type); lprintf(LOG_DEBUG, "Event Type Code : 0x%02x", sensor->event_type); @@ -2509,8 +2473,8 @@ ipmi_sdr_print_sensor_oem(struct ipmi_intf *intf, struct sdr_record_oem *oem) * returns -1 on error */ int -ipmi_sdr_print_name_from_rawentry(struct ipmi_intf *intf,uint16_t id, - uint8_t type,uint8_t * raw) +ipmi_sdr_print_name_from_rawentry(struct ipmi_intf *intf, uint16_t id, + uint8_t type, uint8_t *raw) { union { struct sdr_record_full_sensor *full; diff --git a/lib/ipmi_sel.c b/lib/ipmi_sel.c index b6629a2..8b0395e 100644 --- a/lib/ipmi_sel.c +++ b/lib/ipmi_sel.c @@ -49,6 +49,7 @@ #include <ipmitool/ipmi_sdr.h> #include <ipmitool/ipmi_fru.h> #include <ipmitool/ipmi_sensor.h> +#include <ipmitool/ipmi_strings.h> extern int verbose; static int sel_extended = 0; @@ -446,13 +447,14 @@ ipmi_sel_add_entries_fromfile(struct ipmi_intf * intf, const char * filename) return rc; } -static struct ipmi_event_sensor_types oem_kontron_event_reading_types[] __attribute__((unused)) = { - { 0x70 , 0x00 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "OEM Firmware Info 1", "Code Assert" }, - { 0x71 , 0x00 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "OEM Firmware Info 2", "Code Assert" }, +static struct ipmi_event_sensor_types oem_kontron_event_reading_types[] __attribute__((unused)) = { + { 0x70 , 0x00 , 0xff, "Code Assert" }, + { 0x71 , 0x00 , 0xff, "Code Assert" }, + { 0, 0, 0xFF, NULL } }; char * -get_kontron_evt_desc(struct ipmi_intf * intf, struct sel_event_record * rec) +get_kontron_evt_desc(struct ipmi_intf *intf, struct sel_event_record * rec) { char * description = NULL; /* @@ -462,8 +464,8 @@ get_kontron_evt_desc(struct ipmi_intf * intf, struct sel_event_record * rec) /* Only standard records are defined so far */ if( rec->record_type < 0xC0 ){ - struct ipmi_event_sensor_types *st=NULL; - for ( st=oem_kontron_event_reading_types ; st->type != NULL; st++){ + const struct ipmi_event_sensor_types *st=NULL; + for ( st=oem_kontron_event_types ; st->desc != NULL; st++){ if (st->code == rec->sel_type.standard_type.event_type ){ size_t len =strlen(st->desc); description = (char*)malloc( len + 1 ); @@ -546,7 +548,7 @@ get_supermicro_evt_desc(struct ipmi_intf *intf, struct sel_event_record *rec) struct ipmi_rs *rsp; struct ipmi_rq req; char *desc = NULL; - int chipset_type = 1; + int chipset_type = 4; int data1; int data2; int data3; @@ -612,12 +614,48 @@ get_supermicro_evt_desc(struct ipmi_intf *intf, struct sel_event_record *rec) break; } } + for (i = 0; supermicro_older[i] != 0xFFFF; i++) { + if (oem_id == supermicro_older[i]) { + chipset_type = 0; + break; + } + } + for (i = 0; supermicro_romely[i] != 0xFFFF; i++) { + if (oem_id == supermicro_romely[i]) { + chipset_type = 1; + break; + } + } for (i = 0; supermicro_x9[i] != 0xFFFF; i++) { if (oem_id == supermicro_x9[i]) { chipset_type = 2; break; } } + for (i = 0; supermicro_brickland[i] != 0xFFFF; i++) { + if (oem_id == supermicro_brickland[i]) { + chipset_type = 3; + break; + } + } + for (i = 0; supermicro_x10QRH[i] != 0xFFFF; i++) { + if (oem_id == supermicro_x10QRH[i]) { + chipset_type = 4; + break; + } + } + for (i = 0; supermicro_x10QBL[i] != 0xFFFF; i++) { + if (oem_id == supermicro_x10QBL[i]) { + chipset_type = 4; + break; + } + } + for (i = 0; supermicro_x10OBi[i] != 0xFFFF; i++) { + if (oem_id == supermicro_x10OBi[i]) { + chipset_type = 5; + break; + } + } if (chipset_type == 0) { snprintf(desc, SIZE_OF_DESC, "@DIMM%2X(CPU%x)", data2, @@ -630,6 +668,21 @@ get_supermicro_evt_desc(struct ipmi_intf *intf, struct sel_event_record *rec) snprintf(desc, SIZE_OF_DESC, "@DIMM%c%c(CPU%x)", (data2 >> 4) + 0x40 + (data3 & 0x3) * 3, (data2 & 0xf) + 0x27, (data3 & 0x03) + 1); + } else if (chipset_type == 3) { + snprintf(desc, SIZE_OF_DESC, "@DIMM%c%d(P%dM%d)", + ((data2 & 0xf) >> 4) > 4 + ? '@' - 4 + ((data2 & 0xff) >> 4) + : '@' + ((data2 & 0xff) >> 4), + (data2 & 0xf) - 0x09, (data3 & 0x0f) + 1, + (data2 & 0xff) >> 4 > 4 ? 2 : 1); + } else if (chipset_type == 4) { + snprintf(desc, SIZE_OF_DESC, "@DIMM%c%c(CPU%x)", + (data2 >> 4) + 0x40, + (data2 & 0xf) + 0x27, (data3 & 0x03) + 1); + } else if (chipset_type == 5) { + snprintf(desc, SIZE_OF_DESC, "@DIMM%c%c(CPU%x)", + (data2 >> 4) + 0x40, + (data2 & 0xf) + 0x27, (data3 & 0x07) + 1); } else { /* No description. */ desc[0] = '\0'; @@ -1200,11 +1253,71 @@ ipmi_get_oem_desc(struct ipmi_intf * intf, struct sel_event_record * rec) } +const struct ipmi_event_sensor_types * +ipmi_get_first_event_sensor_type(struct ipmi_intf *intf, + uint8_t sensor_type, uint8_t event_type) +{ + const struct ipmi_event_sensor_types *evt, *start, *next = NULL; + uint8_t code; + + if (event_type == 0x6f) { + if (sensor_type >= 0xC0 + && sensor_type < 0xF0 + && ipmi_get_oem(intf) == IPMI_OEM_KONTRON) { + /* check Kontron OEM sensor event types */ + start = oem_kontron_event_types; + } else if (intf->vita_avail) { + /* check VITA sensor event types first */ + start = vita_sensor_event_types; + + /* then check generic sensor types */ + next = sensor_specific_event_types; + } else { + /* check generic sensor types */ + start = sensor_specific_event_types; + } + code = sensor_type; + } else { + start = generic_event_types; + code = event_type; + } + + for (evt = start; evt->desc != NULL || next != NULL; evt++) { + /* check if VITA sensor event types has finished */ + if (evt->desc == NULL) { + /* proceed with next table */ + evt = next; + next = NULL; + } + + if (code == evt->code) + return evt; + } + + return NULL; +} + + +const struct ipmi_event_sensor_types * +ipmi_get_next_event_sensor_type(const struct ipmi_event_sensor_types *evt) +{ + const struct ipmi_event_sensor_types *start = evt; + + for (evt = start + 1; evt->desc != NULL; evt++) { + if (evt->code == start->code) { + return evt; + } + } + + return NULL; +} + + void ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char ** desc) { - uint8_t code, offset; - struct ipmi_event_sensor_types *evt = NULL; + uint8_t offset; + const struct ipmi_event_sensor_types *evt = NULL; char *sfx = NULL; /* This will be assigned if the Platform is DELL, additional info is appended to the current Description */ @@ -1223,86 +1336,61 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char case IPMI_OEM_KONTRON: lprintf(LOG_DEBUG, "oem sensor type %x %d using oem type supplied description", rec->sel_type.standard_type.sensor_type , iana); - - evt = oem_kontron_event_types; - code = rec->sel_type.standard_type.sensor_type; break; case IPMI_OEM_DELL: /* OEM Bytes Decoding for DELLi */ - evt = sensor_specific_types; - code = rec->sel_type.standard_type.sensor_type; if ( (OEM_CODE_IN_BYTE2 == (rec->sel_type.standard_type.event_data[0] & DATA_BYTE2_SPECIFIED_MASK)) || (OEM_CODE_IN_BYTE3 == (rec->sel_type.standard_type.event_data[0] & DATA_BYTE3_SPECIFIED_MASK)) ) { - if(rec->sel_type.standard_type.event_data[0] & DATA_BYTE2_SPECIFIED_MASK) - evt->data = rec->sel_type.standard_type.event_data[1]; - sfx = ipmi_get_oem_desc(intf, rec); } break; case IPMI_OEM_SUPERMICRO: case IPMI_OEM_SUPERMICRO_47488: - evt = sensor_specific_types; - code = rec->sel_type.standard_type.sensor_type; sfx = ipmi_get_oem_desc(intf, rec); break; /* add your oem sensor assignation here */ default: + lprintf(LOG_DEBUG, "oem sensor type %x using standard type supplied description", + rec->sel_type.standard_type.sensor_type ); break; - } - if( evt == NULL ){ - lprintf(LOG_DEBUG, "oem sensor type %x using standard type supplied description", - rec->sel_type.standard_type.sensor_type ); } } else { switch (ipmi_get_oem(intf)) { case IPMI_OEM_SUPERMICRO: case IPMI_OEM_SUPERMICRO_47488: - evt = sensor_specific_types; - code = rec->sel_type.standard_type.sensor_type; sfx = ipmi_get_oem_desc(intf, rec); break; default: break; } } - if( evt == NULL ){ - evt = sensor_specific_types; - code = rec->sel_type.standard_type.sensor_type; - } /* * Check for the OEM DELL Interface based on the Dell Specific Vendor Code. * If its Dell Platform, do the OEM Byte decode from the SEL Records. * Additional information should be written by the ipmi_get_oem_desc() */ if(ipmi_get_oem(intf) == IPMI_OEM_DELL) { - code = rec->sel_type.standard_type.sensor_type; if ( (OEM_CODE_IN_BYTE2 == (rec->sel_type.standard_type.event_data[0] & DATA_BYTE2_SPECIFIED_MASK)) || (OEM_CODE_IN_BYTE3 == (rec->sel_type.standard_type.event_data[0] & DATA_BYTE3_SPECIFIED_MASK)) ) { - if(rec->sel_type.standard_type.event_data[0] & DATA_BYTE2_SPECIFIED_MASK) - evt->data = rec->sel_type.standard_type.event_data[1]; - sfx = ipmi_get_oem_desc(intf, rec); - + sfx = ipmi_get_oem_desc(intf, rec); } else if(SENSOR_TYPE_OEM_SEC_EVENT == rec->sel_type.standard_type.event_data[0]) { /* 0x23 : Sensor Number.*/ if(0x23 == rec->sel_type.standard_type.sensor_num) - { - evt->data = rec->sel_type.standard_type.event_data[1]; sfx = ipmi_get_oem_desc(intf, rec); - } } } - } else { - evt = generic_event_types; - code = rec->sel_type.standard_type.event_type; } offset = rec->sel_type.standard_type.event_data[0] & 0xf; - while (evt->type) { - if ((evt->code == code && evt->offset == offset && evt->desc != NULL) && + for (evt = ipmi_get_first_event_sensor_type(intf, + rec->sel_type.standard_type.sensor_type, + rec->sel_type.standard_type.event_type); + evt != NULL; evt = ipmi_get_next_event_sensor_type(evt)) { + if ((evt->offset == offset && evt->desc != NULL) && ((evt->data == ALL_OFFSETS_SPECIFIED) || ((rec->sel_type.standard_type.event_data[0] & DATA_BYTE2_SPECIFIED_MASK) && (evt->data == rec->sel_type.standard_type.event_data[1])))) @@ -1326,15 +1414,14 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char sprintf(*desc, "%s", evt->desc); } return; - } - evt++; + } } /* The Above while Condition was not met beacouse the below sensor type were Newly defined OEM Secondary Events. 0xC1, 0xC2, 0xC3. */ if((sfx) && (0x6F == rec->sel_type.standard_type.event_type)) { uint8_t flag = 0x00; - switch(code) + switch(rec->sel_type.standard_type.sensor_type) { case SENSOR_TYPE_FRM_PROG: if(0x0F == offset) @@ -1379,74 +1466,58 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char } -const char * -ipmi_sel_get_oem_sensor_type(IPMI_OEM iana, uint8_t code) +const char* +ipmi_get_generic_sensor_type(uint8_t code) { - struct ipmi_event_sensor_types *st = NULL; - - switch(iana){ - case IPMI_OEM_KONTRON: - st = oem_kontron_event_types; - break; - /* add you oem sensor type lookup assignement here */ - default: - lprintf(LOG_DEBUG, "ipmitool: missing OEM sensor type for %ul",iana); - break; + if (code <= SENSOR_TYPE_MAX) { + return ipmi_generic_sensor_type_vals[code]; } - if( st != NULL ) - for (; st->type != NULL; st++) - if (st->code == code) - return st->type; - - return ipmi_sel_get_sensor_type(code); + return NULL; } + const char * -ipmi_sel_get_oem_sensor_type_offset(IPMI_OEM iana, uint8_t code, uint8_t offset) +ipmi_get_oem_sensor_type(struct ipmi_intf *intf, uint8_t code) { - struct ipmi_event_sensor_types *st = NULL; + const struct oemvalstr *v, *found = NULL; + uint32_t iana = ipmi_get_oem(intf); - switch(iana){ - case IPMI_OEM_KONTRON: - st = oem_kontron_event_types; - break; - /* add you oem sensor type lookup assignement here */ - default: - lprintf(LOG_DEBUG, - "ipmitool: missing OEM sensor type offset for %ul",iana); - break; - } + for (v = ipmi_oem_sensor_type_vals; v->str; v++) { + if (v->oem == iana && v->val == code) { + return v->str; + } - if( st != NULL ) - for (; st->type != NULL; st++) - { - if (st->code == code && st->offset == (offset&0xf)) - return st->type; + if ((intf->picmg_avail + && v->oem == IPMI_OEM_PICMG + && v->val == code) + || (intf->vita_avail + && v->oem == IPMI_OEM_VITA + && v->val == code)) { + found = v; } + } - return ipmi_sel_get_oem_sensor_type(iana,code); + return found ? found->str : NULL; } -const char * -ipmi_sel_get_sensor_type(uint8_t code) -{ - struct ipmi_event_sensor_types *st; - for (st = sensor_specific_types; st->type != NULL; st++) - if (st->code == code) - return st->type; - return "Unknown"; -} const char * -ipmi_sel_get_sensor_type_offset(uint8_t code, uint8_t offset) +ipmi_get_sensor_type(struct ipmi_intf *intf, uint8_t code) { - struct ipmi_event_sensor_types *st; - for (st = sensor_specific_types; st->type != NULL; st++) - if (st->code == code && st->offset == (offset&0xf)) - return st->type; + const char *type; + + if (code >= 0xC0) { + type = ipmi_get_oem_sensor_type(intf, code); + } else { + type = ipmi_get_generic_sensor_type(code); + } + + if (type == NULL) { + type = "Unknown"; + } - return ipmi_sel_get_sensor_type(code); + return type; } static int @@ -1693,13 +1764,7 @@ ipmi_sel_print_event_file(struct ipmi_intf * intf, struct sel_event_record * evt evt->sel_type.standard_type.event_data[0], evt->sel_type.standard_type.event_data[1], evt->sel_type.standard_type.event_data[2], - ( - (evt->sel_type.standard_type.sensor_type >=0xC0 && evt->sel_type.standard_type.sensor_type < 0xF0) - ? - ipmi_sel_get_oem_sensor_type_offset(ipmi_get_oem(intf),evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0]) - : - ipmi_sel_get_sensor_type_offset(evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0]) - ), + ipmi_get_sensor_type(intf, evt->sel_type.standard_type.sensor_type), evt->sel_type.standard_type.sensor_num, (description != NULL) ? description : "Unknown"); @@ -1819,15 +1884,8 @@ ipmi_sel_print_std_entry(struct ipmi_intf * intf, struct sel_event_record * evt) /* lookup SDR entry based on sensor number and type */ if (sdr != NULL) { - printf("%s ", - ( - (evt->sel_type.standard_type.sensor_type >=0xC0 && evt->sel_type.standard_type.sensor_type < 0xF0) - ? - ipmi_sel_get_oem_sensor_type_offset(ipmi_get_oem(intf),evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0]) - : - ipmi_sel_get_sensor_type_offset(evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0]) - ) - ); + printf("%s ", ipmi_get_sensor_type(intf, + evt->sel_type.standard_type.sensor_type)); switch (sdr->type) { case SDR_RECORD_TYPE_FULL_SENSOR: printf("%s", sdr->record.full->id_string); @@ -1852,13 +1910,8 @@ ipmi_sel_print_std_entry(struct ipmi_intf * intf, struct sel_event_record * evt) break; } } else { - printf("%s",( - (evt->sel_type.standard_type.sensor_type >=0xC0 && evt->sel_type.standard_type.sensor_type < 0xF0) - ? - ipmi_sel_get_oem_sensor_type_offset(ipmi_get_oem(intf),evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0]) - : - ipmi_sel_get_sensor_type_offset(evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0]) - )); + printf("%s", ipmi_get_sensor_type(intf, + evt->sel_type.standard_type.sensor_type)); if (evt->sel_type.standard_type.sensor_num != 0) printf(" #0x%02x", evt->sel_type.standard_type.sensor_num); } @@ -2025,14 +2078,8 @@ ipmi_sel_print_std_entry_verbose(struct ipmi_intf * intf, struct sel_event_recor printf(" EvM Revision : %02x\n", evt->sel_type.standard_type.evm_rev); printf(" Sensor Type : %s\n", - ( - (evt->sel_type.standard_type.sensor_type >=0xC0 && evt->sel_type.standard_type.sensor_type < 0xF0) - ? - ipmi_sel_get_oem_sensor_type_offset(ipmi_get_oem(intf),evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0]) - : - ipmi_sel_get_sensor_type_offset(evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0]) - ) - ); + ipmi_get_sensor_type(intf, + evt->sel_type.standard_type.sensor_type)); printf(" Sensor Number : %02x\n", evt->sel_type.standard_type.sensor_num); printf(" Event Type : %s\n", @@ -2096,7 +2143,7 @@ ipmi_sel_print_extended_entry_verbose(struct ipmi_intf * intf, struct sel_event_ printf(" EvM Revision : %02x\n", evt->sel_type.standard_type.evm_rev); printf(" Sensor Type : %s\n", - ipmi_sel_get_sensor_type_offset(evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0])); + ipmi_get_sensor_type(intf, evt->sel_type.standard_type.sensor_type)); printf(" Sensor Number : %02x\n", evt->sel_type.standard_type.sensor_num); printf(" Event Type : %s\n", @@ -2255,7 +2302,7 @@ __ipmi_sel_savelist_entries(struct ipmi_intf * intf, int count, const char * sav if (count < 0) { /** Show only the most recent 'count' records. */ - int delta; + int i; uint16_t entries; req.msg.cmd = IPMI_CMD_GET_SEL_INFO; @@ -2273,15 +2320,20 @@ __ipmi_sel_savelist_entries(struct ipmi_intf * intf, int count, const char * sav if (-count > entries) count = -entries; - /* Get first record. */ - next_id = ipmi_sel_get_std_entry(intf, 0, &evt); - - delta = next_id - evt.record_id; - - /* Get last record. */ - next_id = ipmi_sel_get_std_entry(intf, 0xffff, &evt); - - next_id = evt.record_id + count * delta + delta; + for(i = 0; i < entries + count; i++) { + next_id = ipmi_sel_get_std_entry(intf, next_id, &evt); + if (next_id == 0) { + /* + * usually next_id of zero means end but + * retry because some hardware has quirks + * and will return 0 randomly. + */ + next_id = ipmi_sel_get_std_entry(intf, next_id, &evt); + if (next_id == 0) { + break; + } + } + } } if (savefile != NULL) { @@ -2402,7 +2454,7 @@ ipmi_sel_interpret(struct ipmi_intf *intf, unsigned long iana, evt.sel_type.standard_type.evm_rev = 4; /* FIXME: convert*/ - evt.sel_type.standard_type.timestamp; + /* evt.sel_type.standard_type.timestamp; */ /* skip timestamp */ cursor = index((const char *)cursor, ';'); diff --git a/lib/ipmi_sensor.c b/lib/ipmi_sensor.c index 063dfb0..a0b7eb8 100644 --- a/lib/ipmi_sensor.c +++ b/lib/ipmi_sensor.c @@ -200,14 +200,14 @@ ipmi_sensor_print_fc_discrete(struct ipmi_intf *intf, printf(" Entity ID : %d.%d\n", sensor->entity.id, sensor->entity.instance); printf(" Sensor Type (Discrete): %s\n", - ipmi_sdr_get_sensor_type_desc(sensor->sensor. + ipmi_get_sensor_type(intf, sensor->sensor. type)); if( sr->s_reading_valid ) { if (sr->s_has_analog_value) { printf(" Sensor Reading : %s %s\n", sr->s_a_str, sr->s_a_units); } - ipmi_sdr_print_discrete_state("States Asserted", + ipmi_sdr_print_discrete_state(intf, "States Asserted", sensor->sensor.type, sensor->event_type, sr->s_data2, @@ -315,7 +315,7 @@ ipmi_sensor_print_fc_threshold(struct ipmi_intf *intf, sensor->entity.id, sensor->entity.instance); printf(" Sensor Type (Threshold) : %s\n", - ipmi_sdr_get_sensor_type_desc(sensor->sensor. + ipmi_get_sensor_type(intf, sensor->sensor. type)); printf(" Sensor Reading : "); diff --git a/lib/ipmi_session.c b/lib/ipmi_session.c index 4855bc4..141f0f4 100644 --- a/lib/ipmi_session.c +++ b/lib/ipmi_session.c @@ -99,13 +99,8 @@ print_session_info_csv(const struct get_session_info_rsp * session_info, buffer, 16)); - printf(",%02x:%02x:%02x:%02x:%02x:%02x", - session_info->channel_data.lan_data.console_mac[0], - session_info->channel_data.lan_data.console_mac[1], - session_info->channel_data.lan_data.console_mac[2], - session_info->channel_data.lan_data.console_mac[3], - session_info->channel_data.lan_data.console_mac[4], - session_info->channel_data.lan_data.console_mac[5]); + printf(",%s", mac2str( + session_info->channel_data.lan_data.console_mac)); console_port_tmp = session_info->channel_data.lan_data.console_port; #if WORDS_BIGENDIAN @@ -187,13 +182,8 @@ print_session_info_verbose(const struct get_session_info_rsp * session_info, buffer, 16)); - printf("console mac : %02x:%02x:%02x:%02x:%02x:%02x\n", - session_info->channel_data.lan_data.console_mac[0], - session_info->channel_data.lan_data.console_mac[1], - session_info->channel_data.lan_data.console_mac[2], - session_info->channel_data.lan_data.console_mac[3], - session_info->channel_data.lan_data.console_mac[4], - session_info->channel_data.lan_data.console_mac[5]); + printf("console mac : %s\n", mac2str( + session_info->channel_data.lan_data.console_mac)); console_port_tmp = session_info->channel_data.lan_data.console_port; #if WORDS_BIGENDIAN diff --git a/lib/ipmi_sol.c b/lib/ipmi_sol.c index 333ce90..3acd5bb 100644 --- a/lib/ipmi_sol.c +++ b/lib/ipmi_sol.c @@ -1648,15 +1648,11 @@ ipmi_sol_red_pill(struct ipmi_intf * intf, int instance) else if (FD_ISSET(intf->fd, &read_fds)) { struct ipmi_rs * rs =intf->recv_sol(intf); - if ( rs) - { + if (rs) { output(rs); + } else { + bShouldExit = bBmcClosedSession = 1; } - /* - * Should recv_sol come back null, the incoming packet was not ours. - * Just fall through, the keepalive logic will determine if - * the BMC has dropped the session. - */ } diff --git a/lib/ipmi_strings.c b/lib/ipmi_strings.c index 7fefee9..94b2abd 100644 --- a/lib/ipmi_strings.c +++ b/lib/ipmi_strings.c @@ -64,12 +64,13 @@ const struct valstr ipmi_oem_info[] = { { IPMI_OEM_TOSHIBA, "Toshiba" }, { IPMI_OEM_HITACHI_116, "Hitachi" }, { IPMI_OEM_HITACHI_399, "Hitachi" }, - { IPMI_OEM_NOKIA_SOLUTIONS_AND_NETWORKS, "Nokia Solutions and Networks (formerly 'Nokia Siemens Networks')" }, + { IPMI_OEM_NOKIA_SOLUTIONS_AND_NETWORKS, "Nokia Solutions and Networks" }, { IPMI_OEM_BULL, "Bull Company" }, { IPMI_OEM_PPS, "Pigeon Point Systems" }, { IPMI_OEM_BROADCOM, "Broadcom Corporation" }, { IPMI_OEM_ERICSSON, "Ericsson AB"}, { IPMI_OEM_QUANTA, "Quanta" }, + { IPMI_OEM_VITA, "VITA" }, { IPMI_OEM_ADVANTECH, "Advantech" }, /************************************************************************ * Add ID String for IANA Enterprise Number of IBM & ADLINK @@ -286,34 +287,63 @@ const struct oemvalstr ipmi_oem_product_info[] = { { 0xffffff , 0xffff , NULL }, }; -const struct oemvalstr ipmi_oem_sdr_type_vals[] = { +const char *ipmi_generic_sensor_type_vals[] = { + "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", + NULL +}; + +const struct oemvalstr ipmi_oem_sensor_type_vals[] = { /* Keep OEM grouped together */ - { IPMI_OEM_KONTRON , 0xC0 , "OEM Firmware Info" }, - { IPMI_OEM_KONTRON , 0xC2 , "OEM Init Agent" }, - { IPMI_OEM_KONTRON , 0xC3 , "OEM IPMBL Link State" }, - { IPMI_OEM_KONTRON , 0xC4 , "OEM Board Reset" }, - { IPMI_OEM_KONTRON , 0xC5 , "OEM FRU Information Agent" }, - { IPMI_OEM_KONTRON , 0xC6 , "OEM POST Value Sensor" }, - { IPMI_OEM_KONTRON , 0xC7 , "OEM FWUM Status" }, - { IPMI_OEM_KONTRON , 0xC8 , "OEM Switch Mngt Software Status" }, - { IPMI_OEM_KONTRON , 0xC9 , "OEM OEM Diagnostic Status" }, - { IPMI_OEM_KONTRON , 0xCA , "OEM Component Firmware Upgrade" }, - { IPMI_OEM_KONTRON , 0xCB , "OEM FRU Over Current" }, - { IPMI_OEM_KONTRON , 0xCC , "OEM FRU Sensor Error" }, - { IPMI_OEM_KONTRON , 0xCD , "OEM FRU Power Denied" }, - { IPMI_OEM_KONTRON , 0xCE , "OEM Reserved" }, - { IPMI_OEM_KONTRON , 0xCF , "OEM Board Reset" }, - { IPMI_OEM_KONTRON , 0xD0 , "OEM Clock Resource Control" }, - { IPMI_OEM_KONTRON , 0xD1 , "OEM Power State" }, - { IPMI_OEM_KONTRON , 0xD2 , "OEM FRU Mngt Power Failure" }, - { IPMI_OEM_KONTRON , 0xD3 , "OEM Jumper Status" }, - { IPMI_OEM_KONTRON , 0xF2 , "OEM RTM Module Hotswap" }, - - { IPMI_OEM_PICMG , 0xF0 , "PICMG FRU Hotswap" }, - { IPMI_OEM_PICMG , 0xF1 , "PICMG IPMB0 Link State" }, - { IPMI_OEM_PICMG , 0xF2 , "PICMG Module Hotswap" }, - - { 0xffffff, 0x00, NULL } + { IPMI_OEM_KONTRON, 0xC0, "Firmware Info" }, + { IPMI_OEM_KONTRON, 0xC2, "Init Agent" }, + { IPMI_OEM_KONTRON, 0xC2, "Board Reset(cPCI)" }, + { IPMI_OEM_KONTRON, 0xC3, "IPMBL Link State" }, + { IPMI_OEM_KONTRON, 0xC4, "Board Reset" }, + { IPMI_OEM_KONTRON, 0xC5, "FRU Information Agent" }, + { IPMI_OEM_KONTRON, 0xC6, "POST Value Sensor" }, + { IPMI_OEM_KONTRON, 0xC7, "FWUM Status" }, + { IPMI_OEM_KONTRON, 0xC8, "Switch Mngt Software Status" }, + { IPMI_OEM_KONTRON, 0xC9, "OEM Diagnostic Status" }, + { IPMI_OEM_KONTRON, 0xCA, "Component Firmware Upgrade" }, + { IPMI_OEM_KONTRON, 0xCB, "FRU Over Current" }, + { IPMI_OEM_KONTRON, 0xCC, "FRU Sensor Error" }, + { IPMI_OEM_KONTRON, 0xCD, "FRU Power Denied" }, + { IPMI_OEM_KONTRON, 0xCE, "Reserved" }, + { IPMI_OEM_KONTRON, 0xCF, "Board Reset" }, + { IPMI_OEM_KONTRON, 0xD0, "Clock Resource Control" }, + { IPMI_OEM_KONTRON, 0xD1, "Power State" }, + { IPMI_OEM_KONTRON, 0xD2, "FRU Mngt Power Failure" }, + { IPMI_OEM_KONTRON, 0xD3, "Jumper Status" }, + { IPMI_OEM_KONTRON, 0xF2, "RTM Module Hotswap" }, + /* PICMG Sensor Types */ + { IPMI_OEM_PICMG, 0xF0, "FRU Hot Swap" }, + { IPMI_OEM_PICMG, 0xF1,"IPMB Physical Link" }, + { IPMI_OEM_PICMG, 0xF2, "Module Hot Swap" }, + { IPMI_OEM_PICMG, 0xF3, "Power Channel Notification" }, + { IPMI_OEM_PICMG, 0xF4, "Telco Alarm Input" }, + /* VITA 46.11 Sensor Types */ + { IPMI_OEM_VITA, 0xF0, "FRU State" }, + { IPMI_OEM_VITA, 0xF1, "System IPMB Link" }, + { IPMI_OEM_VITA, 0xF2, "FRU Health" }, + { IPMI_OEM_VITA, 0xF3, "FRU Temperature" }, + { IPMI_OEM_VITA, 0xF4, "Payload Test Results" }, + { IPMI_OEM_VITA, 0xF5, "Payload Test Status" }, + + { 0xffffff, 0x00, NULL } }; const struct valstr ipmi_netfn_vals[] = { @@ -591,6 +621,9 @@ const struct valstr ipmi_auth_algorithms[] = { { IPMI_AUTH_RAKP_NONE, "none" }, { IPMI_AUTH_RAKP_HMAC_SHA1, "hmac_sha1" }, { IPMI_AUTH_RAKP_HMAC_MD5, "hmac_md5" }, +#ifdef HAVE_CRYPTO_SHA256 + { IPMI_AUTH_RAKP_HMAC_SHA256, "hmac_sha256" }, +#endif /* HAVE_CRYPTO_SHA256 */ { 0x00, NULL } }; @@ -599,6 +632,9 @@ const struct valstr ipmi_integrity_algorithms[] = { { IPMI_INTEGRITY_HMAC_SHA1_96, "hmac_sha1_96" }, { IPMI_INTEGRITY_HMAC_MD5_128, "hmac_md5_128" }, { IPMI_INTEGRITY_MD5_128 , "md5_128" }, +#ifdef HAVE_CRYPTO_SHA256 + { IPMI_INTEGRITY_HMAC_SHA256_128, "sha256_128" }, +#endif /* HAVE_CRYPTO_SHA256 */ { 0x00, NULL } }; @@ -610,6 +646,14 @@ const struct valstr ipmi_encryption_algorithms[] = { { 0x00, NULL } }; +const struct valstr ipmi_user_enable_status_vals[] = { + { 0x00, "unknown" }, + { 0x40, "enabled" }, + { 0x80, "disabled" }, + { 0xC0, "reserved" }, + { 0xFF, NULL }, +}; + const struct valstr picmg_frucontrol_vals[] = { { 0, "Cold Reset" }, { 1, "Warm Reset" }, diff --git a/lib/ipmi_sunoem.c b/lib/ipmi_sunoem.c index e4fae65..ecbcbd9 100644 --- a/lib/ipmi_sunoem.c +++ b/lib/ipmi_sunoem.c @@ -1436,7 +1436,7 @@ ipmi_sunoem_echo(struct ipmi_intf * intf, int argc, char *argv[]) received++; if (!quiet_mode) { - printf("Receive %u Bytes - Seq. # %d time=%d ms\n", + printf("Receive %lu Bytes - Seq. # %d time=%d ms\n", sizeof(sunoem_echo_msg_t), echo_rsp->seq_num, resp_time); } } /* for (i = 0; i < num; i++) */ |