diff options
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++) */ | 
